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