Fix bug #6551 - win98 clients cannot connect after server upgrade to samba-3.4.0.
[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         struct smbd_server_connection *sconn = smbd_server_conn;
510
511         /*
512          * We only really use 4 bytes of the outbuf, but for the smb_setlen
513          * calculation & friends (srv_send_smb uses that) we need the full smb
514          * header.
515          */
516         char outbuf[smb_size];
517
518         *name1 = *name2 = 0;
519
520         memset(outbuf, '\0', sizeof(outbuf));
521
522         smb_setlen(outbuf,0);
523
524         switch (msg_type) {
525         case 0x81: /* session request */
526
527                 if (sconn->nbt.got_session) {
528                         exit_server_cleanly("multiple session request not permitted");
529                 }
530
531                 SCVAL(outbuf,0,0x82);
532                 SCVAL(outbuf,3,0);
533                 if (name_len(inbuf+4) > 50 || 
534                     name_len(inbuf+4 + name_len(inbuf + 4)) > 50) {
535                         DEBUG(0,("Invalid name length in session request\n"));
536                         return;
537                 }
538                 name_type1 = name_extract(inbuf,4,name1);
539                 name_type2 = name_extract(inbuf,4 + name_len(inbuf + 4),name2);
540                 DEBUG(2,("netbios connect: name1=%s0x%x name2=%s0x%x\n",
541                          name1, name_type1, name2, name_type2));
542
543                 if (netbios_session_retarget(name1, name_type1)) {
544                         exit_server_cleanly("retargeted client");
545                 }
546
547                 set_local_machine_name(name1, True);
548                 set_remote_machine_name(name2, True);
549
550                 DEBUG(2,("netbios connect: local=%s remote=%s, name type = %x\n",
551                          get_local_machine_name(), get_remote_machine_name(),
552                          name_type2));
553
554                 if (name_type2 == 'R') {
555                         /* We are being asked for a pathworks session --- 
556                            no thanks! */
557                         SCVAL(outbuf, 0,0x83);
558                         break;
559                 }
560
561                 /* only add the client's machine name to the list
562                    of possibly valid usernames if we are operating
563                    in share mode security */
564                 if (lp_security() == SEC_SHARE) {
565                         add_session_user(sconn, get_remote_machine_name());
566                 }
567
568                 reload_services(True);
569                 reopen_logs();
570
571                 sconn->nbt.got_session = true;
572                 break;
573
574         case 0x89: /* session keepalive request 
575                       (some old clients produce this?) */
576                 SCVAL(outbuf,0,SMBkeepalive);
577                 SCVAL(outbuf,3,0);
578                 break;
579
580         case 0x82: /* positive session response */
581         case 0x83: /* negative session response */
582         case 0x84: /* retarget session response */
583                 DEBUG(0,("Unexpected session response\n"));
584                 break;
585
586         case SMBkeepalive: /* session keepalive */
587         default:
588                 return;
589         }
590
591         DEBUG(5,("init msg_type=0x%x msg_flags=0x%x\n",
592                     msg_type, msg_flags));
593
594         srv_send_smb(smbd_server_fd(), outbuf, false, 0, false, NULL);
595         return;
596 }
597
598 /****************************************************************************
599  Reply to a tcon.
600  conn POINTER CAN BE NULL HERE !
601 ****************************************************************************/
602
603 void reply_tcon(struct smb_request *req)
604 {
605         connection_struct *conn = req->conn;
606         const char *service;
607         char *service_buf = NULL;
608         char *password = NULL;
609         char *dev = NULL;
610         int pwlen=0;
611         NTSTATUS nt_status;
612         const char *p;
613         DATA_BLOB password_blob;
614         TALLOC_CTX *ctx = talloc_tos();
615         struct smbd_server_connection *sconn = smbd_server_conn;
616
617         START_PROFILE(SMBtcon);
618
619         if (req->buflen < 4) {
620                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
621                 END_PROFILE(SMBtcon);
622                 return;
623         }
624
625         p = (const char *)req->buf + 1;
626         p += srvstr_pull_req_talloc(ctx, req, &service_buf, p, STR_TERMINATE);
627         p += 1;
628         pwlen = srvstr_pull_req_talloc(ctx, req, &password, p, STR_TERMINATE);
629         p += pwlen+1;
630         p += srvstr_pull_req_talloc(ctx, req, &dev, p, STR_TERMINATE);
631         p += 1;
632
633         if (service_buf == NULL || password == NULL || dev == NULL) {
634                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
635                 END_PROFILE(SMBtcon);
636                 return;
637         }
638         p = strrchr_m(service_buf,'\\');
639         if (p) {
640                 service = p+1;
641         } else {
642                 service = service_buf;
643         }
644
645         password_blob = data_blob(password, pwlen+1);
646
647         conn = make_connection(sconn,service,password_blob,dev,
648                                req->vuid,&nt_status);
649         req->conn = conn;
650
651         data_blob_clear_free(&password_blob);
652
653         if (!conn) {
654                 reply_nterror(req, nt_status);
655                 END_PROFILE(SMBtcon);
656                 return;
657         }
658
659         reply_outbuf(req, 2, 0);
660         SSVAL(req->outbuf,smb_vwv0,sconn->smb1.negprot.max_recv);
661         SSVAL(req->outbuf,smb_vwv1,conn->cnum);
662         SSVAL(req->outbuf,smb_tid,conn->cnum);
663
664         DEBUG(3,("tcon service=%s cnum=%d\n",
665                  service, conn->cnum));
666
667         END_PROFILE(SMBtcon);
668         return;
669 }
670
671 /****************************************************************************
672  Reply to a tcon and X.
673  conn POINTER CAN BE NULL HERE !
674 ****************************************************************************/
675
676 void reply_tcon_and_X(struct smb_request *req)
677 {
678         connection_struct *conn = req->conn;
679         const char *service = NULL;
680         DATA_BLOB password;
681         TALLOC_CTX *ctx = talloc_tos();
682         /* what the cleint thinks the device is */
683         char *client_devicetype = NULL;
684         /* what the server tells the client the share represents */
685         const char *server_devicetype;
686         NTSTATUS nt_status;
687         int passlen;
688         char *path = NULL;
689         const char *p, *q;
690         uint16 tcon_flags;
691         struct smbd_server_connection *sconn = smbd_server_conn;
692
693         START_PROFILE(SMBtconX);
694
695         if (req->wct < 4) {
696                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
697                 END_PROFILE(SMBtconX);
698                 return;
699         }
700
701         passlen = SVAL(req->vwv+3, 0);
702         tcon_flags = SVAL(req->vwv+2, 0);
703
704         /* we might have to close an old one */
705         if ((tcon_flags & 0x1) && conn) {
706                 close_cnum(sconn, conn,req->vuid);
707                 req->conn = NULL;
708                 conn = NULL;
709         }
710
711         if ((passlen > MAX_PASS_LEN) || (passlen >= req->buflen)) {
712                 reply_doserror(req, ERRDOS, ERRbuftoosmall);
713                 END_PROFILE(SMBtconX);
714                 return;
715         }
716
717         if (sconn->smb1.negprot.encrypted_passwords) {
718                 password = data_blob_talloc(talloc_tos(), req->buf, passlen);
719                 if (lp_security() == SEC_SHARE) {
720                         /*
721                          * Security = share always has a pad byte
722                          * after the password.
723                          */
724                         p = (const char *)req->buf + passlen + 1;
725                 } else {
726                         p = (const char *)req->buf + passlen;
727                 }
728         } else {
729                 password = data_blob_talloc(talloc_tos(), req->buf, passlen+1);
730                 /* Ensure correct termination */
731                 password.data[passlen]=0;
732                 p = (const char *)req->buf + passlen + 1;
733         }
734
735         p += srvstr_pull_req_talloc(ctx, req, &path, p, STR_TERMINATE);
736
737         if (path == NULL) {
738                 data_blob_clear_free(&password);
739                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
740                 END_PROFILE(SMBtconX);
741                 return;
742         }
743
744         /*
745          * the service name can be either: \\server\share
746          * or share directly like on the DELL PowerVault 705
747          */
748         if (*path=='\\') {
749                 q = strchr_m(path+2,'\\');
750                 if (!q) {
751                         data_blob_clear_free(&password);
752                         reply_doserror(req, ERRDOS, ERRnosuchshare);
753                         END_PROFILE(SMBtconX);
754                         return;
755                 }
756                 service = q+1;
757         } else {
758                 service = path;
759         }
760
761         p += srvstr_pull_talloc(ctx, req->inbuf, req->flags2,
762                                 &client_devicetype, p,
763                                 MIN(6, smbreq_bufrem(req, p)), STR_ASCII);
764
765         if (client_devicetype == NULL) {
766                 data_blob_clear_free(&password);
767                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
768                 END_PROFILE(SMBtconX);
769                 return;
770         }
771
772         DEBUG(4,("Client requested device type [%s] for share [%s]\n", client_devicetype, service));
773
774         conn = make_connection(sconn, service, password, client_devicetype,
775                                req->vuid, &nt_status);
776         req->conn =conn;
777
778         data_blob_clear_free(&password);
779
780         if (!conn) {
781                 reply_nterror(req, nt_status);
782                 END_PROFILE(SMBtconX);
783                 return;
784         }
785
786         if ( IS_IPC(conn) )
787                 server_devicetype = "IPC";
788         else if ( IS_PRINT(conn) )
789                 server_devicetype = "LPT1:";
790         else
791                 server_devicetype = "A:";
792
793         if (Protocol < PROTOCOL_NT1) {
794                 reply_outbuf(req, 2, 0);
795                 if (message_push_string(&req->outbuf, server_devicetype,
796                                         STR_TERMINATE|STR_ASCII) == -1) {
797                         reply_nterror(req, NT_STATUS_NO_MEMORY);
798                         END_PROFILE(SMBtconX);
799                         return;
800                 }
801         } else {
802                 /* NT sets the fstype of IPC$ to the null string */
803                 const char *fstype = IS_IPC(conn) ? "" : lp_fstype(SNUM(conn));
804
805                 if (tcon_flags & TCONX_FLAG_EXTENDED_RESPONSE) {
806                         /* Return permissions. */
807                         uint32 perm1 = 0;
808                         uint32 perm2 = 0;
809
810                         reply_outbuf(req, 7, 0);
811
812                         if (IS_IPC(conn)) {
813                                 perm1 = FILE_ALL_ACCESS;
814                                 perm2 = FILE_ALL_ACCESS;
815                         } else {
816                                 perm1 = CAN_WRITE(conn) ?
817                                                 SHARE_ALL_ACCESS :
818                                                 SHARE_READ_ONLY;
819                         }
820
821                         SIVAL(req->outbuf, smb_vwv3, perm1);
822                         SIVAL(req->outbuf, smb_vwv5, perm2);
823                 } else {
824                         reply_outbuf(req, 3, 0);
825                 }
826
827                 if ((message_push_string(&req->outbuf, server_devicetype,
828                                          STR_TERMINATE|STR_ASCII) == -1)
829                     || (message_push_string(&req->outbuf, fstype,
830                                             STR_TERMINATE) == -1)) {
831                         reply_nterror(req, NT_STATUS_NO_MEMORY);
832                         END_PROFILE(SMBtconX);
833                         return;
834                 }
835
836                 /* what does setting this bit do? It is set by NT4 and
837                    may affect the ability to autorun mounted cdroms */
838                 SSVAL(req->outbuf, smb_vwv2, SMB_SUPPORT_SEARCH_BITS|
839                       (lp_csc_policy(SNUM(conn)) << 2));
840
841                 if (lp_msdfs_root(SNUM(conn)) && lp_host_msdfs()) {
842                         DEBUG(2,("Serving %s as a Dfs root\n",
843                                  lp_servicename(SNUM(conn)) ));
844                         SSVAL(req->outbuf, smb_vwv2,
845                               SMB_SHARE_IN_DFS | SVAL(req->outbuf, smb_vwv2));
846                 }
847         }
848
849
850         DEBUG(3,("tconX service=%s \n",
851                  service));
852
853         /* set the incoming and outgoing tid to the just created one */
854         SSVAL(req->inbuf,smb_tid,conn->cnum);
855         SSVAL(req->outbuf,smb_tid,conn->cnum);
856
857         END_PROFILE(SMBtconX);
858
859         req->tid = conn->cnum;
860         chain_reply(req);
861         return;
862 }
863
864 /****************************************************************************
865  Reply to an unknown type.
866 ****************************************************************************/
867
868 void reply_unknown_new(struct smb_request *req, uint8 type)
869 {
870         DEBUG(0, ("unknown command type (%s): type=%d (0x%X)\n",
871                   smb_fn_name(type), type, type));
872         reply_doserror(req, ERRSRV, ERRunknownsmb);
873         return;
874 }
875
876 /****************************************************************************
877  Reply to an ioctl.
878  conn POINTER CAN BE NULL HERE !
879 ****************************************************************************/
880
881 void reply_ioctl(struct smb_request *req)
882 {
883         connection_struct *conn = req->conn;
884         uint16 device;
885         uint16 function;
886         uint32 ioctl_code;
887         int replysize;
888         char *p;
889
890         START_PROFILE(SMBioctl);
891
892         if (req->wct < 3) {
893                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
894                 END_PROFILE(SMBioctl);
895                 return;
896         }
897
898         device     = SVAL(req->vwv+1, 0);
899         function   = SVAL(req->vwv+2, 0);
900         ioctl_code = (device << 16) + function;
901
902         DEBUG(4, ("Received IOCTL (code 0x%x)\n", ioctl_code));
903
904         switch (ioctl_code) {
905             case IOCTL_QUERY_JOB_INFO:
906                     replysize = 32;
907                     break;
908             default:
909                     reply_doserror(req, ERRSRV, ERRnosupport);
910                     END_PROFILE(SMBioctl);
911                     return;
912         }
913
914         reply_outbuf(req, 8, replysize+1);
915         SSVAL(req->outbuf,smb_vwv1,replysize); /* Total data bytes returned */
916         SSVAL(req->outbuf,smb_vwv5,replysize); /* Data bytes this buffer */
917         SSVAL(req->outbuf,smb_vwv6,52);        /* Offset to data */
918         p = smb_buf(req->outbuf);
919         memset(p, '\0', replysize+1); /* valgrind-safe. */
920         p += 1;          /* Allow for alignment */
921
922         switch (ioctl_code) {
923                 case IOCTL_QUERY_JOB_INFO:                  
924                 {
925                         files_struct *fsp = file_fsp(
926                                 req, SVAL(req->vwv+0, 0));
927                         if (!fsp) {
928                                 reply_doserror(req, ERRDOS, ERRbadfid);
929                                 END_PROFILE(SMBioctl);
930                                 return;
931                         }
932                         SSVAL(p,0,fsp->rap_print_jobid);             /* Job number */
933                         srvstr_push((char *)req->outbuf, req->flags2, p+2,
934                                     global_myname(), 15,
935                                     STR_TERMINATE|STR_ASCII);
936                         if (conn) {
937                                 srvstr_push((char *)req->outbuf, req->flags2,
938                                             p+18, lp_servicename(SNUM(conn)),
939                                             13, STR_TERMINATE|STR_ASCII);
940                         } else {
941                                 memset(p+18, 0, 13);
942                         }
943                         break;
944                 }
945         }
946
947         END_PROFILE(SMBioctl);
948         return;
949 }
950
951 /****************************************************************************
952  Strange checkpath NTSTATUS mapping.
953 ****************************************************************************/
954
955 static NTSTATUS map_checkpath_error(uint16_t flags2, NTSTATUS status)
956 {
957         /* Strange DOS error code semantics only for checkpath... */
958         if (!(flags2 & FLAGS2_32_BIT_ERROR_CODES)) {
959                 if (NT_STATUS_EQUAL(NT_STATUS_OBJECT_NAME_INVALID,status)) {
960                         /* We need to map to ERRbadpath */
961                         return NT_STATUS_OBJECT_PATH_NOT_FOUND;
962                 }
963         }
964         return status;
965 }
966
967 /****************************************************************************
968  Reply to a checkpath.
969 ****************************************************************************/
970
971 void reply_checkpath(struct smb_request *req)
972 {
973         connection_struct *conn = req->conn;
974         struct smb_filename *smb_fname = NULL;
975         char *name = NULL;
976         NTSTATUS status;
977         TALLOC_CTX *ctx = talloc_tos();
978
979         START_PROFILE(SMBcheckpath);
980
981         srvstr_get_path_req(ctx, req, &name, (const char *)req->buf + 1,
982                             STR_TERMINATE, &status);
983
984         if (!NT_STATUS_IS_OK(status)) {
985                 status = map_checkpath_error(req->flags2, status);
986                 reply_nterror(req, status);
987                 END_PROFILE(SMBcheckpath);
988                 return;
989         }
990
991         DEBUG(3,("reply_checkpath %s mode=%d\n", name, (int)SVAL(req->vwv+0, 0)));
992
993         status = filename_convert(ctx,
994                                 conn,
995                                 req->flags2 & FLAGS2_DFS_PATHNAMES,
996                                 name,
997                                 &smb_fname,
998                                 NULL);
999
1000         if (!NT_STATUS_IS_OK(status)) {
1001                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1002                         reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1003                                         ERRSRV, ERRbadpath);
1004                         END_PROFILE(SMBcheckpath);
1005                         return;
1006                 }
1007                 goto path_err;
1008         }
1009
1010         if (!VALID_STAT(smb_fname->st) &&
1011             (SMB_VFS_STAT(conn, smb_fname) != 0)) {
1012                 DEBUG(3,("reply_checkpath: stat of %s failed (%s)\n",
1013                         smb_fname_str_dbg(smb_fname), strerror(errno)));
1014                 status = map_nt_error_from_unix(errno);
1015                 goto path_err;
1016         }
1017
1018         if (!S_ISDIR(smb_fname->st.st_ex_mode)) {
1019                 reply_botherror(req, NT_STATUS_NOT_A_DIRECTORY,
1020                                 ERRDOS, ERRbadpath);
1021                 goto out;
1022         }
1023
1024         reply_outbuf(req, 0, 0);
1025
1026  path_err:
1027         /* We special case this - as when a Windows machine
1028                 is parsing a path is steps through the components
1029                 one at a time - if a component fails it expects
1030                 ERRbadpath, not ERRbadfile.
1031         */
1032         status = map_checkpath_error(req->flags2, status);
1033         if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
1034                 /*
1035                  * Windows returns different error codes if
1036                  * the parent directory is valid but not the
1037                  * last component - it returns NT_STATUS_OBJECT_NAME_NOT_FOUND
1038                  * for that case and NT_STATUS_OBJECT_PATH_NOT_FOUND
1039                  * if the path is invalid.
1040                  */
1041                 reply_botherror(req, NT_STATUS_OBJECT_NAME_NOT_FOUND,
1042                                 ERRDOS, ERRbadpath);
1043                 goto out;
1044         }
1045
1046         reply_nterror(req, status);
1047
1048  out:
1049         TALLOC_FREE(smb_fname);
1050         END_PROFILE(SMBcheckpath);
1051         return;
1052 }
1053
1054 /****************************************************************************
1055  Reply to a getatr.
1056 ****************************************************************************/
1057
1058 void reply_getatr(struct smb_request *req)
1059 {
1060         connection_struct *conn = req->conn;
1061         struct smb_filename *smb_fname = NULL;
1062         char *fname = NULL;
1063         int mode=0;
1064         SMB_OFF_T size=0;
1065         time_t mtime=0;
1066         const char *p;
1067         NTSTATUS status;
1068         TALLOC_CTX *ctx = talloc_tos();
1069         bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
1070
1071         START_PROFILE(SMBgetatr);
1072
1073         p = (const char *)req->buf + 1;
1074         p += srvstr_get_path_req(ctx, req, &fname, p, STR_TERMINATE, &status);
1075         if (!NT_STATUS_IS_OK(status)) {
1076                 reply_nterror(req, status);
1077                 goto out;
1078         }
1079
1080         /* dos smetimes asks for a stat of "" - it returns a "hidden directory"
1081                 under WfWg - weird! */
1082         if (*fname == '\0') {
1083                 mode = aHIDDEN | aDIR;
1084                 if (!CAN_WRITE(conn)) {
1085                         mode |= aRONLY;
1086                 }
1087                 size = 0;
1088                 mtime = 0;
1089         } else {
1090                 status = filename_convert(ctx,
1091                                 conn,
1092                                 req->flags2 & FLAGS2_DFS_PATHNAMES,
1093                                 fname,
1094                                 &smb_fname,
1095                                 NULL);
1096                 if (!NT_STATUS_IS_OK(status)) {
1097                         if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1098                                 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1099                                                 ERRSRV, ERRbadpath);
1100                                 goto out;
1101                         }
1102                         reply_nterror(req, status);
1103                         goto out;
1104                 }
1105                 if (!VALID_STAT(smb_fname->st) &&
1106                     (SMB_VFS_STAT(conn, smb_fname) != 0)) {
1107                         DEBUG(3,("reply_getatr: stat of %s failed (%s)\n",
1108                                  smb_fname_str_dbg(smb_fname),
1109                                  strerror(errno)));
1110                         reply_nterror(req,  map_nt_error_from_unix(errno));
1111                         goto out;
1112                 }
1113
1114                 mode = dos_mode(conn, smb_fname);
1115                 size = smb_fname->st.st_ex_size;
1116
1117                 if (ask_sharemode) {
1118                         struct timespec write_time_ts;
1119                         struct file_id fileid;
1120
1121                         ZERO_STRUCT(write_time_ts);
1122                         fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
1123                         get_file_infos(fileid, NULL, &write_time_ts);
1124                         if (!null_timespec(write_time_ts)) {
1125                                 update_stat_ex_mtime(&smb_fname->st, write_time_ts);
1126                         }
1127                 }
1128
1129                 mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
1130                 if (mode & aDIR) {
1131                         size = 0;
1132                 }
1133         }
1134
1135         reply_outbuf(req, 10, 0);
1136
1137         SSVAL(req->outbuf,smb_vwv0,mode);
1138         if(lp_dos_filetime_resolution(SNUM(conn)) ) {
1139                 srv_put_dos_date3((char *)req->outbuf,smb_vwv1,mtime & ~1);
1140         } else {
1141                 srv_put_dos_date3((char *)req->outbuf,smb_vwv1,mtime);
1142         }
1143         SIVAL(req->outbuf,smb_vwv3,(uint32)size);
1144
1145         if (Protocol >= PROTOCOL_NT1) {
1146                 SSVAL(req->outbuf, smb_flg2,
1147                       SVAL(req->outbuf, smb_flg2) | FLAGS2_IS_LONG_NAME);
1148         }
1149
1150         DEBUG(3,("reply_getatr: name=%s mode=%d size=%u\n",
1151                  smb_fname_str_dbg(smb_fname), mode, (unsigned int)size));
1152
1153  out:
1154         TALLOC_FREE(smb_fname);
1155         TALLOC_FREE(fname);
1156         END_PROFILE(SMBgetatr);
1157         return;
1158 }
1159
1160 /****************************************************************************
1161  Reply to a setatr.
1162 ****************************************************************************/
1163
1164 void reply_setatr(struct smb_request *req)
1165 {
1166         struct smb_file_time ft;
1167         connection_struct *conn = req->conn;
1168         struct smb_filename *smb_fname = NULL;
1169         char *fname = NULL;
1170         int mode;
1171         time_t mtime;
1172         const char *p;
1173         NTSTATUS status;
1174         TALLOC_CTX *ctx = talloc_tos();
1175
1176         START_PROFILE(SMBsetatr);
1177
1178         ZERO_STRUCT(ft);
1179
1180         if (req->wct < 2) {
1181                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1182                 goto out;
1183         }
1184
1185         p = (const char *)req->buf + 1;
1186         p += srvstr_get_path_req(ctx, req, &fname, p, STR_TERMINATE, &status);
1187         if (!NT_STATUS_IS_OK(status)) {
1188                 reply_nterror(req, status);
1189                 goto out;
1190         }
1191
1192         status = filename_convert(ctx,
1193                                 conn,
1194                                 req->flags2 & FLAGS2_DFS_PATHNAMES,
1195                                 fname,
1196                                 &smb_fname,
1197                                 NULL);
1198         if (!NT_STATUS_IS_OK(status)) {
1199                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1200                         reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1201                                         ERRSRV, ERRbadpath);
1202                         goto out;
1203                 }
1204                 reply_nterror(req, status);
1205                 goto out;
1206         }
1207
1208         if (smb_fname->base_name[0] == '.' &&
1209             smb_fname->base_name[1] == '\0') {
1210                 /*
1211                  * Not sure here is the right place to catch this
1212                  * condition. Might be moved to somewhere else later -- vl
1213                  */
1214                 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1215                 goto out;
1216         }
1217
1218         mode = SVAL(req->vwv+0, 0);
1219         mtime = srv_make_unix_date3(req->vwv+1);
1220
1221         ft.mtime = convert_time_t_to_timespec(mtime);
1222         status = smb_set_file_time(conn, NULL, smb_fname, &ft, true);
1223         if (!NT_STATUS_IS_OK(status)) {
1224                 reply_nterror(req, status);
1225                 goto out;
1226         }
1227
1228         if (mode != FILE_ATTRIBUTE_NORMAL) {
1229                 if (VALID_STAT_OF_DIR(smb_fname->st))
1230                         mode |= aDIR;
1231                 else
1232                         mode &= ~aDIR;
1233
1234                 if (file_set_dosmode(conn, smb_fname, mode, NULL,
1235                                      false) != 0) {
1236                         reply_nterror(req, map_nt_error_from_unix(errno));
1237                         goto out;
1238                 }
1239         }
1240
1241         reply_outbuf(req, 0, 0);
1242
1243         DEBUG(3, ("setatr name=%s mode=%d\n", smb_fname_str_dbg(smb_fname),
1244                  mode));
1245  out:
1246         TALLOC_FREE(smb_fname);
1247         END_PROFILE(SMBsetatr);
1248         return;
1249 }
1250
1251 /****************************************************************************
1252  Reply to a dskattr.
1253 ****************************************************************************/
1254
1255 void reply_dskattr(struct smb_request *req)
1256 {
1257         connection_struct *conn = req->conn;
1258         uint64_t dfree,dsize,bsize;
1259         START_PROFILE(SMBdskattr);
1260
1261         if (get_dfree_info(conn,".",True,&bsize,&dfree,&dsize) == (uint64_t)-1) {
1262                 reply_nterror(req, map_nt_error_from_unix(errno));
1263                 END_PROFILE(SMBdskattr);
1264                 return;
1265         }
1266
1267         reply_outbuf(req, 5, 0);
1268
1269         if (Protocol <= PROTOCOL_LANMAN2) {
1270                 double total_space, free_space;
1271                 /* we need to scale this to a number that DOS6 can handle. We
1272                    use floating point so we can handle large drives on systems
1273                    that don't have 64 bit integers 
1274
1275                    we end up displaying a maximum of 2G to DOS systems
1276                 */
1277                 total_space = dsize * (double)bsize;
1278                 free_space = dfree * (double)bsize;
1279
1280                 dsize = (uint64_t)((total_space+63*512) / (64*512));
1281                 dfree = (uint64_t)((free_space+63*512) / (64*512));
1282
1283                 if (dsize > 0xFFFF) dsize = 0xFFFF;
1284                 if (dfree > 0xFFFF) dfree = 0xFFFF;
1285
1286                 SSVAL(req->outbuf,smb_vwv0,dsize);
1287                 SSVAL(req->outbuf,smb_vwv1,64); /* this must be 64 for dos systems */
1288                 SSVAL(req->outbuf,smb_vwv2,512); /* and this must be 512 */
1289                 SSVAL(req->outbuf,smb_vwv3,dfree);
1290         } else {
1291                 SSVAL(req->outbuf,smb_vwv0,dsize);
1292                 SSVAL(req->outbuf,smb_vwv1,bsize/512);
1293                 SSVAL(req->outbuf,smb_vwv2,512);
1294                 SSVAL(req->outbuf,smb_vwv3,dfree);
1295         }
1296
1297         DEBUG(3,("dskattr dfree=%d\n", (unsigned int)dfree));
1298
1299         END_PROFILE(SMBdskattr);
1300         return;
1301 }
1302
1303 /*
1304  * Utility function to split the filename from the directory.
1305  */
1306 static NTSTATUS split_fname_dir_mask(TALLOC_CTX *ctx, const char *fname_in,
1307                                      char **fname_dir_out,
1308                                      char **fname_mask_out)
1309 {
1310         const char *p = NULL;
1311         char *fname_dir = NULL;
1312         char *fname_mask = NULL;
1313
1314         p = strrchr_m(fname_in, '/');
1315         if (!p) {
1316                 fname_dir = talloc_strdup(ctx, ".");
1317                 fname_mask = talloc_strdup(ctx, fname_in);
1318         } else {
1319                 fname_dir = talloc_strndup(ctx, fname_in,
1320                     PTR_DIFF(p, fname_in));
1321                 fname_mask = talloc_strdup(ctx, p+1);
1322         }
1323
1324         if (!fname_dir || !fname_mask) {
1325                 TALLOC_FREE(fname_dir);
1326                 TALLOC_FREE(fname_mask);
1327                 return NT_STATUS_NO_MEMORY;
1328         }
1329
1330         *fname_dir_out = fname_dir;
1331         *fname_mask_out = fname_mask;
1332         return NT_STATUS_OK;
1333 }
1334
1335 /****************************************************************************
1336  Reply to a search.
1337  Can be called from SMBsearch, SMBffirst or SMBfunique.
1338 ****************************************************************************/
1339
1340 void reply_search(struct smb_request *req)
1341 {
1342         connection_struct *conn = req->conn;
1343         char *path = NULL;
1344         const char *mask = NULL;
1345         char *directory = NULL;
1346         char *fname = NULL;
1347         SMB_OFF_T size;
1348         uint32 mode;
1349         struct timespec date;
1350         uint32 dirtype;
1351         unsigned int numentries = 0;
1352         unsigned int maxentries = 0;
1353         bool finished = False;
1354         const char *p;
1355         int status_len;
1356         char status[21];
1357         int dptr_num= -1;
1358         bool check_descend = False;
1359         bool expect_close = False;
1360         NTSTATUS nt_status;
1361         bool mask_contains_wcard = False;
1362         bool allow_long_path_components = (req->flags2 & FLAGS2_LONG_PATH_COMPONENTS) ? True : False;
1363         TALLOC_CTX *ctx = talloc_tos();
1364         bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
1365
1366         START_PROFILE(SMBsearch);
1367
1368         if (req->wct < 2) {
1369                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1370                 END_PROFILE(SMBsearch);
1371                 return;
1372         }
1373
1374         if (lp_posix_pathnames()) {
1375                 reply_unknown_new(req, req->cmd);
1376                 END_PROFILE(SMBsearch);
1377                 return;
1378         }
1379
1380         /* If we were called as SMBffirst then we must expect close. */
1381         if(req->cmd == SMBffirst) {
1382                 expect_close = True;
1383         }
1384
1385         reply_outbuf(req, 1, 3);
1386         maxentries = SVAL(req->vwv+0, 0);
1387         dirtype = SVAL(req->vwv+1, 0);
1388         p = (const char *)req->buf + 1;
1389         p += srvstr_get_path_req_wcard(ctx, req, &path, p, STR_TERMINATE,
1390                                        &nt_status, &mask_contains_wcard);
1391         if (!NT_STATUS_IS_OK(nt_status)) {
1392                 reply_nterror(req, nt_status);
1393                 END_PROFILE(SMBsearch);
1394                 return;
1395         }
1396
1397         p++;
1398         status_len = SVAL(p, 0);
1399         p += 2;
1400
1401         /* dirtype &= ~aDIR; */
1402
1403         if (status_len == 0) {
1404                 struct smb_filename *smb_fname = NULL;
1405
1406                 nt_status = resolve_dfspath_wcard(ctx, conn,
1407                                           req->flags2 & FLAGS2_DFS_PATHNAMES,
1408                                           path,
1409                                           &path,
1410                                           &mask_contains_wcard);
1411                 if (!NT_STATUS_IS_OK(nt_status)) {
1412                         if (NT_STATUS_EQUAL(nt_status,NT_STATUS_PATH_NOT_COVERED)) {
1413                                 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1414                                                 ERRSRV, ERRbadpath);
1415                                 END_PROFILE(SMBsearch);
1416                                 return;
1417                         }
1418                         reply_nterror(req, nt_status);
1419                         END_PROFILE(SMBsearch);
1420                         return;
1421                 }
1422
1423                 nt_status = unix_convert(ctx, conn, path, &smb_fname,
1424                                          UCF_ALLOW_WCARD_LCOMP);
1425                 if (!NT_STATUS_IS_OK(nt_status)) {
1426                         reply_nterror(req, nt_status);
1427                         END_PROFILE(SMBsearch);
1428                         return;
1429                 }
1430
1431                 nt_status = get_full_smb_filename(ctx, smb_fname, &directory);
1432                 TALLOC_FREE(smb_fname);
1433                 if (!NT_STATUS_IS_OK(nt_status)) {
1434                         reply_nterror(req, nt_status);
1435                         END_PROFILE(SMBsearch);
1436                         return;
1437                 }
1438
1439                 nt_status = check_name(conn, directory);
1440                 if (!NT_STATUS_IS_OK(nt_status)) {
1441                         reply_nterror(req, nt_status);
1442                         END_PROFILE(SMBsearch);
1443                         return;
1444                 }
1445
1446                 p = strrchr_m(directory,'/');
1447                 if ((p != NULL) && (*directory != '/')) {
1448                         mask = p + 1;
1449                         directory = talloc_strndup(ctx, directory,
1450                                                    PTR_DIFF(p, directory));
1451                 } else {
1452                         mask = directory;
1453                         directory = talloc_strdup(ctx,".");
1454                 }
1455
1456                 if (!directory) {
1457                         reply_nterror(req, NT_STATUS_NO_MEMORY);
1458                         END_PROFILE(SMBsearch);
1459                         return;
1460                 }
1461
1462                 memset((char *)status,'\0',21);
1463                 SCVAL(status,0,(dirtype & 0x1F));
1464
1465                 nt_status = dptr_create(conn,
1466                                         directory,
1467                                         True,
1468                                         expect_close,
1469                                         req->smbpid,
1470                                         mask,
1471                                         mask_contains_wcard,
1472                                         dirtype,
1473                                         &conn->dirptr);
1474                 if (!NT_STATUS_IS_OK(nt_status)) {
1475                         reply_nterror(req, nt_status);
1476                         END_PROFILE(SMBsearch);
1477                         return;
1478                 }
1479                 dptr_num = dptr_dnum(conn->dirptr);
1480         } else {
1481                 int status_dirtype;
1482
1483                 memcpy(status,p,21);
1484                 status_dirtype = CVAL(status,0) & 0x1F;
1485                 if (status_dirtype != (dirtype & 0x1F)) {
1486                         dirtype = status_dirtype;
1487                 }
1488
1489                 conn->dirptr = dptr_fetch(status+12,&dptr_num);
1490                 if (!conn->dirptr) {
1491                         goto SearchEmpty;
1492                 }
1493                 string_set(&conn->dirpath,dptr_path(dptr_num));
1494                 mask = dptr_wcard(dptr_num);
1495                 if (!mask) {
1496                         goto SearchEmpty;
1497                 }
1498                 /*
1499                  * For a 'continue' search we have no string. So
1500                  * check from the initial saved string.
1501                  */
1502                 mask_contains_wcard = ms_has_wild(mask);
1503                 dirtype = dptr_attr(dptr_num);
1504         }
1505
1506         DEBUG(4,("dptr_num is %d\n",dptr_num));
1507
1508         /* Initialize per SMBsearch/SMBffirst/SMBfunique operation data */
1509         dptr_init_search_op(conn->dirptr);
1510
1511         if ((dirtype&0x1F) == aVOLID) {
1512                 char buf[DIR_STRUCT_SIZE];
1513                 memcpy(buf,status,21);
1514                 if (!make_dir_struct(ctx,buf,"???????????",volume_label(SNUM(conn)),
1515                                 0,aVOLID,0,!allow_long_path_components)) {
1516                         reply_nterror(req, NT_STATUS_NO_MEMORY);
1517                         END_PROFILE(SMBsearch);
1518                         return;
1519                 }
1520                 dptr_fill(buf+12,dptr_num);
1521                 if (dptr_zero(buf+12) && (status_len==0)) {
1522                         numentries = 1;
1523                 } else {
1524                         numentries = 0;
1525                 }
1526                 if (message_push_blob(&req->outbuf,
1527                                       data_blob_const(buf, sizeof(buf)))
1528                     == -1) {
1529                         reply_nterror(req, NT_STATUS_NO_MEMORY);
1530                         END_PROFILE(SMBsearch);
1531                         return;
1532                 }
1533         } else {
1534                 unsigned int i;
1535                 maxentries = MIN(
1536                         maxentries,
1537                         ((BUFFER_SIZE -
1538                           ((uint8 *)smb_buf(req->outbuf) + 3 - req->outbuf))
1539                          /DIR_STRUCT_SIZE));
1540
1541                 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
1542                         conn->dirpath,lp_dontdescend(SNUM(conn))));
1543                 if (in_list(conn->dirpath, lp_dontdescend(SNUM(conn)),True)) {
1544                         check_descend = True;
1545                 }
1546
1547                 for (i=numentries;(i<maxentries) && !finished;i++) {
1548                         finished = !get_dir_entry(ctx,
1549                                                   conn,
1550                                                   mask,
1551                                                   dirtype,
1552                                                   &fname,
1553                                                   &size,
1554                                                   &mode,
1555                                                   &date,
1556                                                   check_descend,
1557                                                   ask_sharemode);
1558                         if (!finished) {
1559                                 char buf[DIR_STRUCT_SIZE];
1560                                 memcpy(buf,status,21);
1561                                 if (!make_dir_struct(ctx,
1562                                                 buf,
1563                                                 mask,
1564                                                 fname,
1565                                                 size,
1566                                                 mode,
1567                                                 convert_timespec_to_time_t(date),
1568                                                 !allow_long_path_components)) {
1569                                         reply_nterror(req, NT_STATUS_NO_MEMORY);
1570                                         END_PROFILE(SMBsearch);
1571                                         return;
1572                                 }
1573                                 if (!dptr_fill(buf+12,dptr_num)) {
1574                                         break;
1575                                 }
1576                                 if (message_push_blob(&req->outbuf,
1577                                                       data_blob_const(buf, sizeof(buf)))
1578                                     == -1) {
1579                                         reply_nterror(req, NT_STATUS_NO_MEMORY);
1580                                         END_PROFILE(SMBsearch);
1581                                         return;
1582                                 }
1583                                 numentries++;
1584                         }
1585                 }
1586         }
1587
1588   SearchEmpty:
1589
1590         /* If we were called as SMBffirst with smb_search_id == NULL
1591                 and no entries were found then return error and close dirptr 
1592                 (X/Open spec) */
1593
1594         if (numentries == 0) {
1595                 dptr_close(&dptr_num);
1596         } else if(expect_close && status_len == 0) {
1597                 /* Close the dptr - we know it's gone */
1598                 dptr_close(&dptr_num);
1599         }
1600
1601         /* If we were called as SMBfunique, then we can close the dirptr now ! */
1602         if(dptr_num >= 0 && req->cmd == SMBfunique) {
1603                 dptr_close(&dptr_num);
1604         }
1605
1606         if ((numentries == 0) && !mask_contains_wcard) {
1607                 reply_botherror(req, STATUS_NO_MORE_FILES, ERRDOS, ERRnofiles);
1608                 END_PROFILE(SMBsearch);
1609                 return;
1610         }
1611
1612         SSVAL(req->outbuf,smb_vwv0,numentries);
1613         SSVAL(req->outbuf,smb_vwv1,3 + numentries * DIR_STRUCT_SIZE);
1614         SCVAL(smb_buf(req->outbuf),0,5);
1615         SSVAL(smb_buf(req->outbuf),1,numentries*DIR_STRUCT_SIZE);
1616
1617         /* The replies here are never long name. */
1618         SSVAL(req->outbuf, smb_flg2,
1619               SVAL(req->outbuf, smb_flg2) & (~FLAGS2_IS_LONG_NAME));
1620         if (!allow_long_path_components) {
1621                 SSVAL(req->outbuf, smb_flg2,
1622                       SVAL(req->outbuf, smb_flg2)
1623                       & (~FLAGS2_LONG_PATH_COMPONENTS));
1624         }
1625
1626         /* This SMB *always* returns ASCII names. Remove the unicode bit in flags2. */
1627         SSVAL(req->outbuf, smb_flg2,
1628               (SVAL(req->outbuf, smb_flg2) & (~FLAGS2_UNICODE_STRINGS)));
1629
1630         if (!directory) {
1631                 directory = dptr_path(dptr_num);
1632         }
1633
1634         DEBUG(4,("%s mask=%s path=%s dtype=%d nument=%u of %u\n",
1635                 smb_fn_name(req->cmd),
1636                 mask,
1637                 directory ? directory : "./",
1638                 dirtype,
1639                 numentries,
1640                 maxentries ));
1641
1642         END_PROFILE(SMBsearch);
1643         return;
1644 }
1645
1646 /****************************************************************************
1647  Reply to a fclose (stop directory search).
1648 ****************************************************************************/
1649
1650 void reply_fclose(struct smb_request *req)
1651 {
1652         int status_len;
1653         char status[21];
1654         int dptr_num= -2;
1655         const char *p;
1656         char *path = NULL;
1657         NTSTATUS err;
1658         bool path_contains_wcard = False;
1659         TALLOC_CTX *ctx = talloc_tos();
1660
1661         START_PROFILE(SMBfclose);
1662
1663         if (lp_posix_pathnames()) {
1664                 reply_unknown_new(req, req->cmd);
1665                 END_PROFILE(SMBfclose);
1666                 return;
1667         }
1668
1669         p = (const char *)req->buf + 1;
1670         p += srvstr_get_path_req_wcard(ctx, req, &path, p, STR_TERMINATE,
1671                                        &err, &path_contains_wcard);
1672         if (!NT_STATUS_IS_OK(err)) {
1673                 reply_nterror(req, err);
1674                 END_PROFILE(SMBfclose);
1675                 return;
1676         }
1677         p++;
1678         status_len = SVAL(p,0);
1679         p += 2;
1680
1681         if (status_len == 0) {
1682                 reply_doserror(req, ERRSRV, ERRsrverror);
1683                 END_PROFILE(SMBfclose);
1684                 return;
1685         }
1686
1687         memcpy(status,p,21);
1688
1689         if(dptr_fetch(status+12,&dptr_num)) {
1690                 /*  Close the dptr - we know it's gone */
1691                 dptr_close(&dptr_num);
1692         }
1693
1694         reply_outbuf(req, 1, 0);
1695         SSVAL(req->outbuf,smb_vwv0,0);
1696
1697         DEBUG(3,("search close\n"));
1698
1699         END_PROFILE(SMBfclose);
1700         return;
1701 }
1702
1703 /****************************************************************************
1704  Reply to an open.
1705 ****************************************************************************/
1706
1707 void reply_open(struct smb_request *req)
1708 {
1709         connection_struct *conn = req->conn;
1710         struct smb_filename *smb_fname = NULL;
1711         char *fname = NULL;
1712         uint32 fattr=0;
1713         SMB_OFF_T size = 0;
1714         time_t mtime=0;
1715         int info;
1716         files_struct *fsp;
1717         int oplock_request;
1718         int deny_mode;
1719         uint32 dos_attr;
1720         uint32 access_mask;
1721         uint32 share_mode;
1722         uint32 create_disposition;
1723         uint32 create_options = 0;
1724         NTSTATUS status;
1725         bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
1726         TALLOC_CTX *ctx = talloc_tos();
1727
1728         START_PROFILE(SMBopen);
1729
1730         if (req->wct < 2) {
1731                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1732                 goto out;
1733         }
1734
1735         oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
1736         deny_mode = SVAL(req->vwv+0, 0);
1737         dos_attr = SVAL(req->vwv+1, 0);
1738
1739         srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf+1,
1740                             STR_TERMINATE, &status);
1741         if (!NT_STATUS_IS_OK(status)) {
1742                 reply_nterror(req, status);
1743                 goto out;
1744         }
1745
1746         status = filename_convert(ctx,
1747                                 conn,
1748                                 req->flags2 & FLAGS2_DFS_PATHNAMES,
1749                                 fname,
1750                                 &smb_fname,
1751                                 NULL);
1752         if (!NT_STATUS_IS_OK(status)) {
1753                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1754                         reply_botherror(req,
1755                                         NT_STATUS_PATH_NOT_COVERED,
1756                                         ERRSRV, ERRbadpath);
1757                         goto out;
1758                 }
1759                 reply_nterror(req, status);
1760                 goto out;
1761         }
1762
1763         if (!map_open_params_to_ntcreate(
1764                     smb_fname->base_name, deny_mode, OPENX_FILE_EXISTS_OPEN,
1765                     &access_mask, &share_mode, &create_disposition,
1766                     &create_options)) {
1767                 reply_nterror(req, NT_STATUS_DOS(ERRDOS, ERRbadaccess));
1768                 goto out;
1769         }
1770
1771         status = SMB_VFS_CREATE_FILE(
1772                 conn,                                   /* conn */
1773                 req,                                    /* req */
1774                 0,                                      /* root_dir_fid */
1775                 smb_fname,                              /* fname */
1776                 access_mask,                            /* access_mask */
1777                 share_mode,                             /* share_access */
1778                 create_disposition,                     /* create_disposition*/
1779                 create_options,                         /* create_options */
1780                 dos_attr,                               /* file_attributes */
1781                 oplock_request,                         /* oplock_request */
1782                 0,                                      /* allocation_size */
1783                 NULL,                                   /* sd */
1784                 NULL,                                   /* ea_list */
1785                 &fsp,                                   /* result */
1786                 &info);                                 /* pinfo */
1787
1788         if (!NT_STATUS_IS_OK(status)) {
1789                 if (open_was_deferred(req->mid)) {
1790                         /* We have re-scheduled this call. */
1791                         goto out;
1792                 }
1793                 reply_openerror(req, status);
1794                 goto out;
1795         }
1796
1797         size = smb_fname->st.st_ex_size;
1798         fattr = dos_mode(conn, smb_fname);
1799
1800         /* Deal with other possible opens having a modified
1801            write time. JRA. */
1802         if (ask_sharemode) {
1803                 struct timespec write_time_ts;
1804
1805                 ZERO_STRUCT(write_time_ts);
1806                 get_file_infos(fsp->file_id, NULL, &write_time_ts);
1807                 if (!null_timespec(write_time_ts)) {
1808                         update_stat_ex_mtime(&smb_fname->st, write_time_ts);
1809                 }
1810         }
1811
1812         mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
1813
1814         if (fattr & aDIR) {
1815                 DEBUG(3,("attempt to open a directory %s\n",fsp->fsp_name));
1816                 close_file(req, fsp, ERROR_CLOSE);
1817                 reply_doserror(req, ERRDOS,ERRnoaccess);
1818                 goto out;
1819         }
1820
1821         reply_outbuf(req, 7, 0);
1822         SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
1823         SSVAL(req->outbuf,smb_vwv1,fattr);
1824         if(lp_dos_filetime_resolution(SNUM(conn)) ) {
1825                 srv_put_dos_date3((char *)req->outbuf,smb_vwv2,mtime & ~1);
1826         } else {
1827                 srv_put_dos_date3((char *)req->outbuf,smb_vwv2,mtime);
1828         }
1829         SIVAL(req->outbuf,smb_vwv4,(uint32)size);
1830         SSVAL(req->outbuf,smb_vwv6,deny_mode);
1831
1832         if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1833                 SCVAL(req->outbuf,smb_flg,
1834                       CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1835         }
1836
1837         if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1838                 SCVAL(req->outbuf,smb_flg,
1839                       CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1840         }
1841  out:
1842         TALLOC_FREE(smb_fname);
1843         END_PROFILE(SMBopen);
1844         return;
1845 }
1846
1847 /****************************************************************************
1848  Reply to an open and X.
1849 ****************************************************************************/
1850
1851 void reply_open_and_X(struct smb_request *req)
1852 {
1853         connection_struct *conn = req->conn;
1854         struct smb_filename *smb_fname = NULL;
1855         char *fname = NULL;
1856         uint16 open_flags;
1857         int deny_mode;
1858         uint32 smb_attr;
1859         /* Breakout the oplock request bits so we can set the
1860                 reply bits separately. */
1861         int ex_oplock_request;
1862         int core_oplock_request;
1863         int oplock_request;
1864 #if 0
1865         int smb_sattr = SVAL(req->vwv+4, 0);
1866         uint32 smb_time = make_unix_date3(req->vwv+6);
1867 #endif
1868         int smb_ofun;
1869         uint32 fattr=0;
1870         int mtime=0;
1871         int smb_action = 0;
1872         files_struct *fsp;
1873         NTSTATUS status;
1874         uint64_t allocation_size;
1875         ssize_t retval = -1;
1876         uint32 access_mask;
1877         uint32 share_mode;
1878         uint32 create_disposition;
1879         uint32 create_options = 0;
1880         TALLOC_CTX *ctx = talloc_tos();
1881
1882         START_PROFILE(SMBopenX);
1883
1884         if (req->wct < 15) {
1885                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1886                 goto out;
1887         }
1888
1889         open_flags = SVAL(req->vwv+2, 0);
1890         deny_mode = SVAL(req->vwv+3, 0);
1891         smb_attr = SVAL(req->vwv+5, 0);
1892         ex_oplock_request = EXTENDED_OPLOCK_REQUEST(req->inbuf);
1893         core_oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
1894         oplock_request = ex_oplock_request | core_oplock_request;
1895         smb_ofun = SVAL(req->vwv+8, 0);
1896         allocation_size = (uint64_t)IVAL(req->vwv+9, 0);
1897
1898         /* If it's an IPC, pass off the pipe handler. */
1899         if (IS_IPC(conn)) {
1900                 if (lp_nt_pipe_support()) {
1901                         reply_open_pipe_and_X(conn, req);
1902                 } else {
1903                         reply_doserror(req, ERRSRV, ERRaccess);
1904                 }
1905                 goto out;
1906         }
1907
1908         /* XXXX we need to handle passed times, sattr and flags */
1909         srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf,
1910                         STR_TERMINATE, &status);
1911         if (!NT_STATUS_IS_OK(status)) {
1912                 reply_nterror(req, status);
1913                 goto out;
1914         }
1915
1916         status = filename_convert(ctx,
1917                                 conn,
1918                                 req->flags2 & FLAGS2_DFS_PATHNAMES,
1919                                 fname,
1920                                 &smb_fname,
1921                                 NULL);
1922         if (!NT_STATUS_IS_OK(status)) {
1923                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1924                         reply_botherror(req,
1925                                         NT_STATUS_PATH_NOT_COVERED,
1926                                         ERRSRV, ERRbadpath);
1927                         goto out;
1928                 }
1929                 reply_nterror(req, status);
1930                 goto out;
1931         }
1932
1933         if (!map_open_params_to_ntcreate(
1934                     smb_fname->base_name, deny_mode, smb_ofun, &access_mask,
1935                     &share_mode, &create_disposition, &create_options)) {
1936                 reply_nterror(req, NT_STATUS_DOS(ERRDOS, ERRbadaccess));
1937                 goto out;
1938         }
1939
1940         status = SMB_VFS_CREATE_FILE(
1941                 conn,                                   /* conn */
1942                 req,                                    /* req */
1943                 0,                                      /* root_dir_fid */
1944                 smb_fname,                              /* fname */
1945                 access_mask,                            /* access_mask */
1946                 share_mode,                             /* share_access */
1947                 create_disposition,                     /* create_disposition*/
1948                 create_options,                         /* create_options */
1949                 smb_attr,                               /* file_attributes */
1950                 oplock_request,                         /* oplock_request */
1951                 0,                                      /* allocation_size */
1952                 NULL,                                   /* sd */
1953                 NULL,                                   /* ea_list */
1954                 &fsp,                                   /* result */
1955                 &smb_action);                           /* pinfo */
1956
1957         if (!NT_STATUS_IS_OK(status)) {
1958                 if (open_was_deferred(req->mid)) {
1959                         /* We have re-scheduled this call. */
1960                         goto out;
1961                 }
1962                 reply_openerror(req, status);
1963                 goto out;
1964         }
1965
1966         /* Setting the "size" field in vwv9 and vwv10 causes the file to be set to this size,
1967            if the file is truncated or created. */
1968         if (((smb_action == FILE_WAS_CREATED) || (smb_action == FILE_WAS_OVERWRITTEN)) && allocation_size) {
1969                 fsp->initial_allocation_size = smb_roundup(fsp->conn, allocation_size);
1970                 if (vfs_allocate_file_space(fsp, fsp->initial_allocation_size) == -1) {
1971                         close_file(req, fsp, ERROR_CLOSE);
1972                         reply_nterror(req, NT_STATUS_DISK_FULL);
1973                         goto out;
1974                 }
1975                 retval = vfs_set_filelen(fsp, (SMB_OFF_T)allocation_size);
1976                 if (retval < 0) {
1977                         close_file(req, fsp, ERROR_CLOSE);
1978                         reply_nterror(req, NT_STATUS_DISK_FULL);
1979                         goto out;
1980                 }
1981                 smb_fname->st.st_ex_size =
1982                     SMB_VFS_GET_ALLOC_SIZE(conn, fsp, &smb_fname->st);
1983         }
1984
1985         fattr = dos_mode(conn, smb_fname);
1986         mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
1987         if (fattr & aDIR) {
1988                 close_file(req, fsp, ERROR_CLOSE);
1989                 reply_doserror(req, ERRDOS, ERRnoaccess);
1990                 goto out;
1991         }
1992
1993         /* If the caller set the extended oplock request bit
1994                 and we granted one (by whatever means) - set the
1995                 correct bit for extended oplock reply.
1996         */
1997
1998         if (ex_oplock_request && lp_fake_oplocks(SNUM(conn))) {
1999                 smb_action |= EXTENDED_OPLOCK_GRANTED;
2000         }
2001
2002         if(ex_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2003                 smb_action |= EXTENDED_OPLOCK_GRANTED;
2004         }
2005
2006         /* If the caller set the core oplock request bit
2007                 and we granted one (by whatever means) - set the
2008                 correct bit for core oplock reply.
2009         */
2010
2011         if (open_flags & EXTENDED_RESPONSE_REQUIRED) {
2012                 reply_outbuf(req, 19, 0);
2013         } else {
2014                 reply_outbuf(req, 15, 0);
2015         }
2016
2017         if (core_oplock_request && lp_fake_oplocks(SNUM(conn))) {
2018                 SCVAL(req->outbuf, smb_flg,
2019                       CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2020         }
2021
2022         if(core_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2023                 SCVAL(req->outbuf, smb_flg,
2024                       CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2025         }
2026
2027         SSVAL(req->outbuf,smb_vwv2,fsp->fnum);
2028         SSVAL(req->outbuf,smb_vwv3,fattr);
2029         if(lp_dos_filetime_resolution(SNUM(conn)) ) {
2030                 srv_put_dos_date3((char *)req->outbuf,smb_vwv4,mtime & ~1);
2031         } else {
2032                 srv_put_dos_date3((char *)req->outbuf,smb_vwv4,mtime);
2033         }
2034         SIVAL(req->outbuf,smb_vwv6,(uint32)smb_fname->st.st_ex_size);
2035         SSVAL(req->outbuf,smb_vwv8,GET_OPENX_MODE(deny_mode));
2036         SSVAL(req->outbuf,smb_vwv11,smb_action);
2037
2038         if (open_flags & EXTENDED_RESPONSE_REQUIRED) {
2039                 SIVAL(req->outbuf, smb_vwv15, STD_RIGHT_ALL_ACCESS);
2040         }
2041
2042         chain_reply(req);
2043  out:
2044         TALLOC_FREE(smb_fname);
2045         END_PROFILE(SMBopenX);
2046         return;
2047 }
2048
2049 /****************************************************************************
2050  Reply to a SMBulogoffX.
2051 ****************************************************************************/
2052
2053 void reply_ulogoffX(struct smb_request *req)
2054 {
2055         struct smbd_server_connection *sconn = smbd_server_conn;
2056         user_struct *vuser;
2057
2058         START_PROFILE(SMBulogoffX);
2059
2060         vuser = get_valid_user_struct(sconn, req->vuid);
2061
2062         if(vuser == NULL) {
2063                 DEBUG(3,("ulogoff, vuser id %d does not map to user.\n",
2064                          req->vuid));
2065         }
2066
2067         /* in user level security we are supposed to close any files
2068                 open by this user */
2069         if ((vuser != NULL) && (lp_security() != SEC_SHARE)) {
2070                 file_close_user(req->vuid);
2071         }
2072
2073         invalidate_vuid(sconn, req->vuid);
2074
2075         reply_outbuf(req, 2, 0);
2076
2077         DEBUG( 3, ( "ulogoffX vuid=%d\n", req->vuid ) );
2078
2079         END_PROFILE(SMBulogoffX);
2080         req->vuid = UID_FIELD_INVALID;
2081         chain_reply(req);
2082 }
2083
2084 /****************************************************************************
2085  Reply to a mknew or a create.
2086 ****************************************************************************/
2087
2088 void reply_mknew(struct smb_request *req)
2089 {
2090         connection_struct *conn = req->conn;
2091         struct smb_filename *smb_fname = NULL;
2092         char *fname = NULL;
2093         uint32 fattr = 0;
2094         struct smb_file_time ft;
2095         files_struct *fsp;
2096         int oplock_request = 0;
2097         NTSTATUS status;
2098         uint32 access_mask = FILE_GENERIC_READ | FILE_GENERIC_WRITE;
2099         uint32 share_mode = FILE_SHARE_READ|FILE_SHARE_WRITE;
2100         uint32 create_disposition;
2101         uint32 create_options = 0;
2102         TALLOC_CTX *ctx = talloc_tos();
2103
2104         START_PROFILE(SMBcreate);
2105         ZERO_STRUCT(ft);
2106
2107         if (req->wct < 3) {
2108                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2109                 goto out;
2110         }
2111
2112         fattr = SVAL(req->vwv+0, 0);
2113         oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
2114
2115         /* mtime. */
2116         ft.mtime = convert_time_t_to_timespec(srv_make_unix_date3(req->vwv+1));
2117
2118         srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf + 1,
2119                             STR_TERMINATE, &status);
2120         if (!NT_STATUS_IS_OK(status)) {
2121                 reply_nterror(req, status);
2122                 goto out;
2123         }
2124
2125         status = filename_convert(ctx,
2126                                 conn,
2127                                 req->flags2 & FLAGS2_DFS_PATHNAMES,
2128                                 fname,
2129                                 &smb_fname,
2130                                 NULL);
2131         if (!NT_STATUS_IS_OK(status)) {
2132                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2133                         reply_botherror(req,
2134                                         NT_STATUS_PATH_NOT_COVERED,
2135                                         ERRSRV, ERRbadpath);
2136                         goto out;
2137                 }
2138                 reply_nterror(req, status);
2139                 goto out;
2140         }
2141
2142         if (fattr & aVOLID) {
2143                 DEBUG(0,("Attempt to create file (%s) with volid set - "
2144                          "please report this\n",
2145                          smb_fname_str_dbg(smb_fname)));
2146         }
2147
2148         if(req->cmd == SMBmknew) {
2149                 /* We should fail if file exists. */
2150                 create_disposition = FILE_CREATE;
2151         } else {
2152                 /* Create if file doesn't exist, truncate if it does. */
2153                 create_disposition = FILE_OVERWRITE_IF;
2154         }
2155
2156         status = SMB_VFS_CREATE_FILE(
2157                 conn,                                   /* conn */
2158                 req,                                    /* req */
2159                 0,                                      /* root_dir_fid */
2160                 smb_fname,                              /* fname */
2161                 access_mask,                            /* access_mask */
2162                 share_mode,                             /* share_access */
2163                 create_disposition,                     /* create_disposition*/
2164                 create_options,                         /* create_options */
2165                 fattr,                                  /* file_attributes */
2166                 oplock_request,                         /* oplock_request */
2167                 0,                                      /* allocation_size */
2168                 NULL,                                   /* sd */
2169                 NULL,                                   /* ea_list */
2170                 &fsp,                                   /* result */
2171                 NULL);                                  /* pinfo */
2172
2173         if (!NT_STATUS_IS_OK(status)) {
2174                 if (open_was_deferred(req->mid)) {
2175                         /* We have re-scheduled this call. */
2176                         goto out;
2177                 }
2178                 reply_openerror(req, status);
2179                 goto out;
2180         }
2181
2182         ft.atime = smb_fname->st.st_ex_atime; /* atime. */
2183         status = smb_set_file_time(conn, fsp, smb_fname, &ft, true);
2184         if (!NT_STATUS_IS_OK(status)) {
2185                 END_PROFILE(SMBcreate);
2186                 goto out;
2187         }
2188
2189         reply_outbuf(req, 1, 0);
2190         SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
2191
2192         if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
2193                 SCVAL(req->outbuf,smb_flg,
2194                                 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2195         }
2196
2197         if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2198                 SCVAL(req->outbuf,smb_flg,
2199                                 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2200         }
2201
2202         DEBUG(2, ("reply_mknew: file %s\n", smb_fname_str_dbg(smb_fname)));
2203         DEBUG(3, ("reply_mknew %s fd=%d dmode=0x%x\n",
2204                   smb_fname_str_dbg(smb_fname), fsp->fh->fd,
2205                   (unsigned int)fattr));
2206
2207  out:
2208         TALLOC_FREE(smb_fname);
2209         END_PROFILE(SMBcreate);
2210         return;
2211 }
2212
2213 /****************************************************************************
2214  Reply to a create temporary file.
2215 ****************************************************************************/
2216
2217 void reply_ctemp(struct smb_request *req)
2218 {
2219         connection_struct *conn = req->conn;
2220         struct smb_filename *smb_fname = NULL;
2221         char *fname = NULL;
2222         uint32 fattr;
2223         files_struct *fsp;
2224         int oplock_request;
2225         int tmpfd;
2226         char *s;
2227         NTSTATUS status;
2228         TALLOC_CTX *ctx = talloc_tos();
2229
2230         START_PROFILE(SMBctemp);
2231
2232         if (req->wct < 3) {
2233                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2234                 goto out;
2235         }
2236
2237         fattr = SVAL(req->vwv+0, 0);
2238         oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
2239
2240         srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf+1,
2241                             STR_TERMINATE, &status);
2242         if (!NT_STATUS_IS_OK(status)) {
2243                 reply_nterror(req, status);
2244                 goto out;
2245         }
2246         if (*fname) {
2247                 fname = talloc_asprintf(ctx,
2248                                 "%s/TMXXXXXX",
2249                                 fname);
2250         } else {
2251                 fname = talloc_strdup(ctx, "TMXXXXXX");
2252         }
2253
2254         if (!fname) {
2255                 reply_nterror(req, NT_STATUS_NO_MEMORY);
2256                 goto out;
2257         }
2258
2259         status = filename_convert(ctx, conn,
2260                                 req->flags2 & FLAGS2_DFS_PATHNAMES,
2261                                 fname,
2262                                 &smb_fname,
2263                                 NULL);
2264         if (!NT_STATUS_IS_OK(status)) {
2265                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2266                         reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2267                                         ERRSRV, ERRbadpath);
2268                         goto out;
2269                 }
2270                 reply_nterror(req, status);
2271                 goto out;
2272         }
2273
2274         tmpfd = mkstemp(smb_fname->base_name);
2275         if (tmpfd == -1) {
2276                 reply_nterror(req, map_nt_error_from_unix(errno));
2277                 goto out;
2278         }
2279
2280         SMB_VFS_STAT(conn, smb_fname);
2281
2282         /* We should fail if file does not exist. */
2283         status = SMB_VFS_CREATE_FILE(
2284                 conn,                                   /* conn */
2285                 req,                                    /* req */
2286                 0,                                      /* root_dir_fid */
2287                 smb_fname,                              /* fname */
2288                 FILE_GENERIC_READ | FILE_GENERIC_WRITE, /* access_mask */
2289                 FILE_SHARE_READ | FILE_SHARE_WRITE,     /* share_access */
2290                 FILE_OPEN,                              /* create_disposition*/
2291                 0,                                      /* create_options */
2292                 fattr,                                  /* file_attributes */
2293                 oplock_request,                         /* oplock_request */
2294                 0,                                      /* allocation_size */
2295                 NULL,                                   /* sd */
2296                 NULL,                                   /* ea_list */
2297                 &fsp,                                   /* result */
2298                 NULL);                                  /* pinfo */
2299
2300         /* close fd from mkstemp() */
2301         close(tmpfd);
2302
2303         if (!NT_STATUS_IS_OK(status)) {
2304                 if (open_was_deferred(req->mid)) {
2305                         /* We have re-scheduled this call. */
2306                         goto out;
2307                 }
2308                 reply_openerror(req, status);
2309                 goto out;
2310         }
2311
2312         reply_outbuf(req, 1, 0);
2313         SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
2314
2315         /* the returned filename is relative to the directory */
2316         s = strrchr_m(fsp->fsp_name, '/');
2317         if (!s) {
2318                 s = fsp->fsp_name;
2319         } else {
2320                 s++;
2321         }
2322
2323 #if 0
2324         /* Tested vs W2K3 - this doesn't seem to be here - null terminated filename is the only
2325            thing in the byte section. JRA */
2326         SSVALS(p, 0, -1); /* what is this? not in spec */
2327 #endif
2328         if (message_push_string(&req->outbuf, s, STR_ASCII|STR_TERMINATE)
2329             == -1) {
2330                 reply_nterror(req, NT_STATUS_NO_MEMORY);
2331                 goto out;
2332         }
2333
2334         if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
2335                 SCVAL(req->outbuf, smb_flg,
2336                       CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2337         }
2338
2339         if (EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2340                 SCVAL(req->outbuf, smb_flg,
2341                       CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2342         }
2343
2344         DEBUG( 2, ( "reply_ctemp: created temp file %s\n", fsp->fsp_name ) );
2345         DEBUG( 3, ( "reply_ctemp %s fd=%d umode=0%o\n", fsp->fsp_name,
2346                     fsp->fh->fd, (unsigned int)smb_fname->st.st_ex_mode));
2347  out:
2348         TALLOC_FREE(smb_fname);
2349         END_PROFILE(SMBctemp);
2350         return;
2351 }
2352
2353 /*******************************************************************
2354  Check if a user is allowed to rename a file.
2355 ********************************************************************/
2356
2357 static NTSTATUS can_rename(connection_struct *conn, files_struct *fsp,
2358                            uint16 dirtype, SMB_STRUCT_STAT *pst)
2359 {
2360         struct smb_filename *smb_fname = NULL;
2361         NTSTATUS status;
2362         uint32 fmode;
2363
2364         if (!CAN_WRITE(conn)) {
2365                 return NT_STATUS_MEDIA_WRITE_PROTECTED;
2366         }
2367
2368         status = create_synthetic_smb_fname_split(talloc_tos(), fsp->fsp_name,
2369                                                   pst, &smb_fname);
2370         if (!NT_STATUS_IS_OK(status)) {
2371                 return status;
2372         }
2373
2374         fmode = dos_mode(conn, smb_fname);
2375         TALLOC_FREE(smb_fname);
2376         if ((fmode & ~dirtype) & (aHIDDEN | aSYSTEM)) {
2377                 return NT_STATUS_NO_SUCH_FILE;
2378         }
2379
2380         if (S_ISDIR(pst->st_ex_mode)) {
2381                 if (fsp->posix_open) {
2382                         return NT_STATUS_OK;
2383                 }
2384
2385                 /* If no pathnames are open below this
2386                    directory, allow the rename. */
2387
2388                 if (file_find_subpath(fsp)) {
2389                         return NT_STATUS_ACCESS_DENIED;
2390                 }
2391                 return NT_STATUS_OK;
2392         }
2393
2394         if (fsp->access_mask & (DELETE_ACCESS|FILE_WRITE_ATTRIBUTES)) {
2395                 return NT_STATUS_OK;
2396         }
2397
2398         return NT_STATUS_ACCESS_DENIED;
2399 }
2400
2401 /*******************************************************************
2402  * unlink a file with all relevant access checks
2403  *******************************************************************/
2404
2405 static NTSTATUS do_unlink(connection_struct *conn,
2406                         struct smb_request *req,
2407                         struct smb_filename *smb_fname,
2408                         uint32 dirtype)
2409 {
2410         uint32 fattr;
2411         files_struct *fsp;
2412         uint32 dirtype_orig = dirtype;
2413         NTSTATUS status;
2414
2415         DEBUG(10,("do_unlink: %s, dirtype = %d\n",
2416                   smb_fname_str_dbg(smb_fname),
2417                   dirtype));
2418
2419         if (!CAN_WRITE(conn)) {
2420                 return NT_STATUS_MEDIA_WRITE_PROTECTED;
2421         }
2422
2423         if (SMB_VFS_LSTAT(conn, smb_fname) != 0) {
2424                 return map_nt_error_from_unix(errno);
2425         }
2426
2427         fattr = dos_mode(conn, smb_fname);
2428
2429         if (dirtype & FILE_ATTRIBUTE_NORMAL) {
2430                 dirtype = aDIR|aARCH|aRONLY;
2431         }
2432
2433         dirtype &= (aDIR|aARCH|aRONLY|aHIDDEN|aSYSTEM);
2434         if (!dirtype) {
2435                 return NT_STATUS_NO_SUCH_FILE;
2436         }
2437
2438         if (!dir_check_ftype(conn, fattr, dirtype)) {
2439                 if (fattr & aDIR) {
2440                         return NT_STATUS_FILE_IS_A_DIRECTORY;
2441                 }
2442                 return NT_STATUS_NO_SUCH_FILE;
2443         }
2444
2445         if (dirtype_orig & 0x8000) {
2446                 /* These will never be set for POSIX. */
2447                 return NT_STATUS_NO_SUCH_FILE;
2448         }
2449
2450 #if 0
2451         if ((fattr & dirtype) & FILE_ATTRIBUTE_DIRECTORY) {
2452                 return NT_STATUS_FILE_IS_A_DIRECTORY;
2453         }
2454
2455         if ((fattr & ~dirtype) & (FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM)) {
2456                 return NT_STATUS_NO_SUCH_FILE;
2457         }
2458
2459         if (dirtype & 0xFF00) {
2460                 /* These will never be set for POSIX. */
2461                 return NT_STATUS_NO_SUCH_FILE;
2462         }
2463
2464         dirtype &= 0xFF;
2465         if (!dirtype) {
2466                 return NT_STATUS_NO_SUCH_FILE;
2467         }
2468
2469         /* Can't delete a directory. */
2470         if (fattr & aDIR) {
2471                 return NT_STATUS_FILE_IS_A_DIRECTORY;
2472         }
2473 #endif
2474
2475 #if 0 /* JRATEST */
2476         else if (dirtype & aDIR) /* Asked for a directory and it isn't. */
2477                 return NT_STATUS_OBJECT_NAME_INVALID;
2478 #endif /* JRATEST */
2479
2480         /* Fix for bug #3035 from SATOH Fumiyasu <fumiyas@miraclelinux.com>
2481
2482           On a Windows share, a file with read-only dosmode can be opened with
2483           DELETE_ACCESS. But on a Samba share (delete readonly = no), it
2484           fails with NT_STATUS_CANNOT_DELETE error.
2485
2486           This semantic causes a problem that a user can not
2487           rename a file with read-only dosmode on a Samba share
2488           from a Windows command prompt (i.e. cmd.exe, but can rename
2489           from Windows Explorer).
2490         */
2491
2492         if (!lp_delete_readonly(SNUM(conn))) {
2493                 if (fattr & aRONLY) {
2494                         return NT_STATUS_CANNOT_DELETE;
2495                 }
2496         }
2497
2498         /* On open checks the open itself will check the share mode, so
2499            don't do it here as we'll get it wrong. */
2500
2501         status = SMB_VFS_CREATE_FILE
2502                 (conn,                  /* conn */
2503                  req,                   /* req */
2504                  0,                     /* root_dir_fid */
2505                  smb_fname,             /* fname */
2506                  DELETE_ACCESS,         /* access_mask */
2507                  FILE_SHARE_NONE,       /* share_access */
2508                  FILE_OPEN,             /* create_disposition*/
2509                  FILE_NON_DIRECTORY_FILE, /* create_options */
2510                  FILE_ATTRIBUTE_NORMAL, /* file_attributes */
2511                  0,                     /* oplock_request */
2512                  0,                     /* allocation_size */
2513                  NULL,                  /* sd */
2514                  NULL,                  /* ea_list */
2515                  &fsp,                  /* result */
2516                  NULL);                 /* pinfo */
2517
2518         if (!NT_STATUS_IS_OK(status)) {
2519                 DEBUG(10, ("SMB_VFS_CREATEFILE failed: %s\n",
2520                            nt_errstr(status)));
2521                 return status;
2522         }
2523
2524         /* The set is across all open files on this dev/inode pair. */
2525         if (!set_delete_on_close(fsp, True, &conn->server_info->utok)) {
2526                 close_file(req, fsp, NORMAL_CLOSE);
2527                 return NT_STATUS_ACCESS_DENIED;
2528         }
2529
2530         return close_file(req, fsp, NORMAL_CLOSE);
2531 }
2532
2533 /****************************************************************************
2534  The guts of the unlink command, split out so it may be called by the NT SMB
2535  code.
2536 ****************************************************************************/
2537
2538 NTSTATUS unlink_internals(connection_struct *conn, struct smb_request *req,
2539                           uint32 dirtype, const char *name_in, bool has_wild)
2540 {
2541         struct smb_filename *smb_fname = NULL;
2542         char *fname_dir = NULL;
2543         char *fname_mask = NULL;
2544         int count=0;
2545         NTSTATUS status = NT_STATUS_OK;
2546         TALLOC_CTX *ctx = talloc_tos();
2547
2548         status = unix_convert(ctx, conn, name_in, &smb_fname,
2549                               has_wild ? UCF_ALLOW_WCARD_LCOMP : 0);
2550         if (!NT_STATUS_IS_OK(status)) {
2551                 goto out;
2552         }
2553
2554         /* Split up the directory from the filename/mask. */
2555         status = split_fname_dir_mask(ctx, smb_fname->base_name,
2556                                       &fname_dir, &fname_mask);
2557         if (!NT_STATUS_IS_OK(status)) {
2558                 goto out;
2559         }
2560
2561         /*
2562          * We should only check the mangled cache
2563          * here if unix_convert failed. This means
2564          * that the path in 'mask' doesn't exist
2565          * on the file system and so we need to look
2566          * for a possible mangle. This patch from
2567          * Tine Smukavec <valentin.smukavec@hermes.si>.
2568          */
2569
2570         if (!VALID_STAT(smb_fname->st) &&
2571             mangle_is_mangled(fname_mask, conn->params)) {
2572                 char *new_mask = NULL;
2573                 mangle_lookup_name_from_8_3(ctx, fname_mask,
2574                                             &new_mask, conn->params);
2575                 if (new_mask) {
2576                         TALLOC_FREE(fname_mask);
2577                         fname_mask = new_mask;
2578                 }
2579         }
2580
2581         if (!has_wild) {
2582
2583                 /*
2584                  * Only one file needs to be unlinked. Append the mask back
2585                  * onto the directory.
2586                  */
2587                 TALLOC_FREE(smb_fname->base_name);
2588                 smb_fname->base_name = talloc_asprintf(smb_fname,
2589                                                        "%s/%s",
2590                                                        fname_dir,
2591                                                        fname_mask);
2592                 if (!smb_fname->base_name) {
2593                         status = NT_STATUS_NO_MEMORY;
2594                         goto out;
2595                 }
2596                 if (dirtype == 0) {
2597                         dirtype = FILE_ATTRIBUTE_NORMAL;
2598                 }
2599
2600                 status = check_name(conn, smb_fname->base_name);
2601                 if (!NT_STATUS_IS_OK(status)) {
2602                         goto out;
2603                 }
2604
2605                 status = do_unlink(conn, req, smb_fname, dirtype);
2606                 if (!NT_STATUS_IS_OK(status)) {
2607                         goto out;
2608                 }
2609
2610                 count++;
2611         } else {
2612                 struct smb_Dir *dir_hnd = NULL;
2613                 long offset = 0;
2614                 const char *dname;
2615
2616                 if ((dirtype & SAMBA_ATTRIBUTES_MASK) == aDIR) {
2617                         status = NT_STATUS_OBJECT_NAME_INVALID;
2618                         goto out;
2619                 }
2620
2621                 if (strequal(fname_mask,"????????.???")) {
2622                         TALLOC_FREE(fname_mask);
2623                         fname_mask = talloc_strdup(ctx, "*");
2624                         if (!fname_mask) {
2625                                 status = NT_STATUS_NO_MEMORY;
2626                                 goto out;
2627                         }
2628                 }
2629
2630                 status = check_name(conn, fname_dir);
2631                 if (!NT_STATUS_IS_OK(status)) {
2632                         goto out;
2633                 }
2634
2635                 dir_hnd = OpenDir(talloc_tos(), conn, fname_dir, fname_mask,
2636                                   dirtype);
2637                 if (dir_hnd == NULL) {
2638                         status = map_nt_error_from_unix(errno);
2639                         goto out;
2640                 }
2641
2642                 /* XXXX the CIFS spec says that if bit0 of the flags2 field is set then
2643                    the pattern matches against the long name, otherwise the short name 
2644                    We don't implement this yet XXXX
2645                 */
2646
2647                 status = NT_STATUS_NO_SUCH_FILE;
2648
2649                 while ((dname = ReadDirName(dir_hnd, &offset,
2650                                             &smb_fname->st))) {
2651                         TALLOC_CTX *frame = talloc_stackframe();
2652
2653                         if (!is_visible_file(conn, fname_dir, dname,
2654                                              &smb_fname->st, true)) {
2655                                 TALLOC_FREE(frame);
2656                                 continue;
2657                         }
2658
2659                         /* Quick check for "." and ".." */
2660                         if (ISDOT(dname) || ISDOTDOT(dname)) {
2661                                 TALLOC_FREE(frame);
2662                                 continue;
2663                         }
2664
2665                         if(!mask_match(dname, fname_mask,
2666                                        conn->case_sensitive)) {
2667                                 TALLOC_FREE(frame);
2668                                 continue;
2669                         }
2670
2671                         TALLOC_FREE(smb_fname->base_name);
2672                         smb_fname->base_name =
2673                             talloc_asprintf(smb_fname, "%s/%s",
2674                                             fname_dir, dname);
2675
2676                         if (!smb_fname->base_name) {
2677                                 TALLOC_FREE(dir_hnd);
2678                                 status = NT_STATUS_NO_MEMORY;
2679                                 TALLOC_FREE(frame);
2680                                 goto out;
2681                         }
2682
2683                         status = check_name(conn, smb_fname->base_name);
2684                         if (!NT_STATUS_IS_OK(status)) {
2685                                 TALLOC_FREE(dir_hnd);
2686                                 TALLOC_FREE(frame);
2687                                 goto out;
2688                         }
2689
2690                         status = do_unlink(conn, req, smb_fname, dirtype);
2691                         if (!NT_STATUS_IS_OK(status)) {
2692                                 TALLOC_FREE(frame);
2693                                 continue;
2694                         }
2695
2696                         count++;
2697                         DEBUG(3,("unlink_internals: successful unlink [%s]\n",
2698                                  smb_fname->base_name));
2699
2700                         TALLOC_FREE(frame);
2701                 }
2702                 TALLOC_FREE(dir_hnd);
2703         }
2704
2705         if (count == 0 && NT_STATUS_IS_OK(status) && errno != 0) {
2706                 status = map_nt_error_from_unix(errno);
2707         }
2708
2709  out:
2710         TALLOC_FREE(smb_fname);
2711         TALLOC_FREE(fname_dir);
2712         TALLOC_FREE(fname_mask);
2713         return status;
2714 }
2715
2716 /****************************************************************************
2717  Reply to a unlink
2718 ****************************************************************************/
2719
2720 void reply_unlink(struct smb_request *req)
2721 {
2722         connection_struct *conn = req->conn;
2723         char *name = NULL;
2724         uint32 dirtype;
2725         NTSTATUS status;
2726         bool path_contains_wcard = False;
2727         TALLOC_CTX *ctx = talloc_tos();
2728
2729         START_PROFILE(SMBunlink);
2730
2731         if (req->wct < 1) {
2732                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2733                 END_PROFILE(SMBunlink);
2734                 return;
2735         }
2736
2737         dirtype = SVAL(req->vwv+0, 0);
2738
2739         srvstr_get_path_req_wcard(ctx, req, &name, (const char *)req->buf + 1,
2740                                   STR_TERMINATE, &status,
2741                                   &path_contains_wcard);
2742         if (!NT_STATUS_IS_OK(status)) {
2743                 reply_nterror(req, status);
2744                 END_PROFILE(SMBunlink);
2745                 return;
2746         }
2747
2748         status = resolve_dfspath_wcard(ctx, conn,
2749                                        req->flags2 & FLAGS2_DFS_PATHNAMES,
2750                                        name,
2751                                        &name,
2752                                        &path_contains_wcard);
2753         if (!NT_STATUS_IS_OK(status)) {
2754                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2755                         reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2756                                         ERRSRV, ERRbadpath);
2757                         END_PROFILE(SMBunlink);
2758                         return;
2759                 }
2760                 reply_nterror(req, status);
2761                 END_PROFILE(SMBunlink);
2762                 return;
2763         }
2764
2765         DEBUG(3,("reply_unlink : %s\n",name));
2766
2767         status = unlink_internals(conn, req, dirtype, name,
2768                                   path_contains_wcard);
2769         if (!NT_STATUS_IS_OK(status)) {
2770                 if (open_was_deferred(req->mid)) {
2771                         /* We have re-scheduled this call. */
2772                         END_PROFILE(SMBunlink);
2773                         return;
2774                 }
2775                 reply_nterror(req, status);
2776                 END_PROFILE(SMBunlink);
2777                 return;
2778         }
2779
2780         reply_outbuf(req, 0, 0);
2781         END_PROFILE(SMBunlink);
2782
2783         return;
2784 }
2785
2786 /****************************************************************************
2787  Fail for readbraw.
2788 ****************************************************************************/
2789
2790 static void fail_readraw(void)
2791 {
2792         const char *errstr = talloc_asprintf(talloc_tos(),
2793                         "FAIL ! reply_readbraw: socket write fail (%s)",
2794                         strerror(errno));
2795         if (!errstr) {
2796                 errstr = "";
2797         }
2798         exit_server_cleanly(errstr);
2799 }
2800
2801 /****************************************************************************
2802  Fake (read/write) sendfile. Returns -1 on read or write fail.
2803 ****************************************************************************/
2804
2805 static ssize_t fake_sendfile(files_struct *fsp, SMB_OFF_T startpos,
2806                              size_t nread)
2807 {
2808         size_t bufsize;
2809         size_t tosend = nread;
2810         char *buf;
2811
2812         if (nread == 0) {
2813                 return 0;
2814         }
2815
2816         bufsize = MIN(nread, 65536);
2817
2818         if (!(buf = SMB_MALLOC_ARRAY(char, bufsize))) {
2819                 return -1;
2820         }
2821
2822         while (tosend > 0) {
2823                 ssize_t ret;
2824                 size_t cur_read;
2825
2826                 if (tosend > bufsize) {
2827                         cur_read = bufsize;
2828                 } else {
2829                         cur_read = tosend;
2830                 }
2831                 ret = read_file(fsp,buf,startpos,cur_read);
2832                 if (ret == -1) {
2833                         SAFE_FREE(buf);
2834                         return -1;
2835                 }
2836
2837                 /* If we had a short read, fill with zeros. */
2838                 if (ret < cur_read) {
2839                         memset(buf + ret, '\0', cur_read - ret);
2840                 }
2841
2842                 if (write_data(smbd_server_fd(),buf,cur_read) != cur_read) {
2843                         SAFE_FREE(buf);
2844                         return -1;
2845                 }
2846                 tosend -= cur_read;
2847                 startpos += cur_read;
2848         }
2849
2850         SAFE_FREE(buf);
2851         return (ssize_t)nread;
2852 }
2853
2854 #if defined(WITH_SENDFILE)
2855 /****************************************************************************
2856  Deal with the case of sendfile reading less bytes from the file than
2857  requested. Fill with zeros (all we can do).
2858 ****************************************************************************/
2859
2860 static void sendfile_short_send(files_struct *fsp,
2861                                 ssize_t nread,
2862                                 size_t headersize,
2863                                 size_t smb_maxcnt)
2864 {
2865 #define SHORT_SEND_BUFSIZE 1024
2866         if (nread < headersize) {
2867                 DEBUG(0,("sendfile_short_send: sendfile failed to send "
2868                         "header for file %s (%s). Terminating\n",
2869                         fsp->fsp_name, strerror(errno) ));
2870                 exit_server_cleanly("sendfile_short_send failed");
2871         }
2872
2873         nread -= headersize;
2874
2875         if (nread < smb_maxcnt) {
2876                 char *buf = SMB_CALLOC_ARRAY(char, SHORT_SEND_BUFSIZE);
2877                 if (!buf) {
2878                         exit_server_cleanly("sendfile_short_send: "
2879                                 "malloc failed");
2880                 }
2881
2882                 DEBUG(0,("sendfile_short_send: filling truncated file %s "
2883                         "with zeros !\n", fsp->fsp_name));
2884
2885                 while (nread < smb_maxcnt) {
2886                         /*
2887                          * We asked for the real file size and told sendfile
2888                          * to not go beyond the end of the file. But it can
2889                          * happen that in between our fstat call and the
2890                          * sendfile call the file was truncated. This is very
2891                          * bad because we have already announced the larger
2892                          * number of bytes to the client.
2893                          *
2894                          * The best we can do now is to send 0-bytes, just as
2895                          * a read from a hole in a sparse file would do.
2896                          *
2897                          * This should happen rarely enough that I don't care
2898                          * about efficiency here :-)
2899                          */
2900                         size_t to_write;
2901
2902                         to_write = MIN(SHORT_SEND_BUFSIZE, smb_maxcnt - nread);
2903                         if (write_data(smbd_server_fd(), buf, to_write) != to_write) {
2904                                 exit_server_cleanly("sendfile_short_send: "
2905                                         "write_data failed");
2906                         }
2907                         nread += to_write;
2908                 }
2909                 SAFE_FREE(buf);
2910         }
2911 }
2912 #endif /* defined WITH_SENDFILE */
2913
2914 /****************************************************************************
2915  Return a readbraw error (4 bytes of zero).
2916 ****************************************************************************/
2917
2918 static void reply_readbraw_error(void)
2919 {
2920         char header[4];
2921         SIVAL(header,0,0);
2922         if (write_data(smbd_server_fd(),header,4) != 4) {
2923                 fail_readraw();
2924         }
2925 }
2926
2927 /****************************************************************************
2928  Use sendfile in readbraw.
2929 ****************************************************************************/
2930
2931 static void send_file_readbraw(connection_struct *conn,
2932                                struct smb_request *req,
2933                                files_struct *fsp,
2934                                SMB_OFF_T startpos,
2935                                size_t nread,
2936                                ssize_t mincount)
2937 {
2938         char *outbuf = NULL;
2939         ssize_t ret=0;
2940
2941 #if defined(WITH_SENDFILE)
2942         /*
2943          * We can only use sendfile on a non-chained packet 
2944          * but we can use on a non-oplocked file. tridge proved this
2945          * on a train in Germany :-). JRA.
2946          * reply_readbraw has already checked the length.
2947          */
2948
2949         if ( !req_is_in_chain(req) && (nread > 0) && (fsp->base_fsp == NULL) &&
2950             (fsp->wcp == NULL) &&
2951             lp_use_sendfile(SNUM(conn), smbd_server_conn->smb1.signing_state) ) {
2952                 ssize_t sendfile_read = -1;
2953                 char header[4];
2954                 DATA_BLOB header_blob;
2955
2956                 _smb_setlen(header,nread);
2957                 header_blob = data_blob_const(header, 4);
2958
2959                 if ((sendfile_read = SMB_VFS_SENDFILE(smbd_server_fd(), fsp,
2960                                 &header_blob, startpos, nread)) == -1) {
2961                         /* Returning ENOSYS means no data at all was sent.
2962                          * Do this as a normal read. */
2963                         if (errno == ENOSYS) {
2964                                 goto normal_readbraw;
2965                         }
2966
2967                         /*
2968                          * Special hack for broken Linux with no working sendfile. If we
2969                          * return EINTR we sent the header but not the rest of the data.
2970                          * Fake this up by doing read/write calls.
2971                          */
2972                         if (errno == EINTR) {
2973                                 /* Ensure we don't do this again. */
2974                                 set_use_sendfile(SNUM(conn), False);
2975                                 DEBUG(0,("send_file_readbraw: sendfile not available. Faking..\n"));
2976
2977                                 if (fake_sendfile(fsp, startpos, nread) == -1) {
2978                                         DEBUG(0,("send_file_readbraw: fake_sendfile failed for file %s (%s).\n",
2979                                                 fsp->fsp_name, strerror(errno) ));
2980                                         exit_server_cleanly("send_file_readbraw fake_sendfile failed");
2981                                 }
2982                                 return;
2983                         }
2984
2985                         DEBUG(0,("send_file_readbraw: sendfile failed for file %s (%s). Terminating\n",
2986                                 fsp->fsp_name, strerror(errno) ));
2987                         exit_server_cleanly("send_file_readbraw sendfile failed");
2988                 } else if (sendfile_read == 0) {
2989                         /*
2990                          * Some sendfile implementations return 0 to indicate
2991                          * that there was a short read, but nothing was
2992                          * actually written to the socket.  In this case,
2993                          * fallback to the normal read path so the header gets
2994                          * the correct byte count.
2995                          */
2996                         DEBUG(3, ("send_file_readbraw: sendfile sent zero "
2997                                   "bytes falling back to the normal read: "
2998                                   "%s\n", fsp->fsp_name));
2999                         goto normal_readbraw;
3000                 }
3001
3002                 /* Deal with possible short send. */
3003                 if (sendfile_read != 4+nread) {
3004                         sendfile_short_send(fsp, sendfile_read, 4, nread);
3005                 }
3006                 return;
3007         }
3008
3009 normal_readbraw:
3010 #endif
3011
3012         outbuf = TALLOC_ARRAY(NULL, char, nread+4);
3013         if (!outbuf) {
3014                 DEBUG(0,("send_file_readbraw: TALLOC_ARRAY failed for size %u.\n",
3015                         (unsigned)(nread+4)));
3016                 reply_readbraw_error();
3017                 return;
3018         }
3019
3020         if (nread > 0) {
3021                 ret = read_file(fsp,outbuf+4,startpos,nread);
3022 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
3023                 if (ret < mincount)
3024                         ret = 0;
3025 #else
3026                 if (ret < nread)
3027                         ret = 0;
3028 #endif
3029         }
3030
3031         _smb_setlen(outbuf,ret);
3032         if (write_data(smbd_server_fd(),outbuf,4+ret) != 4+ret)
3033                 fail_readraw();
3034
3035         TALLOC_FREE(outbuf);
3036 }
3037
3038 /****************************************************************************
3039  Reply to a readbraw (core+ protocol).
3040 ****************************************************************************/
3041
3042 void reply_readbraw(struct smb_request *req)
3043 {
3044         connection_struct *conn = req->conn;
3045         ssize_t maxcount,mincount;
3046         size_t nread = 0;
3047         SMB_OFF_T startpos;
3048         files_struct *fsp;
3049         struct lock_struct lock;
3050         SMB_STRUCT_STAT st;
3051         SMB_OFF_T size = 0;
3052
3053         START_PROFILE(SMBreadbraw);
3054
3055         if (srv_is_signing_active(smbd_server_conn) ||
3056             is_encrypted_packet(req->inbuf)) {
3057                 exit_server_cleanly("reply_readbraw: SMB signing/sealing is active - "
3058                         "raw reads/writes are disallowed.");
3059         }
3060
3061         if (req->wct < 8) {
3062                 reply_readbraw_error();
3063                 END_PROFILE(SMBreadbraw);
3064                 return;
3065         }
3066
3067         /*
3068          * Special check if an oplock break has been issued
3069          * and the readraw request croses on the wire, we must
3070          * return a zero length response here.
3071          */
3072
3073         fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3074
3075         /*
3076          * We have to do a check_fsp by hand here, as
3077          * we must always return 4 zero bytes on error,
3078          * not a NTSTATUS.
3079          */
3080
3081         if (!fsp || !conn || conn != fsp->conn ||
3082                         req->vuid != fsp->vuid ||
3083                         fsp->is_directory || fsp->fh->fd == -1) {
3084                 /*
3085                  * fsp could be NULL here so use the value from the packet. JRA.
3086                  */
3087                 DEBUG(3,("reply_readbraw: fnum %d not valid "
3088                         "- cache prime?\n",
3089                         (int)SVAL(req->vwv+0, 0)));
3090                 reply_readbraw_error();
3091                 END_PROFILE(SMBreadbraw);
3092                 return;
3093         }
3094
3095         /* Do a "by hand" version of CHECK_READ. */
3096         if (!(fsp->can_read ||
3097                         ((req->flags2 & FLAGS2_READ_PERMIT_EXECUTE) &&
3098                                 (fsp->access_mask & FILE_EXECUTE)))) {
3099                 DEBUG(3,("reply_readbraw: fnum %d not readable.\n",
3100                                 (int)SVAL(req->vwv+0, 0)));
3101                 reply_readbraw_error();
3102                 END_PROFILE(SMBreadbraw);
3103                 return;
3104         }
3105
3106         flush_write_cache(fsp, READRAW_FLUSH);
3107
3108         startpos = IVAL_TO_SMB_OFF_T(req->vwv+1, 0);
3109         if(req->wct == 10) {
3110                 /*
3111                  * This is a large offset (64 bit) read.
3112                  */
3113 #ifdef LARGE_SMB_OFF_T
3114
3115                 startpos |= (((SMB_OFF_T)IVAL(req->vwv+8, 0)) << 32);
3116
3117 #else /* !LARGE_SMB_OFF_T */
3118
3119                 /*
3120                  * Ensure we haven't been sent a >32 bit offset.
3121                  */
3122
3123                 if(IVAL(req->vwv+8, 0) != 0) {
3124                         DEBUG(0,("reply_readbraw: large offset "
3125                                 "(%x << 32) used and we don't support "
3126                                 "64 bit offsets.\n",
3127                         (unsigned int)IVAL(req->vwv+8, 0) ));
3128                         reply_readbraw_error();
3129                         END_PROFILE(SMBreadbraw);
3130                         return;
3131                 }
3132
3133 #endif /* LARGE_SMB_OFF_T */
3134
3135                 if(startpos < 0) {
3136                         DEBUG(0,("reply_readbraw: negative 64 bit "
3137                                 "readraw offset (%.0f) !\n",
3138                                 (double)startpos ));
3139                         reply_readbraw_error();
3140                         END_PROFILE(SMBreadbraw);
3141                         return;
3142                 }      
3143         }
3144
3145         maxcount = (SVAL(req->vwv+3, 0) & 0xFFFF);
3146         mincount = (SVAL(req->vwv+4, 0) & 0xFFFF);
3147
3148         /* ensure we don't overrun the packet size */
3149         maxcount = MIN(65535,maxcount);
3150
3151         init_strict_lock_struct(fsp, (uint32)req->smbpid,
3152             (uint64_t)startpos, (uint64_t)maxcount, READ_LOCK,
3153             &lock);
3154
3155         if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
3156                 reply_readbraw_error();
3157                 END_PROFILE(SMBreadbraw);
3158                 return;
3159         }
3160
3161         if (SMB_VFS_FSTAT(fsp, &st) == 0) {
3162                 size = st.st_ex_size;
3163         }
3164
3165         if (startpos >= size) {
3166                 nread = 0;
3167         } else {
3168                 nread = MIN(maxcount,(size - startpos));