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