The branch, master has been updated via 8076e50fad6346e3ca6e18a044ea01b31ca182dd (commit) from 39d42378b260240544b5649ff373fc15fbddaed8 (commit)
http://gitweb.samba.org/?p=samba.git;a=shortlog;h=master - Log ----------------------------------------------------------------- commit 8076e50fad6346e3ca6e18a044ea01b31ca182dd Author: Jeremy Allison <[EMAIL PROTECTED]> Date: Mon Nov 10 17:57:22 2008 -0800 Added vfs_acl_tdb.c module to do ACLs completely in userspace. Passes all of RAW-ACLS except for the last test which uses a non-POSIX chown. More testing/documentation to follow. Jeremy. ----------------------------------------------------------------------- Summary of changes: source3/Makefile.in | 5 + source3/configure.in | 3 +- source3/modules/{vfs_acl_xattr.c => vfs_acl_tdb.c} | 456 ++++++++++++++------ source3/modules/vfs_acl_xattr.c | 98 +++-- 4 files changed, 396 insertions(+), 166 deletions(-) copy source3/modules/{vfs_acl_xattr.c => vfs_acl_tdb.c} (60%) Changeset truncated at 500 lines: diff --git a/source3/Makefile.in b/source3/Makefile.in index d216e1c..be075ad 100644 --- a/source3/Makefile.in +++ b/source3/Makefile.in @@ -643,6 +643,7 @@ VFS_FILEID_OBJ = modules/vfs_fileid.o VFS_AIO_FORK_OBJ = modules/vfs_aio_fork.o VFS_SYNCOPS_OBJ = modules/vfs_syncops.o VFS_ACL_XATTR_OBJ = modules/vfs_acl_xattr.o +VFS_ACL_TDB_OBJ = modules/vfs_acl_tdb.o VFS_SMB_TRAFFIC_ANALYZER_OBJ = modules/vfs_smb_traffic_analyzer.o PLAINTEXT_AUTH_OBJ = auth/pampass.o auth/pass_check.o @@ -2459,6 +2460,10 @@ bin/[EMAIL PROTECTED]@: $(BINARY_PREREQS) $(VFS_SMB_TRAFFIC_ANALYZE @echo "Building plugin $@" @$(SHLD_MODULE) $(VFS_SMB_TRAFFIC_ANALYZER_OBJ) +bin/[EMAIL PROTECTED]@: $(BINARY_PREREQS) $(VFS_ACL_TDB_OBJ) + @echo "Building plugin $@" + @$(SHLD_MODULE) $(VFS_ACL_TDB_OBJ) + bin/[EMAIL PROTECTED]@: $(BINARY_PREREQS) libgpo/gpext/registry.o @echo "Building plugin $@" @$(SHLD_MODULE) libgpo/gpext/registry.o diff --git a/source3/configure.in b/source3/configure.in index 0aeefe4..5e3eac5 100644 --- a/source3/configure.in +++ b/source3/configure.in @@ -399,7 +399,7 @@ dnl These have to be built static: default_static_modules="pdb_smbpasswd pdb_tdbsam rpc_lsarpc rpc_samr rpc_winreg rpc_initshutdown rpc_dssetup rpc_wkssvc rpc_svcctl2 rpc_ntsvcs2 rpc_netlogon rpc_netdfs rpc_srvsvc rpc_spoolss rpc_eventlog2 auth_sam auth_unix auth_winbind auth_server auth_domain auth_builtin auth_netlogond vfs_default nss_info_template" dnl These are preferably build shared, and static if dlopen() is not available -default_shared_modules="vfs_recycle vfs_audit vfs_extd_audit vfs_full_audit vfs_netatalk vfs_fake_perms vfs_default_quota vfs_readonly vfs_cap vfs_expand_msdfs vfs_shadow_copy vfs_shadow_copy2 charset_CP850 charset_CP437 auth_script vfs_readahead vfs_xattr_tdb vfs_streams_xattr vfs_acl_xattr vfs_smb_traffic_analyzer" +default_shared_modules="vfs_recycle vfs_audit vfs_extd_audit vfs_full_audit vfs_netatalk vfs_fake_perms vfs_default_quota vfs_readonly vfs_cap vfs_expand_msdfs vfs_shadow_copy vfs_shadow_copy2 charset_CP850 charset_CP437 auth_script vfs_readahead vfs_xattr_tdb vfs_streams_xattr vfs_acl_xattr vfs_acl_tdb vfs_smb_traffic_analyzer" if test "x$developer" = xyes; then default_static_modules="$default_static_modules rpc_rpcecho" @@ -6087,6 +6087,7 @@ SMB_MODULE(vfs_syncops, \$(VFS_SYNCOPS_OBJ), "bin/syncops.$SHLIBEXT", VFS) SMB_MODULE(vfs_zfsacl, \$(VFS_ZFSACL_OBJ), "bin/zfsacl.$SHLIBEXT", VFS) SMB_MODULE(vfs_notify_fam, \$(VFS_NOTIFY_FAM_OBJ), "bin/notify_fam.$SHLIBEXT", VFS) SMB_MODULE(vfs_acl_xattr, \$(VFS_ACL_XATTR_OBJ), "bin/acl_xattr.$SHLIBEXT", VFS) +SMB_MODULE(vfs_acl_tdb, \$(VFS_ACL_TDB_OBJ), "bin/acl_tdb.$SHLIBEXT", VFS) SMB_MODULE(vfs_smb_traffic_analyzer, \$(VFS_SMB_TRAFFIC_ANALYZER_OBJ), "bin/smb_traffic_analyzer.$SHLIBEXT", VFS) SMB_SUBSYSTEM(VFS,smbd/vfs.o) diff --git a/source3/modules/vfs_acl_xattr.c b/source3/modules/vfs_acl_tdb.c similarity index 60% copy from source3/modules/vfs_acl_xattr.c copy to source3/modules/vfs_acl_tdb.c index a5d9395..be49bb7 100644 --- a/source3/modules/vfs_acl_xattr.c +++ b/source3/modules/vfs_acl_tdb.c @@ -1,5 +1,5 @@ /* - * Store Windows ACLs in xattrs. + * Store Windows ACLs in xattrs, or a tdb if configured that way. * * Copyright (C) Volker Lendecke, 2008 * Copyright (C) Jeremy Allison, 2008 @@ -27,8 +27,83 @@ #undef DBGC_CLASS #define DBGC_CLASS DBGC_VFS +static unsigned int ref_count; +static struct db_context *acl_db; + +/******************************************************************* + Open acl_db if not already open, increment ref count. +*******************************************************************/ + +static bool acl_tdb_init(struct db_context **pp_db) +{ + const char *dbname; + + if (acl_db) { + *pp_db = acl_db; + ref_count++; + return true; + } + + dbname = lock_path("file_ntacls.tdb"); + + if (dbname == NULL) { + errno = ENOSYS; + return false; + } + + become_root(); + *pp_db = db_open(NULL, dbname, 0, TDB_DEFAULT, O_RDWR|O_CREAT, 0600); + unbecome_root(); + + if (*pp_db == NULL) { +#if defined(ENOTSUP) + errno = ENOTSUP; +#else + errno = ENOSYS; +#endif + return false; + } + + ref_count++; + return true; +} + +/******************************************************************* + Lower ref count and close acl_db if zero. +*******************************************************************/ + +static void free_acl_xattr_data(void **pptr) +{ + struct db_context **pp_db = (struct db_context **)pptr; + + ref_count--; + if (ref_count == 0) { + TALLOC_FREE(*pp_db); + acl_db = NULL; + } +} + +/******************************************************************* + Fetch_lock the tdb acl record for a file +*******************************************************************/ + +static struct db_record *acl_xattr_tdb_lock(TALLOC_CTX *mem_ctx, + struct db_context *db, + const struct file_id *id) +{ + uint8 id_buf[16]; + push_file_id_16((char *)id_buf, id); + return db->fetch_locked(db, + mem_ctx, + make_tdb_data(id_buf, + sizeof(id_buf))); +} + +/******************************************************************* + Parse out a struct security_descriptor from a DATA_BLOB. +*******************************************************************/ + static NTSTATUS parse_acl_blob(const DATA_BLOB *pblob, - const struct timespec cts, uint32 security_info, struct security_descriptor **ppdesc) { @@ -37,7 +112,7 @@ static NTSTATUS parse_acl_blob(const DATA_BLOB *pblob, enum ndr_err_code ndr_err; size_t sd_size; - ndr_err = ndr_pull_struct_blob(pblob, ctx, NULL, &xacl, + ndr_err = ndr_pull_struct_blob(pblob, ctx, &xacl, (ndr_pull_flags_fn_t)ndr_pull_xattr_NTACL); if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { @@ -50,30 +125,6 @@ static NTSTATUS parse_acl_blob(const DATA_BLOB *pblob, return NT_STATUS_REVISION_MISMATCH; } -#if 0 - { - struct timespec ts; - /* Arg. This doesn't work. Too many activities - * change the ctime. May have to roll back to - * version 1. - */ - /* - * Check that the ctime timestamp is ealier - * than the stored timestamp. - */ - - ts = nt_time_to_unix_timespec(&xacl.info.sd_ts->last_changed); - - if (timespec_compare(&cts, &ts) > 0) { - DEBUG(5, ("parse_acl_blob: stored ACL out of date " - "(%s > %s.\n", - timestring(ctx, cts.tv_sec), - timestring(ctx, ts.tv_sec))); - return NT_STATUS_EA_CORRUPT_ERROR; - } - } -#endif - *ppdesc = make_sec_desc(ctx, SEC_DESC_REVISION, xacl.info.sd_ts->sd->type | SEC_DESC_SELF_RELATIVE, (security_info & OWNER_SECURITY_INFORMATION) ? xacl.info.sd_ts->sd->owner_sid : NULL, @@ -90,60 +141,61 @@ static NTSTATUS parse_acl_blob(const DATA_BLOB *pblob, return (*ppdesc != NULL) ? NT_STATUS_OK : NT_STATUS_NO_MEMORY; } +/******************************************************************* + Pull a security descriptor into a DATA_BLOB from a tdb store. +*******************************************************************/ + static NTSTATUS get_acl_blob(TALLOC_CTX *ctx, vfs_handle_struct *handle, files_struct *fsp, const char *name, DATA_BLOB *pblob) { - size_t size = 1024; - uint8_t *val = NULL; - uint8_t *tmp; - ssize_t sizeret; - int saved_errno = 0; - - ZERO_STRUCTP(pblob); - - again: + uint8 id_buf[16]; + TDB_DATA data; + struct file_id id; + struct db_context *db; + SMB_STRUCT_STAT sbuf; - tmp = TALLOC_REALLOC_ARRAY(ctx, val, uint8_t, size); - if (tmp == NULL) { - TALLOC_FREE(val); - return NT_STATUS_NO_MEMORY; - } - val = tmp; + SMB_VFS_HANDLE_GET_DATA(handle, db, struct db_context, + return NT_STATUS_INTERNAL_DB_CORRUPTION); - become_root(); if (fsp && fsp->fh->fd != -1) { - sizeret = SMB_VFS_FGETXATTR(fsp, XATTR_NTACL_NAME, val, size); + if (SMB_VFS_FSTAT(fsp, &sbuf) == -1) { + return map_nt_error_from_unix(errno); + } } else { - sizeret = SMB_VFS_GETXATTR(handle->conn, name, - XATTR_NTACL_NAME, val, size); - } - if (sizeret == -1) { - saved_errno = errno; + if (SMB_VFS_STAT(handle->conn, name, &sbuf) == -1) { + return map_nt_error_from_unix(errno); + } } - unbecome_root(); + id = vfs_file_id_from_sbuf(handle->conn, &sbuf); - /* Max ACL size is 65536 bytes. */ - if (sizeret == -1) { - errno = saved_errno; - if ((errno == ERANGE) && (size != 65536)) { - /* Too small, try again. */ - size = 65536; - goto again; - } + push_file_id_16((char *)id_buf, &id); - /* Real error - exit here. */ - TALLOC_FREE(val); - return map_nt_error_from_unix(errno); + if (db->fetch(db, + ctx, + make_tdb_data(id_buf, sizeof(id_buf)), + &data) == -1) { + return NT_STATUS_INTERNAL_DB_CORRUPTION; } - pblob->data = val; - pblob->length = sizeret; + pblob->data = data.dptr; + pblob->length = data.dsize; + + DEBUG(10,("get_acl_blob: returned %u bytes from file %s\n", + (unsigned int)data.dsize, name )); + + if (pblob->length == 0 || pblob->data == NULL) { + return NT_STATUS_OBJECT_NAME_NOT_FOUND; + } return NT_STATUS_OK; } +/******************************************************************* + Create a DATA_BLOB from a security descriptor. +*******************************************************************/ + static NTSTATUS create_acl_blob(const struct security_descriptor *psd, DATA_BLOB *pblob) { struct xattr_NTACL xacl; @@ -170,7 +222,7 @@ static NTSTATUS create_acl_blob(const struct security_descriptor *psd, DATA_BLOB timestring(ctx, curr.tv_sec) )); ndr_err = ndr_push_struct_blob( - pblob, ctx, NULL, &xacl, + pblob, ctx, &xacl, (ndr_push_flags_fn_t)ndr_push_xattr_NTACL); if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { @@ -182,69 +234,95 @@ static NTSTATUS create_acl_blob(const struct security_descriptor *psd, DATA_BLOB return NT_STATUS_OK; } -static NTSTATUS store_acl_blob_fsp(files_struct *fsp, +/******************************************************************* + Store a DATA_BLOB into a tdb record given an fsp pointer. +*******************************************************************/ + +static NTSTATUS store_acl_blob_fsp(vfs_handle_struct *handle, + files_struct *fsp, DATA_BLOB *pblob) { - int ret; - int saved_errno = 0; + uint8 id_buf[16]; + struct file_id id; + SMB_STRUCT_STAT sbuf; + TDB_DATA data; + struct db_context *db; + struct db_record *rec; DEBUG(10,("store_acl_blob_fsp: storing blob length %u on file %s\n", (unsigned int)pblob->length, fsp->fsp_name)); - become_root(); + SMB_VFS_HANDLE_GET_DATA(handle, db, struct db_context, + return NT_STATUS_INTERNAL_DB_CORRUPTION); + if (fsp->fh->fd != -1) { - ret = SMB_VFS_FSETXATTR(fsp, XATTR_NTACL_NAME, - pblob->data, pblob->length, 0); + if (SMB_VFS_FSTAT(fsp, &sbuf) == -1) { + return map_nt_error_from_unix(errno); + } } else { - ret = SMB_VFS_SETXATTR(fsp->conn, fsp->fsp_name, - XATTR_NTACL_NAME, - pblob->data, pblob->length, 0); - } - if (ret) { - saved_errno = errno; + if (SMB_VFS_STAT(handle->conn, fsp->fsp_name, &sbuf) == -1) { + return map_nt_error_from_unix(errno); + } } - unbecome_root(); - if (ret) { - errno = saved_errno; - DEBUG(5, ("store_acl_blob_fsp: setting attr failed for file %s" - "with error %s\n", - fsp->fsp_name, - strerror(errno) )); - return map_nt_error_from_unix(errno); + id = vfs_file_id_from_sbuf(handle->conn, &sbuf); + + push_file_id_16((char *)id_buf, &id); + rec = db->fetch_locked(db, talloc_tos(), + make_tdb_data(id_buf, + sizeof(id_buf))); + if (rec == NULL) { + DEBUG(0, ("store_acl_blob_fsp_tdb: fetch_lock failed\n")); + return NT_STATUS_INTERNAL_DB_CORRUPTION; } - return NT_STATUS_OK; + data.dptr = pblob->data; + data.dsize = pblob->length; + return rec->store(rec, data, 0); } -static NTSTATUS store_acl_blob_pathname(connection_struct *conn, +/******************************************************************* + Store a DATA_BLOB into a tdb record given a pathname. +*******************************************************************/ + +static NTSTATUS store_acl_blob_pathname(vfs_handle_struct *handle, const char *fname, DATA_BLOB *pblob) { - int ret; - int saved_errno = 0; + uint8 id_buf[16]; + struct file_id id; + TDB_DATA data; + SMB_STRUCT_STAT sbuf; + struct db_context *db; + struct db_record *rec; DEBUG(10,("store_acl_blob_pathname: storing blob " "length %u on file %s\n", (unsigned int)pblob->length, fname)); - become_root(); - ret = SMB_VFS_SETXATTR(conn, fname, - XATTR_NTACL_NAME, - pblob->data, pblob->length, 0); - if (ret) { - saved_errno = errno; - } - unbecome_root(); - if (ret) { - errno = saved_errno; - DEBUG(5, ("store_acl_blob_pathname: setting attr failed " - "for file %s with error %s\n", - fname, - strerror(errno) )); + SMB_VFS_HANDLE_GET_DATA(handle, db, struct db_context, + return NT_STATUS_INTERNAL_DB_CORRUPTION); + + if (SMB_VFS_STAT(handle->conn, fname, &sbuf) == -1) { return map_nt_error_from_unix(errno); } - return NT_STATUS_OK; + + id = vfs_file_id_from_sbuf(handle->conn, &sbuf); + push_file_id_16((char *)id_buf, &id); + + rec = db->fetch_locked(db, talloc_tos(), + make_tdb_data(id_buf, + sizeof(id_buf))); + if (rec == NULL) { + DEBUG(0, ("store_acl_blob_pathname_tdb: fetch_lock failed\n")); + return NT_STATUS_INTERNAL_DB_CORRUPTION; + } + data.dptr = pblob->data; + data.dsize = pblob->length; + return rec->store(rec, data, 0); } +/******************************************************************* + Store a DATA_BLOB into an xattr given a pathname. +*******************************************************************/ static NTSTATUS get_nt_acl_xattr_internal(vfs_handle_struct *handle, files_struct *fsp, @@ -254,7 +332,6 @@ static NTSTATUS get_nt_acl_xattr_internal(vfs_handle_struct *handle, { TALLOC_CTX *ctx = talloc_tos(); DATA_BLOB blob; - SMB_STRUCT_STAT sbuf; NTSTATUS status; if (fsp && name == NULL) { @@ -269,18 +346,7 @@ static NTSTATUS get_nt_acl_xattr_internal(vfs_handle_struct *handle, return status; } - if (fsp && fsp->fh->fd != -1) { - if (SMB_VFS_FSTAT(fsp, &sbuf) == -1) { - return map_nt_error_from_unix(errno); - } - } else { - if (SMB_VFS_STAT(handle->conn, name, &sbuf) == -1) { - return map_nt_error_from_unix(errno); - } - } - - status = parse_acl_blob(&blob, get_ctimespec(&sbuf), - security_info, ppdesc); + status = parse_acl_blob(&blob, security_info, ppdesc); if (!NT_STATUS_IS_OK(status)) { DEBUG(10, ("parse_acl_blob returned %s\n", nt_errstr(status))); @@ -427,9 +493,9 @@ static NTSTATUS inherit_new_acl(vfs_handle_struct *handle, return status; } if (fsp) { - return store_acl_blob_fsp(fsp, &blob); + return store_acl_blob_fsp(handle, fsp, &blob); } else { - return store_acl_blob_pathname(handle->conn, fname, &blob); + return store_acl_blob_pathname(handle, fname, &blob); } } @@ -487,6 +553,55 @@ static int open_acl_xattr(vfs_handle_struct *handle, return fsp->fh->fd; } +/********************************************************************* + On unlink we need to delete the tdb record (if using tdb). +*********************************************************************/ + +static int unlink_acl_xattr(vfs_handle_struct *handle, const char *path) +{ + SMB_STRUCT_STAT sbuf; + struct file_id id; + struct db_context *db; + struct db_record *rec; + int ret; + + SMB_VFS_HANDLE_GET_DATA(handle, db, struct db_context, return -1); + + if (SMB_VFS_STAT(handle->conn, path, &sbuf) == -1) { + return -1; + } + + ret = SMB_VFS_NEXT_UNLINK(handle, path); + + if (ret == -1) { + return -1; + } + + id = vfs_file_id_from_sbuf(handle->conn, &sbuf); + + rec = acl_xattr_tdb_lock(talloc_tos(), db, &id); + + /* + * If rec == NULL there's not much we can do about it + */ -- Samba Shared Repository