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