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