c15ebbe35e34b903346d89cc0283f51f2991591d
[ira/wip.git] / source3 / smbd / reply.c
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 extern enum protocol_types Protocol;
31
32 /****************************************************************************
33  Ensure we check the path in *exactly* the same way as W2K for a findfirst/findnext
34  path or anything including wildcards.
35  We're assuming here that '/' is not the second byte in any multibyte char
36  set (a safe assumption). '\\' *may* be the second byte in a multibyte char
37  set.
38 ****************************************************************************/
39
40 /* Custom version for processing POSIX paths. */
41 #define IS_PATH_SEP(c,posix_only) ((c) == '/' || (!(posix_only) && (c) == '\\'))
42
43 static NTSTATUS check_path_syntax_internal(char *path,
44                                            bool posix_path,
45                                            bool *p_last_component_contains_wcard)
46 {
47         char *d = path;
48         const char *s = path;
49         NTSTATUS ret = NT_STATUS_OK;
50         bool start_of_name_component = True;
51         bool stream_started = false;
52
53         *p_last_component_contains_wcard = False;
54
55         while (*s) {
56                 if (stream_started) {
57                         switch (*s) {
58                         case '/':
59                         case '\\':
60                                 return NT_STATUS_OBJECT_NAME_INVALID;
61                         case ':':
62                                 if (s[1] == '\0') {
63                                         return NT_STATUS_OBJECT_NAME_INVALID;
64                                 }
65                                 if (strchr_m(&s[1], ':')) {
66                                         return NT_STATUS_OBJECT_NAME_INVALID;
67                                 }
68                                 if (StrCaseCmp(s, ":$DATA") != 0) {
69                                         return NT_STATUS_INVALID_PARAMETER;
70                                 }
71                                 break;
72                         }
73                 }
74
75                 if (!posix_path && !stream_started && *s == ':') {
76                         if (*p_last_component_contains_wcard) {
77                                 return NT_STATUS_OBJECT_NAME_INVALID;
78                         }
79                         /* Stream names allow more characters than file names.
80                            We're overloading posix_path here to allow a wider
81                            range of characters. If stream_started is true this
82                            is still a Windows path even if posix_path is true.
83                            JRA.
84                         */
85                         stream_started = true;
86                         start_of_name_component = false;
87                         posix_path = true;
88
89                         if (s[1] == '\0') {
90                                 return NT_STATUS_OBJECT_NAME_INVALID;
91                         }
92                 }
93
94                 if (!stream_started && IS_PATH_SEP(*s,posix_path)) {
95                         /*
96                          * Safe to assume is not the second part of a mb char
97                          * as this is handled below.
98                          */
99                         /* Eat multiple '/' or '\\' */
100                         while (IS_PATH_SEP(*s,posix_path)) {
101                                 s++;
102                         }
103                         if ((d != path) && (*s != '\0')) {
104                                 /* We only care about non-leading or trailing '/' or '\\' */
105                                 *d++ = '/';
106                         }
107
108                         start_of_name_component = True;
109                         /* New component. */
110                         *p_last_component_contains_wcard = False;
111                         continue;
112                 }
113
114                 if (start_of_name_component) {
115                         if ((s[0] == '.') && (s[1] == '.') && (IS_PATH_SEP(s[2],posix_path) || s[2] == '\0')) {
116                                 /* Uh oh - "/../" or "\\..\\"  or "/..\0" or "\\..\0" ! */
117
118                                 /*
119                                  * No mb char starts with '.' so we're safe checking the directory separator here.
120                                  */
121
122                                 /* If  we just added a '/' - delete it */
123                                 if ((d > path) && (*(d-1) == '/')) {
124                                         *(d-1) = '\0';
125                                         d--;
126                                 }
127
128                                 /* Are we at the start ? Can't go back further if so. */
129                                 if (d <= path) {
130                                         ret = NT_STATUS_OBJECT_PATH_SYNTAX_BAD;
131                                         break;
132                                 }
133                                 /* Go back one level... */
134                                 /* We know this is safe as '/' cannot be part of a mb sequence. */
135                                 /* NOTE - if this assumption is invalid we are not in good shape... */
136                                 /* Decrement d first as d points to the *next* char to write into. */
137                                 for (d--; d > path; d--) {
138                                         if (*d == '/')
139                                                 break;
140                                 }
141                                 s += 2; /* Else go past the .. */
142                                 /* We're still at the start of a name component, just the previous one. */
143                                 continue;
144
145                         } else if ((s[0] == '.') && ((s[1] == '\0') || IS_PATH_SEP(s[1],posix_path))) {
146                                 if (posix_path) {
147                                         /* Eat the '.' */
148                                         s++;
149                                         continue;
150                                 }
151                         }
152
153                 }
154
155                 if (!(*s & 0x80)) {
156                         if (!posix_path) {
157                                 if (*s <= 0x1f || *s == '|') {
158                                         return NT_STATUS_OBJECT_NAME_INVALID;
159                                 }
160                                 switch (*s) {
161                                         case '*':
162                                         case '?':
163                                         case '<':
164                                         case '>':
165                                         case '"':
166                                                 *p_last_component_contains_wcard = True;
167                                                 break;
168                                         default:
169                                                 break;
170                                 }
171                         }
172                         *d++ = *s++;
173                 } else {
174                         size_t siz;
175                         /* Get the size of the next MB character. */
176                         next_codepoint(s,&siz);
177                         switch(siz) {
178                                 case 5:
179                                         *d++ = *s++;
180                                         /*fall through*/
181                                 case 4:
182                                         *d++ = *s++;
183                                         /*fall through*/
184                                 case 3:
185                                         *d++ = *s++;
186                                         /*fall through*/
187                                 case 2:
188                                         *d++ = *s++;
189                                         /*fall through*/
190                                 case 1:
191                                         *d++ = *s++;
192                                         break;
193                                 default:
194                                         DEBUG(0,("check_path_syntax_internal: character length assumptions invalid !\n"));
195                                         *d = '\0';
196                                         return NT_STATUS_INVALID_PARAMETER;
197                         }
198                 }
199                 start_of_name_component = False;
200         }
201
202         *d = '\0';
203
204         return ret;
205 }
206
207 /****************************************************************************
208  Ensure we check the path in *exactly* the same way as W2K for regular pathnames.
209  No wildcards allowed.
210 ****************************************************************************/
211
212 NTSTATUS check_path_syntax(char *path)
213 {
214         bool ignore;
215         return check_path_syntax_internal(path, False, &ignore);
216 }
217
218 /****************************************************************************
219  Ensure we check the path in *exactly* the same way as W2K for regular pathnames.
220  Wildcards allowed - p_contains_wcard returns true if the last component contained
221  a wildcard.
222 ****************************************************************************/
223
224 NTSTATUS check_path_syntax_wcard(char *path, bool *p_contains_wcard)
225 {
226         return check_path_syntax_internal(path, False, p_contains_wcard);
227 }
228
229 /****************************************************************************
230  Check the path for a POSIX client.
231  We're assuming here that '/' is not the second byte in any multibyte char
232  set (a safe assumption).
233 ****************************************************************************/
234
235 NTSTATUS check_path_syntax_posix(char *path)
236 {
237         bool ignore;
238         return check_path_syntax_internal(path, True, &ignore);
239 }
240
241 /****************************************************************************
242  Pull a string and check the path allowing a wilcard - provide for error return.
243 ****************************************************************************/
244
245 size_t srvstr_get_path_wcard(TALLOC_CTX *ctx,
246                         const char *base_ptr,
247                         uint16 smb_flags2,
248                         char **pp_dest,
249                         const char *src,
250                         size_t src_len,
251                         int flags,
252                         NTSTATUS *err,
253                         bool *contains_wcard)
254 {
255         size_t ret;
256
257         *pp_dest = NULL;
258
259         ret = srvstr_pull_talloc(ctx, base_ptr, smb_flags2, pp_dest, src,
260                                  src_len, flags);
261
262         if (!*pp_dest) {
263                 *err = NT_STATUS_INVALID_PARAMETER;
264                 return ret;
265         }
266
267         *contains_wcard = False;
268
269         if (smb_flags2 & FLAGS2_DFS_PATHNAMES) {
270                 /*
271                  * For a DFS path the function parse_dfs_path()
272                  * will do the path processing, just make a copy.
273                  */
274                 *err = NT_STATUS_OK;
275                 return ret;
276         }
277
278         if (lp_posix_pathnames()) {
279                 *err = check_path_syntax_posix(*pp_dest);
280         } else {
281                 *err = check_path_syntax_wcard(*pp_dest, contains_wcard);
282         }
283
284         return ret;
285 }
286
287 /****************************************************************************
288  Pull a string and check the path - provide for error return.
289 ****************************************************************************/
290
291 size_t srvstr_get_path(TALLOC_CTX *ctx,
292                         const char *base_ptr,
293                         uint16 smb_flags2,
294                         char **pp_dest,
295                         const char *src,
296                         size_t src_len,
297                         int flags,
298                         NTSTATUS *err)
299 {
300         bool ignore;
301         return srvstr_get_path_wcard(ctx, base_ptr, smb_flags2, pp_dest, src,
302                                      src_len, flags, err, &ignore);
303 }
304
305 size_t srvstr_get_path_req_wcard(TALLOC_CTX *mem_ctx, struct smb_request *req,
306                                  char **pp_dest, const char *src, int flags,
307                                  NTSTATUS *err, bool *contains_wcard)
308 {
309         return srvstr_get_path_wcard(mem_ctx, (char *)req->inbuf, req->flags2,
310                                      pp_dest, src, smbreq_bufrem(req, src),
311                                      flags, err, contains_wcard);
312 }
313
314 size_t srvstr_get_path_req(TALLOC_CTX *mem_ctx, struct smb_request *req,
315                            char **pp_dest, const char *src, int flags,
316                            NTSTATUS *err)
317 {
318         bool ignore;
319         return srvstr_get_path_req_wcard(mem_ctx, req, pp_dest, src,
320                                          flags, err, &ignore);
321 }
322
323 /****************************************************************************
324  Check if we have a correct fsp pointing to a file. Basic check for open fsp.
325 ****************************************************************************/
326
327 bool check_fsp_open(connection_struct *conn, struct smb_request *req,
328                     files_struct *fsp)
329 {
330         if (!(fsp) || !(conn)) {
331                 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
332                 return False;
333         }
334         if (((conn) != (fsp)->conn) || req->vuid != (fsp)->vuid) {
335                 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
336                 return False;
337         }
338         return True;
339 }
340
341 /****************************************************************************
342  Check if we have a correct fsp pointing to a file.
343 ****************************************************************************/
344
345 bool check_fsp(connection_struct *conn, struct smb_request *req,
346                files_struct *fsp)
347 {
348         if (!check_fsp_open(conn, req, fsp)) {
349                 return False;
350         }
351         if ((fsp)->is_directory) {
352                 reply_nterror(req, NT_STATUS_INVALID_DEVICE_REQUEST);
353                 return False;
354         }
355         if ((fsp)->fh->fd == -1) {
356                 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
357                 return False;
358         }
359         (fsp)->num_smb_operations++;
360         return True;
361 }
362
363 /****************************************************************************
364  Check if we have a correct fsp pointing to a quota fake file. Replacement for
365  the CHECK_NTQUOTA_HANDLE_OK macro.
366 ****************************************************************************/
367
368 bool check_fsp_ntquota_handle(connection_struct *conn, struct smb_request *req,
369                               files_struct *fsp)
370 {
371         if (!check_fsp_open(conn, req, fsp)) {
372                 return false;
373         }
374
375         if (fsp->is_directory) {
376                 return false;
377         }
378
379         if (fsp->fake_file_handle == NULL) {
380                 return false;
381         }
382
383         if (fsp->fake_file_handle->type != FAKE_FILE_TYPE_QUOTA) {
384                 return false;
385         }
386
387         if (fsp->fake_file_handle->private_data == NULL) {
388                 return false;
389         }
390
391         return true;
392 }
393
394 /****************************************************************************
395  Check if we have a correct fsp. Replacement for the FSP_BELONGS_CONN macro
396 ****************************************************************************/
397
398 bool fsp_belongs_conn(connection_struct *conn, struct smb_request *req,
399                       files_struct *fsp)
400 {
401         if ((fsp) && (conn) && ((conn)==(fsp)->conn)
402             && (req->vuid == (fsp)->vuid)) {
403                 return True;
404         }
405
406         reply_nterror(req, NT_STATUS_INVALID_HANDLE);
407         return False;
408 }
409
410 static bool netbios_session_retarget(const char *name, int name_type)
411 {
412         char *trim_name;
413         char *trim_name_type;
414         const char *retarget_parm;
415         char *retarget;
416         char *p;
417         int retarget_type = 0x20;
418         int retarget_port = 139;
419         struct sockaddr_storage retarget_addr;
420         struct sockaddr_in *in_addr;
421         bool ret = false;
422         uint8_t outbuf[10];
423
424         if (get_socket_port(smbd_server_fd()) != 139) {
425                 return false;
426         }
427
428         trim_name = talloc_strdup(talloc_tos(), name);
429         if (trim_name == NULL) {
430                 goto fail;
431         }
432         trim_char(trim_name, ' ', ' ');
433
434         trim_name_type = talloc_asprintf(trim_name, "%s#%2.2x", trim_name,
435                                          name_type);
436         if (trim_name_type == NULL) {
437                 goto fail;
438         }
439
440         retarget_parm = lp_parm_const_string(-1, "netbios retarget",
441                                              trim_name_type, NULL);
442         if (retarget_parm == NULL) {
443                 retarget_parm = lp_parm_const_string(-1, "netbios retarget",
444                                                      trim_name, NULL);
445         }
446         if (retarget_parm == NULL) {
447                 goto fail;
448         }
449
450         retarget = talloc_strdup(trim_name, retarget_parm);
451         if (retarget == NULL) {
452                 goto fail;
453         }
454
455         DEBUG(10, ("retargeting %s to %s\n", trim_name_type, retarget));
456
457         p = strchr(retarget, ':');
458         if (p != NULL) {
459                 *p++ = '\0';
460                 retarget_port = atoi(p);
461         }
462
463         p = strchr_m(retarget, '#');
464         if (p != NULL) {
465                 *p++ = '\0';
466                 sscanf(p, "%x", &retarget_type);
467         }
468
469         ret = resolve_name(retarget, &retarget_addr, retarget_type);
470         if (!ret) {
471                 DEBUG(10, ("could not resolve %s\n", retarget));
472                 goto fail;
473         }
474
475         if (retarget_addr.ss_family != AF_INET) {
476                 DEBUG(10, ("Retarget target not an IPv4 addr\n"));
477                 goto fail;
478         }
479
480         in_addr = (struct sockaddr_in *)(void *)&retarget_addr;
481
482         _smb_setlen(outbuf, 6);
483         SCVAL(outbuf, 0, 0x84);
484         *(uint32_t *)(outbuf+4) = in_addr->sin_addr.s_addr;
485         *(uint16_t *)(outbuf+8) = htons(retarget_port);
486
487         if (!srv_send_smb(smbd_server_fd(), (char *)outbuf, false, 0, false,
488                           NULL)) {
489                 exit_server_cleanly("netbios_session_regarget: srv_send_smb "
490                                     "failed.");
491         }
492
493         ret = true;
494  fail:
495         TALLOC_FREE(trim_name);
496         return ret;
497 }
498
499 /****************************************************************************
500  Reply to a (netbios-level) special message.
501 ****************************************************************************/
502
503 void reply_special(char *inbuf)
504 {
505         int msg_type = CVAL(inbuf,0);
506         int msg_flags = CVAL(inbuf,1);
507         fstring name1,name2;
508         char name_type1, name_type2;
509
510         /*
511          * We only really use 4 bytes of the outbuf, but for the smb_setlen
512          * calculation & friends (srv_send_smb uses that) we need the full smb
513          * header.
514          */
515         char outbuf[smb_size];
516
517         *name1 = *name2 = 0;
518
519         memset(outbuf, '\0', sizeof(outbuf));
520
521         smb_setlen(outbuf,0);
522
523         switch (msg_type) {
524         case 0x81: /* session request */
525
526                 if (already_got_session) {
527                         exit_server_cleanly("multiple session request not permitted");
528                 }
529
530                 SCVAL(outbuf,0,0x82);
531                 SCVAL(outbuf,3,0);
532                 if (name_len(inbuf+4) > 50 || 
533                     name_len(inbuf+4 + name_len(inbuf + 4)) > 50) {
534                         DEBUG(0,("Invalid name length in session request\n"));
535                         return;
536                 }
537                 name_type1 = name_extract(inbuf,4,name1);
538                 name_type2 = name_extract(inbuf,4 + name_len(inbuf + 4),name2);
539                 DEBUG(2,("netbios connect: name1=%s0x%x name2=%s0x%x\n",
540                          name1, name_type1, name2, name_type2));
541
542                 if (netbios_session_retarget(name1, name_type1)) {
543                         exit_server_cleanly("retargeted client");
544                 }
545
546                 set_local_machine_name(name1, True);
547                 set_remote_machine_name(name2, True);
548
549                 DEBUG(2,("netbios connect: local=%s remote=%s, name type = %x\n",
550                          get_local_machine_name(), get_remote_machine_name(),
551                          name_type2));
552
553                 if (name_type2 == 'R') {
554                         /* We are being asked for a pathworks session --- 
555                            no thanks! */
556                         SCVAL(outbuf, 0,0x83);
557                         break;
558                 }
559
560                 /* only add the client's machine name to the list
561                    of possibly valid usernames if we are operating
562                    in share mode security */
563                 if (lp_security() == SEC_SHARE) {
564                         add_session_user(get_remote_machine_name());
565                 }
566
567                 reload_services(True);
568                 reopen_logs();
569
570                 already_got_session = True;
571                 break;
572
573         case 0x89: /* session keepalive request 
574                       (some old clients produce this?) */
575                 SCVAL(outbuf,0,SMBkeepalive);
576                 SCVAL(outbuf,3,0);
577                 break;
578
579         case 0x82: /* positive session response */
580         case 0x83: /* negative session response */
581         case 0x84: /* retarget session response */
582                 DEBUG(0,("Unexpected session response\n"));
583                 break;
584
585         case SMBkeepalive: /* session keepalive */
586         default:
587                 return;
588         }
589
590         DEBUG(5,("init msg_type=0x%x msg_flags=0x%x\n",
591                     msg_type, msg_flags));
592
593         srv_send_smb(smbd_server_fd(), outbuf, false, 0, false, NULL);
594         return;
595 }
596
597 /****************************************************************************
598  Reply to a tcon.
599  conn POINTER CAN BE NULL HERE !
600 ****************************************************************************/
601
602 void reply_tcon(struct smb_request *req)
603 {
604         connection_struct *conn = req->conn;
605         const char *service;
606         char *service_buf = NULL;
607         char *password = NULL;
608         char *dev = NULL;
609         int pwlen=0;
610         NTSTATUS nt_status;
611         const char *p;
612         DATA_BLOB password_blob;
613         TALLOC_CTX *ctx = talloc_tos();
614
615         START_PROFILE(SMBtcon);
616
617         if (req->buflen < 4) {
618                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
619                 END_PROFILE(SMBtcon);
620                 return;
621         }
622
623         p = (const char *)req->buf + 1;
624         p += srvstr_pull_req_talloc(ctx, req, &service_buf, p, STR_TERMINATE);
625         p += 1;
626         pwlen = srvstr_pull_req_talloc(ctx, req, &password, p, STR_TERMINATE);
627         p += pwlen+1;
628         p += srvstr_pull_req_talloc(ctx, req, &dev, p, STR_TERMINATE);
629         p += 1;
630
631         if (service_buf == NULL || password == NULL || dev == NULL) {
632                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
633                 END_PROFILE(SMBtcon);
634                 return;
635         }
636         p = strrchr_m(service_buf,'\\');
637         if (p) {
638                 service = p+1;
639         } else {
640                 service = service_buf;
641         }
642
643         password_blob = data_blob(password, pwlen+1);
644
645         conn = make_connection(service,password_blob,dev,req->vuid,&nt_status);
646         req->conn = conn;
647
648         data_blob_clear_free(&password_blob);
649
650         if (!conn) {
651                 reply_nterror(req, nt_status);
652                 END_PROFILE(SMBtcon);
653                 return;
654         }
655
656         reply_outbuf(req, 2, 0);
657         SSVAL(req->outbuf,smb_vwv0,max_recv);
658         SSVAL(req->outbuf,smb_vwv1,conn->cnum);
659         SSVAL(req->outbuf,smb_tid,conn->cnum);
660
661         DEBUG(3,("tcon service=%s cnum=%d\n",
662                  service, conn->cnum));
663
664         END_PROFILE(SMBtcon);
665         return;
666 }
667
668 /****************************************************************************
669  Reply to a tcon and X.
670  conn POINTER CAN BE NULL HERE !
671 ****************************************************************************/
672
673 void reply_tcon_and_X(struct smb_request *req)
674 {
675         connection_struct *conn = req->conn;
676         const char *service = NULL;
677         DATA_BLOB password;
678         TALLOC_CTX *ctx = talloc_tos();
679         /* what the cleint thinks the device is */
680         char *client_devicetype = NULL;
681         /* what the server tells the client the share represents */
682         const char *server_devicetype;
683         NTSTATUS nt_status;
684         int passlen;
685         char *path = NULL;
686         const char *p, *q;
687         uint16 tcon_flags;
688
689         START_PROFILE(SMBtconX);
690
691         if (req->wct < 4) {
692                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
693                 END_PROFILE(SMBtconX);
694                 return;
695         }
696
697         passlen = SVAL(req->vwv+3, 0);
698         tcon_flags = SVAL(req->vwv+2, 0);
699
700         /* we might have to close an old one */
701         if ((tcon_flags & 0x1) && conn) {
702                 close_cnum(conn,req->vuid);
703                 req->conn = NULL;
704                 conn = NULL;
705         }
706
707         if ((passlen > MAX_PASS_LEN) || (passlen >= req->buflen)) {
708                 reply_doserror(req, ERRDOS, ERRbuftoosmall);
709                 END_PROFILE(SMBtconX);
710                 return;
711         }
712
713         if (global_encrypted_passwords_negotiated) {
714                 password = data_blob_talloc(talloc_tos(), req->buf, passlen);
715                 if (lp_security() == SEC_SHARE) {
716                         /*
717                          * Security = share always has a pad byte
718                          * after the password.
719                          */
720                         p = (const char *)req->buf + passlen + 1;
721                 } else {
722                         p = (const char *)req->buf + passlen;
723                 }
724         } else {
725                 password = data_blob_talloc(talloc_tos(), req->buf, passlen+1);
726                 /* Ensure correct termination */
727                 password.data[passlen]=0;
728                 p = (const char *)req->buf + passlen + 1;
729         }
730
731         p += srvstr_pull_req_talloc(ctx, req, &path, p, STR_TERMINATE);
732
733         if (path == NULL) {
734                 data_blob_clear_free(&password);
735                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
736                 END_PROFILE(SMBtconX);
737                 return;
738         }
739
740         /*
741          * the service name can be either: \\server\share
742          * or share directly like on the DELL PowerVault 705
743          */
744         if (*path=='\\') {
745                 q = strchr_m(path+2,'\\');
746                 if (!q) {
747                         data_blob_clear_free(&password);
748                         reply_doserror(req, ERRDOS, ERRnosuchshare);
749                         END_PROFILE(SMBtconX);
750                         return;
751                 }
752                 service = q+1;
753         } else {
754                 service = path;
755         }
756
757         p += srvstr_pull_talloc(ctx, req->inbuf, req->flags2,
758                                 &client_devicetype, p,
759                                 MIN(6, smbreq_bufrem(req, p)), STR_ASCII);
760
761         if (client_devicetype == NULL) {
762                 data_blob_clear_free(&password);
763                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
764                 END_PROFILE(SMBtconX);
765                 return;
766         }
767
768         DEBUG(4,("Client requested device type [%s] for share [%s]\n", client_devicetype, service));
769
770         conn = make_connection(service, password, client_devicetype,
771                                req->vuid, &nt_status);
772         req->conn =conn;
773
774         data_blob_clear_free(&password);
775
776         if (!conn) {
777                 reply_nterror(req, nt_status);
778                 END_PROFILE(SMBtconX);
779                 return;
780         }
781
782         if ( IS_IPC(conn) )
783                 server_devicetype = "IPC";
784         else if ( IS_PRINT(conn) )
785                 server_devicetype = "LPT1:";
786         else
787                 server_devicetype = "A:";
788
789         if (Protocol < PROTOCOL_NT1) {
790                 reply_outbuf(req, 2, 0);
791                 if (message_push_string(&req->outbuf, server_devicetype,
792                                         STR_TERMINATE|STR_ASCII) == -1) {
793                         reply_nterror(req, NT_STATUS_NO_MEMORY);
794                         END_PROFILE(SMBtconX);
795                         return;
796                 }
797         } else {
798                 /* NT sets the fstype of IPC$ to the null string */
799                 const char *fstype = IS_IPC(conn) ? "" : lp_fstype(SNUM(conn));
800
801                 if (tcon_flags & TCONX_FLAG_EXTENDED_RESPONSE) {
802                         /* Return permissions. */
803                         uint32 perm1 = 0;
804                         uint32 perm2 = 0;
805
806                         reply_outbuf(req, 7, 0);
807
808                         if (IS_IPC(conn)) {
809                                 perm1 = FILE_ALL_ACCESS;
810                                 perm2 = FILE_ALL_ACCESS;
811                         } else {
812                                 perm1 = CAN_WRITE(conn) ?
813                                                 SHARE_ALL_ACCESS :
814                                                 SHARE_READ_ONLY;
815                         }
816
817                         SIVAL(req->outbuf, smb_vwv3, perm1);
818                         SIVAL(req->outbuf, smb_vwv5, perm2);
819                 } else {
820                         reply_outbuf(req, 3, 0);
821                 }
822
823                 if ((message_push_string(&req->outbuf, server_devicetype,
824                                          STR_TERMINATE|STR_ASCII) == -1)
825                     || (message_push_string(&req->outbuf, fstype,
826                                             STR_TERMINATE) == -1)) {
827                         reply_nterror(req, NT_STATUS_NO_MEMORY);
828                         END_PROFILE(SMBtconX);
829                         return;
830                 }
831
832                 /* what does setting this bit do? It is set by NT4 and
833                    may affect the ability to autorun mounted cdroms */
834                 SSVAL(req->outbuf, smb_vwv2, SMB_SUPPORT_SEARCH_BITS|
835                       (lp_csc_policy(SNUM(conn)) << 2));
836
837                 if (lp_msdfs_root(SNUM(conn)) && lp_host_msdfs()) {
838                         DEBUG(2,("Serving %s as a Dfs root\n",
839                                  lp_servicename(SNUM(conn)) ));
840                         SSVAL(req->outbuf, smb_vwv2,
841                               SMB_SHARE_IN_DFS | SVAL(req->outbuf, smb_vwv2));
842                 }
843         }
844
845
846         DEBUG(3,("tconX service=%s \n",
847                  service));
848
849         /* set the incoming and outgoing tid to the just created one */
850         SSVAL(req->inbuf,smb_tid,conn->cnum);
851         SSVAL(req->outbuf,smb_tid,conn->cnum);
852
853         END_PROFILE(SMBtconX);
854
855         chain_reply(req);
856         return;
857 }
858
859 /****************************************************************************
860  Reply to an unknown type.
861 ****************************************************************************/
862
863 void reply_unknown_new(struct smb_request *req, uint8 type)
864 {
865         DEBUG(0, ("unknown command type (%s): type=%d (0x%X)\n",
866                   smb_fn_name(type), type, type));
867         reply_doserror(req, ERRSRV, ERRunknownsmb);
868         return;
869 }
870
871 /****************************************************************************
872  Reply to an ioctl.
873  conn POINTER CAN BE NULL HERE !
874 ****************************************************************************/
875
876 void reply_ioctl(struct smb_request *req)
877 {
878         connection_struct *conn = req->conn;
879         uint16 device;
880         uint16 function;
881         uint32 ioctl_code;
882         int replysize;
883         char *p;
884
885         START_PROFILE(SMBioctl);
886
887         if (req->wct < 3) {
888                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
889                 END_PROFILE(SMBioctl);
890                 return;
891         }
892
893         device     = SVAL(req->vwv+1, 0);
894         function   = SVAL(req->vwv+2, 0);
895         ioctl_code = (device << 16) + function;
896
897         DEBUG(4, ("Received IOCTL (code 0x%x)\n", ioctl_code));
898
899         switch (ioctl_code) {
900             case IOCTL_QUERY_JOB_INFO:
901                     replysize = 32;
902                     break;
903             default:
904                     reply_doserror(req, ERRSRV, ERRnosupport);
905                     END_PROFILE(SMBioctl);
906                     return;
907         }
908
909         reply_outbuf(req, 8, replysize+1);
910         SSVAL(req->outbuf,smb_vwv1,replysize); /* Total data bytes returned */
911         SSVAL(req->outbuf,smb_vwv5,replysize); /* Data bytes this buffer */
912         SSVAL(req->outbuf,smb_vwv6,52);        /* Offset to data */
913         p = smb_buf(req->outbuf);
914         memset(p, '\0', replysize+1); /* valgrind-safe. */
915         p += 1;          /* Allow for alignment */
916
917         switch (ioctl_code) {
918                 case IOCTL_QUERY_JOB_INFO:                  
919                 {
920                         files_struct *fsp = file_fsp(
921                                 req, SVAL(req->vwv+0, 0));
922                         if (!fsp) {
923                                 reply_doserror(req, ERRDOS, ERRbadfid);
924                                 END_PROFILE(SMBioctl);
925                                 return;
926                         }
927                         SSVAL(p,0,fsp->rap_print_jobid);             /* Job number */
928                         srvstr_push((char *)req->outbuf, req->flags2, p+2,
929                                     global_myname(), 15,
930                                     STR_TERMINATE|STR_ASCII);
931                         if (conn) {
932                                 srvstr_push((char *)req->outbuf, req->flags2,
933                                             p+18, lp_servicename(SNUM(conn)),
934                                             13, STR_TERMINATE|STR_ASCII);
935                         } else {
936                                 memset(p+18, 0, 13);
937                         }
938                         break;
939                 }
940         }
941
942         END_PROFILE(SMBioctl);
943         return;
944 }
945
946 /****************************************************************************
947  Strange checkpath NTSTATUS mapping.
948 ****************************************************************************/
949
950 static NTSTATUS map_checkpath_error(uint16_t flags2, NTSTATUS status)
951 {
952         /* Strange DOS error code semantics only for checkpath... */
953         if (!(flags2 & FLAGS2_32_BIT_ERROR_CODES)) {
954                 if (NT_STATUS_EQUAL(NT_STATUS_OBJECT_NAME_INVALID,status)) {
955                         /* We need to map to ERRbadpath */
956                         return NT_STATUS_OBJECT_PATH_NOT_FOUND;
957                 }
958         }
959         return status;
960 }
961
962 /****************************************************************************
963  Reply to a checkpath.
964 ****************************************************************************/
965
966 void reply_checkpath(struct smb_request *req)
967 {
968         connection_struct *conn = req->conn;
969         struct smb_filename *smb_fname = NULL;
970         char *name = NULL;
971         NTSTATUS status;
972         TALLOC_CTX *ctx = talloc_tos();
973
974         START_PROFILE(SMBcheckpath);
975
976         srvstr_get_path_req(ctx, req, &name, (const char *)req->buf + 1,
977                             STR_TERMINATE, &status);
978
979         if (!NT_STATUS_IS_OK(status)) {
980                 status = map_checkpath_error(req->flags2, status);
981                 reply_nterror(req, status);
982                 END_PROFILE(SMBcheckpath);
983                 return;
984         }
985
986         status = resolve_dfspath(ctx, conn,
987                         req->flags2 & FLAGS2_DFS_PATHNAMES,
988                         name,
989                         &name);
990         if (!NT_STATUS_IS_OK(status)) {
991                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
992                         reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
993                                         ERRSRV, ERRbadpath);
994                         END_PROFILE(SMBcheckpath);
995                         return;
996                 }
997                 goto path_err;
998         }
999
1000         DEBUG(3,("reply_checkpath %s mode=%d\n", name, (int)SVAL(req->vwv+0, 0)));
1001
1002         status = unix_convert(ctx, conn, name, &smb_fname, 0);
1003         if (!NT_STATUS_IS_OK(status)) {
1004                 goto path_err;
1005         }
1006
1007         status = get_full_smb_filename(ctx, smb_fname, &name);
1008         if (!NT_STATUS_IS_OK(status)) {
1009                 goto path_err;
1010         }
1011
1012         status = check_name(conn, name);
1013         if (!NT_STATUS_IS_OK(status)) {
1014                 DEBUG(3,("reply_checkpath: check_name of %s failed (%s)\n",name,nt_errstr(status)));
1015                 goto path_err;
1016         }
1017
1018         if (!VALID_STAT(smb_fname->st) &&
1019             (SMB_VFS_STAT(conn, name, &smb_fname->st) != 0)) {
1020                 DEBUG(3,("reply_checkpath: stat of %s failed (%s)\n",name,strerror(errno)));
1021                 status = map_nt_error_from_unix(errno);
1022                 goto path_err;
1023         }
1024
1025         if (!S_ISDIR(smb_fname->st.st_mode)) {
1026                 reply_botherror(req, NT_STATUS_NOT_A_DIRECTORY,
1027                                 ERRDOS, ERRbadpath);
1028                 goto out;
1029         }
1030
1031         reply_outbuf(req, 0, 0);
1032  out:
1033         if (smb_fname) {
1034                 TALLOC_FREE(smb_fname);
1035         }
1036         END_PROFILE(SMBcheckpath);
1037         return;
1038
1039  path_err:
1040
1041         if (smb_fname) {
1042                 TALLOC_FREE(smb_fname);
1043         }
1044
1045         END_PROFILE(SMBcheckpath);
1046
1047         /* We special case this - as when a Windows machine
1048                 is parsing a path is steps through the components
1049                 one at a time - if a component fails it expects
1050                 ERRbadpath, not ERRbadfile.
1051         */
1052         status = map_checkpath_error(req->flags2, status);
1053         if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
1054                 /*
1055                  * Windows returns different error codes if
1056                  * the parent directory is valid but not the
1057                  * last component - it returns NT_STATUS_OBJECT_NAME_NOT_FOUND
1058                  * for that case and NT_STATUS_OBJECT_PATH_NOT_FOUND
1059                  * if the path is invalid.
1060                  */
1061                 reply_botherror(req, NT_STATUS_OBJECT_NAME_NOT_FOUND,
1062                                 ERRDOS, ERRbadpath);
1063                 return;
1064         }
1065
1066         reply_nterror(req, status);
1067 }
1068
1069 /****************************************************************************
1070  Reply to a getatr.
1071 ****************************************************************************/
1072
1073 void 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
1085         START_PROFILE(SMBgetatr);
1086
1087         p = (const char *)req->buf + 1;
1088         p += srvstr_get_path_req(ctx, req, &fname, p, STR_TERMINATE, &status);
1089         if (!NT_STATUS_IS_OK(status)) {
1090                 reply_nterror(req, status);
1091                 goto out;
1092         }
1093
1094         status = resolve_dfspath(ctx, conn,
1095                                 req->flags2 & FLAGS2_DFS_PATHNAMES,
1096                                 fname,
1097                                 &fname);
1098         if (!NT_STATUS_IS_OK(status)) {
1099                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1100                         reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1101                                         ERRSRV, ERRbadpath);
1102                         goto out;
1103                 }
1104                 reply_nterror(req, status);
1105                 goto out;
1106         }
1107
1108         /* dos smetimes asks for a stat of "" - it returns a "hidden directory"
1109                 under WfWg - weird! */
1110         if (*fname == '\0') {
1111                 mode = aHIDDEN | aDIR;
1112                 if (!CAN_WRITE(conn)) {
1113                         mode |= aRONLY;
1114                 }
1115                 size = 0;
1116                 mtime = 0;
1117         } else {
1118                 status = unix_convert(ctx, conn, fname, &smb_fname, 0);
1119                 if (!NT_STATUS_IS_OK(status)) {
1120                         reply_nterror(req, status);
1121                         goto out;
1122                 }
1123                 status = get_full_smb_filename(ctx, smb_fname, &fname);
1124                 if (!NT_STATUS_IS_OK(status)) {
1125                         reply_nterror(req, status);
1126                         goto out;
1127                 }
1128                 status = check_name(conn, fname);
1129                 if (!NT_STATUS_IS_OK(status)) {
1130                         DEBUG(3,("reply_getatr: check_name of %s failed (%s)\n",fname,nt_errstr(status)));
1131                         reply_nterror(req, status);
1132                         goto out;
1133                 }
1134                 if (!VALID_STAT(smb_fname->st) &&
1135                     (SMB_VFS_STAT(conn, fname, &smb_fname->st) != 0)) {
1136                         DEBUG(3,("reply_getatr: stat of %s failed (%s)\n",fname,strerror(errno)));
1137                         reply_unixerror(req, ERRDOS,ERRbadfile);
1138                         goto out;
1139                 }
1140
1141                 mode = dos_mode(conn, fname, &smb_fname->st);
1142                 size = smb_fname->st.st_size;
1143                 mtime = smb_fname->st.st_mtime;
1144                 if (mode & aDIR) {
1145                         size = 0;
1146                 }
1147         }
1148
1149         reply_outbuf(req, 10, 0);
1150
1151         SSVAL(req->outbuf,smb_vwv0,mode);
1152         if(lp_dos_filetime_resolution(SNUM(conn)) ) {
1153                 srv_put_dos_date3((char *)req->outbuf,smb_vwv1,mtime & ~1);
1154         } else {
1155                 srv_put_dos_date3((char *)req->outbuf,smb_vwv1,mtime);
1156         }
1157         SIVAL(req->outbuf,smb_vwv3,(uint32)size);
1158
1159         if (Protocol >= PROTOCOL_NT1) {
1160                 SSVAL(req->outbuf, smb_flg2,
1161                       SVAL(req->outbuf, smb_flg2) | FLAGS2_IS_LONG_NAME);
1162         }
1163
1164         DEBUG(3,("reply_getatr: name=%s mode=%d size=%u\n", fname, mode, (unsigned int)size ) );
1165
1166  out:
1167         if (smb_fname) {
1168                 TALLOC_FREE(smb_fname);
1169         }
1170         END_PROFILE(SMBgetatr);
1171         return;
1172 }
1173
1174 /****************************************************************************
1175  Reply to a setatr.
1176 ****************************************************************************/
1177
1178 void reply_setatr(struct smb_request *req)
1179 {
1180         struct smb_file_time ft;
1181         connection_struct *conn = req->conn;
1182         struct smb_filename *smb_fname = NULL;
1183         char *fname = NULL;
1184         int mode;
1185         time_t mtime;
1186         const char *p;
1187         NTSTATUS status;
1188         TALLOC_CTX *ctx = talloc_tos();
1189
1190         START_PROFILE(SMBsetatr);
1191
1192         ZERO_STRUCT(ft);
1193
1194         if (req->wct < 2) {
1195                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1196                 goto out;
1197         }
1198
1199         p = (const char *)req->buf + 1;
1200         p += srvstr_get_path_req(ctx, req, &fname, p, STR_TERMINATE, &status);
1201         if (!NT_STATUS_IS_OK(status)) {
1202                 reply_nterror(req, status);
1203                 goto out;
1204         }
1205
1206         status = resolve_dfspath(ctx, conn,
1207                                 req->flags2 & FLAGS2_DFS_PATHNAMES,
1208                                 fname,
1209                                 &fname);
1210         if (!NT_STATUS_IS_OK(status)) {
1211                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1212                         reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1213                                         ERRSRV, ERRbadpath);
1214                         goto out;
1215                 }
1216                 reply_nterror(req, status);
1217                 goto out;
1218         }
1219
1220         status = unix_convert(ctx, conn, fname, &smb_fname, 0);
1221         if (!NT_STATUS_IS_OK(status)) {
1222                 reply_nterror(req, status);
1223                 goto out;
1224         }
1225
1226         status = get_full_smb_filename(ctx, smb_fname, &fname);
1227         if (!NT_STATUS_IS_OK(status)) {
1228                 reply_nterror(req, status);
1229                 goto out;
1230         }
1231
1232         status = check_name(conn, fname);
1233         if (!NT_STATUS_IS_OK(status)) {
1234                 reply_nterror(req, status);
1235                 goto out;
1236         }
1237
1238         if (fname[0] == '.' && fname[1] == '\0') {
1239                 /*
1240                  * Not sure here is the right place to catch this
1241                  * condition. Might be moved to somewhere else later -- vl
1242                  */
1243                 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1244                 goto out;
1245         }
1246
1247         mode = SVAL(req->vwv+0, 0);
1248         mtime = srv_make_unix_date3(req->vwv+1);
1249
1250         ft.mtime = convert_time_t_to_timespec(mtime);
1251         status = smb_set_file_time(conn, NULL, fname,
1252                                    &smb_fname->st, &ft, true);
1253         if (!NT_STATUS_IS_OK(status)) {
1254                 reply_unixerror(req, ERRDOS, ERRnoaccess);
1255                 goto out;
1256         }
1257
1258         if (mode != FILE_ATTRIBUTE_NORMAL) {
1259                 if (VALID_STAT_OF_DIR(smb_fname->st))
1260                         mode |= aDIR;
1261                 else
1262                         mode &= ~aDIR;
1263
1264                 if (file_set_dosmode(conn, fname, mode, &smb_fname->st, NULL,
1265                                      false) != 0) {
1266                         reply_unixerror(req, ERRDOS, ERRnoaccess);
1267                         goto out;
1268                 }
1269         }
1270
1271         reply_outbuf(req, 0, 0);
1272
1273         DEBUG( 3, ( "setatr name=%s mode=%d\n", fname, mode ) );
1274  out:
1275         if (smb_fname) {
1276                 TALLOC_FREE(smb_fname);
1277         }
1278         END_PROFILE(SMBsetatr);
1279         return;
1280 }
1281
1282 /****************************************************************************
1283  Reply to a dskattr.
1284 ****************************************************************************/
1285
1286 void reply_dskattr(struct smb_request *req)
1287 {
1288         connection_struct *conn = req->conn;
1289         uint64_t dfree,dsize,bsize;
1290         START_PROFILE(SMBdskattr);
1291
1292         if (get_dfree_info(conn,".",True,&bsize,&dfree,&dsize) == (uint64_t)-1) {
1293                 reply_unixerror(req, ERRHRD, ERRgeneral);
1294                 END_PROFILE(SMBdskattr);
1295                 return;
1296         }
1297
1298         reply_outbuf(req, 5, 0);
1299
1300         if (Protocol <= PROTOCOL_LANMAN2) {
1301                 double total_space, free_space;
1302                 /* we need to scale this to a number that DOS6 can handle. We
1303                    use floating point so we can handle large drives on systems
1304                    that don't have 64 bit integers 
1305
1306                    we end up displaying a maximum of 2G to DOS systems
1307                 */
1308                 total_space = dsize * (double)bsize;
1309                 free_space = dfree * (double)bsize;
1310
1311                 dsize = (uint64_t)((total_space+63*512) / (64*512));
1312                 dfree = (uint64_t)((free_space+63*512) / (64*512));
1313
1314                 if (dsize > 0xFFFF) dsize = 0xFFFF;
1315                 if (dfree > 0xFFFF) dfree = 0xFFFF;
1316
1317                 SSVAL(req->outbuf,smb_vwv0,dsize);
1318                 SSVAL(req->outbuf,smb_vwv1,64); /* this must be 64 for dos systems */
1319                 SSVAL(req->outbuf,smb_vwv2,512); /* and this must be 512 */
1320                 SSVAL(req->outbuf,smb_vwv3,dfree);
1321         } else {
1322                 SSVAL(req->outbuf,smb_vwv0,dsize);
1323                 SSVAL(req->outbuf,smb_vwv1,bsize/512);
1324                 SSVAL(req->outbuf,smb_vwv2,512);
1325                 SSVAL(req->outbuf,smb_vwv3,dfree);
1326         }
1327
1328         DEBUG(3,("dskattr dfree=%d\n", (unsigned int)dfree));
1329
1330         END_PROFILE(SMBdskattr);
1331         return;
1332 }
1333
1334 /****************************************************************************
1335  Reply to a search.
1336  Can be called from SMBsearch, SMBffirst or SMBfunique.
1337 ****************************************************************************/
1338
1339 void reply_search(struct smb_request *req)
1340 {
1341         connection_struct *conn = req->conn;
1342         const char *mask = NULL;
1343         char *directory = NULL;
1344         char *fname = NULL;
1345         SMB_OFF_T size;
1346         uint32 mode;
1347         time_t date;
1348         uint32 dirtype;
1349         unsigned int numentries = 0;
1350         unsigned int maxentries = 0;
1351         bool finished = False;
1352         const char *p;
1353         int status_len;
1354         char *path = NULL;
1355         char status[21];
1356         int dptr_num= -1;
1357         bool check_descend = False;
1358         bool expect_close = False;
1359         NTSTATUS nt_status;
1360         bool mask_contains_wcard = False;
1361         bool allow_long_path_components = (req->flags2 & FLAGS2_LONG_PATH_COMPONENTS) ? True : False;
1362         TALLOC_CTX *ctx = talloc_tos();
1363         bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
1364
1365         START_PROFILE(SMBsearch);
1366
1367         if (req->wct < 2) {
1368                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1369                 END_PROFILE(SMBsearch);
1370                 return;
1371         }
1372
1373         if (lp_posix_pathnames()) {
1374                 reply_unknown_new(req, req->cmd);
1375                 END_PROFILE(SMBsearch);
1376                 return;
1377         }
1378
1379         /* If we were called as SMBffirst then we must expect close. */
1380         if(req->cmd == SMBffirst) {
1381                 expect_close = True;
1382         }
1383
1384         reply_outbuf(req, 1, 3);
1385         maxentries = SVAL(req->vwv+0, 0);
1386         dirtype = SVAL(req->vwv+1, 0);
1387         p = (const char *)req->buf + 1;
1388         p += srvstr_get_path_req_wcard(ctx, req, &path, p, STR_TERMINATE,
1389                                        &nt_status, &mask_contains_wcard);
1390         if (!NT_STATUS_IS_OK(nt_status)) {
1391                 reply_nterror(req, nt_status);
1392                 END_PROFILE(SMBsearch);
1393                 return;
1394         }
1395
1396         nt_status = resolve_dfspath_wcard(ctx, conn,
1397                                           req->flags2 & FLAGS2_DFS_PATHNAMES,
1398                                           path,
1399                                           &path,
1400                                           &mask_contains_wcard);
1401         if (!NT_STATUS_IS_OK(nt_status)) {
1402                 if (NT_STATUS_EQUAL(nt_status,NT_STATUS_PATH_NOT_COVERED)) {
1403                         reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1404                                         ERRSRV, ERRbadpath);
1405                         END_PROFILE(SMBsearch);
1406                         return;
1407                 }
1408                 reply_nterror(req, nt_status);
1409                 END_PROFILE(SMBsearch);
1410                 return;
1411         }
1412
1413         p++;
1414         status_len = SVAL(p, 0);
1415         p += 2;
1416
1417         /* dirtype &= ~aDIR; */
1418
1419         if (status_len == 0) {
1420                 struct smb_filename *smb_fname = NULL;
1421
1422                 nt_status = unix_convert(ctx, conn, path, &smb_fname,
1423                                          UCF_ALLOW_WCARD_LCOMP);
1424                 if (!NT_STATUS_IS_OK(nt_status)) {
1425                         reply_nterror(req, nt_status);
1426                         END_PROFILE(SMBsearch);
1427                         return;
1428                 }
1429
1430                 nt_status = get_full_smb_filename(ctx, smb_fname, &directory);
1431                 TALLOC_FREE(smb_fname);
1432                 if (!NT_STATUS_IS_OK(nt_status)) {
1433                         reply_nterror(req, nt_status);
1434                         END_PROFILE(SMBsearch);
1435                         return;
1436                 }
1437
1438                 nt_status = check_name(conn, directory);
1439                 if (!NT_STATUS_IS_OK(nt_status)) {
1440                         reply_nterror(req, nt_status);
1441                         END_PROFILE(SMBsearch);
1442                         return;
1443                 }
1444
1445                 p = strrchr_m(directory,'/');
1446                 if ((p != NULL) && (*directory != '/')) {
1447                         mask = p + 1;
1448                         directory = talloc_strndup(ctx, directory,
1449                                                    PTR_DIFF(p, directory));
1450                 } else {
1451                         mask = directory;
1452                         directory = talloc_strdup(ctx,".");
1453                 }
1454
1455                 if (!directory) {
1456                         reply_nterror(req, NT_STATUS_NO_MEMORY);
1457                         END_PROFILE(SMBsearch);
1458                         return;
1459                 }
1460
1461                 memset((char *)status,'\0',21);
1462                 SCVAL(status,0,(dirtype & 0x1F));
1463
1464                 nt_status = dptr_create(conn,
1465                                         directory,
1466                                         True,
1467                                         expect_close,
1468                                         req->smbpid,
1469                                         mask,
1470                                         mask_contains_wcard,
1471                                         dirtype,
1472                                         &conn->dirptr);
1473                 if (!NT_STATUS_IS_OK(nt_status)) {
1474                         reply_nterror(req, nt_status);
1475                         END_PROFILE(SMBsearch);
1476                         return;
1477                 }
1478                 dptr_num = dptr_dnum(conn->dirptr);
1479         } else {
1480                 int status_dirtype;
1481
1482                 memcpy(status,p,21);
1483                 status_dirtype = CVAL(status,0) & 0x1F;
1484                 if (status_dirtype != (dirtype & 0x1F)) {
1485                         dirtype = status_dirtype;
1486                 }
1487
1488                 conn->dirptr = dptr_fetch(status+12,&dptr_num);
1489                 if (!conn->dirptr) {
1490                         goto SearchEmpty;
1491                 }
1492                 string_set(&conn->dirpath,dptr_path(dptr_num));
1493                 mask = dptr_wcard(dptr_num);
1494                 if (!mask) {
1495                         goto SearchEmpty;
1496                 }
1497                 /*
1498                  * For a 'continue' search we have no string. So
1499                  * check from the initial saved string.
1500                  */
1501                 mask_contains_wcard = ms_has_wild(mask);
1502                 dirtype = dptr_attr(dptr_num);
1503         }
1504
1505         DEBUG(4,("dptr_num is %d\n",dptr_num));
1506
1507         /* Initialize per SMBsearch/SMBffirst/SMBfunique operation data */
1508         dptr_init_search_op(conn->dirptr);
1509
1510         if ((dirtype&0x1F) == aVOLID) {
1511                 char buf[DIR_STRUCT_SIZE];
1512                 memcpy(buf,status,21);
1513                 if (!make_dir_struct(ctx,buf,"???????????",volume_label(SNUM(conn)),
1514                                 0,aVOLID,0,!allow_long_path_components)) {
1515                         reply_nterror(req, NT_STATUS_NO_MEMORY);
1516                         END_PROFILE(SMBsearch);
1517                         return;
1518                 }
1519                 dptr_fill(buf+12,dptr_num);
1520                 if (dptr_zero(buf+12) && (status_len==0)) {
1521                         numentries = 1;
1522                 } else {
1523                         numentries = 0;
1524                 }
1525                 if (message_push_blob(&req->outbuf,
1526                                       data_blob_const(buf, sizeof(buf)))
1527                     == -1) {
1528                         reply_nterror(req, NT_STATUS_NO_MEMORY);
1529                         END_PROFILE(SMBsearch);
1530                         return;
1531                 }
1532         } else {
1533                 unsigned int i;
1534                 maxentries = MIN(
1535                         maxentries,
1536                         ((BUFFER_SIZE -
1537                           ((uint8 *)smb_buf(req->outbuf) + 3 - req->outbuf))
1538                          /DIR_STRUCT_SIZE));
1539
1540                 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
1541                         conn->dirpath,lp_dontdescend(SNUM(conn))));
1542                 if (in_list(conn->dirpath, lp_dontdescend(SNUM(conn)),True)) {
1543                         check_descend = True;
1544                 }
1545
1546                 for (i=numentries;(i<maxentries) && !finished;i++) {
1547                         finished = !get_dir_entry(ctx,
1548                                                   conn,
1549                                                   mask,
1550                                                   dirtype,
1551                                                   &fname,
1552                                                   &size,
1553                                                   &mode,
1554                                                   &date,
1555                                                   check_descend,
1556                                                   ask_sharemode);
1557                         if (!finished) {
1558                                 char buf[DIR_STRUCT_SIZE];
1559                                 memcpy(buf,status,21);
1560                                 if (!make_dir_struct(ctx,
1561                                                 buf,
1562                                                 mask,
1563                                                 fname,
1564                                                 size,
1565                                                 mode,
1566                                                 date,
1567                                                 !allow_long_path_components)) {
1568                                         reply_nterror(req, NT_STATUS_NO_MEMORY);
1569                                         END_PROFILE(SMBsearch);
1570                                         return;
1571                                 }
1572                                 if (!dptr_fill(buf+12,dptr_num)) {
1573                                         break;
1574                                 }
1575                                 if (message_push_blob(&req->outbuf,
1576                                                       data_blob_const(buf, sizeof(buf)))
1577                                     == -1) {
1578                                         reply_nterror(req, NT_STATUS_NO_MEMORY);
1579                                         END_PROFILE(SMBsearch);
1580                                         return;
1581                                 }
1582                                 numentries++;
1583                         }
1584                 }
1585         }
1586
1587   SearchEmpty:
1588
1589         /* If we were called as SMBffirst with smb_search_id == NULL
1590                 and no entries were found then return error and close dirptr 
1591                 (X/Open spec) */
1592
1593         if (numentries == 0) {
1594                 dptr_close(&dptr_num);
1595         } else if(expect_close && status_len == 0) {
1596                 /* Close the dptr - we know it's gone */
1597                 dptr_close(&dptr_num);
1598         }
1599
1600         /* If we were called as SMBfunique, then we can close the dirptr now ! */
1601         if(dptr_num >= 0 && req->cmd == SMBfunique) {
1602                 dptr_close(&dptr_num);
1603         }
1604
1605         if ((numentries == 0) && !mask_contains_wcard) {
1606                 reply_botherror(req, STATUS_NO_MORE_FILES, ERRDOS, ERRnofiles);
1607                 END_PROFILE(SMBsearch);
1608                 return;
1609         }
1610
1611         SSVAL(req->outbuf,smb_vwv0,numentries);
1612         SSVAL(req->outbuf,smb_vwv1,3 + numentries * DIR_STRUCT_SIZE);
1613         SCVAL(smb_buf(req->outbuf),0,5);
1614         SSVAL(smb_buf(req->outbuf),1,numentries*DIR_STRUCT_SIZE);
1615
1616         /* The replies here are never long name. */
1617         SSVAL(req->outbuf, smb_flg2,
1618               SVAL(req->outbuf, smb_flg2) & (~FLAGS2_IS_LONG_NAME));
1619         if (!allow_long_path_components) {
1620                 SSVAL(req->outbuf, smb_flg2,
1621                       SVAL(req->outbuf, smb_flg2)
1622                       & (~FLAGS2_LONG_PATH_COMPONENTS));
1623         }
1624
1625         /* This SMB *always* returns ASCII names. Remove the unicode bit in flags2. */
1626         SSVAL(req->outbuf, smb_flg2,
1627               (SVAL(req->outbuf, smb_flg2) & (~FLAGS2_UNICODE_STRINGS)));
1628
1629         if (!directory) {
1630                 directory = dptr_path(dptr_num);
1631         }
1632
1633         DEBUG(4,("%s mask=%s path=%s dtype=%d nument=%u of %u\n",
1634                 smb_fn_name(req->cmd),
1635                 mask,
1636                 directory ? directory : "./",
1637                 dirtype,
1638                 numentries,
1639                 maxentries ));
1640
1641         END_PROFILE(SMBsearch);
1642         return;
1643 }
1644
1645 /****************************************************************************
1646  Reply to a fclose (stop directory search).
1647 ****************************************************************************/
1648
1649 void reply_fclose(struct smb_request *req)
1650 {
1651         int status_len;
1652         char status[21];
1653         int dptr_num= -2;
1654         const char *p;
1655         char *path = NULL;
1656         NTSTATUS err;
1657         bool path_contains_wcard = False;
1658         TALLOC_CTX *ctx = talloc_tos();
1659
1660         START_PROFILE(SMBfclose);
1661
1662         if (lp_posix_pathnames()) {
1663                 reply_unknown_new(req, req->cmd);
1664                 END_PROFILE(SMBfclose);
1665                 return;
1666         }
1667
1668         p = (const char *)req->buf + 1;
1669         p += srvstr_get_path_req_wcard(ctx, req, &path, p, STR_TERMINATE,
1670                                        &err, &path_contains_wcard);
1671         if (!NT_STATUS_IS_OK(err)) {
1672                 reply_nterror(req, err);
1673                 END_PROFILE(SMBfclose);
1674                 return;
1675         }
1676         p++;
1677         status_len = SVAL(p,0);
1678         p += 2;
1679
1680         if (status_len == 0) {
1681                 reply_doserror(req, ERRSRV, ERRsrverror);
1682                 END_PROFILE(SMBfclose);
1683                 return;
1684         }
1685
1686         memcpy(status,p,21);
1687
1688         if(dptr_fetch(status+12,&dptr_num)) {
1689                 /*  Close the dptr - we know it's gone */
1690                 dptr_close(&dptr_num);
1691         }
1692
1693         reply_outbuf(req, 1, 0);
1694         SSVAL(req->outbuf,smb_vwv0,0);
1695
1696         DEBUG(3,("search close\n"));
1697
1698         END_PROFILE(SMBfclose);
1699         return;
1700 }
1701
1702 /****************************************************************************
1703  Reply to an open.
1704 ****************************************************************************/
1705
1706 void reply_open(struct smb_request *req)
1707 {
1708         connection_struct *conn = req->conn;
1709         char *fname = NULL;
1710         uint32 fattr=0;
1711         SMB_OFF_T size = 0;
1712         time_t mtime=0;
1713         int info;
1714         SMB_STRUCT_STAT sbuf;
1715         files_struct *fsp;
1716         int oplock_request;
1717         int deny_mode;
1718         uint32 dos_attr;
1719         uint32 access_mask;
1720         uint32 share_mode;
1721         uint32 create_disposition;
1722         uint32 create_options = 0;
1723         NTSTATUS status;
1724         TALLOC_CTX *ctx = talloc_tos();
1725
1726         START_PROFILE(SMBopen);
1727
1728         SET_STAT_INVALID(sbuf);
1729
1730         if (req->wct < 2) {
1731                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1732                 END_PROFILE(SMBopen);
1733                 return;
1734         }
1735
1736         oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
1737         deny_mode = SVAL(req->vwv+0, 0);
1738         dos_attr = SVAL(req->vwv+1, 0);
1739
1740         srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf+1,
1741                             STR_TERMINATE, &status);
1742         if (!NT_STATUS_IS_OK(status)) {
1743                 reply_nterror(req, status);
1744                 END_PROFILE(SMBopen);
1745                 return;
1746         }
1747
1748         if (!map_open_params_to_ntcreate(
1749                     fname, deny_mode, OPENX_FILE_EXISTS_OPEN, &access_mask,
1750                     &share_mode, &create_disposition, &create_options)) {
1751                 reply_nterror(req, NT_STATUS_DOS(ERRDOS, ERRbadaccess));
1752                 END_PROFILE(SMBopen);
1753                 return;
1754         }
1755
1756         status = SMB_VFS_CREATE_FILE(
1757                 conn,                                   /* conn */
1758                 req,                                    /* req */
1759                 0,                                      /* root_dir_fid */
1760                 fname,                                  /* fname */
1761                 CFF_DOS_PATH,                           /* create_file_flags */
1762                 access_mask,                            /* access_mask */
1763                 share_mode,                             /* share_access */
1764                 create_disposition,                     /* create_disposition*/
1765                 create_options,                         /* create_options */
1766                 dos_attr,                               /* file_attributes */
1767                 oplock_request,                         /* oplock_request */
1768                 0,                                      /* allocation_size */
1769                 NULL,                                   /* sd */
1770                 NULL,                                   /* ea_list */
1771                 &fsp,                                   /* result */
1772                 &info,                                  /* pinfo */
1773                 &sbuf);                                 /* psbuf */
1774
1775         if (!NT_STATUS_IS_OK(status)) {
1776                 if (open_was_deferred(req->mid)) {
1777                         /* We have re-scheduled this call. */
1778                         END_PROFILE(SMBopen);
1779                         return;
1780                 }
1781                 reply_openerror(req, status);
1782                 END_PROFILE(SMBopen);
1783                 return;
1784         }
1785
1786         size = sbuf.st_size;
1787         fattr = dos_mode(conn,fsp->fsp_name,&sbuf);
1788         mtime = sbuf.st_mtime;
1789
1790         if (fattr & aDIR) {
1791                 DEBUG(3,("attempt to open a directory %s\n",fsp->fsp_name));
1792                 close_file(req, fsp, ERROR_CLOSE);
1793                 reply_doserror(req, ERRDOS,ERRnoaccess);
1794                 END_PROFILE(SMBopen);
1795                 return;
1796         }
1797
1798         reply_outbuf(req, 7, 0);
1799         SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
1800         SSVAL(req->outbuf,smb_vwv1,fattr);
1801         if(lp_dos_filetime_resolution(SNUM(conn)) ) {
1802                 srv_put_dos_date3((char *)req->outbuf,smb_vwv2,mtime & ~1);
1803         } else {
1804                 srv_put_dos_date3((char *)req->outbuf,smb_vwv2,mtime);
1805         }
1806         SIVAL(req->outbuf,smb_vwv4,(uint32)size);
1807         SSVAL(req->outbuf,smb_vwv6,deny_mode);
1808
1809         if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1810                 SCVAL(req->outbuf,smb_flg,
1811                       CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1812         }
1813
1814         if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1815                 SCVAL(req->outbuf,smb_flg,
1816                       CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1817         }
1818         END_PROFILE(SMBopen);
1819         return;
1820 }
1821
1822 /****************************************************************************
1823  Reply to an open and X.
1824 ****************************************************************************/
1825
1826 void reply_open_and_X(struct smb_request *req)
1827 {
1828         connection_struct *conn = req->conn;
1829         char *fname = NULL;
1830         uint16 open_flags;
1831         int deny_mode;
1832         uint32 smb_attr;
1833         /* Breakout the oplock request bits so we can set the
1834                 reply bits separately. */
1835         int ex_oplock_request;
1836         int core_oplock_request;
1837         int oplock_request;
1838 #if 0
1839         int smb_sattr = SVAL(req->vwv+4, 0);
1840         uint32 smb_time = make_unix_date3(req->vwv+6);
1841 #endif
1842         int smb_ofun;
1843         uint32 fattr=0;
1844         int mtime=0;
1845         SMB_STRUCT_STAT sbuf;
1846         int smb_action = 0;
1847         files_struct *fsp;
1848         NTSTATUS status;
1849         uint64_t allocation_size;
1850         ssize_t retval = -1;
1851         uint32 access_mask;
1852         uint32 share_mode;
1853         uint32 create_disposition;
1854         uint32 create_options = 0;
1855         TALLOC_CTX *ctx = talloc_tos();
1856
1857         START_PROFILE(SMBopenX);
1858
1859         if (req->wct < 15) {
1860                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1861                 END_PROFILE(SMBopenX);
1862                 return;
1863         }
1864
1865         SET_STAT_INVALID(sbuf);
1866
1867         open_flags = SVAL(req->vwv+2, 0);
1868         deny_mode = SVAL(req->vwv+3, 0);
1869         smb_attr = SVAL(req->vwv+5, 0);
1870         ex_oplock_request = EXTENDED_OPLOCK_REQUEST(req->inbuf);
1871         core_oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
1872         oplock_request = ex_oplock_request | core_oplock_request;
1873         smb_ofun = SVAL(req->vwv+8, 0);
1874         allocation_size = (uint64_t)IVAL(req->vwv+9, 0);
1875
1876         /* If it's an IPC, pass off the pipe handler. */
1877         if (IS_IPC(conn)) {
1878                 if (lp_nt_pipe_support()) {
1879                         reply_open_pipe_and_X(conn, req);
1880                 } else {
1881                         reply_doserror(req, ERRSRV, ERRaccess);
1882                 }
1883                 END_PROFILE(SMBopenX);
1884                 return;
1885         }
1886
1887         /* XXXX we need to handle passed times, sattr and flags */
1888         srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf,
1889                         STR_TERMINATE, &status);
1890         if (!NT_STATUS_IS_OK(status)) {
1891                 reply_nterror(req, status);
1892                 END_PROFILE(SMBopenX);
1893                 return;
1894         }
1895
1896         if (!map_open_params_to_ntcreate(
1897                     fname, deny_mode, smb_ofun, &access_mask,
1898                     &share_mode, &create_disposition, &create_options)) {
1899                 reply_nterror(req, NT_STATUS_DOS(ERRDOS, ERRbadaccess));
1900                 END_PROFILE(SMBopenX);
1901                 return;
1902         }
1903
1904         status = SMB_VFS_CREATE_FILE(
1905                 conn,                                   /* conn */
1906                 req,                                    /* req */
1907                 0,                                      /* root_dir_fid */
1908                 fname,                                  /* fname */
1909                 CFF_DOS_PATH,                           /* create_file_flags */
1910                 access_mask,                            /* access_mask */
1911                 share_mode,                             /* share_access */
1912                 create_disposition,                     /* create_disposition*/
1913                 create_options,                         /* create_options */
1914                 smb_attr,                               /* file_attributes */
1915                 oplock_request,                         /* oplock_request */
1916                 0,                                      /* allocation_size */
1917                 NULL,                                   /* sd */
1918                 NULL,                                   /* ea_list */
1919                 &fsp,                                   /* result */
1920                 &smb_action,                            /* pinfo */
1921                 &sbuf);                                 /* psbuf */
1922
1923         if (!NT_STATUS_IS_OK(status)) {
1924                 END_PROFILE(SMBopenX);
1925                 if (open_was_deferred(req->mid)) {
1926                         /* We have re-scheduled this call. */
1927                         return;
1928                 }
1929                 reply_openerror(req, status);
1930                 return;
1931         }
1932
1933         /* Setting the "size" field in vwv9 and vwv10 causes the file to be set to this size,
1934            if the file is truncated or created. */
1935         if (((smb_action == FILE_WAS_CREATED) || (smb_action == FILE_WAS_OVERWRITTEN)) && allocation_size) {
1936                 fsp->initial_allocation_size = smb_roundup(fsp->conn, allocation_size);
1937                 if (vfs_allocate_file_space(fsp, fsp->initial_allocation_size) == -1) {
1938                         close_file(req, fsp, ERROR_CLOSE);
1939                         reply_nterror(req, NT_STATUS_DISK_FULL);
1940                         END_PROFILE(SMBopenX);
1941                         return;
1942                 }
1943                 retval = vfs_set_filelen(fsp, (SMB_OFF_T)allocation_size);
1944                 if (retval < 0) {
1945                         close_file(req, fsp, ERROR_CLOSE);
1946                         reply_nterror(req, NT_STATUS_DISK_FULL);
1947                         END_PROFILE(SMBopenX);
1948                         return;
1949                 }
1950                 sbuf.st_size = SMB_VFS_GET_ALLOC_SIZE(conn,fsp,&sbuf);
1951         }
1952
1953         fattr = dos_mode(conn,fsp->fsp_name,&sbuf);
1954         mtime = sbuf.st_mtime;
1955         if (fattr & aDIR) {
1956                 close_file(req, fsp, ERROR_CLOSE);
1957                 reply_doserror(req, ERRDOS, ERRnoaccess);
1958                 END_PROFILE(SMBopenX);
1959                 return;
1960         }
1961
1962         /* If the caller set the extended oplock request bit
1963                 and we granted one (by whatever means) - set the
1964                 correct bit for extended oplock reply.
1965         */
1966
1967         if (ex_oplock_request && lp_fake_oplocks(SNUM(conn))) {
1968                 smb_action |= EXTENDED_OPLOCK_GRANTED;
1969         }
1970
1971         if(ex_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1972                 smb_action |= EXTENDED_OPLOCK_GRANTED;
1973         }
1974
1975         /* If the caller set the core oplock request bit
1976                 and we granted one (by whatever means) - set the
1977                 correct bit for core oplock reply.
1978         */
1979
1980         if (open_flags & EXTENDED_RESPONSE_REQUIRED) {
1981                 reply_outbuf(req, 19, 0);
1982         } else {
1983                 reply_outbuf(req, 15, 0);
1984         }
1985
1986         if (core_oplock_request && lp_fake_oplocks(SNUM(conn))) {
1987                 SCVAL(req->outbuf, smb_flg,
1988                       CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1989         }
1990
1991         if(core_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1992                 SCVAL(req->outbuf, smb_flg,
1993                       CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1994         }
1995
1996         SSVAL(req->outbuf,smb_vwv2,fsp->fnum);
1997         SSVAL(req->outbuf,smb_vwv3,fattr);
1998         if(lp_dos_filetime_resolution(SNUM(conn)) ) {
1999                 srv_put_dos_date3((char *)req->outbuf,smb_vwv4,mtime & ~1);
2000         } else {
2001                 srv_put_dos_date3((char *)req->outbuf,smb_vwv4,mtime);
2002         }
2003         SIVAL(req->outbuf,smb_vwv6,(uint32)sbuf.st_size);
2004         SSVAL(req->outbuf,smb_vwv8,GET_OPENX_MODE(deny_mode));
2005         SSVAL(req->outbuf,smb_vwv11,smb_action);
2006
2007         if (open_flags & EXTENDED_RESPONSE_REQUIRED) {
2008                 SIVAL(req->outbuf, smb_vwv15, STD_RIGHT_ALL_ACCESS);
2009         }
2010
2011         END_PROFILE(SMBopenX);
2012         chain_reply(req);
2013         return;
2014 }
2015
2016 /****************************************************************************
2017  Reply to a SMBulogoffX.
2018 ****************************************************************************/
2019
2020 void reply_ulogoffX(struct smb_request *req)
2021 {
2022         user_struct *vuser;
2023
2024         START_PROFILE(SMBulogoffX);
2025
2026         vuser = get_valid_user_struct(req->vuid);
2027
2028         if(vuser == NULL) {
2029                 DEBUG(3,("ulogoff, vuser id %d does not map to user.\n",
2030                          req->vuid));
2031         }
2032
2033         /* in user level security we are supposed to close any files
2034                 open by this user */
2035         if ((vuser != NULL) && (lp_security() != SEC_SHARE)) {
2036                 file_close_user(req->vuid);
2037         }
2038
2039         invalidate_vuid(req->vuid);
2040
2041         reply_outbuf(req, 2, 0);
2042
2043         DEBUG( 3, ( "ulogoffX vuid=%d\n", req->vuid ) );
2044
2045         END_PROFILE(SMBulogoffX);
2046         chain_reply(req);
2047 }
2048
2049 /****************************************************************************
2050  Reply to a mknew or a create.
2051 ****************************************************************************/
2052
2053 void reply_mknew(struct smb_request *req)
2054 {
2055         connection_struct *conn = req->conn;
2056         char *fname = NULL;
2057         uint32 fattr = 0;
2058         struct smb_file_time ft;
2059         files_struct *fsp;
2060         int oplock_request = 0;
2061         SMB_STRUCT_STAT sbuf;
2062         NTSTATUS status;
2063         uint32 access_mask = FILE_GENERIC_READ | FILE_GENERIC_WRITE;
2064         uint32 share_mode = FILE_SHARE_READ|FILE_SHARE_WRITE;
2065         uint32 create_disposition;
2066         uint32 create_options = 0;
2067         TALLOC_CTX *ctx = talloc_tos();
2068
2069         START_PROFILE(SMBcreate);
2070         ZERO_STRUCT(ft);
2071         SET_STAT_INVALID(sbuf);
2072
2073         if (req->wct < 3) {
2074                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2075                 END_PROFILE(SMBcreate);
2076                 return;
2077         }
2078
2079         fattr = SVAL(req->vwv+0, 0);
2080         oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
2081
2082         /* mtime. */
2083         ft.mtime = convert_time_t_to_timespec(srv_make_unix_date3(req->vwv+1));
2084
2085         srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf + 1,
2086                             STR_TERMINATE, &status);
2087         if (!NT_STATUS_IS_OK(status)) {
2088                 reply_nterror(req, status);
2089                 END_PROFILE(SMBcreate);
2090                 return;
2091         }
2092
2093         if (fattr & aVOLID) {
2094                 DEBUG(0,("Attempt to create file (%s) with volid set - "
2095                         "please report this\n", fname));
2096         }
2097
2098         if(req->cmd == SMBmknew) {
2099                 /* We should fail if file exists. */
2100                 create_disposition = FILE_CREATE;
2101         } else {
2102                 /* Create if file doesn't exist, truncate if it does. */
2103                 create_disposition = FILE_OVERWRITE_IF;
2104         }
2105
2106         status = SMB_VFS_CREATE_FILE(
2107                 conn,                                   /* conn */
2108                 req,                                    /* req */
2109                 0,                                      /* root_dir_fid */
2110                 fname,                                  /* fname */
2111                 CFF_DOS_PATH,                           /* create_file_flags */
2112                 access_mask,                            /* access_mask */
2113                 share_mode,                             /* share_access */
2114                 create_disposition,                     /* create_disposition*/
2115                 create_options,                         /* create_options */
2116                 fattr,                                  /* file_attributes */
2117                 oplock_request,                         /* oplock_request */
2118                 0,                                      /* allocation_size */
2119                 NULL,                                   /* sd */
2120                 NULL,                                   /* ea_list */
2121                 &fsp,                                   /* result */
2122                 NULL,                                   /* pinfo */
2123                 &sbuf);                                 /* psbuf */
2124
2125         if (!NT_STATUS_IS_OK(status)) {
2126                 END_PROFILE(SMBcreate);
2127                 if (open_was_deferred(req->mid)) {
2128                         /* We have re-scheduled this call. */
2129                         return;
2130                 }
2131                 reply_openerror(req, status);
2132                 return;
2133         }
2134
2135         ft.atime = get_atimespec(&sbuf); /* atime. */
2136         status = smb_set_file_time(conn, fsp, fsp->fsp_name, &sbuf, &ft, true);
2137         if (!NT_STATUS_IS_OK(status)) {
2138                 END_PROFILE(SMBcreate);
2139                 reply_openerror(req, status);
2140                 return;
2141         }
2142
2143         reply_outbuf(req, 1, 0);
2144         SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
2145
2146         if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
2147                 SCVAL(req->outbuf,smb_flg,
2148                                 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2149         }
2150
2151         if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2152                 SCVAL(req->outbuf,smb_flg,
2153                                 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2154         }
2155
2156         DEBUG( 2, ( "reply_mknew: file %s\n", fsp->fsp_name ) );
2157         DEBUG( 3, ( "reply_mknew %s fd=%d dmode=0x%x\n",
2158                     fsp->fsp_name, fsp->fh->fd, (unsigned int)fattr ) );
2159
2160         END_PROFILE(SMBcreate);
2161         return;
2162 }
2163
2164 /****************************************************************************
2165  Reply to a create temporary file.
2166 ****************************************************************************/
2167
2168 void reply_ctemp(struct smb_request *req)
2169 {
2170         connection_struct *conn = req->conn;
2171         struct smb_filename *smb_fname = NULL;
2172         char *fname = NULL;
2173         uint32 fattr;
2174         files_struct *fsp;
2175         int oplock_request;
2176         int tmpfd;
2177         char *s;
2178         NTSTATUS status;
2179         TALLOC_CTX *ctx = talloc_tos();
2180
2181         START_PROFILE(SMBctemp);
2182
2183         if (req->wct < 3) {
2184                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2185                 goto out;
2186         }
2187
2188         fattr = SVAL(req->vwv+0, 0);
2189         oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
2190
2191         srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf+1,
2192                             STR_TERMINATE, &status);
2193         if (!NT_STATUS_IS_OK(status)) {
2194                 reply_nterror(req, status);
2195                 goto out;
2196         }
2197         if (*fname) {
2198                 fname = talloc_asprintf(ctx,
2199                                 "%s/TMXXXXXX",
2200                                 fname);
2201         } else {
2202                 fname = talloc_strdup(ctx, "TMXXXXXX");
2203         }
2204
2205         if (!fname) {
2206                 reply_nterror(req, NT_STATUS_NO_MEMORY);
2207                 goto out;
2208         }
2209
2210         status = resolve_dfspath(ctx, conn,
2211                                 req->flags2 & FLAGS2_DFS_PATHNAMES,
2212                                 fname,
2213                                 &fname);
2214         if (!NT_STATUS_IS_OK(status)) {
2215                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2216                         reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2217                                         ERRSRV, ERRbadpath);
2218                         goto out;
2219                 }
2220                 reply_nterror(req, status);
2221                 goto out;
2222         }
2223
2224         status = unix_convert(ctx, conn, fname, &smb_fname, 0);
2225         if (!NT_STATUS_IS_OK(status)) {
2226                 reply_nterror(req, status);
2227                 goto out;
2228         }
2229
2230         status = get_full_smb_filename(ctx, smb_fname, &fname);
2231         if (!NT_STATUS_IS_OK(status)) {
2232                 reply_nterror(req, status);
2233                 goto out;
2234         }
2235
2236         status = check_name(conn, fname);
2237         if (!NT_STATUS_IS_OK(status)) {
2238                 reply_nterror(req, status);
2239                 goto out;
2240         }
2241
2242         tmpfd = mkstemp(fname);
2243         if (tmpfd == -1) {
2244                 reply_unixerror(req, ERRDOS, ERRnoaccess);
2245                 goto out;
2246         }
2247
2248         SET_STAT_INVALID(smb_fname->st);
2249         SMB_VFS_STAT(conn, fname, &smb_fname->st);
2250
2251         /* We should fail if file does not exist. */
2252         status = SMB_VFS_CREATE_FILE(
2253                 conn,                                   /* conn */
2254                 req,                                    /* req */
2255                 0,                                      /* root_dir_fid */
2256                 fname,                                  /* fname */
2257                 0,                                      /* create_file_flags */
2258                 FILE_GENERIC_READ | FILE_GENERIC_WRITE, /* access_mask */
2259                 FILE_SHARE_READ | FILE_SHARE_WRITE,     /* share_access */
2260                 FILE_OPEN,                              /* create_disposition*/
2261                 0,                                      /* create_options */
2262                 fattr,                                  /* file_attributes */
2263                 oplock_request,                         /* oplock_request */
2264                 0,                                      /* allocation_size */
2265                 NULL,                                   /* sd */
2266                 NULL,                                   /* ea_list */
2267                 &fsp,                                   /* result */
2268                 NULL,                                   /* pinfo */
2269                 &smb_fname->st);                        /* psbuf */
2270
2271         /* close fd from mkstemp() */
2272         close(tmpfd);
2273
2274         if (!NT_STATUS_IS_OK(status)) {
2275                 if (open_was_deferred(req->mid)) {
2276                         /* We have re-scheduled this call. */
2277                         goto out;
2278                 }
2279                 reply_openerror(req, status);
2280                 goto out;
2281         }
2282
2283         reply_outbuf(req, 1, 0);
2284         SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
2285
2286         /* the returned filename is relative to the directory */
2287         s = strrchr_m(fsp->fsp_name, '/');
2288         if (!s) {
2289                 s = fsp->fsp_name;
2290         } else {
2291                 s++;
2292         }
2293
2294 #if 0
2295         /* Tested vs W2K3 - this doesn't seem to be here - null terminated filename is the only
2296            thing in the byte section. JRA */
2297         SSVALS(p, 0, -1); /* what is this? not in spec */
2298 #endif
2299         if (message_push_string(&req->outbuf, s, STR_ASCII|STR_TERMINATE)
2300             == -1) {
2301                 reply_nterror(req, NT_STATUS_NO_MEMORY);
2302                 goto out;
2303         }
2304
2305         if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
2306                 SCVAL(req->outbuf, smb_flg,
2307                       CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2308         }
2309
2310         if (EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2311                 SCVAL(req->outbuf, smb_flg,
2312                       CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2313         }
2314
2315         DEBUG( 2, ( "reply_ctemp: created temp file %s\n", fsp->fsp_name ) );
2316         DEBUG( 3, ( "reply_ctemp %s fd=%d umode=0%o\n", fsp->fsp_name,
2317                     fsp->fh->fd, (unsigned int)smb_fname->st.st_mode));
2318  out:
2319         if (smb_fname) {
2320                 TALLOC_FREE(smb_fname);
2321         }
2322         END_PROFILE(SMBctemp);
2323         return;
2324 }
2325
2326 /*******************************************************************
2327  Check if a user is allowed to rename a file.
2328 ********************************************************************/
2329
2330 static NTSTATUS can_rename(connection_struct *conn, files_struct *fsp,
2331                            uint16 dirtype, SMB_STRUCT_STAT *pst)
2332 {
2333         uint32 fmode;
2334
2335         if (!CAN_WRITE(conn)) {
2336                 return NT_STATUS_MEDIA_WRITE_PROTECTED;
2337         }
2338
2339         fmode = dos_mode(conn, fsp->fsp_name, pst);
2340         if ((fmode & ~dirtype) & (aHIDDEN | aSYSTEM)) {
2341                 return NT_STATUS_NO_SUCH_FILE;
2342         }
2343
2344         if (S_ISDIR(pst->st_mode)) {
2345                 if (fsp->posix_open) {
2346                         return NT_STATUS_OK;
2347                 }
2348
2349                 /* If no pathnames are open below this
2350                    directory, allow the rename. */
2351
2352                 if (file_find_subpath(fsp)) {
2353                         return NT_STATUS_ACCESS_DENIED;
2354                 }
2355                 return NT_STATUS_OK;
2356         }
2357
2358         if (fsp->access_mask & (DELETE_ACCESS|FILE_WRITE_ATTRIBUTES)) {
2359                 return NT_STATUS_OK;
2360         }
2361
2362         return NT_STATUS_ACCESS_DENIED;
2363 }
2364
2365 /*******************************************************************
2366  * unlink a file with all relevant access checks
2367  *******************************************************************/
2368
2369 static NTSTATUS do_unlink(connection_struct *conn,
2370                         struct smb_request *req,
2371                         const char *fname,
2372                         uint32 dirtype)
2373 {
2374         SMB_STRUCT_STAT sbuf;
2375         uint32 fattr;
2376         files_struct *fsp;
2377         uint32 dirtype_orig = dirtype;
2378         NTSTATUS status;
2379
2380         DEBUG(10,("do_unlink: %s, dirtype = %d\n", fname, dirtype ));
2381
2382         if (!CAN_WRITE(conn)) {
2383                 return NT_STATUS_MEDIA_WRITE_PROTECTED;
2384         }
2385
2386         if (SMB_VFS_LSTAT(conn,fname,&sbuf) != 0) {
2387                 return map_nt_error_from_unix(errno);
2388         }
2389
2390         fattr = dos_mode(conn,fname,&sbuf);
2391
2392         if (dirtype & FILE_ATTRIBUTE_NORMAL) {
2393                 dirtype = aDIR|aARCH|aRONLY;
2394         }
2395
2396         dirtype &= (aDIR|aARCH|aRONLY|aHIDDEN|aSYSTEM);
2397         if (!dirtype) {
2398                 return NT_STATUS_NO_SUCH_FILE;
2399         }
2400
2401         if (!dir_check_ftype(conn, fattr, dirtype)) {
2402                 if (fattr & aDIR) {
2403                         return NT_STATUS_FILE_IS_A_DIRECTORY;
2404                 }
2405                 return NT_STATUS_NO_SUCH_FILE;
2406         }
2407
2408         if (dirtype_orig & 0x8000) {
2409                 /* These will never be set for POSIX. */
2410                 return NT_STATUS_NO_SUCH_FILE;
2411         }
2412
2413 #if 0
2414         if ((fattr & dirtype) & FILE_ATTRIBUTE_DIRECTORY) {
2415                 return NT_STATUS_FILE_IS_A_DIRECTORY;
2416         }
2417
2418         if ((fattr & ~dirtype) & (FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM)) {
2419                 return NT_STATUS_NO_SUCH_FILE;
2420         }
2421
2422         if (dirtype & 0xFF00) {
2423                 /* These will never be set for POSIX. */
2424                 return NT_STATUS_NO_SUCH_FILE;
2425         }
2426
2427         dirtype &= 0xFF;
2428         if (!dirtype) {
2429                 return NT_STATUS_NO_SUCH_FILE;
2430         }
2431
2432         /* Can't delete a directory. */
2433         if (fattr & aDIR) {
2434                 return NT_STATUS_FILE_IS_A_DIRECTORY;
2435         }
2436 #endif
2437
2438 #if 0 /* JRATEST */
2439         else if (dirtype & aDIR) /* Asked for a directory and it isn't. */
2440                 return NT_STATUS_OBJECT_NAME_INVALID;
2441 #endif /* JRATEST */
2442
2443         /* Fix for bug #3035 from SATOH Fumiyasu <fumiyas@miraclelinux.com>
2444
2445           On a Windows share, a file with read-only dosmode can be opened with
2446           DELETE_ACCESS. But on a Samba share (delete readonly = no), it
2447           fails with NT_STATUS_CANNOT_DELETE error.
2448
2449           This semantic causes a problem that a user can not
2450           rename a file with read-only dosmode on a Samba share
2451           from a Windows command prompt (i.e. cmd.exe, but can rename
2452           from Windows Explorer).
2453         */
2454
2455         if (!lp_delete_readonly(SNUM(conn))) {
2456                 if (fattr & aRONLY) {
2457                         return NT_STATUS_CANNOT_DELETE;
2458                 }
2459         }
2460
2461         /* On open checks the open itself will check the share mode, so
2462            don't do it here as we'll get it wrong. */
2463
2464         status = SMB_VFS_CREATE_FILE
2465                 (conn,                  /* conn */
2466                  req,                   /* req */
2467                  0,                     /* root_dir_fid */
2468                  fname,                 /* fname */
2469                  0,                     /* create_file_flags */
2470                  DELETE_ACCESS,         /* access_mask */
2471                  FILE_SHARE_NONE,       /* share_access */
2472                  FILE_OPEN,             /* create_disposition*/
2473                  FILE_NON_DIRECTORY_FILE, /* create_options */
2474                  FILE_ATTRIBUTE_NORMAL, /* file_attributes */
2475                  0,                     /* oplock_request */
2476                  0,                     /* allocation_size */
2477                  NULL,                  /* sd */
2478                  NULL,                  /* ea_list */
2479                  &fsp,                  /* result */
2480                  NULL,                  /* pinfo */
2481                  &sbuf);                /* psbuf */
2482
2483         if (!NT_STATUS_IS_OK(status)) {
2484                 DEBUG(10, ("SMB_VFS_CREATEFILE failed: %s\n",
2485                            nt_errstr(status)));
2486                 return status;
2487         }
2488
2489         /* The set is across all open files on this dev/inode pair. */
2490         if (!set_delete_on_close(fsp, True, &conn->server_info->utok)) {
2491                 close_file(req, fsp, NORMAL_CLOSE);
2492                 return NT_STATUS_ACCESS_DENIED;
2493         }
2494
2495         return close_file(req, fsp, NORMAL_CLOSE);
2496 }
2497
2498 /****************************************************************************
2499  The guts of the unlink command, split out so it may be called by the NT SMB
2500  code.
2501 ****************************************************************************/
2502
2503 NTSTATUS unlink_internals(connection_struct *conn, struct smb_request *req,
2504                           uint32 dirtype, const char *name_in, bool has_wild)
2505 {
2506         struct smb_filename *smb_fname = NULL;
2507         const char *directory = NULL;
2508         char *mask = NULL;
2509         char *name = NULL;
2510         char *p = NULL;
2511         int count=0;
2512         NTSTATUS status = NT_STATUS_OK;
2513         SMB_STRUCT_STAT st;
2514         TALLOC_CTX *ctx = talloc_tos();
2515
2516         status = unix_convert(ctx, conn, name_in, &smb_fname,
2517                               has_wild ? UCF_ALLOW_WCARD_LCOMP : 0);
2518         if (!NT_STATUS_IS_OK(status)) {
2519                 return status;
2520         }
2521
2522         status = get_full_smb_filename(ctx, smb_fname, &name);
2523         if (!NT_STATUS_IS_OK(status)) {
2524                 TALLOC_FREE(smb_fname);
2525                 return status;
2526         }
2527
2528         p = strrchr_m(name,'/');
2529         if (!p) {
2530                 directory = talloc_strdup(ctx, ".");
2531                 if (!directory) {
2532                         TALLOC_FREE(smb_fname);
2533                         return NT_STATUS_NO_MEMORY;
2534                 }
2535                 mask = name;
2536         } else {
2537                 *p = 0;
2538                 directory = name;
2539                 mask = p+1;
2540         }
2541
2542         /*
2543          * We should only check the mangled cache
2544          * here if unix_convert failed. This means
2545          * that the path in 'mask' doesn't exist
2546          * on the file system and so we need to look
2547          * for a possible mangle. This patch from
2548          * Tine Smukavec <valentin.smukavec@hermes.si>.
2549          */
2550
2551         if (!VALID_STAT(smb_fname->st) && mangle_is_mangled(mask,conn->params)) {
2552                 char *new_mask = NULL;
2553                 mangle_lookup_name_from_8_3(ctx,
2554                                 mask,
2555                                 &new_mask,
2556                                 conn->params );
2557                 if (new_mask) {
2558                         mask = new_mask;
2559                 }
2560         }
2561         TALLOC_FREE(smb_fname);
2562
2563         if (!has_wild) {
2564                 directory = talloc_asprintf(ctx,
2565                                 "%s/%s",
2566                                 directory,
2567                                 mask);
2568                 if (!directory) {
2569                         return NT_STATUS_NO_MEMORY;
2570                 }
2571                 if (dirtype == 0) {
2572                         dirtype = FILE_ATTRIBUTE_NORMAL;
2573                 }
2574
2575                 status = check_name(conn, directory);
2576                 if (!NT_STATUS_IS_OK(status)) {
2577                         return status;
2578                 }
2579
2580                 status = do_unlink(conn, req, directory, dirtype);
2581                 if (!NT_STATUS_IS_OK(status)) {
2582                         return status;
2583                 }
2584
2585                 count++;
2586         } else {
2587                 struct smb_Dir *dir_hnd = NULL;
2588                 long offset = 0;
2589                 const char *dname;
2590
2591                 if ((dirtype & SAMBA_ATTRIBUTES_MASK) == aDIR) {
2592                         return NT_STATUS_OBJECT_NAME_INVALID;
2593                 }
2594
2595                 if (strequal(mask,"????????.???")) {
2596                         mask[0] = '*';
2597                         mask[1] = '\0';
2598                 }
2599
2600                 status = check_name(conn, directory);
2601                 if (!NT_STATUS_IS_OK(status)) {
2602                         return status;
2603                 }
2604
2605                 dir_hnd = OpenDir(talloc_tos(), conn, directory, mask,
2606                                   dirtype);
2607                 if (dir_hnd == NULL) {
2608                         return map_nt_error_from_unix(errno);
2609                 }
2610
2611                 /* XXXX the CIFS spec says that if bit0 of the flags2 field is set then
2612                    the pattern matches against the long name, otherwise the short name 
2613                    We don't implement this yet XXXX
2614                 */
2615
2616                 status = NT_STATUS_NO_SUCH_FILE;
2617
2618                 while ((dname = ReadDirName(dir_hnd, &offset, &st))) {
2619                         char *fname = NULL;
2620
2621                         if (!is_visible_file(conn, directory, dname, &st,
2622                             true))
2623                         {
2624                                 continue;
2625                         }
2626
2627                         /* Quick check for "." and ".." */
2628                         if (ISDOT(dname) || ISDOTDOT(dname)) {
2629                                 continue;
2630                         }
2631
2632                         if(!mask_match(dname, mask, conn->case_sensitive)) {
2633                                 continue;
2634                         }
2635
2636                         fname = talloc_asprintf(ctx, "%s/%s",
2637                                         directory,
2638                                         dname);
2639                         if (!fname) {
2640                                 return NT_STATUS_NO_MEMORY;
2641                         }
2642
2643                         status = check_name(conn, fname);
2644                         if (!NT_STATUS_IS_OK(status)) {
2645                                 TALLOC_FREE(dir_hnd);
2646                                 return status;
2647                         }
2648
2649                         status = do_unlink(conn, req, fname, dirtype);
2650                         if (!NT_STATUS_IS_OK(status)) {
2651                                 TALLOC_FREE(fname);
2652                                 continue;
2653                         }
2654
2655                         count++;
2656                         DEBUG(3,("unlink_internals: successful unlink [%s]\n",
2657                                  fname));
2658
2659                         TALLOC_FREE(fname);
2660                 }
2661                 TALLOC_FREE(dir_hnd);
2662         }
2663
2664         if (count == 0 && NT_STATUS_IS_OK(status) && errno != 0) {
2665                 status = map_nt_error_from_unix(errno);
2666         }
2667
2668         return status;
2669 }
2670
2671 /****************************************************************************
2672  Reply to a unlink
2673 ****************************************************************************/
2674
2675 void reply_unlink(struct smb_request *req)
2676 {
2677         connection_struct *conn = req->conn;
2678         char *name = NULL;
2679         uint32 dirtype;
2680         NTSTATUS status;
2681         bool path_contains_wcard = False;
2682         TALLOC_CTX *ctx = talloc_tos();
2683
2684         START_PROFILE(SMBunlink);
2685
2686         if (req->wct < 1) {
2687                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2688                 END_PROFILE(SMBunlink);
2689                 return;
2690         }
2691
2692         dirtype = SVAL(req->vwv+0, 0);
2693
2694         srvstr_get_path_req_wcard(ctx, req, &name, (const char *)req->buf + 1,
2695                                   STR_TERMINATE, &status,
2696                                   &path_contains_wcard);
2697         if (!NT_STATUS_IS_OK(status)) {
2698                 reply_nterror(req, status);
2699                 END_PROFILE(SMBunlink);
2700                 return;
2701         }
2702
2703         status = resolve_dfspath_wcard(ctx, conn,
2704                                        req->flags2 & FLAGS2_DFS_PATHNAMES,
2705                                        name,
2706                                        &name,
2707                                        &path_contains_wcard);
2708         if (!NT_STATUS_IS_OK(status)) {
2709                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2710                         reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2711                                         ERRSRV, ERRbadpath);
2712                         END_PROFILE(SMBunlink);
2713                         return;
2714                 }
2715                 reply_nterror(req, status);
2716                 END_PROFILE(SMBunlink);
2717                 return;
2718         }
2719
2720         DEBUG(3,("reply_unlink : %s\n",name));
2721
2722         status = unlink_internals(conn, req, dirtype, name,
2723                                   path_contains_wcard);
2724         if (!NT_STATUS_IS_OK(status)) {
2725                 if (open_was_deferred(req->mid)) {
2726                         /* We have re-scheduled this call. */
2727                         END_PROFILE(SMBunlink);
2728                         return;
2729                 }
2730                 reply_nterror(req, status);
2731                 END_PROFILE(SMBunlink);
2732                 return;
2733         }
2734
2735         reply_outbuf(req, 0, 0);
2736         END_PROFILE(SMBunlink);
2737
2738         return;
2739 }
2740
2741 /****************************************************************************
2742  Fail for readbraw.
2743 ****************************************************************************/
2744
2745 static void fail_readraw(void)
2746 {
2747         const char *errstr = talloc_asprintf(talloc_tos(),
2748                         "FAIL ! reply_readbraw: socket write fail (%s)",
2749                         strerror(errno));
2750         if (!errstr) {
2751                 errstr = "";
2752         }
2753         exit_server_cleanly(errstr);
2754 }
2755
2756 /****************************************************************************
2757  Fake (read/write) sendfile. Returns -1 on read or write fail.
2758 ****************************************************************************/
2759
2760 static ssize_t fake_sendfile(files_struct *fsp, SMB_OFF_T startpos,
2761                              size_t nread)
2762 {
2763         size_t bufsize;
2764         size_t tosend = nread;
2765         char *buf;
2766
2767         if (nread == 0) {
2768                 return 0;
2769         }
2770
2771         bufsize = MIN(nread, 65536);
2772
2773         if (!(buf = SMB_MALLOC_ARRAY(char, bufsize))) {
2774                 return -1;
2775         }
2776
2777         while (tosend > 0) {
2778                 ssize_t ret;
2779                 size_t cur_read;
2780
2781                 if (tosend > bufsize) {
2782                         cur_read = bufsize;
2783                 } else {
2784                         cur_read = tosend;
2785                 }
2786                 ret = read_file(fsp,buf,startpos,cur_read);
2787                 if (ret == -1) {
2788                         SAFE_FREE(buf);
2789                         return -1;
2790                 }
2791
2792                 /* If we had a short read, fill with zeros. */
2793                 if (ret < cur_read) {
2794                         memset(buf + ret, '\0', cur_read - ret);
2795                 }
2796
2797                 if (write_data(smbd_server_fd(),buf,cur_read) != cur_read) {
2798                         SAFE_FREE(buf);
2799                         return -1;
2800                 }
2801                 tosend -= cur_read;
2802                 startpos += cur_read;
2803         }
2804
2805         SAFE_FREE(buf);
2806         return (ssize_t)nread;
2807 }
2808
2809 #if defined(WITH_SENDFILE)
2810 /****************************************************************************
2811  Deal with the case of sendfile reading less bytes from the file than
2812  requested. Fill with zeros (all we can do).
2813 ****************************************************************************/
2814
2815 static void sendfile_short_send(files_struct *fsp,
2816                                 ssize_t nread,
2817                                 size_t headersize,
2818                                 size_t smb_maxcnt)
2819 {
2820 #define SHORT_SEND_BUFSIZE 1024
2821         if (nread < headersize) {
2822                 DEBUG(0,("sendfile_short_send: sendfile failed to send "
2823                         "header for file %s (%s). Terminating\n",
2824                         fsp->fsp_name, strerror(errno) ));
2825                 exit_server_cleanly("sendfile_short_send failed");
2826         }
2827
2828         nread -= headersize;
2829
2830         if (nread < smb_maxcnt) {
2831                 char *buf = SMB_CALLOC_ARRAY(char, SHORT_SEND_BUFSIZE);
2832                 if (!buf) {
2833                         exit_server_cleanly("sendfile_short_send: "
2834                                 "malloc failed");
2835                 }
2836
2837                 DEBUG(0,("sendfile_short_send: filling truncated file %s "
2838                         "with zeros !\n", fsp->fsp_name));
2839
2840                 while (nread < smb_maxcnt) {
2841                         /*
2842                          * We asked for the real file size and told sendfile
2843                          * to not go beyond the end of the file. But it can
2844                          * happen that in between our fstat call and the
2845                          * sendfile call the file was truncated. This is very
2846                          * bad because we have already announced the larger
2847                          * number of bytes to the client.
2848                          *
2849                          * The best we can do now is to send 0-bytes, just as
2850                          * a read from a hole in a sparse file would do.
2851                          *
2852                          * This should happen rarely enough that I don't care
2853                          * about efficiency here :-)
2854                          */
2855                         size_t to_write;
2856
2857                         to_write = MIN(SHORT_SEND_BUFSIZE, smb_maxcnt - nread);
2858                         if (write_data(smbd_server_fd(), buf, to_write) != to_write) {
2859                                 exit_server_cleanly("sendfile_short_send: "
2860                                         "write_data failed");
2861                         }
2862                         nread += to_write;
2863                 }
2864                 SAFE_FREE(buf);
2865         }
2866 }
2867 #endif /* defined WITH_SENDFILE */
2868
2869 /****************************************************************************
2870  Return a readbraw error (4 bytes of zero).
2871 ****************************************************************************/
2872
2873 static void reply_readbraw_error(void)
2874 {
2875         char header[4];
2876         SIVAL(header,0,0);
2877         if (write_data(smbd_server_fd(),header,4) != 4) {
2878                 fail_readraw();
2879         }
2880 }
2881
2882 /****************************************************************************
2883  Use sendfile in readbraw.
2884 ****************************************************************************/
2885
2886 static void send_file_readbraw(connection_struct *conn,
2887                                struct smb_request *req,
2888                                files_struct *fsp,
2889                                SMB_OFF_T startpos,
2890                                size_t nread,
2891                                ssize_t mincount)
2892 {
2893         char *outbuf = NULL;
2894         ssize_t ret=0;
2895
2896 #if defined(WITH_SENDFILE)
2897         /*
2898          * We can only use sendfile on a non-chained packet 
2899          * but we can use on a non-oplocked file. tridge proved this
2900          * on a train in Germany :-). JRA.
2901          * reply_readbraw has already checked the length.
2902          */
2903
2904         if ( !req_is_in_chain(req) && (nread > 0) && (fsp->base_fsp == NULL) &&
2905             (fsp->wcp == NULL) &&
2906             lp_use_sendfile(SNUM(conn), smbd_server_conn->signing_state) ) {
2907                 ssize_t sendfile_read = -1;
2908                 char header[4];
2909                 DATA_BLOB header_blob;
2910
2911                 _smb_setlen(header,nread);
2912                 header_blob = data_blob_const(header, 4);
2913
2914                 if ((sendfile_read = SMB_VFS_SENDFILE(smbd_server_fd(), fsp,
2915                                 &header_blob, startpos, nread)) == -1) {
2916                         /* Returning ENOSYS means no data at all was sent.
2917                          * Do this as a normal read. */
2918                         if (errno == ENOSYS) {
2919                                 goto normal_readbraw;
2920                         }
2921
2922                         /*
2923                          * Special hack for broken Linux with no working sendfile. If we
2924                          * return EINTR we sent the header but not the rest of the data.
2925                          * Fake this up by doing read/write calls.
2926                          */
2927                         if (errno == EINTR) {
2928                                 /* Ensure we don't do this again. */
2929                                 set_use_sendfile(SNUM(conn), False);
2930                                 DEBUG(0,("send_file_readbraw: sendfile not available. Faking..\n"));
2931
2932                                 if (fake_sendfile(fsp, startpos, nread) == -1) {
2933                                         DEBUG(0,("send_file_readbraw: fake_sendfile failed for file %s (%s).\n",
2934                                                 fsp->fsp_name, strerror(errno) ));
2935                                         exit_server_cleanly("send_file_readbraw fake_sendfile failed");
2936                                 }
2937                                 return;
2938                         }
2939
2940                         DEBUG(0,("send_file_readbraw: sendfile failed for file %s (%s). Terminating\n",
2941                                 fsp->fsp_name, strerror(errno) ));
2942                         exit_server_cleanly("send_file_readbraw sendfile failed");
2943                 } else if (sendfile_read == 0) {
2944                         /*
2945                          * Some sendfile implementations return 0 to indicate
2946                          * that there was a short read, but nothing was
2947                          * actually written to the socket.  In this case,
2948                          * fallback to the normal read path so the header gets
2949                          * the correct byte count.
2950                          */
2951                         DEBUG(3, ("send_file_readbraw: sendfile sent zero "
2952                                   "bytes falling back to the normal read: "
2953                                   "%s\n", fsp->fsp_name));
2954                         goto normal_readbraw;
2955                 }
2956
2957                 /* Deal with possible short send. */
2958                 if (sendfile_read != 4+nread) {
2959                         sendfile_short_send(fsp, sendfile_read, 4, nread);
2960                 }
2961                 return;
2962         }
2963
2964 normal_readbraw:
2965 #endif
2966
2967         outbuf = TALLOC_ARRAY(NULL, char, nread+4);
2968         if (!outbuf) {
2969                 DEBUG(0,("send_file_readbraw: TALLOC_ARRAY failed for size %u.\n",
2970                         (unsigned)(nread+4)));
2971                 reply_readbraw_error();
2972                 return;
2973         }
2974
2975         if (nread > 0) {
2976                 ret = read_file(fsp,outbuf+4,startpos,nread);
2977 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
2978                 if (ret < mincount)
2979                         ret = 0;
2980 #else
2981                 if (ret < nread)
2982                         ret = 0;
2983 #endif
2984         }
2985
2986         _smb_setlen(outbuf,ret);
2987         if (write_data(smbd_server_fd(),outbuf,4+ret) != 4+ret)
2988                 fail_readraw();
2989
2990         TALLOC_FREE(outbuf);
2991 }
2992
2993 /****************************************************************************
2994  Reply to a readbraw (core+ protocol).
2995 ****************************************************************************/
2996
2997 void reply_readbraw(struct smb_request *req)
2998 {
2999         connection_struct *conn = req->conn;
3000         ssize_t maxcount,mincount;
3001         size_t nread = 0;
3002         SMB_OFF_T startpos;
3003         files_struct *fsp;
3004         struct lock_struct lock;
3005         SMB_STRUCT_STAT st;
3006         SMB_OFF_T size = 0;
3007
3008         START_PROFILE(SMBreadbraw);
3009
3010         if (srv_is_signing_active(smbd_server_conn) ||
3011             is_encrypted_packet(req->inbuf)) {
3012                 exit_server_cleanly("reply_readbraw: SMB signing/sealing is active - "
3013                         "raw reads/writes are disallowed.");
3014         }
3015
3016         if (req->wct < 8) {
3017                 reply_readbraw_error();
3018                 END_PROFILE(SMBreadbraw);
3019                 return;
3020         }
3021
3022         /*
3023          * Special check if an oplock break has been issued
3024          * and the readraw request croses on the wire, we must
3025          * return a zero length response here.
3026          */
3027
3028         fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3029
3030         /*
3031          * We have to do a check_fsp by hand here, as
3032          * we must always return 4 zero bytes on error,
3033          * not a NTSTATUS.
3034          */
3035
3036         if (!fsp || !conn || conn != fsp->conn ||
3037                         req->vuid != fsp->vuid ||
3038                         fsp->is_directory || fsp->fh->fd == -1) {
3039                 /*
3040                  * fsp could be NULL here so use the value from the packet. JRA.
3041                  */
3042                 DEBUG(3,("reply_readbraw: fnum %d not valid "
3043                         "- cache prime?\n",
3044                         (int)SVAL(req->vwv+0, 0)));
3045                 reply_readbraw_error();
3046                 END_PROFILE(SMBreadbraw);
3047                 return;
3048         }
3049
3050         /* Do a "by hand" version of CHECK_READ. */
3051         if (!(fsp->can_read ||
3052                         ((req->flags2 & FLAGS2_READ_PERMIT_EXECUTE) &&
3053                                 (fsp->access_mask & FILE_EXECUTE)))) {
3054                 DEBUG(3,("reply_readbraw: fnum %d not readable.\n",
3055                                 (int)SVAL(req->vwv+0, 0)));
3056                 reply_readbraw_error();
3057                 END_PROFILE(SMBreadbraw);
3058                 return;
3059         }
3060
3061         flush_write_cache(fsp, READRAW_FLUSH);
3062
3063         startpos = IVAL_TO_SMB_OFF_T(req->vwv+1, 0);
3064         if(req->wct == 10) {
3065                 /*
3066                  * This is a large offset (64 bit) read.
3067                  */
3068 #ifdef LARGE_SMB_OFF_T
3069
3070                 startpos |= (((SMB_OFF_T)IVAL(req->vwv+8, 0)) << 32);
3071
3072 #else /* !LARGE_SMB_OFF_T */
3073
3074                 /*
3075                  * Ensure we haven't been sent a >32 bit offset.
3076                  */
3077
3078                 if(IVAL(req->vwv+8, 0) != 0) {
3079                         DEBUG(0,("reply_readbraw: large offset "
3080                                 "(%x << 32) used and we don't support "
3081                                 "64 bit offsets.\n",
3082                         (unsigned int)IVAL(req->vwv+8, 0) ));
3083                         reply_readbraw_error();
3084                         END_PROFILE(SMBreadbraw);
3085                         return;
3086                 }
3087
3088 #endif /* LARGE_SMB_OFF_T */
3089
3090                 if(startpos < 0) {
3091                         DEBUG(0,("reply_readbraw: negative 64 bit "
3092                                 "readraw offset (%.0f) !\n",
3093                                 (double)startpos ));
3094                         reply_readbraw_error();
3095                         END_PROFILE(SMBreadbraw);
3096                         return;
3097                 }      
3098         }
3099
3100         maxcount = (SVAL(req->vwv+3, 0) & 0xFFFF);
3101         mincount = (SVAL(req->vwv+4, 0) & 0xFFFF);
3102
3103         /* ensure we don't overrun the packet size */
3104         maxcount = MIN(65535,maxcount);
3105
3106         init_strict_lock_struct(fsp, (uint32)req->smbpid,
3107             (uint64_t)startpos, (uint64_t)maxcount, READ_LOCK,
3108             &lock);
3109
3110         if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
3111                 reply_readbraw_error();
3112                 END_PROFILE(SMBreadbraw);
3113                 return;
3114         }
3115
3116         if (SMB_VFS_FSTAT(fsp, &st) == 0) {
3117                 size = st.st_size;
3118         }
3119
3120         if (startpos >= size) {
3121                 nread = 0;
3122         } else {
3123                 nread = MIN(maxcount,(size - startpos));
3124         }
3125
3126 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
3127         if (nread < mincount)
3128                 nread = 0;
3129 #endif
3130
3131         DEBUG( 3, ( "reply_readbraw: fnum=%d start=%.0f max=%lu "
3132                 "min=%lu nread=%lu\n",
3133                 fsp->fnum, (double)startpos,
3134                 (unsigned long)maxcount,
3135                 (unsigned long)mincount,
3136                 (unsigned long)nread ) );
3137
3138         send_file_readbraw(conn, req, fsp, startpos, nread, mincount);
3139
3140         DEBUG(5,("reply_readbraw finished\n"));
3141
3142         SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3143
3144         END_PROFILE(SMBreadbraw);
3145         return;
3146 }
3147
3148 #undef DBGC_CLASS
3149 #define DBGC_CLASS DBGC_LOCKING
3150
3151 /****************************************************************************
3152  Reply to a lockread (core+ protocol).
3153 ****************************************************************************/
3154
3155 void reply_lockread(struct smb_request *req)
3156 {
3157         connection_struct *conn = req->conn;
3158         ssize_t nread = -1;
3159         char *data;
3160         SMB_OFF_T startpos;
3161         size_t numtoread;
3162         NTSTATUS status;
3163         files_struct *fsp;
3164         struct byte_range_lock *br_lck = NULL;
3165         char *p = NULL;
3166
3167         START_PROFILE(SMBlockread);
3168
3169         if (req->wct < 5) {
3170                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3171                 END_PROFILE(SMBlockread);
3172                 return;
3173         }
3174
3175         fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3176
3177         if (!check_fsp(conn, req, fsp)) {
3178                 END_PROFILE(SMBlockread);
3179                 return;
3180         }
3181
3182         if (!CHECK_READ(fsp,req)) {
3183                 reply_doserror(req, ERRDOS, ERRbadaccess);
3184                 END_PROFILE(SMBlockread);
3185                 return;
3186         }
3187
3188         numtoread = SVAL(req->vwv+1, 0);
3189         startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
3190
3191         numtoread = MIN(BUFFER_SIZE - (smb_size + 3*2 + 3), numtoread);
3192
3193         reply_outbuf(req, 5, numtoread + 3);
3194
3195         data = smb_buf(req->outbuf) + 3;
3196
3197         /*
3198          * NB. Discovered by Menny Hamburger at Mainsoft. This is a core+
3199          * protocol request that predates the read/write lock concept. 
3200          * Thus instead of asking for a read lock here we need to ask
3201          * for a write lock. JRA.
3202          * Note that the requested lock size is unaffected by max_recv.
3203          */
3204
3205         br_lck = do_lock(smbd_messaging_context(),
3206                         fsp,
3207                         req->smbpid,
3208                         (uint64_t)numtoread,
3209                         (uint64_t)startpos,
3210                         WRITE_LOCK,
3211                         WINDOWS_LOCK,
3212                         False, /* Non-blocking lock. */
3213                         &status,
3214                         NULL,
3215                         NULL);
3216         TALLOC_FREE(br_lck);
3217
3218         if (NT_STATUS_V(status)) {
3219                 reply_nterror(req, status);
3220                 END_PROFILE(SMBlockread);
3221                 return;
3222         }
3223
3224         /*
3225          * However the requested READ size IS affected by max_recv. Insanity.... JRA.
3226          */
3227
3228         if (numtoread > max_recv) {
3229                 DEBUG(0,("reply_lockread: requested read size (%u) is greater than maximum allowed (%u). \
3230 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
3231                         (unsigned int)numtoread, (unsigned int)max_recv ));
3232                 numtoread = MIN(numtoread,max_recv);
3233         }
3234         nread = read_file(fsp,data,startpos,numtoread);
3235
3236         if (nread < 0) {
3237                 reply_unixerror(req, ERRDOS, ERRnoaccess);
3238                 END_PROFILE(SMBlockread);
3239                 return;
3240         }
3241
3242         srv_set_message((char *)req->outbuf, 5, nread+3, False);
3243
3244         SSVAL(req->outbuf,smb_vwv0,nread);
3245         SSVAL(req->outbuf,smb_vwv5,nread+3);
3246         p = smb_buf(req->outbuf);
3247         SCVAL(p,0,0); /* pad byte. */
3248         SSVAL(p,1,nread);
3249
3250         DEBUG(3,("lockread fnum=%d num=%d nread=%d\n",
3251                  fsp->fnum, (int)numtoread, (int)nread));
3252
3253         END_PROFILE(SMBlockread);
3254         return;
3255 }
3256
3257 #undef DBGC_CLASS
3258 #define DBGC_CLASS DBGC_ALL
3259
3260 /****************************************************************************
3261  Reply to a read.
3262 ****************************************************************************/
3263
3264 void reply_read(struct smb_request *req)
3265 {
3266         connection_struct *conn = req->conn;
3267         size_t numtoread;
3268         ssize_t nread = 0;
3269         char *data;
3270         SMB_OFF_T startpos;
3271         int outsize = 0;
3272         files_struct *fsp;
3273         struct lock_struct lock;
3274
3275         START_PROFILE(SMBread);
3276
3277         if (req->wct < 3) {
3278                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3279                 END_PROFILE(SMBread);
3280                 return;
3281         }
3282
3283         fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3284
3285         if (!check_fsp(conn, req, fsp)) {
3286                 END_PROFILE(SMBread);
3287                 return;
3288         }
3289
3290         if (!CHECK_READ(fsp,req)) {
3291                 reply_doserror(req, ERRDOS, ERRbadaccess);
3292                 END_PROFILE(SMBread);
3293                 return;
3294         }
3295
3296         numtoread = SVAL(req->vwv+1, 0);
3297         startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
3298
3299         numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
3300
3301         /*
3302          * The requested read size cannot be greater than max_recv. JRA.
3303          */
3304         if (numtoread > max_recv) {
3305                 DEBUG(0,("reply_read: requested read size (%u) is greater than maximum allowed (%u). \
3306 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
3307                         (unsigned int)numtoread, (unsigned int)max_recv ));
3308                 numtoread = MIN(numtoread,max_recv);
3309         }
3310
3311         reply_outbuf(req, 5, numtoread+3);
3312
3313         data = smb_buf(req->outbuf) + 3;
3314
3315         init_strict_lock_struct(fsp, (uint32)req->smbpid,
3316             (uint64_t)startpos, (uint64_t)numtoread, READ_LOCK,
3317             &lock);
3318
3319         if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
3320                 reply_doserror(req, ERRDOS,ERRlock);
3321                 END_PROFILE(SMBread);
3322                 return;
3323         }
3324
3325         if (numtoread > 0)
3326                 nread = read_file(fsp,data,startpos,numtoread);
3327
3328         if (nread < 0) {
3329                 reply_unixerror(req, ERRDOS,ERRnoaccess);
3330                 goto strict_unlock;
3331         }
3332
3333         srv_set_message((char *)req->outbuf, 5, nread+3, False);
3334
3335         SSVAL(req->outbuf,smb_vwv0,nread);
3336         SSVAL(req->outbuf,smb_vwv5,nread+3);
3337         SCVAL(smb_buf(req->outbuf),0,1);
3338         SSVAL(smb_buf(req->outbuf),1,nread);
3339
3340         DEBUG( 3, ( "read fnum=%d num=%d nread=%d\n",
3341                 fsp->fnum, (int)numtoread, (int)nread ) );
3342
3343 strict_unlock:
3344         SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3345
3346         END_PROFILE(SMBread);
3347         return;
3348 }
3349
3350 /****************************************************************************
3351  Setup readX header.
3352 ****************************************************************************/
3353
3354 static int setup_readX_header(struct smb_request *req, char *outbuf,
3355                               size_t smb_maxcnt)
3356 {
3357         int outsize;
3358         char *data;
3359
3360         outsize = srv_set_message(outbuf,12,smb_maxcnt,False);
3361         data = smb_buf(outbuf);
3362
3363         memset(outbuf+smb_vwv0,'\0',24); /* valgrind init. */
3364
3365         SCVAL(outbuf,smb_vwv0,0xFF);
3366         SSVAL(outbuf,smb_vwv2,0xFFFF); /* Remaining - must be -1. */
3367         SSVAL(outbuf,smb_vwv5,smb_maxcnt);
3368         SSVAL(outbuf,smb_vwv6,
3369               req_wct_ofs(req)
3370               + 1               /* the wct field */
3371               + 12 * sizeof(uint16_t) /* vwv */
3372               + 2);             /* the buflen field */
3373         SSVAL(outbuf,smb_vwv7,(smb_maxcnt >> 16));
3374         SSVAL(outbuf,smb_vwv11,smb_maxcnt);
3375         /* Reset the outgoing length, set_message truncates at 0x1FFFF. */
3376         _smb_setlen_large(outbuf,(smb_size + 12*2 + smb_maxcnt - 4));
3377         return outsize;
3378 }
3379
3380 /****************************************************************************
3381  Reply to a read and X - possibly using sendfile.
3382 ****************************************************************************/
3383
3384 static void send_file_readX(connection_struct *conn, struct smb_request *req,
3385                             files_struct *fsp, SMB_OFF_T startpos,
3386                             size_t smb_maxcnt)
3387 {
3388         SMB_STRUCT_STAT sbuf;
3389         ssize_t nread = -1;
3390         struct lock_struct lock;
3391
3392         if(SMB_VFS_FSTAT(fsp, &sbuf) == -1) {
3393                 reply_unixerror(req, ERRDOS, ERRnoaccess);
3394                 return;
3395         }
3396
3397         init_strict_lock_struct(fsp, (uint32)req->smbpid,
3398             (uint64_t)startpos, (uint64_t)smb_maxcnt, READ_LOCK,
3399             &lock);
3400
3401         if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
3402                 reply_doserror(req, ERRDOS, ERRlock);
3403                 return;
3404         }
3405
3406         if (!S_ISREG(sbuf.st_mode) || (startpos > sbuf.st_size)
3407             || (smb_maxcnt > (sbuf.st_size - startpos))) {
3408                 /*
3409                  * We already know that we would do a short read, so don't
3410                  * try the sendfile() path.
3411                  */
3412                 goto nosendfile_read;
3413         }
3414
3415 #if defined(WITH_SENDFILE)
3416         /*
3417          * We can only use sendfile on a non-chained packet
3418          * but we can use on a non-oplocked file. tridge proved this
3419          * on a train in Germany :-). JRA.
3420          */
3421
3422         if (!req_is_in_chain(req) &&
3423             !is_encrypted_packet(req->inbuf) && (fsp->base_fsp == NULL) &&
3424             (fsp->wcp == NULL) &&
3425             lp_use_sendfile(SNUM(conn), smbd_server_conn->signing_state) ) {
3426                 uint8 headerbuf[smb_size + 12 * 2];
3427                 DATA_BLOB header;
3428
3429                 /*
3430                  * Set up the packet header before send. We
3431                  * assume here the sendfile will work (get the
3432                  * correct amount of data).
3433                  */
3434
3435                 header = data_blob_const(headerbuf, sizeof(headerbuf));
3436
3437                 construct_reply_common_req(req, (char *)headerbuf);
3438                 setup_readX_header(req, (char *)headerbuf, smb_maxcnt);
3439
3440                 if ((nread = SMB_VFS_SENDFILE(smbd_server_fd(), fsp, &header, startpos, smb_maxcnt)) == -1) {
3441                         /* Returning ENOSYS means no data at all was sent.
3442                            Do this as a normal read. */
3443                         if (errno == ENOSYS) {
3444                                 goto normal_read;
3445                         }
3446
3447                         /*
3448                          * Special hack for broken Linux with no working sendfile. If we
3449                          * return EINTR we sent the header but not the rest of the data.
3450                          * Fake this up by doing read/write calls.
3451                          */
3452
3453                         if (errno == EINTR) {
3454                                 /* Ensure we don't do this again. */
3455                                 set_use_sendfile(SNUM(conn), False);
3456                                 DEBUG(0,("send_file_readX: sendfile not available. Faking..\n"));
3457                                 nread = fake_sendfile(fsp, startpos,
3458                                                       smb_maxcnt);
3459                                 if (nread == -1) {
3460                                         DEBUG(0,("send_file_readX: fake_sendfile failed for file %s (%s).\n",
3461                                                 fsp->fsp_name, strerror(errno) ));
3462                                         exit_server_cleanly("send_file_readX: fake_sendfile failed");
3463                                 }
3464                                 DEBUG( 3, ( "send_file_readX: fake_sendfile fnum=%d max=%d nread=%d\n",
3465                                         fsp->fnum, (int)smb_maxcnt, (int)nread ) );
3466                                 /* No outbuf here means successful sendfile. */
3467                                 goto strict_unlock;
3468                         }
3469
3470                         DEBUG(0,("send_file_readX: sendfile failed for file %s (%s). Terminating\n",
3471                                 fsp->fsp_name, strerror(errno) ));
3472                         exit_server_cleanly("send_file_readX sendfile failed");
3473                 } else if (nread == 0) {
3474                         /*
3475                          * Some sendfile implementations return 0 to indicate
3476                          * that there was a short read, but nothing was
3477                          * actually written to the socket.  In this case,
3478                          * fallback to the normal read path so the header gets
3479                          * the correct byte count.
3480                          */
3481                         DEBUG(3, ("send_file_readX: sendfile sent zero bytes "
3482                                   "falling back to the normal read: %s\n",
3483                                   fsp->fsp_name));
3484                         goto normal_read;
3485                 }
3486
3487                 DEBUG( 3, ( "send_file_readX: sendfile fnum=%d max=%d nread=%d\n",
3488                         fsp->fnum, (int)smb_maxcnt, (int)nread ) );
3489
3490                 /* Deal with possible short send. */
3491                 if (nread != smb_maxcnt + sizeof(headerbuf)) {
3492                         sendfile_short_send(fsp, nread, sizeof(headerbuf), smb_maxcnt);
3493                 }
3494                 /* No outbuf here means successful sendfile. */
3495                 SMB_PERFCOUNT_SET_MSGLEN_OUT(&req->pcd, nread);
3496                 SMB_PERFCOUNT_END(&req->pcd);
3497                 goto strict_unlock;
3498         }
3499
3500 normal_read:
3501
3502 #endif
3503
3504         if ((smb_maxcnt & 0xFF0000) > 0x10000) {
3505                 uint8 headerbuf[smb_size + 2*12];
3506
3507                 construct_reply_common_req(req, (char *)headerbuf);
3508                 setup_readX_header(req, (char *)headerbuf, smb_maxcnt);
3509
3510                 /* Send out the header. */
3511                 if (write_data(smbd_server_fd(), (char *)headerbuf,
3512                                sizeof(headerbuf)) != sizeof(headerbuf)) {
3513                         DEBUG(0,("send_file_readX: write_data failed for file %s (%s). Terminating\n",
3514                                 fsp->fsp_name, strerror(errno) ));
3515                         exit_server_cleanly("send_file_readX sendfile failed");
3516                 }
3517                 nread = fake_sendfile(fsp, startpos, smb_maxcnt);
3518                 if (nread == -1) {
3519                         DEBUG(0,("send_file_readX: fake_sendfile failed for file %s (%s).\n",
3520                                 fsp->fsp_name, strerror(errno) ));
3521                         exit_server_cleanly("send_file_readX: fake_sendfile failed");
3522                 }
3523                 goto strict_unlock;
3524         }
3525
3526 nosendfile_read:
3527
3528         reply_outbuf(req, 12, smb_maxcnt);
3529
3530         nread = read_file(fsp, smb_buf(req->outbuf), startpos, smb_maxcnt);
3531
3532         SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3533
3534         if (nread < 0) {
3535                 reply_unixerror(req, ERRDOS, ERRnoaccess);
3536                 return;
3537         }
3538
3539         setup_readX_header(req, (char *)req->outbuf, nread);
3540
3541         DEBUG( 3, ( "send_file_readX fnum=%d max=%d nread=%d\n",
3542                     fsp->fnum, (int)smb_maxcnt, (int)nread ) );
3543
3544         chain_reply(req);
3545         return;
3546
3547  strict_unlock:
3548         SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3549         TALLOC_FREE(req->outbuf);
3550         return;
3551 }
3552
3553 /****************************************************************************
3554  Reply to a read and X.
3555 ****************************************************************************/
3556
3557 void reply_read_and_X(struct smb_request *req)
3558 {
3559         connection_struct *conn = req->conn;
3560         files_struct *fsp;
3561         SMB_OFF_T startpos;
3562         size_t smb_maxcnt;
3563         bool big_readX = False;
3564 #if 0
3565         size_t smb_mincnt = SVAL(req->vwv+6, 0);
3566 #endif
3567
3568         START_PROFILE(SMBreadX);
3569
3570         if ((req->wct != 10) && (req->wct != 12)) {
3571                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3572                 return;
3573         }
3574
3575         fsp = file_fsp(req, SVAL(req->vwv+2, 0));
3576         startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
3577         smb_maxcnt = SVAL(req->vwv+5, 0);
3578
3579         /* If it's an IPC, pass off the pipe handler. */
3580         if (IS_IPC(conn)) {
3581                 reply_pipe_read_and_X(req);
3582                 END_PROFILE(SMBreadX);
3583                 return;
3584         }
3585
3586         if (!check_fsp(conn, req, fsp)) {
3587                 END_PROFILE(SMBreadX);
3588                 return;
3589         }
3590
3591         if (!CHECK_READ(fsp,req)) {
3592                 reply_doserror(req, ERRDOS,ERRbadaccess);
3593                 END_PROFILE(SMBreadX);
3594                 return;
3595         }
3596
3597         if (global_client_caps & CAP_LARGE_READX) {
3598                 size_t upper_size = SVAL(req->vwv+7, 0);
3599                 smb_maxcnt |= (upper_size<<16);
3600                 if (upper_size > 1) {
3601                         /* Can't do this on a chained packet. */
3602                         if ((CVAL(req->vwv+0, 0) != 0xFF)) {
3603                                 reply_nterror(req, NT_STATUS_NOT_SUPPORTED);
3604                                 END_PROFILE(SMBreadX);
3605                                 return;
3606                         }
3607                         /* We currently don't do this on signed or sealed data. */
3608                         if (srv_is_signing_active(smbd_server_conn) ||
3609                             is_encrypted_packet(req->inbuf)) {
3610                                 reply_nterror(req, NT_STATUS_NOT_SUPPORTED);
3611                                 END_PROFILE(SMBreadX);
3612                                 return;
3613                         }
3614                         /* Is there room in the reply for this data ? */
3615                         if (smb_maxcnt > (0xFFFFFF - (smb_size -4 + 12*2)))  {
3616                                 reply_nterror(req,
3617                                               NT_STATUS_INVALID_PARAMETER);
3618                                 END_PROFILE(SMBreadX);
3619                                 return;
3620                         }
3621                         big_readX = True;
3622                 }
3623         }
3624
3625         if (req->wct == 12) {
3626 #ifdef LARGE_SMB_OFF_T
3627                 /*
3628                  * This is a large offset (64 bit) read.
3629                  */
3630                 startpos |= (((SMB_OFF_T)IVAL(req->vwv+10, 0)) << 32);
3631
3632 #else /* !LARGE_SMB_OFF_T */
3633
3634                 /*
3635                  * Ensure we haven't been sent a >32 bit offset.
3636                  */
3637
3638                 if(IVAL(req->vwv+10, 0) != 0) {
3639                         DEBUG(0,("reply_read_and_X - large offset (%x << 32) "
3640                                  "used and we don't support 64 bit offsets.\n",
3641                                  (unsigned int)IVAL(req->vwv+10, 0) ));
3642                         END_PROFILE(SMBreadX);
3643                         reply_doserror(req, ERRDOS, ERRbadaccess);
3644                         return;
3645                 }
3646
3647 #endif /* LARGE_SMB_OFF_T */
3648
3649         }
3650
3651         if (!big_readX &&
3652             schedule_aio_read_and_X(conn, req, fsp, startpos, smb_maxcnt)) {
3653                 goto out;
3654         }
3655
3656         send_file_readX(conn, req, fsp, startpos, smb_maxcnt);
3657
3658  out:
3659         END_PROFILE(SMBreadX);
3660         return;
3661 }
3662
3663 /****************************************************************************
3664  Error replies to writebraw must have smb_wct == 1. Fix this up.
3665 ****************************************************************************/
3666
3667 void error_to_writebrawerr(struct smb_request *req)
3668 {
3669         uint8 *old_outbuf = req->outbuf;
3670
3671         reply_outbuf(req, 1, 0);
3672
3673         memcpy(req->outbuf, old_outbuf, smb_size);
3674         TALLOC_FREE(old_outbuf);
3675 }
3676
3677 /****************************************************************************
3678  Reply to a writebraw (core+ or LANMAN1.0 protocol).
3679 ****************************************************************************/
3680
3681 void reply_writebraw(struct smb_request *req)
3682 {
3683         connection_struct *conn = req->conn;
3684         char *buf = NULL;
3685         ssize_t nwritten=0;
3686         ssize_t total_written=0;
3687         size_t numtowrite=0;
3688         size_t tcount;
3689         SMB_OFF_T startpos;
3690         char *data=NULL;
3691         bool write_through;
3692         files_struct *fsp;
3693         struct lock_struct lock;
3694         NTSTATUS status;
3695
3696         START_PROFILE(SMBwritebraw);
3697
3698         /*
3699          * If we ever reply with an error, it must have the SMB command
3700          * type of SMBwritec, not SMBwriteBraw, as this tells the client
3701          * we're finished.
3702          */
3703         SCVAL(req->inbuf,smb_com,SMBwritec);
3704
3705         if (srv_is_signing_active(smbd_server_conn)) {
3706                 END_PROFILE(SMBwritebraw);
3707                 exit_server_cleanly("reply_writebraw: SMB signing is active - "
3708                                 "raw reads/writes are&nbs