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