s3:smbd: try to make fsp->fh->gen_id as globally unique as possible
[kai/samba-autobuild/.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 <ccan/hash/hash.h>
26 #include "lib/util/bitmap.h"
27
28 #define FILE_HANDLE_OFFSET 0x1000
29
30 /****************************************************************************
31  Return a unique number identifying this fsp over the life of this pid,
32  and try to make it as globally unique as possible.
33  See bug #8995 for the details.
34 ****************************************************************************/
35
36 static unsigned long get_gen_count(struct smbd_server_connection *sconn)
37 {
38         /*
39          * While fsp->fh->gen_id is 'unsigned long' currently
40          * (which might by 8 bytes),
41          * there's some oplock code which truncates it to
42          * uint32_t(using IVAL()).
43          */
44         if (sconn->file_gen_counter == 0) {
45                 sconn->file_gen_counter = generate_random();
46         }
47         sconn->file_gen_counter += 1;
48         if (sconn->file_gen_counter >= UINT32_MAX) {
49                 sconn->file_gen_counter = 0;
50         }
51         if (sconn->file_gen_counter == 0) {
52                 sconn->file_gen_counter += 1;
53         }
54         return sconn->file_gen_counter;
55 }
56
57 /****************************************************************************
58  Find first available file slot.
59 ****************************************************************************/
60
61 NTSTATUS file_new(struct smb_request *req, connection_struct *conn,
62                   files_struct **result)
63 {
64         struct smbd_server_connection *sconn = conn->sconn;
65         int i = -1;
66         files_struct *fsp;
67         NTSTATUS status;
68
69         if (sconn->file_bmap != NULL) {
70
71                 /*
72                  * we want to give out file handles differently on each new
73                  * connection because of a common bug in MS clients where they
74                  * try to reuse a file descriptor from an earlier smb
75                  * connection. This code increases the chance that the errant
76                  * client will get an error rather than causing corruption
77                  */
78                 if (sconn->first_file == 0) {
79                         sconn->first_file = (getpid() ^ (int)time(NULL));
80                         sconn->first_file %= sconn->real_max_open_files;
81                 }
82
83                 /* TODO: Port the id-tree implementation from Samba4 */
84
85                 i = bitmap_find(sconn->file_bmap, sconn->first_file);
86                 if (i == -1) {
87                         DEBUG(0,("ERROR! Out of file structures\n"));
88                         /*
89                          * TODO: We have to unconditionally return a DOS error
90                          * here, W2k3 even returns ERRDOS/ERRnofids for
91                          * ntcreate&x with NTSTATUS negotiated
92                          */
93                         return NT_STATUS_TOO_MANY_OPENED_FILES;
94                 }
95         }
96
97         /*
98          * Make a child of the connection_struct as an fsp can't exist
99          * independent of a connection.
100          */
101         fsp = talloc_zero(conn, struct files_struct);
102         if (!fsp) {
103                 return NT_STATUS_NO_MEMORY;
104         }
105
106         /*
107          * This can't be a child of fsp because the file_handle can be ref'd
108          * when doing a dos/fcb open, which will then share the file_handle
109          * across multiple fsps.
110          */
111         fsp->fh = talloc_zero(conn, struct fd_handle);
112         if (!fsp->fh) {
113                 TALLOC_FREE(fsp);
114                 return NT_STATUS_NO_MEMORY;
115         }
116
117         fsp->fh->ref_count = 1;
118         fsp->fh->fd = -1;
119
120         fsp->fnum = -1;
121         fsp->conn = conn;
122         fsp->fh->gen_id = get_gen_count(sconn);
123         GetTimeOfDay(&fsp->open_time);
124
125         if (sconn->file_bmap != NULL) {
126                 sconn->first_file = (i+1) % (sconn->real_max_open_files);
127
128                 bitmap_set(sconn->file_bmap, i);
129
130                 fsp->fnum = i + FILE_HANDLE_OFFSET;
131                 SMB_ASSERT(fsp->fnum < 65536);
132         }
133
134         DLIST_ADD(sconn->files, fsp);
135         sconn->num_files += 1;
136
137         conn->num_files_open++;
138
139         /*
140          * Create an smb_filename with "" for the base_name.  There are very
141          * few NULL checks, so make sure it's initialized with something. to
142          * be safe until an audit can be done.
143          */
144         status = create_synthetic_smb_fname(fsp, "", NULL, NULL,
145                                             &fsp->fsp_name);
146         if (!NT_STATUS_IS_OK(status)) {
147                 file_free(NULL, fsp);
148                 return status;
149         }
150
151         DEBUG(5,("allocated file structure %d, fnum = %d (%u used)\n",
152                  i, fsp->fnum, (unsigned int)sconn->num_files));
153
154         if (req != NULL) {
155                 req->chain_fsp = fsp;
156         }
157
158         /* A new fsp invalidates the positive and
159           negative fsp_fi_cache as the new fsp is pushed
160           at the start of the list and we search from
161           a cache hit to the *end* of the list. */
162
163         ZERO_STRUCT(sconn->fsp_fi_cache);
164
165         *result = fsp;
166         return NT_STATUS_OK;
167 }
168
169 /****************************************************************************
170  Close all open files for a connection.
171 ****************************************************************************/
172
173 void file_close_conn(connection_struct *conn)
174 {
175         files_struct *fsp, *next;
176
177         for (fsp=conn->sconn->files; fsp; fsp=next) {
178                 next = fsp->next;
179                 if (fsp->conn == conn) {
180                         close_file(NULL, fsp, SHUTDOWN_CLOSE);
181                 }
182         }
183 }
184
185 /****************************************************************************
186  Close all open files for a pid and a vuid.
187 ****************************************************************************/
188
189 void file_close_pid(struct smbd_server_connection *sconn, uint16 smbpid,
190                     uint64_t vuid)
191 {
192         files_struct *fsp, *next;
193
194         for (fsp=sconn->files;fsp;fsp=next) {
195                 next = fsp->next;
196                 if ((fsp->file_pid == smbpid) && (fsp->vuid == vuid)) {
197                         close_file(NULL, fsp, SHUTDOWN_CLOSE);
198                 }
199         }
200 }
201
202 /****************************************************************************
203  Initialise file structures.
204 ****************************************************************************/
205
206 static int files_max_open_fds;
207
208 bool file_init_global(void)
209 {
210         int request_max = lp_max_open_files();
211         int real_lim;
212         int real_max;
213
214         if (files_max_open_fds != 0) {
215                 return true;
216         }
217
218         /*
219          * Set the max_open files to be the requested
220          * max plus a fudgefactor to allow for the extra
221          * fd's we need such as log files etc...
222          */
223         real_lim = set_maxfiles(request_max + MAX_OPEN_FUDGEFACTOR);
224
225         real_max = real_lim - MAX_OPEN_FUDGEFACTOR;
226
227         if (real_max + FILE_HANDLE_OFFSET + MAX_OPEN_PIPES > 65536) {
228                 real_max = 65536 - FILE_HANDLE_OFFSET - MAX_OPEN_PIPES;
229         }
230
231         if (real_max != request_max) {
232                 DEBUG(1, ("file_init_global: Information only: requested %d "
233                           "open files, %d are available.\n",
234                           request_max, real_max));
235         }
236
237         SMB_ASSERT(real_max > 100);
238
239         files_max_open_fds = real_max;
240         return true;
241 }
242
243 bool file_init(struct smbd_server_connection *sconn)
244 {
245         bool ok;
246
247         ok = file_init_global();
248         if (!ok) {
249                 return false;
250         }
251
252         sconn->real_max_open_files = files_max_open_fds;
253
254         sconn->file_bmap = bitmap_talloc(sconn, sconn->real_max_open_files);
255         if (!sconn->file_bmap) {
256                 return false;
257         }
258
259         return true;
260 }
261
262 /****************************************************************************
263  Close files open by a specified vuid.
264 ****************************************************************************/
265
266 void file_close_user(struct smbd_server_connection *sconn, uint64_t vuid)
267 {
268         files_struct *fsp, *next;
269
270         for (fsp=sconn->files; fsp; fsp=next) {
271                 next=fsp->next;
272                 if (fsp->vuid == vuid) {
273                         close_file(NULL, fsp, SHUTDOWN_CLOSE);
274                 }
275         }
276 }
277
278 /*
279  * Walk the files table until "fn" returns non-NULL
280  */
281
282 struct files_struct *files_forall(
283         struct smbd_server_connection *sconn,
284         struct files_struct *(*fn)(struct files_struct *fsp,
285                                    void *private_data),
286         void *private_data)
287 {
288         struct files_struct *fsp, *next;
289
290         for (fsp = sconn->files; fsp; fsp = next) {
291                 struct files_struct *ret;
292                 next = fsp->next;
293                 ret = fn(fsp, private_data);
294                 if (ret != NULL) {
295                         return ret;
296                 }
297         }
298         return NULL;
299 }
300
301 /****************************************************************************
302  Find a fsp given a file descriptor.
303 ****************************************************************************/
304
305 files_struct *file_find_fd(struct smbd_server_connection *sconn, int fd)
306 {
307         int count=0;
308         files_struct *fsp;
309
310         for (fsp=sconn->files; fsp; fsp=fsp->next,count++) {
311                 if (fsp->fh->fd == fd) {
312                         if (count > 10) {
313                                 DLIST_PROMOTE(sconn->files, fsp);
314                         }
315                         return fsp;
316                 }
317         }
318
319         return NULL;
320 }
321
322 /****************************************************************************
323  Find a fsp given a device, inode and file_id.
324 ****************************************************************************/
325
326 files_struct *file_find_dif(struct smbd_server_connection *sconn,
327                             struct file_id id, unsigned long gen_id)
328 {
329         int count=0;
330         files_struct *fsp;
331
332         if (gen_id == 0) {
333                 return NULL;
334         }
335
336         for (fsp=sconn->files; fsp; fsp=fsp->next,count++) {
337                 /* We can have a fsp->fh->fd == -1 here as it could be a stat open. */
338                 if (file_id_equal(&fsp->file_id, &id) &&
339                     fsp->fh->gen_id == gen_id ) {
340                         if (count > 10) {
341                                 DLIST_PROMOTE(sconn->files, fsp);
342                         }
343                         /* Paranoia check. */
344                         if ((fsp->fh->fd == -1) &&
345                             (fsp->oplock_type != NO_OPLOCK) &&
346                             (fsp->oplock_type != FAKE_LEVEL_II_OPLOCK)) {
347                                 DEBUG(0,("file_find_dif: file %s file_id = "
348                                          "%s, gen = %u oplock_type = %u is a "
349                                          "stat open with oplock type !\n",
350                                          fsp_str_dbg(fsp),
351                                          file_id_string_tos(&fsp->file_id),
352                                          (unsigned int)fsp->fh->gen_id,
353                                          (unsigned int)fsp->oplock_type ));
354                                 smb_panic("file_find_dif");
355                         }
356                         return fsp;
357                 }
358         }
359
360         return NULL;
361 }
362
363 /****************************************************************************
364  Find the first fsp given a device and inode.
365  We use a singleton cache here to speed up searching from getfilepathinfo
366  calls.
367 ****************************************************************************/
368
369 files_struct *file_find_di_first(struct smbd_server_connection *sconn,
370                                  struct file_id id)
371 {
372         files_struct *fsp;
373
374         if (file_id_equal(&sconn->fsp_fi_cache.id, &id)) {
375                 /* Positive or negative cache hit. */
376                 return sconn->fsp_fi_cache.fsp;
377         }
378
379         sconn->fsp_fi_cache.id = id;
380
381         for (fsp=sconn->files;fsp;fsp=fsp->next) {
382                 if (file_id_equal(&fsp->file_id, &id)) {
383                         /* Setup positive cache. */
384                         sconn->fsp_fi_cache.fsp = fsp;
385                         return fsp;
386                 }
387         }
388
389         /* Setup negative cache. */
390         sconn->fsp_fi_cache.fsp = NULL;
391         return NULL;
392 }
393
394 /****************************************************************************
395  Find the next fsp having the same device and inode.
396 ****************************************************************************/
397
398 files_struct *file_find_di_next(files_struct *start_fsp)
399 {
400         files_struct *fsp;
401
402         for (fsp = start_fsp->next;fsp;fsp=fsp->next) {
403                 if (file_id_equal(&fsp->file_id, &start_fsp->file_id)) {
404                         return fsp;
405                 }
406         }
407
408         return NULL;
409 }
410
411 /****************************************************************************
412  Find any fsp open with a pathname below that of an already open path.
413 ****************************************************************************/
414
415 bool file_find_subpath(files_struct *dir_fsp)
416 {
417         files_struct *fsp;
418         size_t dlen;
419         char *d_fullname = NULL;
420
421         d_fullname = talloc_asprintf(talloc_tos(), "%s/%s",
422                                      dir_fsp->conn->connectpath,
423                                      dir_fsp->fsp_name->base_name);
424
425         if (!d_fullname) {
426                 return false;
427         }
428
429         dlen = strlen(d_fullname);
430
431         for (fsp=dir_fsp->conn->sconn->files; fsp; fsp=fsp->next) {
432                 char *d1_fullname;
433
434                 if (fsp == dir_fsp) {
435                         continue;
436                 }
437
438                 d1_fullname = talloc_asprintf(talloc_tos(),
439                                         "%s/%s",
440                                         fsp->conn->connectpath,
441                                         fsp->fsp_name->base_name);
442
443                 /*
444                  * If the open file has a path that is a longer
445                  * component, then it's a subpath.
446                  */
447                 if (strnequal(d_fullname, d1_fullname, dlen) &&
448                                 (d1_fullname[dlen] == '/')) {
449                         TALLOC_FREE(d1_fullname);
450                         TALLOC_FREE(d_fullname);
451                         return true;
452                 }
453                 TALLOC_FREE(d1_fullname);
454         }
455
456         TALLOC_FREE(d_fullname);
457         return false;
458 }
459
460 /****************************************************************************
461  Sync open files on a connection.
462 ****************************************************************************/
463
464 void file_sync_all(connection_struct *conn)
465 {
466         files_struct *fsp, *next;
467
468         for (fsp=conn->sconn->files; fsp; fsp=next) {
469                 next=fsp->next;
470                 if ((conn == fsp->conn) && (fsp->fh->fd != -1)) {
471                         sync_file(conn, fsp, True /* write through */);
472                 }
473         }
474 }
475
476 /****************************************************************************
477  Free up a fsp.
478 ****************************************************************************/
479
480 void file_free(struct smb_request *req, files_struct *fsp)
481 {
482         struct smbd_server_connection *sconn = fsp->conn->sconn;
483
484         DLIST_REMOVE(sconn->files, fsp);
485         SMB_ASSERT(sconn->num_files > 0);
486         sconn->num_files--;
487
488         TALLOC_FREE(fsp->fake_file_handle);
489
490         if (fsp->fh->ref_count == 1) {
491                 TALLOC_FREE(fsp->fh);
492         } else {
493                 fsp->fh->ref_count--;
494         }
495
496         if (fsp->notify) {
497                 struct notify_context *notify_ctx =
498                         fsp->conn->sconn->notify_ctx;
499                 notify_remove(notify_ctx, fsp);
500                 TALLOC_FREE(fsp->notify);
501         }
502
503         /* Ensure this event will never fire. */
504         TALLOC_FREE(fsp->update_write_time_event);
505
506         if (sconn->file_bmap != NULL) {
507                 bitmap_clear(sconn->file_bmap, fsp->fnum - FILE_HANDLE_OFFSET);
508         }
509         DEBUG(5,("freed files structure %d (%u used)\n",
510                  fsp->fnum, (unsigned int)sconn->num_files));
511
512         fsp->conn->num_files_open--;
513
514         if ((req != NULL) && (fsp == req->chain_fsp)) {
515                 req->chain_fsp = NULL;
516         }
517
518         /*
519          * Clear all possible chained fsp
520          * pointers in the SMB2 request queue.
521          */
522         if (req != NULL && req->smb2req) {
523                 remove_smb2_chained_fsp(fsp);
524         }
525
526         /* Closing a file can invalidate the positive cache. */
527         if (fsp == sconn->fsp_fi_cache.fsp) {
528                 ZERO_STRUCT(sconn->fsp_fi_cache);
529         }
530
531         /* Drop all remaining extensions. */
532         vfs_remove_all_fsp_extensions(fsp);
533
534         /* this is paranoia, just in case someone tries to reuse the
535            information */
536         ZERO_STRUCTP(fsp);
537
538         /* fsp->fsp_name is a talloc child and is free'd automatically. */
539         TALLOC_FREE(fsp);
540 }
541
542 /****************************************************************************
543  Get an fsp from a 16 bit fnum.
544 ****************************************************************************/
545
546 static struct files_struct *file_fnum(struct smbd_server_connection *sconn,
547                                       uint16 fnum)
548 {
549         files_struct *fsp;
550         int count=0;
551
552         for (fsp=sconn->files; fsp; fsp=fsp->next, count++) {
553                 if (fsp->fnum == -1) {
554                         continue;
555                 }
556
557                 if (fsp->fnum == fnum) {
558                         if (count > 10) {
559                                 DLIST_PROMOTE(sconn->files, fsp);
560                         }
561                         return fsp;
562                 }
563         }
564         return NULL;
565 }
566
567 /****************************************************************************
568  Get an fsp from a packet given a 16 bit fnum.
569 ****************************************************************************/
570
571 files_struct *file_fsp(struct smb_request *req, uint16 fid)
572 {
573         files_struct *fsp;
574
575         if (req == NULL) {
576                 /*
577                  * We should never get here. req==NULL could in theory
578                  * only happen from internal opens with a non-zero
579                  * root_dir_fid. Internal opens just don't do that, at
580                  * least they are not supposed to do so. And if they
581                  * start to do so, they better fake up a smb_request
582                  * from which we get the right smbd_server_conn. While
583                  * this should never happen, let's return NULL here.
584                  */
585                 return NULL;
586         }
587
588         if (req->chain_fsp != NULL) {
589                 return req->chain_fsp;
590         }
591
592         fsp = file_fnum(req->sconn, fid);
593         if (fsp != NULL) {
594                 req->chain_fsp = fsp;
595         }
596         return fsp;
597 }
598
599 struct files_struct *file_fsp_smb2(struct smbd_smb2_request *smb2req,
600                                    uint64_t persistent_id,
601                                    uint64_t volatile_id)
602 {
603         struct files_struct *fsp;
604
605         if (smb2req->compat_chain_fsp != NULL) {
606                 return smb2req->compat_chain_fsp;
607         }
608
609         if (persistent_id != volatile_id) {
610                 return NULL;
611         }
612
613         if (volatile_id > UINT16_MAX) {
614                 return NULL;
615         }
616
617         fsp = file_fnum(smb2req->sconn, (uint16_t)volatile_id);
618         if (fsp == NULL) {
619                 return NULL;
620         }
621
622         if (smb2req->tcon == NULL) {
623                 return NULL;
624         }
625
626         if (smb2req->tcon->compat_conn != fsp->conn) {
627                 return NULL;
628         }
629
630         if (smb2req->session == NULL) {
631                 return NULL;
632         }
633
634         if (smb2req->session->vuid != fsp->vuid) {
635                 return NULL;
636         }
637
638         smb2req->compat_chain_fsp = fsp;
639         return fsp;
640 }
641
642 /****************************************************************************
643  Duplicate the file handle part for a DOS or FCB open.
644 ****************************************************************************/
645
646 NTSTATUS dup_file_fsp(struct smb_request *req, files_struct *from,
647                       uint32 access_mask, uint32 share_access,
648                       uint32 create_options, files_struct *to)
649 {
650         /* this can never happen for print files */
651         SMB_ASSERT(from->print_file == NULL);
652
653         TALLOC_FREE(to->fh);
654
655         to->fh = from->fh;
656         to->fh->ref_count++;
657
658         to->file_id = from->file_id;
659         to->initial_allocation_size = from->initial_allocation_size;
660         to->file_pid = from->file_pid;
661         to->vuid = from->vuid;
662         to->open_time = from->open_time;
663         to->access_mask = access_mask;
664         to->share_access = share_access;
665         to->oplock_type = from->oplock_type;
666         to->can_lock = from->can_lock;
667         to->can_read = ((access_mask & FILE_READ_DATA) != 0);
668         to->can_write =
669                 CAN_WRITE(from->conn) &&
670                 ((access_mask & (FILE_WRITE_DATA | FILE_APPEND_DATA)) != 0);
671         to->modified = from->modified;
672         to->is_directory = from->is_directory;
673         to->aio_write_behind = from->aio_write_behind;
674
675         return fsp_set_smb_fname(to, from->fsp_name);
676 }
677
678 /**
679  * Return a jenkins hash of a pathname on a connection.
680  */
681
682 NTSTATUS file_name_hash(connection_struct *conn,
683                         const char *name, uint32_t *p_name_hash)
684 {
685         char *fullpath = NULL;
686
687         /* Set the hash of the full pathname. */
688         fullpath = talloc_asprintf(talloc_tos(),
689                         "%s/%s",
690                         conn->connectpath,
691                         name);
692         if (!fullpath) {
693                 return NT_STATUS_NO_MEMORY;
694         }
695         *p_name_hash = hash(fullpath, talloc_get_size(fullpath), 0);
696
697         DEBUG(10,("file_name_hash: %s hash 0x%x\n",
698                 fullpath,
699                 (unsigned int)*p_name_hash ));
700
701         TALLOC_FREE(fullpath);
702         return NT_STATUS_OK;
703 }
704
705 /**
706  * The only way that the fsp->fsp_name field should ever be set.
707  */
708 NTSTATUS fsp_set_smb_fname(struct files_struct *fsp,
709                            const struct smb_filename *smb_fname_in)
710 {
711         NTSTATUS status;
712         struct smb_filename *smb_fname_new;
713
714         status = copy_smb_filename(fsp, smb_fname_in, &smb_fname_new);
715         if (!NT_STATUS_IS_OK(status)) {
716                 return status;
717         }
718
719         TALLOC_FREE(fsp->fsp_name);
720         fsp->fsp_name = smb_fname_new;
721
722         return file_name_hash(fsp->conn,
723                         smb_fname_str_dbg(fsp->fsp_name),
724                         &fsp->name_hash);
725 }