root/source3/modules/vfs_acl_tdb.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. acl_tdb_init
  2. free_acl_tdb_data
  3. acl_tdb_lock
  4. acl_tdb_delete
  5. parse_acl_blob
  6. get_acl_blob
  7. create_acl_blob
  8. store_acl_blob_fsp
  9. store_acl_blob_pathname
  10. get_nt_acl_tdb_internal
  11. default_file_sd
  12. inherit_new_acl
  13. open_acl_tdb
  14. unlink_acl_tdb
  15. mkdir_acl_tdb
  16. rmdir_acl_tdb
  17. fget_nt_acl_tdb
  18. get_nt_acl_tdb
  19. fset_nt_acl_tdb
  20. connect_acl_tdb
  21. sys_acl_set_file_tdb
  22. sys_acl_set_fd_tdb
  23. vfs_acl_tdb_init

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

/* [<][>][^][v][top][bottom][index][help] */