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