source: branches/samba-3.3.x/source/modules/vfs_acl_tdb.c

Last change on this file was 222, checked in by Herwig Bauernfeind, 16 years ago

Update Samba 3.3 branch to 3.3.2

File size: 25.5 KB
Line 
1/*
2 * Store Windows ACLs in a tdb.
3 *
4 * Copyright (C) Volker Lendecke, 2008
5 * Copyright (C) Jeremy Allison, 2008
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 3 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, see <http://www.gnu.org/licenses/>.
19 */
20
21/* NOTE: This is an experimental module, not yet finished. JRA. */
22
23#include "includes.h"
24#include "librpc/gen_ndr/xattr.h"
25#include "librpc/gen_ndr/ndr_xattr.h"
26
27#undef DBGC_CLASS
28#define DBGC_CLASS DBGC_VFS
29
30static unsigned int ref_count;
31static struct db_context *acl_db;
32
33/*******************************************************************
34 Open acl_db if not already open, increment ref count.
35*******************************************************************/
36
37static bool acl_tdb_init(struct db_context **pp_db)
38{
39 const char *dbname;
40
41 if (acl_db) {
42 *pp_db = acl_db;
43 ref_count++;
44 return true;
45 }
46
47 dbname = lock_path("file_ntacls.tdb");
48
49 if (dbname == NULL) {
50 errno = ENOSYS;
51 return false;
52 }
53
54 become_root();
55 *pp_db = db_open(NULL, dbname, 0, TDB_DEFAULT, O_RDWR|O_CREAT, 0600);
56 unbecome_root();
57
58 if (*pp_db == NULL) {
59#if defined(ENOTSUP)
60 errno = ENOTSUP;
61#else
62 errno = ENOSYS;
63#endif
64 return false;
65 }
66
67 ref_count++;
68 return true;
69}
70
71/*******************************************************************
72 Lower ref count and close acl_db if zero.
73*******************************************************************/
74
75static void free_acl_tdb_data(void **pptr)
76{
77 struct db_context **pp_db = (struct db_context **)pptr;
78
79 ref_count--;
80 if (ref_count == 0) {
81 TALLOC_FREE(*pp_db);
82 acl_db = NULL;
83 }
84}
85
86/*******************************************************************
87 Fetch_lock the tdb acl record for a file
88*******************************************************************/
89
90static struct db_record *acl_tdb_lock(TALLOC_CTX *mem_ctx,
91 struct db_context *db,
92 const struct file_id *id)
93{
94 uint8 id_buf[16];
95 push_file_id_16((char *)id_buf, id);
96 return db->fetch_locked(db,
97 mem_ctx,
98 make_tdb_data(id_buf,
99 sizeof(id_buf)));
100}
101
102/*******************************************************************
103 Delete the tdb acl record for a file
104*******************************************************************/
105
106static NTSTATUS acl_tdb_delete(vfs_handle_struct *handle,
107 struct db_context *db,
108 SMB_STRUCT_STAT *psbuf)
109{
110 NTSTATUS status;
111 struct file_id id = vfs_file_id_from_sbuf(handle->conn, psbuf);
112 struct db_record *rec = acl_tdb_lock(talloc_tos(), db, &id);
113
114 /*
115 * If rec == NULL there's not much we can do about it
116 */
117
118 if (rec == NULL) {
119 DEBUG(10,("acl_tdb_delete: rec == NULL\n"));
120 TALLOC_FREE(rec);
121 return NT_STATUS_OK;
122 }
123
124 status = rec->delete_rec(rec);
125 TALLOC_FREE(rec);
126 return status;
127}
128
129/*******************************************************************
130 Parse out a struct security_descriptor from a DATA_BLOB.
131*******************************************************************/
132
133static NTSTATUS parse_acl_blob(const DATA_BLOB *pblob,
134 uint32 security_info,
135 struct security_descriptor **ppdesc)
136{
137 TALLOC_CTX *ctx = talloc_tos();
138 struct xattr_NTACL xacl;
139 enum ndr_err_code ndr_err;
140 size_t sd_size;
141
142 ndr_err = ndr_pull_struct_blob(pblob, ctx, &xacl,
143 (ndr_pull_flags_fn_t)ndr_pull_xattr_NTACL);
144
145 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
146 DEBUG(5, ("parse_acl_blob: ndr_pull_xattr_NTACL failed: %s\n",
147 ndr_errstr(ndr_err)));
148 return ndr_map_error2ntstatus(ndr_err);;
149 }
150
151 if (xacl.version != 2) {
152 return NT_STATUS_REVISION_MISMATCH;
153 }
154
155 *ppdesc = make_sec_desc(ctx, SEC_DESC_REVISION, xacl.info.sd_hs->sd->type | SEC_DESC_SELF_RELATIVE,
156 (security_info & OWNER_SECURITY_INFORMATION)
157 ? xacl.info.sd_hs->sd->owner_sid : NULL,
158 (security_info & GROUP_SECURITY_INFORMATION)
159 ? xacl.info.sd_hs->sd->group_sid : NULL,
160 (security_info & SACL_SECURITY_INFORMATION)
161 ? xacl.info.sd_hs->sd->sacl : NULL,
162 (security_info & DACL_SECURITY_INFORMATION)
163 ? xacl.info.sd_hs->sd->dacl : NULL,
164 &sd_size);
165
166 TALLOC_FREE(xacl.info.sd);
167
168 return (*ppdesc != NULL) ? NT_STATUS_OK : NT_STATUS_NO_MEMORY;
169}
170
171/*******************************************************************
172 Pull a security descriptor into a DATA_BLOB from a tdb store.
173*******************************************************************/
174
175static NTSTATUS get_acl_blob(TALLOC_CTX *ctx,
176 vfs_handle_struct *handle,
177 files_struct *fsp,
178 const char *name,
179 DATA_BLOB *pblob)
180{
181 uint8 id_buf[16];
182 TDB_DATA data;
183 struct file_id id;
184 struct db_context *db;
185 int ret = -1;
186 SMB_STRUCT_STAT sbuf;
187
188 SMB_VFS_HANDLE_GET_DATA(handle, db, struct db_context,
189 return NT_STATUS_INTERNAL_DB_CORRUPTION);
190
191 if (fsp && fsp->fh->fd != -1) {
192 ret = SMB_VFS_FSTAT(fsp, &sbuf);
193 } else {
194 if (fsp && fsp->posix_open) {
195 ret = SMB_VFS_LSTAT(handle->conn, name, &sbuf);
196 } else {
197 ret = SMB_VFS_STAT(handle->conn, name, &sbuf);
198 }
199 }
200
201 if (ret == -1) {
202 return map_nt_error_from_unix(errno);
203 }
204
205 id = vfs_file_id_from_sbuf(handle->conn, &sbuf);
206
207 push_file_id_16((char *)id_buf, &id);
208
209 if (db->fetch(db,
210 ctx,
211 make_tdb_data(id_buf, sizeof(id_buf)),
212 &data) == -1) {
213 return NT_STATUS_INTERNAL_DB_CORRUPTION;
214 }
215
216 pblob->data = data.dptr;
217 pblob->length = data.dsize;
218
219 DEBUG(10,("get_acl_blob: returned %u bytes from file %s\n",
220 (unsigned int)data.dsize, name ));
221
222 if (pblob->length == 0 || pblob->data == NULL) {
223 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
224 }
225 return NT_STATUS_OK;
226}
227
228/*******************************************************************
229 Create a DATA_BLOB from a security descriptor.
230*******************************************************************/
231
232static NTSTATUS create_acl_blob(const struct security_descriptor *psd, DATA_BLOB *pblob)
233{
234 struct xattr_NTACL xacl;
235 struct security_descriptor_hash sd_hs;
236 enum ndr_err_code ndr_err;
237 TALLOC_CTX *ctx = talloc_tos();
238
239 ZERO_STRUCT(xacl);
240 ZERO_STRUCT(sd_hs);
241
242 xacl.version = 2;
243 xacl.info.sd_hs = &sd_hs;
244 xacl.info.sd_hs->sd = CONST_DISCARD(struct security_descriptor *, psd);
245 memset(&xacl.info.sd_hs->hash[0], '\0', 16);
246
247 ndr_err = ndr_push_struct_blob(
248 pblob, ctx, &xacl,
249 (ndr_push_flags_fn_t)ndr_push_xattr_NTACL);
250
251 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
252 DEBUG(5, ("create_acl_blob: ndr_push_xattr_NTACL failed: %s\n",
253 ndr_errstr(ndr_err)));
254 return ndr_map_error2ntstatus(ndr_err);;
255 }
256
257 return NT_STATUS_OK;
258}
259
260/*******************************************************************
261 Store a DATA_BLOB into a tdb record given an fsp pointer.
262*******************************************************************/
263
264static NTSTATUS store_acl_blob_fsp(vfs_handle_struct *handle,
265 files_struct *fsp,
266 DATA_BLOB *pblob)
267{
268 uint8 id_buf[16];
269 struct file_id id;
270 SMB_STRUCT_STAT sbuf;
271 TDB_DATA data;
272 struct db_context *db;
273 struct db_record *rec;
274 int ret = -1;
275
276 DEBUG(10,("store_acl_blob_fsp: storing blob length %u on file %s\n",
277 (unsigned int)pblob->length, fsp->fsp_name));
278
279 SMB_VFS_HANDLE_GET_DATA(handle, db, struct db_context,
280 return NT_STATUS_INTERNAL_DB_CORRUPTION);
281
282 if (fsp->fh->fd != -1) {
283 ret = SMB_VFS_FSTAT(fsp, &sbuf);
284 } else {
285 if (fsp->posix_open) {
286 ret = SMB_VFS_LSTAT(handle->conn, fsp->fsp_name, &sbuf);
287 } else {
288 ret = SMB_VFS_STAT(handle->conn, fsp->fsp_name, &sbuf);
289 }
290 }
291
292 if (ret == -1) {
293 return map_nt_error_from_unix(errno);
294 }
295
296 id = vfs_file_id_from_sbuf(handle->conn, &sbuf);
297
298 push_file_id_16((char *)id_buf, &id);
299 rec = db->fetch_locked(db, talloc_tos(),
300 make_tdb_data(id_buf,
301 sizeof(id_buf)));
302 if (rec == NULL) {
303 DEBUG(0, ("store_acl_blob_fsp_tdb: fetch_lock failed\n"));
304 return NT_STATUS_INTERNAL_DB_CORRUPTION;
305 }
306 data.dptr = pblob->data;
307 data.dsize = pblob->length;
308 return rec->store(rec, data, 0);
309}
310
311/*******************************************************************
312 Store a DATA_BLOB into a tdb record given a pathname.
313*******************************************************************/
314
315static NTSTATUS store_acl_blob_pathname(vfs_handle_struct *handle,
316 const char *fname,
317 DATA_BLOB *pblob)
318{
319 uint8 id_buf[16];
320 struct file_id id;
321 TDB_DATA data;
322 SMB_STRUCT_STAT sbuf;
323 struct db_context *db;
324 struct db_record *rec;
325 int ret = -1;
326
327 DEBUG(10,("store_acl_blob_pathname: storing blob "
328 "length %u on file %s\n",
329 (unsigned int)pblob->length, fname));
330
331 SMB_VFS_HANDLE_GET_DATA(handle, db, struct db_context,
332 return NT_STATUS_INTERNAL_DB_CORRUPTION);
333
334 if (lp_posix_pathnames()) {
335 ret = SMB_VFS_LSTAT(handle->conn, fname, &sbuf);
336 } else {
337 ret = SMB_VFS_STAT(handle->conn, fname, &sbuf);
338 }
339
340 if (ret == -1) {
341 return map_nt_error_from_unix(errno);
342 }
343
344 id = vfs_file_id_from_sbuf(handle->conn, &sbuf);
345 push_file_id_16((char *)id_buf, &id);
346
347 rec = db->fetch_locked(db, talloc_tos(),
348 make_tdb_data(id_buf,
349 sizeof(id_buf)));
350 if (rec == NULL) {
351 DEBUG(0, ("store_acl_blob_pathname_tdb: fetch_lock failed\n"));
352 return NT_STATUS_INTERNAL_DB_CORRUPTION;
353 }
354 data.dptr = pblob->data;
355 data.dsize = pblob->length;
356 return rec->store(rec, data, 0);
357}
358
359/*******************************************************************
360 Store a DATA_BLOB into an tdb given a pathname.
361*******************************************************************/
362
363static NTSTATUS get_nt_acl_tdb_internal(vfs_handle_struct *handle,
364 files_struct *fsp,
365 const char *name,
366 uint32 security_info,
367 struct security_descriptor **ppdesc)
368{
369 TALLOC_CTX *ctx = talloc_tos();
370 DATA_BLOB blob;
371 NTSTATUS status;
372
373 if (fsp && name == NULL) {
374 name = fsp->fsp_name;
375 }
376
377 DEBUG(10, ("get_nt_acl_tdb_internal: name=%s\n", name));
378
379 status = get_acl_blob(ctx, handle, fsp, name, &blob);
380 if (!NT_STATUS_IS_OK(status)) {
381 DEBUG(10, ("get_acl_blob returned %s\n", nt_errstr(status)));
382 return status;
383 }
384
385 status = parse_acl_blob(&blob, security_info, ppdesc);
386 if (!NT_STATUS_IS_OK(status)) {
387 DEBUG(10, ("parse_acl_blob returned %s\n",
388 nt_errstr(status)));
389 return status;
390 }
391
392 TALLOC_FREE(blob.data);
393 return status;
394}
395
396/*********************************************************************
397 Create a default security descriptor for a file in case no inheritance
398 exists. All permissions to the owner and SYSTEM.
399*********************************************************************/
400
401static struct security_descriptor *default_file_sd(TALLOC_CTX *mem_ctx,
402 SMB_STRUCT_STAT *psbuf)
403{
404 struct dom_sid owner_sid, group_sid;
405 size_t sd_size;
406 struct security_ace *pace = NULL;
407 struct security_acl *pacl = NULL;
408
409 uid_to_sid(&owner_sid, psbuf->st_uid);
410 gid_to_sid(&group_sid, psbuf->st_gid);
411
412 pace = TALLOC_ARRAY(mem_ctx, struct security_ace, 2);
413 if (!pace) {
414 return NULL;
415 }
416
417 init_sec_ace(&pace[0], &owner_sid, SEC_ACE_TYPE_ACCESS_ALLOWED,
418 SEC_RIGHTS_FILE_ALL, 0);
419 init_sec_ace(&pace[1], &global_sid_System, SEC_ACE_TYPE_ACCESS_ALLOWED,
420 SEC_RIGHTS_FILE_ALL, 0);
421
422 pacl = make_sec_acl(mem_ctx,
423 NT4_ACL_REVISION,
424 2,
425 pace);
426 if (!pacl) {
427 return NULL;
428 }
429 return make_sec_desc(mem_ctx,
430 SECURITY_DESCRIPTOR_REVISION_1,
431 SEC_DESC_SELF_RELATIVE|SEC_DESC_DACL_PRESENT,
432 &owner_sid,
433 &group_sid,
434 NULL,
435 pacl,
436 &sd_size);
437}
438
439/*********************************************************************
440*********************************************************************/
441
442static NTSTATUS inherit_new_acl(vfs_handle_struct *handle,
443 const char *fname,
444 files_struct *fsp,
445 bool container)
446{
447 TALLOC_CTX *ctx = talloc_tos();
448 NTSTATUS status;
449 struct security_descriptor *parent_desc = NULL;
450 struct security_descriptor *psd = NULL;
451 DATA_BLOB blob;
452 size_t size;
453 char *parent_name;
454
455 if (!parent_dirname_talloc(ctx,
456 fname,
457 &parent_name,
458 NULL)) {
459 return NT_STATUS_NO_MEMORY;
460 }
461
462 DEBUG(10,("inherit_new_acl: check directory %s\n",
463 parent_name));
464
465 status = get_nt_acl_tdb_internal(handle,
466 NULL,
467 parent_name,
468 (OWNER_SECURITY_INFORMATION |
469 GROUP_SECURITY_INFORMATION |
470 DACL_SECURITY_INFORMATION),
471 &parent_desc);
472 if (NT_STATUS_IS_OK(status)) {
473 /* Create an inherited descriptor from the parent. */
474
475 if (DEBUGLEVEL >= 10) {
476 DEBUG(10,("inherit_new_acl: parent acl is:\n"));
477 NDR_PRINT_DEBUG(security_descriptor, parent_desc);
478 }
479
480 status = se_create_child_secdesc(ctx,
481 &psd,
482 &size,
483 parent_desc,
484 &handle->conn->server_info->ptok->user_sids[PRIMARY_USER_SID_INDEX],
485 &handle->conn->server_info->ptok->user_sids[PRIMARY_GROUP_SID_INDEX],
486 container);
487 if (!NT_STATUS_IS_OK(status)) {
488 return status;
489 }
490
491 if (DEBUGLEVEL >= 10) {
492 DEBUG(10,("inherit_new_acl: child acl is:\n"));
493 NDR_PRINT_DEBUG(security_descriptor, psd);
494 }
495
496 } else {
497 DEBUG(10,("inherit_new_acl: directory %s failed "
498 "to get acl %s\n",
499 parent_name,
500 nt_errstr(status) ));
501 }
502
503 if (!psd || psd->dacl == NULL) {
504 SMB_STRUCT_STAT sbuf;
505 int ret;
506
507 TALLOC_FREE(psd);
508 if (fsp && !fsp->is_directory && fsp->fh->fd != -1) {
509 ret = SMB_VFS_FSTAT(fsp, &sbuf);
510 } else {
511 if (fsp && fsp->posix_open) {
512 ret = SMB_VFS_LSTAT(handle->conn,fname, &sbuf);
513 } else {
514 ret = SMB_VFS_STAT(handle->conn,fname, &sbuf);
515 }
516 }
517 if (ret == -1) {
518 return map_nt_error_from_unix(errno);
519 }
520 psd = default_file_sd(ctx, &sbuf);
521 if (!psd) {
522 return NT_STATUS_NO_MEMORY;
523 }
524
525 if (DEBUGLEVEL >= 10) {
526 DEBUG(10,("inherit_new_acl: default acl is:\n"));
527 NDR_PRINT_DEBUG(security_descriptor, psd);
528 }
529 }
530
531 status = create_acl_blob(psd, &blob);
532 if (!NT_STATUS_IS_OK(status)) {
533 return status;
534 }
535 if (fsp) {
536 return store_acl_blob_fsp(handle, fsp, &blob);
537 } else {
538 return store_acl_blob_pathname(handle, fname, &blob);
539 }
540}
541
542/*********************************************************************
543 Check ACL on open. For new files inherit from parent directory.
544*********************************************************************/
545
546static int open_acl_tdb(vfs_handle_struct *handle,
547 const char *fname,
548 files_struct *fsp,
549 int flags,
550 mode_t mode)
551{
552 uint32_t access_granted = 0;
553 struct security_descriptor *pdesc = NULL;
554 bool file_existed = true;
555 NTSTATUS status = get_nt_acl_tdb_internal(handle,
556 NULL,
557 fname,
558 (OWNER_SECURITY_INFORMATION |
559 GROUP_SECURITY_INFORMATION |
560 DACL_SECURITY_INFORMATION),
561 &pdesc);
562 if (NT_STATUS_IS_OK(status)) {
563 /* See if we can access it. */
564 status = smb1_file_se_access_check(pdesc,
565 handle->conn->server_info->ptok,
566 fsp->access_mask,
567 &access_granted);
568 if (!NT_STATUS_IS_OK(status)) {
569 DEBUG(10,("open_acl_tdb: file %s open "
570 "refused with error %s\n",
571 fname,
572 nt_errstr(status) ));
573 errno = map_errno_from_nt_status(status);
574 return -1;
575 }
576 } else if (NT_STATUS_EQUAL(status,NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
577 file_existed = false;
578 }
579
580 DEBUG(10,("open_acl_tdb: get_nt_acl_attr_internal for "
581 "file %s returned %s\n",
582 fname,
583 nt_errstr(status) ));
584
585 fsp->fh->fd = SMB_VFS_NEXT_OPEN(handle, fname, fsp, flags, mode);
586
587 if (!file_existed && fsp->fh->fd != -1) {
588 /* File was created. Inherit from parent directory. */
589 string_set(&fsp->fsp_name, fname);
590 inherit_new_acl(handle, fname, fsp, false);
591 }
592
593 return fsp->fh->fd;
594}
595
596/*********************************************************************
597 On unlink we need to delete the tdb record (if using tdb).
598*********************************************************************/
599
600static int unlink_acl_tdb(vfs_handle_struct *handle, const char *path)
601{
602 SMB_STRUCT_STAT sbuf;
603 struct db_context *db;
604 int ret = -1;
605
606 SMB_VFS_HANDLE_GET_DATA(handle, db, struct db_context, return -1);
607
608 if (lp_posix_pathnames()) {
609 ret = SMB_VFS_LSTAT(handle->conn, path, &sbuf);
610 } else {
611 ret = SMB_VFS_STAT(handle->conn, path, &sbuf);
612 }
613
614 if (ret == -1) {
615 return -1;
616 }
617
618 ret = SMB_VFS_NEXT_UNLINK(handle, path);
619
620 if (ret == -1) {
621 return -1;
622 }
623
624 acl_tdb_delete(handle, db, &sbuf);
625 return 0;
626}
627
628/*********************************************************************
629 Store an inherited SD on mkdir.
630*********************************************************************/
631
632static int mkdir_acl_tdb(vfs_handle_struct *handle, const char *path, mode_t mode)
633{
634 int ret = SMB_VFS_NEXT_MKDIR(handle, path, mode);
635
636 if (ret == -1) {
637 return ret;
638 }
639 /* New directory - inherit from parent. */
640 inherit_new_acl(handle, path, NULL, true);
641 return ret;
642}
643
644/*********************************************************************
645 On rmdir we need to delete the tdb record (if using tdb).
646*********************************************************************/
647
648static int rmdir_acl_tdb(vfs_handle_struct *handle, const char *path)
649{
650
651 SMB_STRUCT_STAT sbuf;
652 struct db_context *db;
653 int ret = -1;
654
655 SMB_VFS_HANDLE_GET_DATA(handle, db, struct db_context, return -1);
656
657 if (lp_posix_pathnames()) {
658 ret = SMB_VFS_LSTAT(handle->conn, path, &sbuf);
659 } else {
660 ret = SMB_VFS_STAT(handle->conn, path, &sbuf);
661 }
662
663 if (ret == -1) {
664 return -1;
665 }
666
667 ret = SMB_VFS_NEXT_RMDIR(handle, path);
668 if (ret == -1) {
669 return -1;
670 }
671
672 acl_tdb_delete(handle, db, &sbuf);
673 return 0;
674}
675
676/*********************************************************************
677 Fetch a security descriptor given an fsp.
678*********************************************************************/
679
680static NTSTATUS fget_nt_acl_tdb(vfs_handle_struct *handle, files_struct *fsp,
681 uint32 security_info, struct security_descriptor **ppdesc)
682{
683 NTSTATUS status = get_nt_acl_tdb_internal(handle, fsp,
684 NULL, security_info, ppdesc);
685 if (NT_STATUS_IS_OK(status)) {
686 if (DEBUGLEVEL >= 10) {
687 DEBUG(10,("fget_nt_acl_tdb: returning tdb sd for file %s\n",
688 fsp->fsp_name));
689 NDR_PRINT_DEBUG(security_descriptor, *ppdesc);
690 }
691 return NT_STATUS_OK;
692 }
693
694 DEBUG(10,("fget_nt_acl_tdb: failed to get tdb sd for file %s, Error %s\n",
695 fsp->fsp_name,
696 nt_errstr(status) ));
697
698 return SMB_VFS_NEXT_FGET_NT_ACL(handle, fsp,
699 security_info, ppdesc);
700}
701
702/*********************************************************************
703 Fetch a security descriptor given a pathname.
704*********************************************************************/
705
706static NTSTATUS get_nt_acl_tdb(vfs_handle_struct *handle,
707 const char *name, uint32 security_info, struct security_descriptor **ppdesc)
708{
709 NTSTATUS status = get_nt_acl_tdb_internal(handle, NULL,
710 name, security_info, ppdesc);
711 if (NT_STATUS_IS_OK(status)) {
712 if (DEBUGLEVEL >= 10) {
713 DEBUG(10,("get_nt_acl_tdb: returning tdb sd for file %s\n",
714 name));
715 NDR_PRINT_DEBUG(security_descriptor, *ppdesc);
716 }
717 return NT_STATUS_OK;
718 }
719
720 DEBUG(10,("get_nt_acl_tdb: failed to get tdb sd for file %s, Error %s\n",
721 name,
722 nt_errstr(status) ));
723
724 return SMB_VFS_NEXT_GET_NT_ACL(handle, name,
725 security_info, ppdesc);
726}
727
728/*********************************************************************
729 Store a security descriptor given an fsp.
730*********************************************************************/
731
732static NTSTATUS fset_nt_acl_tdb(vfs_handle_struct *handle, files_struct *fsp,
733 uint32 security_info_sent, const struct security_descriptor *psd)
734{
735 NTSTATUS status;
736 DATA_BLOB blob;
737
738 if (DEBUGLEVEL >= 10) {
739 DEBUG(10,("fset_nt_acl_tdb: incoming sd for file %s\n",
740 fsp->fsp_name));
741 NDR_PRINT_DEBUG(security_descriptor,
742 CONST_DISCARD(struct security_descriptor *,psd));
743 }
744
745 status = SMB_VFS_NEXT_FSET_NT_ACL(handle, fsp, security_info_sent, psd);
746 if (!NT_STATUS_IS_OK(status)) {
747 return status;
748 }
749
750 /* Ensure owner and group are set. */
751 if (!psd->owner_sid || !psd->group_sid) {
752 int ret;
753 SMB_STRUCT_STAT sbuf;
754 DOM_SID owner_sid, group_sid;
755 struct security_descriptor *nc_psd = dup_sec_desc(talloc_tos(), psd);
756
757 if (!nc_psd) {
758 return NT_STATUS_OK;
759 }
760 if (fsp->is_directory || fsp->fh->fd == -1) {
761 if (fsp->posix_open) {
762 ret = SMB_VFS_LSTAT(fsp->conn,fsp->fsp_name, &sbuf);
763 } else {
764 ret = SMB_VFS_STAT(fsp->conn,fsp->fsp_name, &sbuf);
765 }
766 } else {
767 ret = SMB_VFS_FSTAT(fsp, &sbuf);
768 }
769 if (ret == -1) {
770 /* Lower level acl set succeeded,
771 * so still return OK. */
772 return NT_STATUS_OK;
773 }
774 create_file_sids(&sbuf, &owner_sid, &group_sid);
775 /* This is safe as nc_psd is discarded at fn exit. */
776 nc_psd->owner_sid = &owner_sid;
777 nc_psd->group_sid = &group_sid;
778 security_info_sent |= (OWNER_SECURITY_INFORMATION|GROUP_SECURITY_INFORMATION);
779 psd = nc_psd;
780 }
781
782#if 0
783 if ((security_info_sent & DACL_SECURITY_INFORMATION) &&
784 psd->dacl != NULL &&
785 (psd->type & (SE_DESC_DACL_AUTO_INHERITED|
786 SE_DESC_DACL_AUTO_INHERIT_REQ))==
787 (SE_DESC_DACL_AUTO_INHERITED|
788 SE_DESC_DACL_AUTO_INHERIT_REQ) ) {
789 struct security_descriptor *new_psd = NULL;
790 status = append_parent_acl(fsp, psd, &new_psd);
791 if (!NT_STATUS_IS_OK(status)) {
792 /* Lower level acl set succeeded,
793 * so still return OK. */
794 return NT_STATUS_OK;
795 }
796 psd = new_psd;
797 }
798#endif
799
800 if (DEBUGLEVEL >= 10) {
801 DEBUG(10,("fset_nt_acl_tdb: storing tdb sd for file %s\n",
802 fsp->fsp_name));
803 NDR_PRINT_DEBUG(security_descriptor,
804 CONST_DISCARD(struct security_descriptor *,psd));
805 }
806 create_acl_blob(psd, &blob);
807 store_acl_blob_fsp(handle, fsp, &blob);
808
809 return NT_STATUS_OK;
810}
811
812/*******************************************************************
813 Handle opening the storage tdb if so configured.
814*******************************************************************/
815
816static int connect_acl_tdb(struct vfs_handle_struct *handle,
817 const char *service,
818 const char *user)
819{
820 struct db_context *db;
821 int res;
822
823 res = SMB_VFS_NEXT_CONNECT(handle, service, user);
824 if (res < 0) {
825 return res;
826 }
827
828 if (!acl_tdb_init(&db)) {
829 SMB_VFS_NEXT_DISCONNECT(handle);
830 return -1;
831 }
832
833 SMB_VFS_HANDLE_SET_DATA(handle, db, free_acl_tdb_data,
834 struct db_context, return -1);
835
836 return 0;
837}
838
839/*********************************************************************
840 Remove a Windows ACL - we're setting the underlying POSIX ACL.
841*********************************************************************/
842
843static int sys_acl_set_file_tdb(vfs_handle_struct *handle,
844 const char *path,
845 SMB_ACL_TYPE_T type,
846 SMB_ACL_T theacl)
847{
848 SMB_STRUCT_STAT sbuf;
849 struct db_context *db;
850 int ret = -1;
851
852 SMB_VFS_HANDLE_GET_DATA(handle, db, struct db_context, return -1);
853
854 if (lp_posix_pathnames()) {
855 ret = SMB_VFS_LSTAT(handle->conn, path, &sbuf);
856 } else {
857 ret = SMB_VFS_STAT(handle->conn, path, &sbuf);
858 }
859
860 if (ret == -1) {
861 return -1;
862 }
863
864 ret = SMB_VFS_NEXT_SYS_ACL_SET_FILE(handle,
865 path,
866 type,
867 theacl);
868 if (ret == -1) {
869 return -1;
870 }
871
872 acl_tdb_delete(handle, db, &sbuf);
873 return 0;
874}
875
876/*********************************************************************
877 Remove a Windows ACL - we're setting the underlying POSIX ACL.
878*********************************************************************/
879
880static int sys_acl_set_fd_tdb(vfs_handle_struct *handle,
881 files_struct *fsp,
882 SMB_ACL_T theacl)
883{
884 SMB_STRUCT_STAT sbuf;
885 struct db_context *db;
886 int ret;
887
888 SMB_VFS_HANDLE_GET_DATA(handle, db, struct db_context, return -1);
889
890 if (fsp->is_directory || fsp->fh->fd == -1) {
891 if (fsp->posix_open) {
892 ret = SMB_VFS_LSTAT(fsp->conn,fsp->fsp_name, &sbuf);
893 } else {
894 ret = SMB_VFS_STAT(fsp->conn,fsp->fsp_name, &sbuf);
895 }
896 } else {
897 ret = SMB_VFS_FSTAT(fsp, &sbuf);
898 }
899 if (ret == -1) {
900 return -1;
901 }
902
903 ret = SMB_VFS_NEXT_SYS_ACL_SET_FD(handle,
904 fsp,
905 theacl);
906 if (ret == -1) {
907 return -1;
908 }
909
910 acl_tdb_delete(handle, db, &sbuf);
911 return 0;
912}
913
914/* VFS operations structure */
915
916static vfs_op_tuple skel_op_tuples[] =
917{
918 {SMB_VFS_OP(connect_acl_tdb), SMB_VFS_OP_CONNECT, SMB_VFS_LAYER_TRANSPARENT},
919
920 {SMB_VFS_OP(mkdir_acl_tdb), SMB_VFS_OP_MKDIR, SMB_VFS_LAYER_TRANSPARENT},
921 {SMB_VFS_OP(rmdir_acl_tdb), SMB_VFS_OP_RMDIR, SMB_VFS_LAYER_TRANSPARENT},
922
923 {SMB_VFS_OP(open_acl_tdb), SMB_VFS_OP_OPEN, SMB_VFS_LAYER_TRANSPARENT},
924 {SMB_VFS_OP(unlink_acl_tdb), SMB_VFS_OP_UNLINK, SMB_VFS_LAYER_TRANSPARENT},
925
926 /* NT File ACL operations */
927
928 {SMB_VFS_OP(fget_nt_acl_tdb),SMB_VFS_OP_FGET_NT_ACL,SMB_VFS_LAYER_TRANSPARENT},
929 {SMB_VFS_OP(get_nt_acl_tdb), SMB_VFS_OP_GET_NT_ACL, SMB_VFS_LAYER_TRANSPARENT},
930 {SMB_VFS_OP(fset_nt_acl_tdb),SMB_VFS_OP_FSET_NT_ACL,SMB_VFS_LAYER_TRANSPARENT},
931
932 /* POSIX ACL operations. */
933 {SMB_VFS_OP(sys_acl_set_file_tdb), SMB_VFS_OP_SYS_ACL_SET_FILE, SMB_VFS_LAYER_TRANSPARENT},
934 {SMB_VFS_OP(sys_acl_set_fd_tdb), SMB_VFS_OP_SYS_ACL_SET_FD, SMB_VFS_LAYER_TRANSPARENT},
935
936 {SMB_VFS_OP(NULL), SMB_VFS_OP_NOOP, SMB_VFS_LAYER_NOOP}
937};
938
939NTSTATUS vfs_acl_tdb_init(void)
940{
941 return smb_register_vfs(SMB_VFS_INTERFACE_VERSION, "acl_tdb", skel_op_tuples);
942}
Note: See TracBrowser for help on using the repository browser.