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