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