Convert all uint32/16/8 to _t in source3/libsmb.
[bbaumbach/samba-autobuild/.git] / source3 / libsmb / smb_share_modes.c
1 /*
2    Samba share mode database library external interface library.
3    Used by non-Samba products needing access to the Samba share mode db.
4
5    NOTICE FOR SAMBA 4.2.0
6
7    THIS CODE IS NON-FUNCTIONAL IN SAMBA 4.2.0 AND ABOVE DUE TO THE CHANGES IN
8    SHARE MODE DATABASE SCHEMA FOR SMB2 LEASES.
9
10    CONTACT THE AUTHOR jra@samba.org IF YOU WISH TO RE-ENABLE
11    THIS CODE.
12
13    Copyright (C) Jeremy Allison 2005 - 2006
14
15    sharemodes_procid functions (C) Copyright (C) Volker Lendecke 2005
16
17      ** NOTE! The following LGPL license applies to this module only.
18      ** This does NOT imply that all of Samba is released
19      ** under the LGPL
20
21    This library is free software; you can redistribute it and/or
22    modify it under the terms of the GNU Lesser General Public
23    License as published by the Free Software Foundation; either
24    version 3 of the License, or (at your option) any later version.
25
26    This library is distributed in the hope that it will be useful,
27    but WITHOUT ANY WARRANTY; without even the implied warranty of
28    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
29    Lesser General Public License for more details.
30
31    You should have received a copy of the GNU Lesser General Public
32    License along with this library; if not, see <http://www.gnu.org/licenses/>.
33 */
34
35 #include "includes.h"
36 #include "system/filesys.h"
37 #include "smb_share_modes.h"
38 #include <tdb.h>
39 #include "librpc/gen_ndr/open_files.h"
40
41 /* Database context handle. */
42 struct smbdb_ctx {
43         TDB_CONTEXT *smb_tdb;
44 };
45
46 /* Remove the paranoid malloc checker. */
47 #ifdef malloc
48 #undef malloc
49 #endif
50
51 /*
52  * Internal structure of locking.tdb share mode db.
53  * Used by locking.c and libsmbsharemodes.c
54  */
55
56 struct locking_data {
57         union {
58                 struct {
59                         int num_share_mode_entries;
60                         struct timespec old_write_time;
61                         struct timespec changed_write_time;
62                         uint32_t num_delete_token_entries;
63                 } s;
64                 struct share_mode_entry dummy; /* Needed for alignment. */
65         } u;
66         /* The following four entries are implicit
67
68            (1) struct share_mode_entry modes[num_share_mode_entries];
69
70            (2) A num_delete_token_entries of structs {
71                 uint32_t len_delete_token;
72                 char unix_token[len_delete_token] (divisible by 4).
73            };
74
75            (3) char share_name[];
76            (4) char file_name[];
77         */
78 };
79
80 int smb_create_share_mode_entry_ex(struct smbdb_ctx *db_ctx, uint64_t dev,
81                                 uint64_t ino, uint64_t extid,
82                                 const struct smb_share_mode_entry *new_entry,
83                                 const char *sharepath, const char *filename);
84
85 static bool sharemodes_procid_equal(const struct server_id *p1, const struct server_id *p2)
86 {
87         return (p1->pid == p2->pid);
88 }
89
90 static pid_t sharemodes_procid_to_pid(const struct server_id *proc)
91 {
92         return proc->pid;
93 }
94
95 /*
96  * open/close sharemode database.
97  */
98
99 struct smbdb_ctx *smb_share_mode_db_open(const char *db_path)
100 {
101         struct smbdb_ctx *smb_db = (struct smbdb_ctx *)malloc(sizeof(struct smbdb_ctx));
102
103         if (!smb_db) {
104                 return NULL;
105         }
106
107         memset(smb_db, '\0', sizeof(struct smbdb_ctx));
108
109         /* FIXME: We should *never* open a tdb without logging! */
110         smb_db->smb_tdb = tdb_open(db_path,
111                                    0, TDB_DEFAULT|TDB_CLEAR_IF_FIRST|TDB_INCOMPATIBLE_HASH,
112                                    O_RDWR|O_CREAT,
113                                    0644);
114
115         if (!smb_db->smb_tdb) {
116                 free(smb_db);
117                 return NULL;
118         }
119
120         /* Should check that this is the correct version.... */
121         return smb_db;
122 }
123
124 /* key and data records in the tdb locking database */
125 struct locking_key {
126         SMB_DEV_T dev;
127         SMB_INO_T inode;
128         uint64_t extid;
129 };
130
131 int smb_share_mode_db_close(struct smbdb_ctx *db_ctx)
132 {
133         int ret = tdb_close(db_ctx->smb_tdb);
134         free(db_ctx);
135         return ret;
136 }
137
138 static TDB_DATA get_locking_key(struct locking_key *lk, uint64_t dev,
139                                 uint64_t ino, uint64_t extid)
140 {
141         TDB_DATA ld;
142
143         memset(lk, '\0', sizeof(*lk));
144         lk->dev = (SMB_DEV_T)dev;
145         lk->inode = (SMB_INO_T)ino;
146         lk->extid = extid;
147         ld.dptr = (uint8_t *)lk;
148         ld.dsize = sizeof(*lk);
149         return ld;
150 }
151
152 /*
153  * lock/unlock entry in sharemode database.
154  */
155
156 int smb_lock_share_mode_entry(struct smbdb_ctx *db_ctx,
157                                 uint64_t dev,
158                                 uint64_t ino,
159                                 uint64_t extid)
160 {
161         struct locking_key lk;
162         return tdb_chainlock(db_ctx->smb_tdb, get_locking_key(&lk, dev, ino,
163                                                               extid)) == 0 ? 0 : -1;
164 }
165
166 int smb_unlock_share_mode_entry(struct smbdb_ctx *db_ctx,
167                                 uint64_t dev,
168                                 uint64_t ino,
169                                 uint64_t extid)
170 {
171         struct locking_key lk;
172         tdb_chainunlock(db_ctx->smb_tdb,
173                         get_locking_key(&lk, dev, ino, extid));
174         return 0;
175 }
176
177 /*
178  * Check if an external smb_share_mode_entry and an internal share_mode entry match.
179  */
180
181 static int share_mode_entry_equal(const struct smb_share_mode_entry *e_entry,
182                                 const struct share_mode_entry *entry)
183 {
184         return (sharemodes_procid_equal(&e_entry->pid, &entry->pid) &&
185                 e_entry->file_id == (uint32_t)entry->share_file_id &&
186                 e_entry->open_time.tv_sec == entry->time.tv_sec &&
187                 e_entry->open_time.tv_usec == entry->time.tv_usec &&
188                 e_entry->share_access == (uint32_t)entry->share_access &&
189                 e_entry->access_mask == (uint32_t)entry->access_mask &&
190                 e_entry->dev == entry->id.devid && 
191                 e_entry->ino == entry->id.inode &&
192                 e_entry->extid == entry->id.extid);
193 }
194
195 /*
196  * Create an internal Samba share_mode entry from an external smb_share_mode_entry.
197  */
198
199 static void create_share_mode_entry(struct share_mode_entry *out,
200                                 const struct smb_share_mode_entry *in,
201                                 uint32_t name_hash)
202 {
203         memset(out, '\0', sizeof(struct share_mode_entry));
204
205         out->pid = in->pid;
206         out->share_file_id = (unsigned long)in->file_id;
207         out->time.tv_sec = in->open_time.tv_sec;
208         out->time.tv_usec = in->open_time.tv_usec;
209         out->share_access = in->share_access;
210         out->access_mask = in->access_mask;
211         out->id.devid = in->dev;
212         out->id.inode = in->ino;
213         out->id.extid = in->extid;
214         out->uid = (uint32_t)geteuid();
215         out->flags = 0;
216         out->name_hash = name_hash;
217 }
218
219 /*
220  * Return the current share mode list for an open file.
221  * This uses similar (but simplified) logic to locking/locking.c
222  */
223
224 int smb_get_share_mode_entries(struct smbdb_ctx *db_ctx,
225                                 uint64_t dev,
226                                 uint64_t ino,
227                                 uint64_t extid,
228                                 struct smb_share_mode_entry **pp_list,
229                                 unsigned char *p_delete_on_close)
230 {
231         struct locking_key lk;
232         TDB_DATA db_data;
233         struct smb_share_mode_entry *list = NULL;
234         int num_share_modes = 0;
235         struct locking_data *ld = NULL; /* internal samba db state. */
236         struct share_mode_entry *shares = NULL;
237         size_t i;
238         int list_num;
239
240         *pp_list = NULL;
241         *p_delete_on_close = 0;
242
243         db_data = tdb_fetch(db_ctx->smb_tdb,
244                             get_locking_key(&lk, dev, ino, extid));
245         if (!db_data.dptr) {
246                 return 0;
247         }
248
249         ld = (struct locking_data *)db_data.dptr;
250         num_share_modes = ld->u.s.num_share_mode_entries;
251
252         if (!num_share_modes) {
253                 free(db_data.dptr);
254                 return 0;
255         }
256
257         list = (struct smb_share_mode_entry *)malloc(sizeof(struct smb_share_mode_entry)*num_share_modes);
258         if (!list) {
259                 free(db_data.dptr);
260                 return -1;
261         }
262
263         memset(list, '\0', num_share_modes * sizeof(struct smb_share_mode_entry));
264
265         shares = (struct share_mode_entry *)(db_data.dptr + sizeof(struct locking_data));
266
267         list_num = 0;
268         for (i = 0; i < num_share_modes; i++) {
269                 struct share_mode_entry *share = &shares[i];
270                 struct smb_share_mode_entry *sme = &list[list_num];
271                 struct server_id pid = share->pid;
272
273                 /* Check this process really exists. */
274                 if (kill(sharemodes_procid_to_pid(&pid), 0) == -1 && (errno == ESRCH)) {
275                         continue; /* No longer exists. */
276                 }
277
278                 /* Copy into the external list. */
279                 sme->dev = share->id.devid;
280                 sme->ino = share->id.inode;
281                 sme->extid = share->id.extid;
282                 sme->share_access = (uint32_t)share->share_access;
283                 sme->access_mask = (uint32_t)share->access_mask;
284                 sme->open_time.tv_sec = share->time.tv_sec;
285                 sme->open_time.tv_usec = share->time.tv_usec;
286                 sme->file_id = (uint32_t)share->share_file_id;
287                 sme->pid = share->pid;
288                 list_num++;
289         }
290
291         if (list_num == 0) {
292                 free(db_data.dptr);
293                 free(list);
294                 return 0;
295         }
296
297         *p_delete_on_close = ld->u.s.num_delete_token_entries != 0;
298         *pp_list = list;
299         free(db_data.dptr);
300         return list_num;
301 }
302
303 static uint32_t smb_name_hash(const char *sharepath, const char *filename, int *err)
304 {
305         char *fullpath = NULL;
306         size_t sharepath_size = strlen(sharepath);
307         size_t filename_size = strlen(filename);
308         uint32_t name_hash;
309         TDB_DATA key;
310
311         *err = 0;
312         fullpath = (char *)malloc(sharepath_size + filename_size + 2);
313         if (fullpath == NULL) {
314                 *err = 1;
315                 return 0;
316         }
317         memcpy(fullpath, sharepath, sharepath_size);
318         fullpath[sharepath_size] = '/';
319         memcpy(&fullpath[sharepath_size + 1], filename, filename_size + 1);
320
321         key = (TDB_DATA) { .dptr = (uint8_t *)fullpath,
322                            .dsize = strlen(fullpath) + 1 };
323         name_hash = tdb_jenkins_hash(&key);
324         free(fullpath);
325         return name_hash;
326 }
327
328 /* 
329  * Create an entry in the Samba share mode db.
330  */
331
332 int smb_create_share_mode_entry_ex(struct smbdb_ctx *db_ctx,
333                                 uint64_t dev,
334                                 uint64_t ino,
335                                 uint64_t extid,
336                                 const struct smb_share_mode_entry *new_entry,
337                                 const char *sharepath, /* Must be absolute utf8 path. */
338                                 const char *filename) /* Must be relative utf8 path. */
339 {
340         TDB_DATA db_data;
341         struct locking_key lk;
342         TDB_DATA locking_key =  get_locking_key(&lk, dev, ino, extid);
343         int orig_num_share_modes = 0;
344         struct locking_data *ld = NULL; /* internal samba db state. */
345         struct share_mode_entry *shares = NULL;
346         uint8_t *new_data_p = NULL;
347         size_t new_data_size = 0;
348         int err = 0;
349         uint32_t name_hash = smb_name_hash(sharepath, filename, &err);
350
351         if (err) {
352                 return -1;
353         }
354
355         db_data = tdb_fetch(db_ctx->smb_tdb, locking_key);
356         if (!db_data.dptr) {
357                 /* We must create the entry. */
358                 db_data.dptr = (uint8_t *)malloc(
359                         sizeof(struct locking_data) +
360                         sizeof(struct share_mode_entry) +
361                         strlen(sharepath) + 1 +
362                         strlen(filename) + 1);
363                 if (!db_data.dptr) {
364                         return -1;
365                 }
366                 ld = (struct locking_data *)db_data.dptr;
367                 memset(ld, '\0', sizeof(struct locking_data));
368                 ld->u.s.num_share_mode_entries = 1;
369                 ld->u.s.num_delete_token_entries = 0;
370                 shares = (struct share_mode_entry *)(db_data.dptr + sizeof(struct locking_data));
371                 create_share_mode_entry(shares, new_entry, name_hash);
372
373                 memcpy(db_data.dptr + sizeof(struct locking_data) + sizeof(struct share_mode_entry),
374                         sharepath,
375                         strlen(sharepath) + 1);
376                 memcpy(db_data.dptr + sizeof(struct locking_data) + sizeof(struct share_mode_entry) +
377                         strlen(sharepath) + 1,
378                         filename,
379                         strlen(filename) + 1);
380
381                 db_data.dsize = sizeof(struct locking_data) + sizeof(struct share_mode_entry) +
382                                         strlen(sharepath) + 1 +
383                                         strlen(filename) + 1;
384                 if (tdb_store(db_ctx->smb_tdb, locking_key, db_data, TDB_INSERT) != 0) {
385                         free(db_data.dptr);
386                         return -1;
387                 }
388                 free(db_data.dptr);
389                 return 0;
390         }
391
392         /* Entry exists, we must add a new entry. */
393         new_data_p = (uint8_t *)malloc(
394                 db_data.dsize + sizeof(struct share_mode_entry));
395         if (!new_data_p) {
396                 free(db_data.dptr);
397                 return -1;
398         }
399
400         ld = (struct locking_data *)db_data.dptr;
401         orig_num_share_modes = ld->u.s.num_share_mode_entries;
402
403         /* Copy the original data. */
404         memcpy(new_data_p, db_data.dptr, sizeof(struct locking_data) + (orig_num_share_modes * sizeof(struct share_mode_entry)));
405
406         /* Add in the new share mode */
407         shares = (struct share_mode_entry *)(new_data_p + sizeof(struct locking_data) +
408                         (orig_num_share_modes * sizeof(struct share_mode_entry)));
409
410         create_share_mode_entry(shares, new_entry, name_hash);
411
412         ld = (struct locking_data *)new_data_p;
413         ld->u.s.num_share_mode_entries++;
414
415         /* Append the original delete_tokens and filenames. */
416         memcpy(new_data_p + sizeof(struct locking_data) + (ld->u.s.num_share_mode_entries * sizeof(struct share_mode_entry)),
417                 db_data.dptr + sizeof(struct locking_data) + (orig_num_share_modes * sizeof(struct share_mode_entry)),
418                 db_data.dsize - sizeof(struct locking_data) - (orig_num_share_modes * sizeof(struct share_mode_entry)));
419
420         new_data_size = db_data.dsize + sizeof(struct share_mode_entry);
421
422         free(db_data.dptr);
423
424         db_data.dptr = new_data_p;
425         db_data.dsize = new_data_size;
426
427         if (tdb_store(db_ctx->smb_tdb, locking_key, db_data, TDB_REPLACE) != 0) {
428                 free(db_data.dptr);
429                 return -1;
430         }
431         free(db_data.dptr);
432         return 0;
433 }
434
435 /* 
436  * Create an entry in the Samba share mode db. Original interface - doesn't
437  * Distinguish between share path and filename. Fudge this by using a
438  * sharepath of / and a relative filename of (filename+1).
439  */
440
441 int smb_create_share_mode_entry(struct smbdb_ctx *db_ctx,
442                                 uint64_t dev,
443                                 uint64_t ino,
444                                 uint64_t extid,
445                                 const struct smb_share_mode_entry *new_entry,
446                                 const char *filename) /* Must be absolute utf8 path. */
447 {
448         if (*filename != '/') {
449                 abort();
450         }
451         return smb_create_share_mode_entry_ex(db_ctx, dev, ino, extid, new_entry,
452                                                 "/", &filename[1]);
453 }
454
455 int smb_delete_share_mode_entry(struct smbdb_ctx *db_ctx,
456                                 uint64_t dev,
457                                 uint64_t ino,
458                                 uint64_t extid,
459                                 const struct smb_share_mode_entry *del_entry)
460 {
461         TDB_DATA db_data;
462         struct locking_key lk;
463         TDB_DATA locking_key =  get_locking_key(&lk, dev, ino, extid);
464         int orig_num_share_modes = 0;
465         struct locking_data *ld = NULL; /* internal samba db state. */
466         struct share_mode_entry *shares = NULL;
467         uint8_t *new_data_p = NULL;
468         size_t remaining_size = 0;
469         size_t i, num_share_modes;
470         const uint8_t *remaining_ptr = NULL;
471
472         db_data = tdb_fetch(db_ctx->smb_tdb, locking_key);
473         if (!db_data.dptr) {
474                 return -1; /* Error - missing entry ! */
475         }
476
477         ld = (struct locking_data *)db_data.dptr;
478         orig_num_share_modes = ld->u.s.num_share_mode_entries;
479         shares = (struct share_mode_entry *)(db_data.dptr + sizeof(struct locking_data));
480
481         if (orig_num_share_modes == 1) {
482                 /* Only one entry - better be ours... */
483                 if (!share_mode_entry_equal(del_entry, shares)) {
484                         /* Error ! We can't delete someone else's entry ! */
485                         free(db_data.dptr);
486                         return -1;
487                 }
488                 /* It's ours - just remove the entire record. */
489                 free(db_data.dptr);
490                 return tdb_delete(db_ctx->smb_tdb, locking_key) ? -1 : 0;
491         }
492
493         /* More than one - allocate a new record minus the one we'll delete. */
494         new_data_p = (uint8_t *)malloc(
495                 db_data.dsize - sizeof(struct share_mode_entry));
496         if (!new_data_p) {
497                 free(db_data.dptr);
498                 return -1;
499         }
500
501         /* Copy the header. */
502         memcpy(new_data_p, db_data.dptr, sizeof(struct locking_data));
503
504         num_share_modes = 0;
505         for (i = 0; i < orig_num_share_modes; i++) {
506                 struct share_mode_entry *share = &shares[i];
507                 struct server_id pid = share->pid;
508
509                 /* Check this process really exists. */
510                 if (kill(sharemodes_procid_to_pid(&pid), 0) == -1 && (errno == ESRCH)) {
511                         continue; /* No longer exists. */
512                 }
513
514                 if (share_mode_entry_equal(del_entry, share)) {
515                         continue; /* This is our delete taget. */
516                 }
517
518                 memcpy(new_data_p + sizeof(struct locking_data) +
519                                 (num_share_modes * sizeof(struct share_mode_entry)),
520                         share, sizeof(struct share_mode_entry) );
521
522                 num_share_modes++;
523         }
524
525         if (num_share_modes == 0) {
526                 /* None left after pruning. Delete record. */
527                 free(db_data.dptr);
528                 free(new_data_p);
529                 return tdb_delete(db_ctx->smb_tdb, locking_key) ? -1 : 0;
530         }
531
532         /* Copy any delete tokens plus the terminating filenames. */
533         remaining_ptr = db_data.dptr + sizeof(struct locking_data) + (orig_num_share_modes * sizeof(struct share_mode_entry));
534         remaining_size = db_data.dsize - (remaining_ptr - db_data.dptr);
535
536         memcpy(new_data_p + sizeof(struct locking_data) + (num_share_modes * sizeof(struct share_mode_entry)),
537                 remaining_ptr,
538                 remaining_size);
539
540         free(db_data.dptr);
541
542         db_data.dptr = new_data_p;
543
544         /* Re-save smaller record. */
545         ld = (struct locking_data *)db_data.dptr;
546         ld->u.s.num_share_mode_entries = num_share_modes;
547
548         db_data.dsize = sizeof(struct locking_data) + (num_share_modes * sizeof(struct share_mode_entry)) + remaining_size;
549
550         if (tdb_store(db_ctx->smb_tdb, locking_key, db_data, TDB_REPLACE) != 0) {
551                 free(db_data.dptr);
552                 return -1;
553         }
554         free(db_data.dptr);
555         return 0;
556 }
557
558 int smb_change_share_mode_entry(struct smbdb_ctx *db_ctx,
559                                 uint64_t dev,
560                                 uint64_t ino,
561                                 uint64_t extid,
562                                 const struct smb_share_mode_entry *set_entry,
563                                 const struct smb_share_mode_entry *new_entry)
564 {
565         TDB_DATA db_data;
566         struct locking_key lk;
567         TDB_DATA locking_key =  get_locking_key(&lk, dev, ino, extid);
568         int num_share_modes = 0;
569         struct locking_data *ld = NULL; /* internal samba db state. */
570         struct share_mode_entry *shares = NULL;
571         size_t i;
572         int found_entry = 0;
573
574         db_data = tdb_fetch(db_ctx->smb_tdb, locking_key);
575         if (!db_data.dptr) {
576                 return -1; /* Error - missing entry ! */
577         }
578
579         ld = (struct locking_data *)db_data.dptr;
580         num_share_modes = ld->u.s.num_share_mode_entries;
581         shares = (struct share_mode_entry *)(db_data.dptr + sizeof(struct locking_data));
582
583         for (i = 0; i < num_share_modes; i++) {
584                 struct share_mode_entry *share = &shares[i];
585                 struct server_id pid = share->pid;
586
587                 /* Check this process really exists. */
588                 if (kill(sharemodes_procid_to_pid(&pid), 0) == -1 && (errno == ESRCH)) {
589                         continue; /* No longer exists. */
590                 }
591
592                 if (share_mode_entry_equal(set_entry, share)) {
593                         create_share_mode_entry(share, new_entry, share->name_hash);
594                         found_entry = 1;
595                         break;
596                 }
597         }
598
599         if (!found_entry) {
600                 free(db_data.dptr);
601                 return -1;
602         }
603
604         /* Save modified data. */
605         if (tdb_store(db_ctx->smb_tdb, locking_key, db_data, TDB_REPLACE) != 0) {
606                 free(db_data.dptr);
607                 return -1;
608         }
609         free(db_data.dptr);
610         return 0;
611 }