99b4937c99b4a892c55a95613d682c1bd84e1438
[metze/samba/wip.git] / source3 / smbd / files.c
1 /* 
2    Unix SMB/CIFS implementation.
3    Files[] structure handling
4    Copyright (C) Andrew Tridgell 1998
5
6    This program is free software; you can redistribute it and/or modify
7    it under the terms of the GNU General Public License as published by
8    the Free Software Foundation; either version 3 of the License, or
9    (at your option) any later version.
10
11    This program is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14    GNU General Public License for more details.
15
16    You should have received a copy of the GNU General Public License
17    along with this program.  If not, see <http://www.gnu.org/licenses/>.
18 */
19
20 #include "includes.h"
21 #include "smbd/smbd.h"
22 #include "smbd/globals.h"
23 #include "libcli/security/security.h"
24 #include "util_tdb.h"
25 #include "lib/util/bitmap.h"
26
27 #define FILE_HANDLE_OFFSET 0x1000
28
29 /**
30  * create new fsp to be used for file_new or a durable handle reconnect
31  */
32 NTSTATUS fsp_new(struct connection_struct *conn, TALLOC_CTX *mem_ctx,
33                  files_struct **result)
34 {
35         NTSTATUS status = NT_STATUS_NO_MEMORY;
36         files_struct *fsp = NULL;
37         struct smbd_server_connection *sconn = conn->sconn;
38
39         fsp = talloc_zero(mem_ctx, struct files_struct);
40         if (fsp == NULL) {
41                 goto fail;
42         }
43
44         /*
45          * This can't be a child of fsp because the file_handle can be ref'd
46          * when doing a dos/fcb open, which will then share the file_handle
47          * across multiple fsps.
48          */
49         fsp->fh = talloc_zero(mem_ctx, struct fd_handle);
50         if (fsp->fh == NULL) {
51                 goto fail;
52         }
53
54 #if defined(HAVE_OFD_LOCKS)
55         fsp->use_ofd_locks = true;
56         if (lp_parm_bool(SNUM(conn),
57                          "smbd",
58                          "force process locks",
59                          false)) {
60                 fsp->use_ofd_locks = false;
61         }
62 #endif
63         fsp->fh->ref_count = 1;
64         fsp->fh->fd = -1;
65
66         fsp->fnum = FNUM_FIELD_INVALID;
67         fsp->conn = conn;
68
69         DLIST_ADD(sconn->files, fsp);
70         sconn->num_files += 1;
71
72         conn->num_files_open++;
73
74         *result = fsp;
75         return NT_STATUS_OK;
76
77 fail:
78         if (fsp != NULL) {
79                 TALLOC_FREE(fsp->fh);
80         }
81         TALLOC_FREE(fsp);
82
83         return status;
84 }
85
86 /****************************************************************************
87  Find first available file slot.
88 ****************************************************************************/
89
90 NTSTATUS file_new(struct smb_request *req, connection_struct *conn,
91                   files_struct **result)
92 {
93         struct smbd_server_connection *sconn = conn->sconn;
94         files_struct *fsp;
95         NTSTATUS status;
96
97         status = fsp_new(conn, conn, &fsp);
98         if (!NT_STATUS_IS_OK(status)) {
99                 return status;
100         }
101
102         GetTimeOfDay(&fsp->open_time);
103
104         if (req) {
105                 struct smbXsrv_connection *xconn = req->xconn;
106                 struct smbXsrv_open *op = NULL;
107                 NTTIME now = timeval_to_nttime(&fsp->open_time);
108
109                 status = smbXsrv_open_create(xconn,
110                                              conn->session_info,
111                                              now, &op);
112                 if (!NT_STATUS_IS_OK(status)) {
113                         file_free(NULL, fsp);
114                         return status;
115                 }
116                 fsp->op = op;
117                 op->compat = fsp;
118                 fsp->fnum = op->local_id;
119                 fsp->fh->gen_id = smbXsrv_open_hash(op);
120         } else {
121                 DEBUG(10, ("%s: req==NULL, INTERNAL_OPEN_ONLY, smbXsrv_open "
122                            "allocated\n", __func__));
123         }
124
125         /*
126          * Create an smb_filename with "" for the base_name.  There are very
127          * few NULL checks, so make sure it's initialized with something. to
128          * be safe until an audit can be done.
129          */
130         fsp->fsp_name = synthetic_smb_fname(fsp, "", NULL, NULL, 0);
131         if (fsp->fsp_name == NULL) {
132                 file_free(NULL, fsp);
133                 return NT_STATUS_NO_MEMORY;
134         }
135
136         DEBUG(5,("allocated file structure %s (%u used)\n",
137                  fsp_fnum_dbg(fsp), (unsigned int)sconn->num_files));
138
139         if (req != NULL) {
140                 fsp->mid = req->mid;
141                 req->chain_fsp = fsp;
142         }
143
144         /* A new fsp invalidates the positive and
145           negative fsp_fi_cache as the new fsp is pushed
146           at the start of the list and we search from
147           a cache hit to the *end* of the list. */
148
149         ZERO_STRUCT(sconn->fsp_fi_cache);
150
151         *result = fsp;
152         return NT_STATUS_OK;
153 }
154
155 /****************************************************************************
156  Close all open files for a connection.
157 ****************************************************************************/
158
159 void file_close_conn(connection_struct *conn)
160 {
161         files_struct *fsp, *next;
162
163         for (fsp=conn->sconn->files; fsp; fsp=next) {
164                 next = fsp->next;
165                 if (fsp->conn != conn) {
166                         continue;
167                 }
168                 if (fsp->op != NULL && fsp->op->global->durable) {
169                         /*
170                          * A tree disconnect closes a durable handle
171                          */
172                         fsp->op->global->durable = false;
173                 }
174                 close_file(NULL, fsp, SHUTDOWN_CLOSE);
175         }
176 }
177
178 /****************************************************************************
179  Close all open files for a pid and a vuid.
180 ****************************************************************************/
181
182 void file_close_pid(struct smbd_server_connection *sconn, uint16_t smbpid,
183                     uint64_t vuid)
184 {
185         files_struct *fsp, *next;
186
187         for (fsp=sconn->files;fsp;fsp=next) {
188                 next = fsp->next;
189                 if ((fsp->file_pid == smbpid) && (fsp->vuid == vuid)) {
190                         close_file(NULL, fsp, SHUTDOWN_CLOSE);
191                 }
192         }
193 }
194
195 /****************************************************************************
196  Initialise file structures.
197 ****************************************************************************/
198
199 static int files_max_open_fds;
200
201 bool file_init_global(void)
202 {
203         int request_max = lp_max_open_files();
204         int real_lim;
205         int real_max;
206
207         if (files_max_open_fds != 0) {
208                 return true;
209         }
210
211         /*
212          * Set the max_open files to be the requested
213          * max plus a fudgefactor to allow for the extra
214          * fd's we need such as log files etc...
215          */
216         real_lim = set_maxfiles(request_max + MAX_OPEN_FUDGEFACTOR);
217
218         real_max = real_lim - MAX_OPEN_FUDGEFACTOR;
219
220         if (real_max + FILE_HANDLE_OFFSET + MAX_OPEN_PIPES > 65536) {
221                 real_max = 65536 - FILE_HANDLE_OFFSET - MAX_OPEN_PIPES;
222         }
223
224         if (real_max != request_max) {
225                 DEBUG(1, ("file_init_global: Information only: requested %d "
226                           "open files, %d are available.\n",
227                           request_max, real_max));
228         }
229
230         SMB_ASSERT(real_max > 100);
231
232         files_max_open_fds = real_max;
233         return true;
234 }
235
236 bool file_init(struct smbd_server_connection *sconn)
237 {
238         bool ok;
239
240         ok = file_init_global();
241         if (!ok) {
242                 return false;
243         }
244
245         sconn->real_max_open_files = files_max_open_fds;
246
247         return true;
248 }
249
250 /****************************************************************************
251  Close files open by a specified vuid.
252 ****************************************************************************/
253
254 void file_close_user(struct smbd_server_connection *sconn, uint64_t vuid)
255 {
256         files_struct *fsp, *next;
257
258         for (fsp=sconn->files; fsp; fsp=next) {
259                 next=fsp->next;
260                 if (fsp->vuid == vuid) {
261                         close_file(NULL, fsp, SHUTDOWN_CLOSE);
262                 }
263         }
264 }
265
266 /*
267  * Walk the files table until "fn" returns non-NULL
268  */
269
270 struct files_struct *files_forall(
271         struct smbd_server_connection *sconn,
272         struct files_struct *(*fn)(struct files_struct *fsp,
273                                    void *private_data),
274         void *private_data)
275 {
276         struct files_struct *fsp, *next;
277
278         for (fsp = sconn->files; fsp; fsp = next) {
279                 struct files_struct *ret;
280                 next = fsp->next;
281                 ret = fn(fsp, private_data);
282                 if (ret != NULL) {
283                         return ret;
284                 }
285         }
286         return NULL;
287 }
288
289 /****************************************************************************
290  Find a fsp given a file descriptor.
291 ****************************************************************************/
292
293 files_struct *file_find_fd(struct smbd_server_connection *sconn, int fd)
294 {
295         int count=0;
296         files_struct *fsp;
297
298         for (fsp=sconn->files; fsp; fsp=fsp->next,count++) {
299                 if (fsp->fh->fd == fd) {
300                         if (count > 10) {
301                                 DLIST_PROMOTE(sconn->files, fsp);
302                         }
303                         return fsp;
304                 }
305         }
306
307         return NULL;
308 }
309
310 /****************************************************************************
311  Find a fsp given a device, inode and file_id.
312 ****************************************************************************/
313
314 files_struct *file_find_dif(struct smbd_server_connection *sconn,
315                             struct file_id id, unsigned long gen_id)
316 {
317         int count=0;
318         files_struct *fsp;
319
320         if (gen_id == 0) {
321                 return NULL;
322         }
323
324         for (fsp=sconn->files; fsp; fsp=fsp->next,count++) {
325                 /* We can have a fsp->fh->fd == -1 here as it could be a stat open. */
326                 if (file_id_equal(&fsp->file_id, &id) &&
327                     fsp->fh->gen_id == gen_id ) {
328                         if (count > 10) {
329                                 DLIST_PROMOTE(sconn->files, fsp);
330                         }
331                         /* Paranoia check. */
332                         if ((fsp->fh->fd == -1) &&
333                             (fsp->oplock_type != NO_OPLOCK &&
334                              fsp->oplock_type != LEASE_OPLOCK)) {
335                                 DEBUG(0,("file_find_dif: file %s file_id = "
336                                          "%s, gen = %u oplock_type = %u is a "
337                                          "stat open with oplock type !\n",
338                                          fsp_str_dbg(fsp),
339                                          file_id_string_tos(&fsp->file_id),
340                                          (unsigned int)fsp->fh->gen_id,
341                                          (unsigned int)fsp->oplock_type ));
342                                 smb_panic("file_find_dif");
343                         }
344                         return fsp;
345                 }
346         }
347
348         return NULL;
349 }
350
351 /****************************************************************************
352  Find the first fsp given a device and inode.
353  We use a singleton cache here to speed up searching from getfilepathinfo
354  calls.
355 ****************************************************************************/
356
357 files_struct *file_find_di_first(struct smbd_server_connection *sconn,
358                                  struct file_id id)
359 {
360         files_struct *fsp;
361
362         if (file_id_equal(&sconn->fsp_fi_cache.id, &id)) {
363                 /* Positive or negative cache hit. */
364                 return sconn->fsp_fi_cache.fsp;
365         }
366
367         sconn->fsp_fi_cache.id = id;
368
369         for (fsp=sconn->files;fsp;fsp=fsp->next) {
370                 if (file_id_equal(&fsp->file_id, &id)) {
371                         /* Setup positive cache. */
372                         sconn->fsp_fi_cache.fsp = fsp;
373                         return fsp;
374                 }
375         }
376
377         /* Setup negative cache. */
378         sconn->fsp_fi_cache.fsp = NULL;
379         return NULL;
380 }
381
382 /****************************************************************************
383  Find the next fsp having the same device and inode.
384 ****************************************************************************/
385
386 files_struct *file_find_di_next(files_struct *start_fsp)
387 {
388         files_struct *fsp;
389
390         for (fsp = start_fsp->next;fsp;fsp=fsp->next) {
391                 if (file_id_equal(&fsp->file_id, &start_fsp->file_id)) {
392                         return fsp;
393                 }
394         }
395
396         return NULL;
397 }
398
399 struct files_struct *file_find_one_fsp_from_lease_key(
400         struct smbd_server_connection *sconn,
401         const struct smb2_lease_key *lease_key)
402 {
403         struct files_struct *fsp;
404
405         for (fsp = sconn->files; fsp; fsp=fsp->next) {
406                 if ((fsp->lease != NULL) &&
407                     (fsp->lease->lease.lease_key.data[0] ==
408                      lease_key->data[0]) &&
409                     (fsp->lease->lease.lease_key.data[1] ==
410                      lease_key->data[1])) {
411                         return fsp;
412                 }
413         }
414         return NULL;
415 }
416
417 /****************************************************************************
418  Find any fsp open with a pathname below that of an already open path.
419 ****************************************************************************/
420
421 bool file_find_subpath(files_struct *dir_fsp)
422 {
423         files_struct *fsp;
424         size_t dlen;
425         char *d_fullname = NULL;
426
427         d_fullname = talloc_asprintf(talloc_tos(), "%s/%s",
428                                      dir_fsp->conn->connectpath,
429                                      dir_fsp->fsp_name->base_name);
430
431         if (!d_fullname) {
432                 return false;
433         }
434
435         dlen = strlen(d_fullname);
436
437         for (fsp=dir_fsp->conn->sconn->files; fsp; fsp=fsp->next) {
438                 char *d1_fullname;
439
440                 if (fsp == dir_fsp) {
441                         continue;
442                 }
443
444                 d1_fullname = talloc_asprintf(talloc_tos(),
445                                         "%s/%s",
446                                         fsp->conn->connectpath,
447                                         fsp->fsp_name->base_name);
448
449                 /*
450                  * If the open file has a path that is a longer
451                  * component, then it's a subpath.
452                  */
453                 if (strnequal(d_fullname, d1_fullname, dlen) &&
454                                 (d1_fullname[dlen] == '/')) {
455                         TALLOC_FREE(d1_fullname);
456                         TALLOC_FREE(d_fullname);
457                         return true;
458                 }
459                 TALLOC_FREE(d1_fullname);
460         }
461
462         TALLOC_FREE(d_fullname);
463         return false;
464 }
465
466 /****************************************************************************
467  Free up a fsp.
468 ****************************************************************************/
469
470 void fsp_free(files_struct *fsp)
471 {
472         struct smbd_server_connection *sconn = fsp->conn->sconn;
473
474         if (fsp == sconn->fsp_fi_cache.fsp) {
475                 ZERO_STRUCT(sconn->fsp_fi_cache);
476         }
477
478         DLIST_REMOVE(sconn->files, fsp);
479         SMB_ASSERT(sconn->num_files > 0);
480         sconn->num_files--;
481
482         TALLOC_FREE(fsp->fake_file_handle);
483
484         if (fsp->fh->ref_count == 1) {
485                 TALLOC_FREE(fsp->fh);
486         } else {
487                 fsp->fh->ref_count--;
488         }
489
490         if (fsp->lease != NULL) {
491                 if (fsp->lease->ref_count == 1) {
492                         TALLOC_FREE(fsp->lease);
493                 } else {
494                         fsp->lease->ref_count--;
495                 }
496         }
497
498         fsp->conn->num_files_open--;
499
500         /* this is paranoia, just in case someone tries to reuse the
501            information */
502         ZERO_STRUCTP(fsp);
503
504         /* fsp->fsp_name is a talloc child and is free'd automatically. */
505         TALLOC_FREE(fsp);
506 }
507
508 void file_free(struct smb_request *req, files_struct *fsp)
509 {
510         struct smbd_server_connection *sconn = fsp->conn->sconn;
511         uint64_t fnum = fsp->fnum;
512
513         if (fsp->notify) {
514                 size_t len = fsp_fullbasepath(fsp, NULL, 0);
515                 char fullpath[len+1];
516
517                 fsp_fullbasepath(fsp, fullpath, sizeof(fullpath));
518
519                 /*
520                  * Avoid /. at the end of the path name. notify can't
521                  * deal with it.
522                  */
523                 if (len > 1 && fullpath[len-1] == '.' &&
524                     fullpath[len-2] == '/') {
525                         fullpath[len-2] = '\0';
526                 }
527
528                 notify_remove(fsp->conn->sconn->notify_ctx, fsp, fullpath);
529                 TALLOC_FREE(fsp->notify);
530         }
531
532         /* Ensure this event will never fire. */
533         TALLOC_FREE(fsp->update_write_time_event);
534
535         if (fsp->op != NULL) {
536                 fsp->op->compat = NULL;
537         }
538         TALLOC_FREE(fsp->op);
539
540         if ((req != NULL) && (fsp == req->chain_fsp)) {
541                 req->chain_fsp = NULL;
542         }
543
544         /*
545          * Clear all possible chained fsp
546          * pointers in the SMB2 request queue.
547          */
548         remove_smb2_chained_fsp(fsp);
549
550         /* Drop all remaining extensions. */
551         vfs_remove_all_fsp_extensions(fsp);
552
553         fsp_free(fsp);
554
555         DEBUG(5,("freed files structure %llu (%u used)\n",
556                  (unsigned long long)fnum, (unsigned int)sconn->num_files));
557 }
558
559 /****************************************************************************
560  Get an fsp from a packet given a 16 bit fnum.
561 ****************************************************************************/
562
563 files_struct *file_fsp(struct smb_request *req, uint16_t fid)
564 {
565         struct smbXsrv_open *op;
566         NTSTATUS status;
567         NTTIME now = 0;
568         files_struct *fsp;
569
570         if (req == NULL) {
571                 /*
572                  * We should never get here. req==NULL could in theory
573                  * only happen from internal opens with a non-zero
574                  * root_dir_fid. Internal opens just don't do that, at
575                  * least they are not supposed to do so. And if they
576                  * start to do so, they better fake up a smb_request
577                  * from which we get the right smbd_server_conn. While
578                  * this should never happen, let's return NULL here.
579                  */
580                 return NULL;
581         }
582
583         if (req->chain_fsp != NULL) {
584                 if (req->chain_fsp->deferred_close) {
585                         return NULL;
586                 }
587                 return req->chain_fsp;
588         }
589
590         if (req->xconn == NULL) {
591                 return NULL;
592         }
593
594         now = timeval_to_nttime(&req->request_time);
595
596         status = smb1srv_open_lookup(req->xconn,
597                                      fid, now, &op);
598         if (!NT_STATUS_IS_OK(status)) {
599                 return NULL;
600         }
601
602         fsp = op->compat;
603         if (fsp == NULL) {
604                 return NULL;
605         }
606
607         if (fsp->deferred_close) {
608                 return NULL;
609         }
610
611         req->chain_fsp = fsp;
612         return fsp;
613 }
614
615 struct files_struct *file_fsp_get(struct smbd_smb2_request *smb2req,
616                                   uint64_t persistent_id,
617                                   uint64_t volatile_id)
618 {
619         struct smbXsrv_open *op;
620         NTSTATUS status;
621         NTTIME now = 0;
622         struct files_struct *fsp;
623
624         now = timeval_to_nttime(&smb2req->request_time);
625
626         status = smb2srv_open_lookup(smb2req->xconn,
627                                      persistent_id, volatile_id,
628                                      now, &op);
629         if (!NT_STATUS_IS_OK(status)) {
630                 return NULL;
631         }
632
633         fsp = op->compat;
634         if (fsp == NULL) {
635                 return NULL;
636         }
637
638         if (smb2req->tcon == NULL) {
639                 return NULL;
640         }
641
642         if (smb2req->tcon->compat != fsp->conn) {
643                 return NULL;
644         }
645
646         if (smb2req->session == NULL) {
647                 return NULL;
648         }
649
650         if (smb2req->session->compat == NULL) {
651                 return NULL;
652         }
653
654         if (smb2req->session->compat->vuid != fsp->vuid) {
655                 return NULL;
656         }
657
658         if (fsp->deferred_close) {
659                 return NULL;
660         }
661
662         return fsp;
663 }
664
665 struct files_struct *file_fsp_smb2(struct smbd_smb2_request *smb2req,
666                                    uint64_t persistent_id,
667                                    uint64_t volatile_id)
668 {
669         struct files_struct *fsp;
670
671         if (smb2req->compat_chain_fsp != NULL) {
672                 if (smb2req->compat_chain_fsp->deferred_close) {
673                         return NULL;
674                 }
675                 return smb2req->compat_chain_fsp;
676         }
677
678         fsp = file_fsp_get(smb2req, persistent_id, volatile_id);
679         if (fsp == NULL) {
680                 return NULL;
681         }
682
683         smb2req->compat_chain_fsp = fsp;
684         return fsp;
685 }
686
687 /****************************************************************************
688  Duplicate the file handle part for a DOS or FCB open.
689 ****************************************************************************/
690
691 NTSTATUS dup_file_fsp(struct smb_request *req, files_struct *from,
692                       uint32_t access_mask, uint32_t share_access,
693                       uint32_t create_options, files_struct *to)
694 {
695         /* this can never happen for print files */
696         SMB_ASSERT(from->print_file == NULL);
697
698         TALLOC_FREE(to->fh);
699
700         to->fh = from->fh;
701         to->fh->ref_count++;
702
703         to->file_id = from->file_id;
704         to->initial_allocation_size = from->initial_allocation_size;
705         to->file_pid = from->file_pid;
706         to->vuid = from->vuid;
707         to->open_time = from->open_time;
708         to->access_mask = access_mask;
709         to->share_access = share_access;
710         to->oplock_type = from->oplock_type;
711         to->can_lock = from->can_lock;
712         to->can_read = ((access_mask & FILE_READ_DATA) != 0);
713         to->can_write =
714                 CAN_WRITE(from->conn) &&
715                 ((access_mask & (FILE_WRITE_DATA | FILE_APPEND_DATA)) != 0);
716         to->modified = from->modified;
717         to->is_directory = from->is_directory;
718         to->aio_write_behind = from->aio_write_behind;
719
720         return fsp_set_smb_fname(to, from->fsp_name);
721 }
722
723 /**
724  * Return a jenkins hash of a pathname on a connection.
725  */
726
727 NTSTATUS file_name_hash(connection_struct *conn,
728                         const char *name, uint32_t *p_name_hash)
729 {
730         char tmpbuf[PATH_MAX];
731         char *fullpath, *to_free;
732         ssize_t len;
733         TDB_DATA key;
734
735         /* Set the hash of the full pathname. */
736
737         len = full_path_tos(conn->connectpath, name, tmpbuf, sizeof(tmpbuf),
738                             &fullpath, &to_free);
739         if (len == -1) {
740                 return NT_STATUS_NO_MEMORY;
741         }
742         key = (TDB_DATA) { .dptr = (uint8_t *)fullpath, .dsize = len+1 };
743         *p_name_hash = tdb_jenkins_hash(&key);
744
745         DEBUG(10,("file_name_hash: %s hash 0x%x\n",
746                   fullpath,
747                 (unsigned int)*p_name_hash ));
748
749         TALLOC_FREE(to_free);
750         return NT_STATUS_OK;
751 }
752
753 /**
754  * The only way that the fsp->fsp_name field should ever be set.
755  */
756 NTSTATUS fsp_set_smb_fname(struct files_struct *fsp,
757                            const struct smb_filename *smb_fname_in)
758 {
759         struct smb_filename *smb_fname_new;
760
761         smb_fname_new = cp_smb_filename(fsp, smb_fname_in);
762         if (smb_fname_new == NULL) {
763                 return NT_STATUS_NO_MEMORY;
764         }
765
766         TALLOC_FREE(fsp->fsp_name);
767         fsp->fsp_name = smb_fname_new;
768
769         return file_name_hash(fsp->conn,
770                         smb_fname_str_dbg(fsp->fsp_name),
771                         &fsp->name_hash);
772 }
773
774 const struct GUID *fsp_client_guid(const files_struct *fsp)
775 {
776         return &fsp->conn->sconn->client->connections->smb2.client.guid;
777 }
778
779 size_t fsp_fullbasepath(struct files_struct *fsp, char *buf, size_t buflen)
780 {
781         int len;
782
783         len = snprintf(buf, buflen, "%s/%s", fsp->conn->connectpath,
784                        fsp->fsp_name->base_name);
785         SMB_ASSERT(len>0);
786
787         return len;
788 }