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