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