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