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