summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--source3/Makefile.in16
-rw-r--r--source3/configure.in11
-rw-r--r--source3/include/ctdbd_conn.h6
-rw-r--r--source3/include/dbwrap.h1
-rw-r--r--source3/include/rpc_lsa.h19
-rw-r--r--source3/include/vfs.h19
-rw-r--r--source3/include/vfs_macros.h18
-rw-r--r--source3/lib/conn_tdb.c2
-rw-r--r--source3/lib/ctdbd_conn.c36
-rw-r--r--source3/lib/dbwrap.c12
-rw-r--r--source3/lib/dbwrap_ctdb.c178
-rw-r--r--source3/lib/dbwrap_file.c5
-rw-r--r--source3/lib/dbwrap_tdb.c21
-rw-r--r--source3/lib/dbwrap_util.c90
-rw-r--r--source3/lib/messages_ctdbd.c4
-rw-r--r--source3/lib/netapi/serverinfo.c2
-rw-r--r--source3/lib/util.c13
-rw-r--r--source3/lib/util_reg.c1
-rw-r--r--source3/libads/ads_struct.c16
-rw-r--r--source3/libnet/libnet_join.c4
-rw-r--r--source3/librpc/gen_ndr/cli_lsa.c26
-rw-r--r--source3/librpc/gen_ndr/cli_lsa.h16
-rw-r--r--source3/librpc/gen_ndr/lsa.h135
-rw-r--r--source3/librpc/gen_ndr/ndr_lsa.c679
-rw-r--r--source3/librpc/gen_ndr/ndr_lsa.h46
-rw-r--r--source3/librpc/gen_ndr/srv_lsa.c21
-rw-r--r--source3/librpc/gen_ndr/srv_lsa.h2
-rw-r--r--source3/librpc/idl/lsa.idl127
-rw-r--r--source3/libsmb/namequery.c10
-rw-r--r--source3/locking/brlock.c29
-rw-r--r--source3/modules/gpfs.c20
-rw-r--r--source3/modules/nfs4_acls.c187
-rw-r--r--source3/modules/vfs_default.c42
-rw-r--r--source3/modules/vfs_gpfs.c281
-rw-r--r--source3/modules/vfs_gpfs.h32
-rw-r--r--source3/modules/vfs_prealloc.c8
-rw-r--r--source3/modules/vfs_shadow_copy2.c637
-rw-r--r--source3/modules/vfs_tsmsm.c338
-rw-r--r--source3/param/loadparm.c128
-rw-r--r--source3/rpc_server/srv_lsa_nt.c2
-rw-r--r--source3/smbd/connection.c9
-rw-r--r--source3/smbd/dmapi.c71
-rw-r--r--source3/smbd/dosmode.c44
-rw-r--r--source3/smbd/oplock_linux.c22
-rw-r--r--source3/smbd/posix_acls.c31
-rw-r--r--source3/smbd/reply.c19
-rw-r--r--source3/smbd/server.c67
-rw-r--r--source3/smbd/service.c84
-rw-r--r--source3/smbd/trans2.c23
-rw-r--r--source3/winbindd/idmap_tdb2.c1017
50 files changed, 4113 insertions, 514 deletions
diff --git a/source3/Makefile.in b/source3/Makefile.in
index 46f733c0bc..265d14547c 100644
--- a/source3/Makefile.in
+++ b/source3/Makefile.in
@@ -308,7 +308,7 @@ LIB_WITH_PROTO_OBJ = $(VERSION_OBJ) lib/charcnv.o lib/debug.o lib/fault.o \
lib/util_str.o lib/clobber.o lib/util_sid.o lib/util_uuid.o \
lib/util_unistr.o lib/util_file.o lib/data_blob.o \
lib/util.o lib/util_sock.o lib/sock_exec.o lib/util_sec.o \
- lib/substitute.o lib/fsusage.o \
+ lib/substitute.o lib/fsusage.o lib/dbwrap_util.o \
lib/ms_fnmatch.o lib/select.o lib/errmap_unix.o \
lib/tallocmsg.o lib/dmallocmsg.o libsmb/smb_signing.o \
lib/md5.o lib/hmacmd5.o lib/arc4.o lib/iconv.o \
@@ -503,6 +503,7 @@ VFS_READONLY_OBJ = modules/vfs_readonly.o modules/getdate.o
VFS_CAP_OBJ = modules/vfs_cap.o
VFS_EXPAND_MSDFS_OBJ = modules/vfs_expand_msdfs.o
VFS_SHADOW_COPY_OBJ = modules/vfs_shadow_copy.o
+VFS_SHADOW_COPY2_OBJ = modules/vfs_shadow_copy2.o
VFS_AFSACL_OBJ = modules/vfs_afsacl.o
VFS_XATTR_TDB_OBJ = modules/vfs_xattr_tdb.o librpc/gen_ndr/ndr_xattr.o
VFS_POSIXACL_OBJ = modules/vfs_posixacl.o
@@ -520,6 +521,7 @@ VFS_COMMIT_OBJ = modules/vfs_commit.o
VFS_GPFS_OBJ = modules/vfs_gpfs.o modules/gpfs.o modules/nfs4_acls.o
VFS_NOTIFY_FAM_OBJ = modules/vfs_notify_fam.o
VFS_READAHEAD_OBJ = modules/vfs_readahead.o
+VFS_TSMSM_OBJ = modules/vfs_tsmsm.o
VFS_FILEID_OBJ = modules/vfs_fileid.o
VFS_SYNCOPS_OBJ = modules/vfs_syncops.o
@@ -1611,6 +1613,10 @@ bin/ad.@SHLIBEXT@: $(BINARY_PREREQS) winbindd/idmap_ad.o
@echo "Building plugin $@"
@$(SHLD_MODULE) winbindd/idmap_ad.o
+bin/tdb2.@SHLIBEXT@: $(BINARY_PREREQS) winbindd/idmap_tdb2.o
+ @echo "Building plugin $@"
+ @$(SHLD_MODULE) winbindd/idmap_tdb2.o
+
bin/ldap.@SHLIBEXT@: $(BINARY_PREREQS) winbindd/idmap_ldap.o
@echo "Building plugin $@"
@$(SHLD_MODULE) winbindd/idmap_ldap.o
@@ -1670,6 +1676,10 @@ bin/shadow_copy.@SHLIBEXT@: $(BINARY_PREREQS) $(VFS_SHADOW_COPY_OBJ)
@echo "Building plugin $@"
@$(SHLD_MODULE) $(VFS_SHADOW_COPY_OBJ)
+bin/shadow_copy2.@SHLIBEXT@: $(BINARY_PREREQS) $(VFS_SHADOW_COPY2_OBJ)
+ @echo "Building plugin $@"
+ @$(SHLD_MODULE) $(VFS_SHADOW_COPY2_OBJ)
+
bin/syncops.@SHLIBEXT@: $(BINARY_PREREQS) $(VFS_SYNCOPS_OBJ)
@echo "Building plugin $@"
@$(SHLD_MODULE) $(VFS_SYNCOPS_OBJ)
@@ -1750,6 +1760,10 @@ bin/readahead.@SHLIBEXT@: $(BINARY_PREREQS) $(VFS_READAHEAD_OBJ)
@echo "Building plugin $@"
@$(SHLD_MODULE) $(VFS_READAHEAD_OBJ)
+bin/tsmsm.@SHLIBEXT@: $(BINARY_PREREQS) $(VFS_TSMSM_OBJ)
+ @echo "Building plugin $@"
+ @$(SHLD_MODULE) $(VFS_TSMSM_OBJ)
+
bin/fileid.@SHLIBEXT@: $(BINARY_PREREQS) $(VFS_FILEID_OBJ)
@echo "Building plugin $@"
@$(SHLD_MODULE) $(VFS_FILEID_OBJ)
diff --git a/source3/configure.in b/source3/configure.in
index cd04b598c0..f65eb3c204 100644
--- a/source3/configure.in
+++ b/source3/configure.in
@@ -707,7 +707,7 @@ dnl These have to be built static:
default_static_modules="pdb_smbpasswd pdb_tdbsam rpc_lsa rpc_samr rpc_winreg rpc_initshutdown rpc_lsa_ds rpc_wkssvc rpc_svcctl2 rpc_ntsvcs rpc_net rpc_netdfs rpc_srvsvc2 rpc_spoolss rpc_eventlog2 auth_sam auth_unix auth_winbind auth_server auth_domain auth_builtin 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 charset_CP850 charset_CP437 auth_script vfs_readahead vfs_syncops vfs_xattr_tdb"
+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_syncops vfs_xattr_tdb"
if test "x$developer" = xyes; then
default_static_modules="$default_static_modules rpc_rpcecho"
@@ -2751,6 +2751,12 @@ AC_SUBST(SMB_FAM_LIBS)
SMB_CHECK_DMAPI([], AC_MSG_NOTICE(DMAPI support not present) )
+# Add TSM SM VFS module only if there are both GPFS and DMAPI support
+# Theoretically it should work with AIX JFS2 too but this needs testing
+if test x"$samba_cv_HAVE_GPFS" = x"yes" && test x"$samba_dmapi_libs" != x"" ; then
+ default_shared_modules="$default_shared_modules vfs_tsmsm"
+fi
+
AC_CACHE_CHECK([for kernel share modes],samba_cv_HAVE_KERNEL_SHARE_MODES,[
AC_TRY_RUN([
#include <sys/types.h>
@@ -6452,6 +6458,7 @@ SMB_SUBSYSTEM(RPC,smbd/server.o)
SMB_MODULE(idmap_ldap, winbindd/idmap_ldap.o, "bin/ldap.$SHLIBEXT", IDMAP)
SMB_MODULE(idmap_tdb, winbindd/idmap_tdb.o, "bin/tdb.$SHLIBEXT", IDMAP)
+SMB_MODULE(idmap_tdb2, winbindd/idmap_tdb2.o, "bin/tdb2.$SHLIBEXT", IDMAP)
SMB_MODULE(idmap_passdb, winbindd/idmap_passdb.o, "bin/passdb.$SHLIBEXT", IDMAP)
SMB_MODULE(idmap_nss, winbindd/idmap_nss.o, "bin/nss.$SHLIBEXT", IDMAP)
SMB_MODULE(idmap_rid, winbindd/idmap_rid.o, "bin/rid.$SHLIBEXT", IDMAP)
@@ -6488,6 +6495,7 @@ SMB_MODULE(vfs_readonly, \$(VFS_READONLY_OBJ), "bin/readonly.$SHLIBEXT", VFS)
SMB_MODULE(vfs_cap, \$(VFS_CAP_OBJ), "bin/cap.$SHLIBEXT", VFS)
SMB_MODULE(vfs_expand_msdfs, \$(VFS_EXPAND_MSDFS_OBJ), "bin/expand_msdfs.$SHLIBEXT", VFS)
SMB_MODULE(vfs_shadow_copy, \$(VFS_SHADOW_COPY_OBJ), "bin/shadow_copy.$SHLIBEXT", VFS)
+SMB_MODULE(vfs_shadow_copy2, \$(VFS_SHADOW_COPY2_OBJ), "bin/shadow_copy2.$SHLIBEXT", VFS)
SMB_MODULE(vfs_afsacl, \$(VFS_AFSACL_OBJ), "bin/afsacl.$SHLIBEXT", VFS)
SMB_MODULE(vfs_xattr_tdb, \$(VFS_XATTR_TDB_OBJ), "bin/xattr_tdb.$SHLIBEXT", VFS)
SMB_MODULE(vfs_posixacl, \$(VFS_POSIXACL_OBJ), "bin/posixacl.$SHLIBEXT", VFS)
@@ -6503,6 +6511,7 @@ SMB_MODULE(vfs_prealloc, \$(VFS_PREALLOC_OBJ), "bin/prealloc.$SHLIBEXT", VFS)
SMB_MODULE(vfs_commit, \$(VFS_COMMIT_OBJ), "bin/commit.$SHLIBEXT", VFS)
SMB_MODULE(vfs_gpfs, \$(VFS_GPFS_OBJ), "bin/gpfs.$SHLIBEXT", VFS)
SMB_MODULE(vfs_readahead, \$(VFS_READAHEAD_OBJ), "bin/readahead.$SHLIBEXT", VFS)
+SMB_MODULE(vfs_tsmsm, \$(VFS_TSMSM_OBJ), "bin/tsmsm.$SHLIBEXT", VFS)
SMB_MODULE(vfs_fileid, \$(VFS_FILEID_OBJ), "bin/fileid.$SHLIBEXT", VFS)
SMB_MODULE(vfs_syncops, \$(VFS_SYNCOPS_OBJ), "bin/syncops.$SHLIBEXT", VFS)
SMB_MODULE(vfs_zfsacl, \$(VFS_ZFSACL_OBJ), "bin/zfsacl.$SHLIBEXT", VFS)
diff --git a/source3/include/ctdbd_conn.h b/source3/include/ctdbd_conn.h
index 425cc65a00..6e1b2f737a 100644
--- a/source3/include/ctdbd_conn.h
+++ b/source3/include/ctdbd_conn.h
@@ -17,6 +17,9 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
+#ifndef _CTDBD_CONN_H
+#define _CTDBD_CONN_H
+
struct ctdbd_connection;
NTSTATUS ctdbd_init_connection(TALLOC_CTX *mem_ctx,
@@ -62,3 +65,6 @@ NTSTATUS ctdbd_register_ips(struct ctdbd_connection *conn,
NTSTATUS ctdbd_register_reconfigure(struct ctdbd_connection *conn);
+NTSTATUS ctdbd_persistent_store(struct ctdbd_connection *conn, uint32_t db_id, TDB_DATA key, TDB_DATA data);
+
+#endif /* _CTDBD_CONN_H */
diff --git a/source3/include/dbwrap.h b/source3/include/dbwrap.h
index 3bb378c841..4eb174fef1 100644
--- a/source3/include/dbwrap.h
+++ b/source3/include/dbwrap.h
@@ -43,6 +43,7 @@ struct db_context {
void *private_data);
int (*get_seqnum)(struct db_context *db);
void *private_data;
+ bool persistent;
};
struct db_context *db_open(TALLOC_CTX *mem_ctx,
diff --git a/source3/include/rpc_lsa.h b/source3/include/rpc_lsa.h
index ef6ff6db28..72aabc310e 100644
--- a/source3/include/rpc_lsa.h
+++ b/source3/include/rpc_lsa.h
@@ -87,27 +87,8 @@
#define LSA_AUDIT_NUM_CATEGORIES_NT4 7
#define LSA_AUDIT_NUM_CATEGORIES_WIN2K 9
-
#define LSA_AUDIT_NUM_CATEGORIES LSA_AUDIT_NUM_CATEGORIES_NT4
-#define LSA_AUDIT_POLICY_NONE 0x00
-#define LSA_AUDIT_POLICY_SUCCESS 0x01
-#define LSA_AUDIT_POLICY_FAILURE 0x02
-#define LSA_AUDIT_POLICY_ALL (LSA_AUDIT_POLICY_SUCCESS|LSA_AUDIT_POLICY_FAILURE)
-#define LSA_AUDIT_POLICY_CLEAR 0x04
-
-enum lsa_audit_categories {
- LSA_AUDIT_CATEGORY_SYSTEM = 0,
- LSA_AUDIT_CATEGORY_LOGON = 1,
- LSA_AUDIT_CATEGORY_FILE_AND_OBJECT_ACCESS,
- LSA_AUDIT_CATEGORY_USE_OF_USER_RIGHTS,
- LSA_AUDIT_CATEGORY_PROCCESS_TRACKING,
- LSA_AUDIT_CATEGORY_SECURITY_POLICY_CHANGES,
- LSA_AUDIT_CATEGORY_ACCOUNT_MANAGEMENT,
- LSA_AUDIT_CATEGORY_DIRECTORY_SERVICE_ACCESS, /* only in win2k/2k3 */
- LSA_AUDIT_CATEGORY_ACCOUNT_LOGON /* only in win2k/2k3 */
-};
-
/* level 1 is auditing settings */
typedef struct dom_query_1
{
diff --git a/source3/include/vfs.h b/source3/include/vfs.h
index 0be3886227..be3cd91520 100644
--- a/source3/include/vfs.h
+++ b/source3/include/vfs.h
@@ -70,6 +70,7 @@
* timestamp resolition. JRA. */
/* Changed to version21 to add chflags operation -- jpeach */
/* Changed to version22 to add lchown operation -- jra */
+/* Additional change: add operations for offline files and remote storage volume abstraction -- ab*/
/* Leave at 22 - not yet released. But change set_nt_acl to return an NTSTATUS. jra. */
/* Leave at 22 - not yet released. Add file_id_create operation. --metze */
/* Leave at 22 - not yet released. Change all BOOL parameters (int) to bool. jra. */
@@ -257,6 +258,12 @@ typedef enum _vfs_op_type {
SMB_VFS_OP_AIO_ERROR,
SMB_VFS_OP_AIO_FSYNC,
SMB_VFS_OP_AIO_SUSPEND,
+ SMB_VFS_OP_AIO_FORCE,
+
+ /* offline operations */
+ SMB_VFS_OP_IS_OFFLINE,
+ SMB_VFS_OP_SET_OFFLINE,
+ SMB_VFS_OP_IS_REMOTESTORAGE,
/* This should always be last enum value */
@@ -405,6 +412,12 @@ struct vfs_ops {
int (*aio_error_fn)(struct vfs_handle_struct *handle, struct files_struct *fsp, SMB_STRUCT_AIOCB *aiocb);
int (*aio_fsync)(struct vfs_handle_struct *handle, struct files_struct *fsp, int op, SMB_STRUCT_AIOCB *aiocb);
int (*aio_suspend)(struct vfs_handle_struct *handle, struct files_struct *fsp, const SMB_STRUCT_AIOCB * const aiocb[], int n, const struct timespec *timeout);
+ bool (*aio_force)(struct vfs_handle_struct *handle, struct files_struct *fsp);
+
+ /* offline operations */
+ int (*is_offline)(struct vfs_handle_struct *handle, struct connection_struct *conn, const char *path, SMB_STRUCT_STAT *sbuf, bool *offline);
+ int (*set_offline)(struct vfs_handle_struct *handle, struct connection_struct *conn, const char *path);
+ bool (*is_remotestorage)(struct vfs_handle_struct *handle, struct connection_struct *conn, const char *path);
} ops;
@@ -526,6 +539,12 @@ struct vfs_ops {
struct vfs_handle_struct *aio_error;
struct vfs_handle_struct *aio_fsync;
struct vfs_handle_struct *aio_suspend;
+ struct vfs_handle_struct *aio_force;
+
+ /* offline operations */
+ struct vfs_handle_struct *is_offline;
+ struct vfs_handle_struct *set_offline;
+ struct vfs_handle_struct *is_remotestorage;
} handles;
};
diff --git a/source3/include/vfs_macros.h b/source3/include/vfs_macros.h
index 9232e94a42..dbba781377 100644
--- a/source3/include/vfs_macros.h
+++ b/source3/include/vfs_macros.h
@@ -138,6 +138,12 @@
#define SMB_VFS_AIO_ERROR(fsp,aiocb) ((fsp)->conn->vfs.ops.aio_error_fn((fsp)->conn->vfs.handles.aio_error,(fsp),(aiocb)))
#define SMB_VFS_AIO_FSYNC(fsp,op,aiocb) ((fsp)->conn->vfs.ops.aio_fsync((fsp)->conn->vfs.handles.aio_fsync,(fsp),(op),(aiocb)))
#define SMB_VFS_AIO_SUSPEND(fsp,aiocb,n,ts) ((fsp)->conn->vfs.ops.aio_suspend((fsp)->conn->vfs.handles.aio_suspend,(fsp),(aiocb),(n),(ts)))
+#define SMB_VFS_AIO_FORCE(fsp) ((fsp)->conn->vfs.ops.aio_force((fsp)->conn->vfs.handles.aio_force,(fsp)))
+
+/* Offline operations */
+#define SMB_VFS_IS_OFFLINE(conn,path,sbuf,offline) ((conn)->vfs.ops.is_offline((conn)->vfs.handles.is_offline,(conn),(path),(sbuf),(offline)))
+#define SMB_VFS_SET_OFFLINE(conn,path) ((conn)->vfs.ops.set_offline((conn)->vfs.handles.set_offline,(conn),(path)))
+#define SMB_VFS_IS_REMOTESTORAGE(conn,path) ((conn)->vfs.ops.is_remotestorage((conn)->vfs.handles.is_remotestorage,(conn),(path)))
/*******************************************************************
Don't access conn->vfs_opaque.ops directly!!!
@@ -257,6 +263,12 @@
#define SMB_VFS_OPAQUE_AIO_ERROR(fsp,aiocb) ((fsp)->conn->vfs_opaque.ops.aio_error_fn((fsp)->conn->vfs_opaque.handles.aio_error,(fsp),(aiocb)))
#define SMB_VFS_OPAQUE_AIO_FSYNC(fsp,op,aiocb) ((fsp)->conn->vfs_opaque.ops.aio_fsync((fsp)->conn->vfs_opaque.handles.aio_fsync,(fsp),(op),(aiocb)))
#define SMB_VFS_OPAQUE_AIO_SUSPEND(fsp,aiocb,n,ts) ((fsp)->conn->vfs_opaque.ops.aio_suspend((fsp)->conn->vfs_opaque.handles.aio_suspend,(fsp),(aiocb),(n),(ts)))
+#define SMB_VFS_OPAQUE_AIO_FORCE(fsp) ((fsp)->conn->vfs_opaque.ops.aio_force((fsp)->conn->vfs_opaque.handles.aio_force,(fsp)))
+
+/* Offline operations */
+#define SMB_VFS_OPAQUE_IS_OFFLINE(conn,path,sbuf,offline) ((conn)->vfs_opaque.ops.is_offline((conn)->vfs_opaque.handles.is_offline,(conn),(path),(sbuf),(offline)))
+#define SMB_VFS_OPAQUE_SET_OFFLINE(conn,path) ((conn)->vfs_opaque.ops.set_offline((conn)->vfs_opaque.handles.set_offline,(conn),(path)))
+#define SMB_VFS_OPAQUE_IS_REMOTESTORAGE(conn,path) ((conn)->vfs_opaque.ops.is_remotestorage((conn)->vfs_opaque.handles.is_remotestorage,(conn),(path)))
/*******************************************************************
Don't access handle->vfs_next.ops.* directly!!!
@@ -377,5 +389,11 @@
#define SMB_VFS_NEXT_AIO_ERROR(handle,fsp,aiocb) ((handle)->vfs_next.ops.aio_error_fn((handle)->vfs_next.handles.aio_error,(fsp),(aiocb)))
#define SMB_VFS_NEXT_AIO_FSYNC(handle,fsp,op,aiocb) ((handle)->vfs_next.ops.aio_fsync((handle)->vfs_next.handles.aio_fsync,(fsp),(op),(aiocb)))
#define SMB_VFS_NEXT_AIO_SUSPEND(handle,fsp,aiocb,n,ts) ((handle)->vfs_next.ops.aio_suspend((handle)->vfs_next.handles.aio_suspend,(fsp),(aiocb),(n),(ts)))
+#define SMB_VFS_NEXT_AIO_FORCE(handle,fsp) ((handle)->vfs_next.ops.aio_force((handle)->vfs_next.handles.aio_force,(fsp)))
+
+/* Offline operations */
+#define SMB_VFS_NEXT_IS_OFFLINE(conn,path,sbuf,offline) ((conn)->vfs_next.ops.is_offline((conn)->vfs_next.handles.is_offline,(conn),(path),(sbuf),(offline)))
+#define SMB_VFS_NEXT_SET_OFFLINE(conn,path) ((conn)->vfs_next.ops.set_offline((conn)->vfs_next.handles.set_offline,(conn),(path)))
+#define SMB_VFS_NEXT_IS_REMOTESTORAGE(conn,path) ((conn)->vfs_next.ops.is_remotestorage((conn)->vfs_next.handles.is_remotestorage,(conn),(path)))
#endif /* _VFS_MACROS_H */
diff --git a/source3/lib/conn_tdb.c b/source3/lib/conn_tdb.c
index dd0a354a85..22d85c873d 100644
--- a/source3/lib/conn_tdb.c
+++ b/source3/lib/conn_tdb.c
@@ -34,7 +34,7 @@ static struct db_context *connections_db_ctx(bool rw)
}
else {
db_ctx = db_open(NULL, lock_path("connections.tdb"), 0,
- TDB_DEFAULT, O_RDONLY, 0);
+ TDB_CLEAR_IF_FIRST|TDB_DEFAULT, O_RDONLY, 0);
}
return db_ctx;
diff --git a/source3/lib/ctdbd_conn.c b/source3/lib/ctdbd_conn.c
index 899bbcfcce..18e9879601 100644
--- a/source3/lib/ctdbd_conn.c
+++ b/source3/lib/ctdbd_conn.c
@@ -1203,6 +1203,42 @@ NTSTATUS ctdbd_register_reconfigure(struct ctdbd_connection *conn)
return register_with_ctdbd(conn, CTDB_SRVID_RECONFIGURE);
}
+/*
+ persstent store. Used when we update a record in a persistent database
+ */
+NTSTATUS ctdbd_persistent_store(struct ctdbd_connection *conn, uint32_t db_id, TDB_DATA key, TDB_DATA data)
+{
+ int cstatus=0;
+ struct ctdb_rec_data *rec;
+ TDB_DATA recdata;
+ size_t length;
+ NTSTATUS status;
+
+ length = offsetof(struct ctdb_rec_data, data) + key.dsize + data.dsize;
+
+ rec = (struct ctdb_rec_data *)talloc_size(conn, length);
+ NT_STATUS_HAVE_NO_MEMORY(rec);
+
+ rec->length = length;
+ rec->reqid = db_id;
+ rec->keylen = key.dsize;
+ rec->datalen= data.dsize;
+ memcpy(&rec->data[0], key.dptr, key.dsize);
+ memcpy(&rec->data[key.dsize], data.dptr, data.dsize);
+
+ recdata.dptr = (uint8_t *)rec;
+ recdata.dsize = length;
+
+ status = ctdbd_control(conn, CTDB_CURRENT_NODE,
+ CTDB_CONTROL_PERSISTENT_STORE,
+ 0, recdata, NULL, NULL, &cstatus);
+ if (cstatus != 0) {
+ return NT_STATUS_INTERNAL_DB_CORRUPTION;
+ }
+ return status;
+}
+
+
#else
NTSTATUS ctdbd_init_connection(TALLOC_CTX *mem_ctx,
diff --git a/source3/lib/dbwrap.c b/source3/lib/dbwrap.c
index 4e16d18682..001424a6c0 100644
--- a/source3/lib/dbwrap.c
+++ b/source3/lib/dbwrap.c
@@ -20,7 +20,9 @@
*/
#include "includes.h"
-
+#ifdef CLUSTER_SUPPORT
+#include "ctdb_private.h"
+#endif
/*
* Fall back using fetch_locked if no genuine fetch operation is provided
*/
@@ -46,10 +48,16 @@ struct db_context *db_open(TALLOC_CTX *mem_ctx,
int open_flags, mode_t mode)
{
struct db_context *result = NULL;
+#ifdef CLUSTER_SUPPORT
+ const char *sockname = lp_ctdbd_socket();
+#endif
#ifdef CLUSTER_SUPPORT
+ if(!sockname || !*sockname) {
+ sockname = CTDB_PATH;
+ }
- if (lp_clustering()) {
+ if (lp_clustering() && socket_exist(sockname)) {
const char *partname;
/* ctdb only wants the file part of the name */
partname = strrchr(name, '/');
diff --git a/source3/lib/dbwrap_ctdb.c b/source3/lib/dbwrap_ctdb.c
index 90d0b260c5..f497f871d2 100644
--- a/source3/lib/dbwrap_ctdb.c
+++ b/source3/lib/dbwrap_ctdb.c
@@ -18,16 +18,14 @@
*/
#include "includes.h"
-
#ifdef CLUSTER_SUPPORT
-
#include "ctdb.h"
#include "ctdb_private.h"
+#include "ctdbd_conn.h"
struct db_ctdb_ctx {
struct tdb_wrap *wtdb;
uint32 db_id;
- struct ctdbd_connection *conn;
};
struct db_ctdb_rec {
@@ -35,8 +33,6 @@ struct db_ctdb_rec {
struct ctdb_ltdb_header header;
};
-static struct ctdbd_connection *db_ctdbd_conn(struct db_ctdb_ctx *ctx);
-
static NTSTATUS db_ctdb_store(struct db_record *rec, TDB_DATA data, int flag)
{
struct db_ctdb_rec *crec = talloc_get_type_abort(
@@ -60,6 +56,42 @@ static NTSTATUS db_ctdb_store(struct db_record *rec, TDB_DATA data, int flag)
return (ret == 0) ? NT_STATUS_OK : NT_STATUS_INTERNAL_DB_CORRUPTION;
}
+
+/* for persistent databases the store is a bit different. We have to
+ ask the ctdb daemon to push the record to all nodes after the
+ store */
+static NTSTATUS db_ctdb_store_persistent(struct db_record *rec, TDB_DATA data, int flag)
+{
+ struct db_ctdb_rec *crec = talloc_get_type_abort(
+ rec->private_data, struct db_ctdb_rec);
+ TDB_DATA cdata;
+ int ret;
+ NTSTATUS status;
+
+ cdata.dsize = sizeof(crec->header) + data.dsize;
+
+ if (!(cdata.dptr = SMB_MALLOC_ARRAY(uint8, cdata.dsize))) {
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ crec->header.rsn++;
+
+ memcpy(cdata.dptr, &crec->header, sizeof(crec->header));
+ memcpy(cdata.dptr + sizeof(crec->header), data.dptr, data.dsize);
+
+ ret = tdb_store(crec->ctdb_ctx->wtdb->tdb, rec->key, cdata, TDB_REPLACE);
+ status = (ret == 0) ? NT_STATUS_OK : NT_STATUS_INTERNAL_DB_CORRUPTION;
+
+ /* now tell ctdbd to update this record on all other nodes */
+ if (NT_STATUS_IS_OK(status)) {
+ status = ctdbd_persistent_store(messaging_ctdbd_connection(), crec->ctdb_ctx->db_id, rec->key, cdata);
+ }
+
+ SAFE_FREE(cdata.dptr);
+
+ return status;
+}
+
static NTSTATUS db_ctdb_delete(struct db_record *rec)
{
struct db_ctdb_rec *crec = talloc_get_type_abort(
@@ -110,6 +142,7 @@ static struct db_record *db_ctdb_fetch_locked(struct db_context *db,
struct db_ctdb_rec *crec;
NTSTATUS status;
TDB_DATA ctdb_data;
+ int migrate_attempts = 0;
if (!(result = talloc(mem_ctx, struct db_record))) {
DEBUG(0, ("talloc failed\n"));
@@ -153,7 +186,11 @@ again:
return NULL;
}
- result->store = db_ctdb_store;
+ if (db->persistent) {
+ result->store = db_ctdb_store_persistent;
+ } else {
+ result->store = db_ctdb_store;
+ }
result->delete_rec = db_ctdb_delete;
talloc_set_destructor(result, db_ctdb_record_destr);
@@ -175,12 +212,14 @@ again:
tdb_chainunlock(ctx->wtdb->tdb, key);
talloc_set_destructor(result, NULL);
+ migrate_attempts += 1;
+
DEBUG(10, ("ctdb_data.dptr = %p, dmaster = %u (%u)\n",
ctdb_data.dptr, ctdb_data.dptr ?
((struct ctdb_ltdb_header *)ctdb_data.dptr)->dmaster : -1,
get_my_vnn()));
- status = ctdbd_migrate(db_ctdbd_conn(ctx), ctx->db_id, key);
+ status = ctdbd_migrate(messaging_ctdbd_connection(),ctx->db_id, key);
if (!NT_STATUS_IS_OK(status)) {
DEBUG(5, ("ctdb_migrate failed: %s\n",
nt_errstr(status)));
@@ -191,6 +230,11 @@ again:
goto again;
}
+ if (migrate_attempts > 10) {
+ DEBUG(0, ("db_ctdb_fetch_locked needed %d attempts\n",
+ migrate_attempts));
+ }
+
memcpy(&crec->header, ctdb_data.dptr, sizeof(crec->header));
result->value.dsize = ctdb_data.dsize - sizeof(crec->header);
@@ -226,10 +270,12 @@ static int db_ctdb_fetch(struct db_context *db, TALLOC_CTX *mem_ctx,
/*
* See if we have a valid record and we are the dmaster. If so, we can
* take the shortcut and just return it.
+ * we bypass the dmaster check for persistent databases
*/
if ((ctdb_data.dptr != NULL) &&
(ctdb_data.dsize >= sizeof(struct ctdb_ltdb_header)) &&
- ((struct ctdb_ltdb_header *)ctdb_data.dptr)->dmaster == get_my_vnn()) {
+ (db->persistent ||
+ ((struct ctdb_ltdb_header *)ctdb_data.dptr)->dmaster == get_my_vnn())) {
/* we are the dmaster - avoid the ctdb protocol op */
data->dsize = ctdb_data.dsize - sizeof(struct ctdb_ltdb_header);
@@ -254,8 +300,7 @@ static int db_ctdb_fetch(struct db_context *db, TALLOC_CTX *mem_ctx,
SAFE_FREE(ctdb_data.dptr);
/* we weren't able to get it locally - ask ctdb to fetch it for us */
- status = ctdbd_fetch(db_ctdbd_conn(ctx), ctx->db_id, key, mem_ctx,
- data);
+ status = ctdbd_fetch(messaging_ctdbd_connection(),ctx->db_id, key, mem_ctx, data);
if (!NT_STATUS_IS_OK(status)) {
DEBUG(5, ("ctdbd_fetch failed: %s\n", nt_errstr(status)));
return -1;
@@ -283,6 +328,22 @@ static void traverse_callback(TDB_DATA key, TDB_DATA data, void *private_data)
talloc_free(tmp_ctx);
}
+static int traverse_persistent_callback(TDB_CONTEXT *tdb, TDB_DATA kbuf, TDB_DATA dbuf,
+ void *private_data)
+{
+ struct traverse_state *state = (struct traverse_state *)private_data;
+ struct db_record *rec;
+ TALLOC_CTX *tmp_ctx = talloc_new(state->db);
+ int ret = 0;
+ /* we have to give them a locked record to prevent races */
+ rec = db_ctdb_fetch_locked(state->db, tmp_ctx, kbuf);
+ if (rec && rec->value.dsize > 0) {
+ ret = state->fn(rec, state->private_data);
+ }
+ talloc_free(tmp_ctx);
+ return ret;
+}
+
static int db_ctdb_traverse(struct db_context *db,
int (*fn)(struct db_record *rec,
void *private_data),
@@ -296,6 +357,13 @@ static int db_ctdb_traverse(struct db_context *db,
state.fn = fn;
state.private_data = private_data;
+ if (db->persistent) {
+ /* for persistent databases we don't need to do a ctdb traverse,
+ we can do a faster local traverse */
+ return tdb_traverse(ctx->wtdb->tdb, traverse_persistent_callback, &state);
+ }
+
+
ctdbd_traverse(ctx->db_id, traverse_callback, &state);
return 0;
}
@@ -322,6 +390,27 @@ static void traverse_read_callback(TDB_DATA key, TDB_DATA data, void *private_da
state->fn(&rec, state->private_data);
}
+static int traverse_persistent_callback_read(TDB_CONTEXT *tdb, TDB_DATA kbuf, TDB_DATA dbuf,
+ void *private_data)
+{
+ struct traverse_state *state = (struct traverse_state *)private_data;
+ struct db_record rec;
+ rec.key = kbuf;
+ rec.value = dbuf;
+ rec.store = db_ctdb_store_deny;
+ rec.delete_rec = db_ctdb_delete_deny;
+ rec.private_data = state->db;
+
+ if (rec.value.dsize <= sizeof(struct ctdb_ltdb_header)) {
+ /* a deleted record */
+ return 0;
+ }
+ rec.value.dsize -= sizeof(struct ctdb_ltdb_header);
+ rec.value.dptr += sizeof(struct ctdb_ltdb_header);
+
+ return state->fn(&rec, state->private_data);
+}
+
static int db_ctdb_traverse_read(struct db_context *db,
int (*fn)(struct db_record *rec,
void *private_data),
@@ -335,6 +424,12 @@ static int db_ctdb_traverse_read(struct db_context *db,
state.fn = fn;
state.private_data = private_data;
+ if (db->persistent) {
+ /* for persistent databases we don't need to do a ctdb traverse,
+ we can do a faster local traverse */
+ return tdb_traverse_read(ctx->wtdb->tdb, traverse_persistent_callback_read, &state);
+ }
+
ctdbd_traverse(ctx->db_id, traverse_read_callback, &state);
return 0;
}
@@ -346,41 +441,6 @@ static int db_ctdb_get_seqnum(struct db_context *db)
return tdb_get_seqnum(ctx->wtdb->tdb);
}
-/*
- * Get the ctdbd connection for a database. If possible, re-use the messaging
- * ctdbd connection
- */
-static struct ctdbd_connection *db_ctdbd_conn(struct db_ctdb_ctx *ctx)
-{
- struct ctdbd_connection *result;
-
- result = messaging_ctdbd_connection();
-
- if (result != NULL) {
-
- if (ctx->conn == NULL) {
- /*
- * Someone has initialized messaging since we
- * initialized our own connection, we don't need it
- * anymore.
- */
- TALLOC_FREE(ctx->conn);
- }
-
- return result;
- }
-
- if (ctx->conn == NULL) {
- NTSTATUS status;
- status = ctdbd_init_connection(ctx, &ctx->conn);
- if (!NT_STATUS_IS_OK(status)) {
- return NULL;
- }
- set_my_vnn(ctdbd_vnn(ctx->conn));
- }
-
- return ctx->conn;
-}
struct db_context *db_open_ctdb(TALLOC_CTX *mem_ctx,
const char *name,
@@ -390,7 +450,6 @@ struct db_context *db_open_ctdb(TALLOC_CTX *mem_ctx,
struct db_context *result;
struct db_ctdb_ctx *db_ctdb;
char *db_path;
- NTSTATUS status;
if (!lp_clustering()) {
DEBUG(10, ("Clustering disabled -- no ctdb\n"));
@@ -409,20 +468,15 @@ struct db_context *db_open_ctdb(TALLOC_CTX *mem_ctx,
return NULL;
}
- db_ctdb->conn = NULL;
-
- status = ctdbd_db_attach(db_ctdbd_conn(db_ctdb), name,
- &db_ctdb->db_id, tdb_flags);
-
- if (!NT_STATUS_IS_OK(status)) {
- DEBUG(0, ("ctdbd_db_attach failed for %s: %s\n", name,
- nt_errstr(status)));
+ if (!NT_STATUS_IS_OK(ctdbd_db_attach(messaging_ctdbd_connection(),name, &db_ctdb->db_id, tdb_flags))) {
+ DEBUG(0, ("ctdbd_db_attach failed for %s\n", name));
TALLOC_FREE(result);
return NULL;
}
- db_path = ctdbd_dbpath(db_ctdbd_conn(db_ctdb), db_ctdb,
- db_ctdb->db_id);
+ db_path = ctdbd_dbpath(messaging_ctdbd_connection(), db_ctdb, db_ctdb->db_id);
+
+ result->persistent = ((tdb_flags & TDB_CLEAR_IF_FIRST) == 0);
/* only pass through specific flags */
tdb_flags &= TDB_SEQNUM;
@@ -447,16 +501,4 @@ struct db_context *db_open_ctdb(TALLOC_CTX *mem_ctx,
return result;
}
-
-#else
-
-struct db_context *db_open_ctdb(TALLOC_CTX *mem_ctx,
- const char *name,
- int hash_size, int tdb_flags,
- int open_flags, mode_t mode)
-{
- DEBUG(0, ("no clustering compiled in\n"));
- return NULL;
-}
-
#endif
diff --git a/source3/lib/dbwrap_file.c b/source3/lib/dbwrap_file.c
index 5b41f5941b..e3779de1e4 100644
--- a/source3/lib/dbwrap_file.c
+++ b/source3/lib/dbwrap_file.c
@@ -17,10 +17,6 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-/*
- * Be aware that this is just sample code that has not seen too much testing
- */
-
#include "includes.h"
struct db_file_ctx {
@@ -367,6 +363,7 @@ struct db_context *db_open_file(TALLOC_CTX *mem_ctx,
result->fetch_locked = db_file_fetch_locked;
result->traverse = db_file_traverse;
result->traverse_read = db_file_traverse;
+ result->persistent = ((tdb_flags & TDB_CLEAR_IF_FIRST) == 0);
ctx->locked_record = NULL;
if (!(ctx->dirname = talloc_strdup(ctx, name))) {
diff --git a/source3/lib/dbwrap_tdb.c b/source3/lib/dbwrap_tdb.c
index 710e45de6b..e87ceb428f 100644
--- a/source3/lib/dbwrap_tdb.c
+++ b/source3/lib/dbwrap_tdb.c
@@ -31,6 +31,11 @@ static int db_tdb_record_destr(struct db_record* data)
struct db_tdb_ctx *ctx =
talloc_get_type_abort(data->private_data, struct db_tdb_ctx);
+ /* This hex_encode() call allocates memory on data context. By way how current
+ __talloc_free() code works, it is OK to allocate in the destructor as
+ the children of data will be freed after call to the destructor and this
+ new 'child' will be caught and freed correctly.
+ */
DEBUG(10, (DEBUGLEVEL > 10
? "Unlocking key %s\n" : "Unlocking key %.20s\n",
hex_encode(data, (unsigned char *)data->key.dptr,
@@ -88,8 +93,9 @@ static struct db_record *db_tdb_fetch_locked(struct db_context *db,
struct tdb_fetch_locked_state state;
int res;
- if (DEBUGLEVEL >= 10) {
- char *keystr = hex_encode(NULL, key.dptr, key.dsize);
+ /* Do not accidently allocate/deallocate w/o need when debug level is lower than needed */
+ if(DEBUGLEVEL >= 10) {
+ char *keystr = hex_encode(NULL, (unsigned char*)key.dptr, key.dsize);
DEBUG(10, (DEBUGLEVEL > 10
? "Locking key %s\n" : "Locking key %.20s\n",
keystr));
@@ -191,15 +197,9 @@ static NTSTATUS db_tdb_delete(struct db_record *rec)
{
struct db_tdb_ctx *ctx = talloc_get_type_abort(rec->private_data,
struct db_tdb_ctx);
- int res;
-
- res = tdb_delete(ctx->wtdb->tdb, rec->key);
- if (res == 0) {
- return NT_STATUS_OK;
- }
-
- return map_nt_error_from_tdb(tdb_error(ctx->wtdb->tdb));
+ return (tdb_delete(ctx->wtdb->tdb, rec->key) == 0) ?
+ NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL;
}
struct db_tdb_traverse_ctx {
@@ -318,6 +318,7 @@ struct db_context *db_open_tdb(TALLOC_CTX *mem_ctx,
result->traverse = db_tdb_traverse;
result->traverse_read = db_tdb_traverse_read;
result->get_seqnum = db_tdb_get_seqnum;
+ result->persistent = ((tdb_flags & TDB_CLEAR_IF_FIRST) == 0);
return result;
fail:
diff --git a/source3/lib/dbwrap_util.c b/source3/lib/dbwrap_util.c
new file mode 100644
index 0000000000..002d572019
--- /dev/null
+++ b/source3/lib/dbwrap_util.c
@@ -0,0 +1,90 @@
+/*
+ Unix SMB/CIFS implementation.
+ Utility functions for the dbwrap API
+ Copyright (C) Volker Lendecke 2007
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#include "includes.h"
+
+int32_t dbwrap_fetch_int32(struct db_context *db, const char *keystr)
+{
+ TDB_DATA dbuf;
+ int32 ret;
+
+ if (db->fetch(db, NULL, string_term_tdb_data(keystr), &dbuf) != 0) {
+ return -1;
+ }
+
+ if ((dbuf.dptr == NULL) || (dbuf.dsize != sizeof(int32_t))) {
+ TALLOC_FREE(dbuf.dptr);
+ return -1;
+ }
+
+ ret = IVAL(dbuf.dptr, 0);
+ TALLOC_FREE(dbuf.dptr);
+ return ret;
+}
+
+int dbwrap_store_int32(struct db_context *db, const char *keystr, int32_t v)
+{
+ struct db_record *rec;
+ int32 v_store;
+ NTSTATUS status;
+
+ rec = db->fetch_locked(db, NULL, string_term_tdb_data(keystr));
+ if (rec == NULL) {
+ return -1;
+ }
+
+ SIVAL(&v_store, 0, v);
+
+ status = rec->store(rec, make_tdb_data((const uint8 *)&v_store,
+ sizeof(v_store)),
+ TDB_REPLACE);
+ TALLOC_FREE(rec);
+ return NT_STATUS_IS_OK(status) ? 0 : -1;
+}
+
+uint32_t dbwrap_change_uint32_atomic(struct db_context *db, const char *keystr,
+ uint32_t *oldval, uint32_t change_val)
+{
+ struct db_record *rec;
+ uint32 val = -1;
+ TDB_DATA data;
+
+ if (!(rec = db->fetch_locked(db, NULL,
+ string_term_tdb_data(keystr)))) {
+ return -1;
+ }
+
+ if ((rec->value.dptr != NULL)
+ && (rec->value.dsize == sizeof(val))) {
+ val = IVAL(rec->value.dptr, 0);
+ }
+
+ val += change_val;
+
+ data.dsize = sizeof(val);
+ data.dptr = (uint8 *)&val;
+
+ rec->store(rec, data, TDB_REPLACE);
+
+ TALLOC_FREE(rec);
+
+ return 0;
+}
+
diff --git a/source3/lib/messages_ctdbd.c b/source3/lib/messages_ctdbd.c
index 6e9b934a75..f1a02e6af9 100644
--- a/source3/lib/messages_ctdbd.c
+++ b/source3/lib/messages_ctdbd.c
@@ -22,6 +22,10 @@
#ifdef CLUSTER_SUPPORT
#include "librpc/gen_ndr/messaging.h"
+#include "ctdb.h"
+#include "ctdb_private.h"
+#include "ctdbd_conn.h"
+
struct messaging_ctdbd_context {
struct ctdbd_connection *conn;
diff --git a/source3/lib/netapi/serverinfo.c b/source3/lib/netapi/serverinfo.c
index 67680ba55a..6cd074615b 100644
--- a/source3/lib/netapi/serverinfo.c
+++ b/source3/lib/netapi/serverinfo.c
@@ -167,7 +167,7 @@ static WERROR NetServerSetInfoLocal_1005(struct libnetapi_ctx *ctx,
return WERR_INVALID_PARAM;
}
- if (!lp_include_registry_globals()) {
+ if (!lp_config_backend_is_registry()) {
return WERR_NOT_SUPPORTED;
}
diff --git a/source3/lib/util.c b/source3/lib/util.c
index 0653fc9d3f..bc3eaa8d5e 100644
--- a/source3/lib/util.c
+++ b/source3/lib/util.c
@@ -506,6 +506,19 @@ bool file_exist(const char *fname,SMB_STRUCT_STAT *sbuf)
}
/*******************************************************************
+ Check if a unix domain socket exists - call vfs_file_exist for samba files.
+********************************************************************/
+
+bool socket_exist(const char *fname)
+{
+ SMB_STRUCT_STAT st;
+ if (sys_stat(fname,&st) != 0)
+ return(False);
+
+ return S_ISSOCK(st.st_mode);
+}
+
+/*******************************************************************
Check a files mod time.
********************************************************************/
diff --git a/source3/lib/util_reg.c b/source3/lib/util_reg.c
index 956f0475a5..2d7d70c63f 100644
--- a/source3/lib/util_reg.c
+++ b/source3/lib/util_reg.c
@@ -130,6 +130,7 @@ bool registry_smbconf_valname_forbidden(const char *valname)
"include",
"lock directory",
"lock dir",
+ "config backend",
NULL
};
const char **forbidden = NULL;
diff --git a/source3/libads/ads_struct.c b/source3/libads/ads_struct.c
index 041878916e..44bcdf76ea 100644
--- a/source3/libads/ads_struct.c
+++ b/source3/libads/ads_struct.c
@@ -32,18 +32,23 @@ char *ads_build_path(const char *realm, const char *sep, const char *field, int
r = SMB_STRDUP(realm);
- if (!r || !*r)
+ if (!r || !*r) {
return r;
+ }
- for (p=r; *p; p++)
- if (strchr(sep, *p))
+ for (p=r; *p; p++) {
+ if (strchr(sep, *p)) {
numbits++;
+ }
+ }
len = (numbits+1)*(strlen(field)+1) + strlen(r) + 1;
ret = (char *)SMB_MALLOC(len);
- if (!ret)
+ if (!ret) {
+ free(r);
return NULL;
+ }
strlcpy(ret,field, len);
p=strtok(r,sep);
@@ -57,7 +62,8 @@ char *ads_build_path(const char *realm, const char *sep, const char *field, int
else
asprintf(&s, "%s,%s%s", ret, field, p);
free(ret);
- ret = s;
+ ret = SMB_STRDUP(s);
+ free(s);
}
}
diff --git a/source3/libnet/libnet_join.c b/source3/libnet/libnet_join.c
index af7f9a6a21..a9978ba4b8 100644
--- a/source3/libnet/libnet_join.c
+++ b/source3/libnet/libnet_join.c
@@ -1041,7 +1041,7 @@ static WERROR libnet_join_pre_processing(TALLOC_CTX *mem_ctx,
return WERR_INVALID_PARAM;
}
- if (r->in.modify_config && !lp_include_registry_globals()) {
+ if (r->in.modify_config && !lp_config_backend_is_registry()) {
return WERR_NOT_SUPPORTED;
}
@@ -1350,7 +1350,7 @@ static WERROR libnet_DomainUnjoin(TALLOC_CTX *mem_ctx,
static WERROR libnet_unjoin_pre_processing(TALLOC_CTX *mem_ctx,
struct libnet_UnjoinCtx *r)
{
- if (r->in.modify_config && !lp_include_registry_globals()) {
+ if (r->in.modify_config && !lp_config_backend_is_registry()) {
return WERR_NOT_SUPPORTED;
}
diff --git a/source3/librpc/gen_ndr/cli_lsa.c b/source3/librpc/gen_ndr/cli_lsa.c
index 92ba8bdfee..76370cabf1 100644
--- a/source3/librpc/gen_ndr/cli_lsa.c
+++ b/source3/librpc/gen_ndr/cli_lsa.c
@@ -609,7 +609,7 @@ NTSTATUS rpccli_lsa_LookupNames(struct rpc_pipe_client *cli,
struct lsa_String *names,
struct lsa_RefDomainList *domains,
struct lsa_TransSidArray *sids,
- uint16_t level,
+ enum lsa_LookupNamesLevel level,
uint32_t *count)
{
struct lsa_LookupNames r;
@@ -2528,7 +2528,7 @@ NTSTATUS rpccli_lsa_LookupNames2(struct rpc_pipe_client *cli,
struct lsa_String *names,
struct lsa_RefDomainList *domains,
struct lsa_TransSidArray2 *sids,
- uint16_t level,
+ enum lsa_LookupNamesLevel level,
uint32_t *count,
uint32_t unknown1,
uint32_t unknown2)
@@ -2920,7 +2920,7 @@ NTSTATUS rpccli_lsa_LookupNames3(struct rpc_pipe_client *cli,
struct lsa_String *names,
struct lsa_RefDomainList *domains,
struct lsa_TransSidArray3 *sids,
- uint16_t level,
+ enum lsa_LookupNamesLevel level,
uint32_t *count,
uint32_t unknown1,
uint32_t unknown2)
@@ -3120,16 +3120,23 @@ NTSTATUS rpccli_lsa_LSARUNREGISTERAUDITEVENT(struct rpc_pipe_client *cli,
return r.out.result;
}
-NTSTATUS rpccli_lsa_LSARQUERYFORESTTRUSTINFORMATION(struct rpc_pipe_client *cli,
- TALLOC_CTX *mem_ctx)
+NTSTATUS rpccli_lsa_lsaRQueryForestTrustInformation(struct rpc_pipe_client *cli,
+ TALLOC_CTX *mem_ctx,
+ struct policy_handle *handle,
+ struct lsa_String *trusted_domain_name,
+ uint16_t unknown,
+ struct lsa_ForestTrustInformation **forest_trust_info)
{
- struct lsa_LSARQUERYFORESTTRUSTINFORMATION r;
+ struct lsa_lsaRQueryForestTrustInformation r;
NTSTATUS status;
/* In parameters */
+ r.in.handle = handle;
+ r.in.trusted_domain_name = trusted_domain_name;
+ r.in.unknown = unknown;
if (DEBUGLEVEL >= 10) {
- NDR_PRINT_IN_DEBUG(lsa_LSARQUERYFORESTTRUSTINFORMATION, &r);
+ NDR_PRINT_IN_DEBUG(lsa_lsaRQueryForestTrustInformation, &r);
}
status = cli_do_rpc_ndr(cli,
@@ -3144,7 +3151,7 @@ NTSTATUS rpccli_lsa_LSARQUERYFORESTTRUSTINFORMATION(struct rpc_pipe_client *cli,
}
if (DEBUGLEVEL >= 10) {
- NDR_PRINT_OUT_DEBUG(lsa_LSARQUERYFORESTTRUSTINFORMATION, &r);
+ NDR_PRINT_OUT_DEBUG(lsa_lsaRQueryForestTrustInformation, &r);
}
if (NT_STATUS_IS_ERR(status)) {
@@ -3152,6 +3159,7 @@ NTSTATUS rpccli_lsa_LSARQUERYFORESTTRUSTINFORMATION(struct rpc_pipe_client *cli,
}
/* Return variables */
+ *forest_trust_info = *r.out.forest_trust_info;
/* Return result */
return r.out.result;
@@ -3292,7 +3300,7 @@ NTSTATUS rpccli_lsa_LookupNames4(struct rpc_pipe_client *cli,
struct lsa_String *names,
struct lsa_RefDomainList *domains,
struct lsa_TransSidArray3 *sids,
- uint16_t level,
+ enum lsa_LookupNamesLevel level,
uint32_t *count,
uint32_t unknown1,
uint32_t unknown2)
diff --git a/source3/librpc/gen_ndr/cli_lsa.h b/source3/librpc/gen_ndr/cli_lsa.h
index 4ab8be9939..c45aed1d37 100644
--- a/source3/librpc/gen_ndr/cli_lsa.h
+++ b/source3/librpc/gen_ndr/cli_lsa.h
@@ -71,7 +71,7 @@ NTSTATUS rpccli_lsa_LookupNames(struct rpc_pipe_client *cli,
struct lsa_String *names,
struct lsa_RefDomainList *domains,
struct lsa_TransSidArray *sids,
- uint16_t level,
+ enum lsa_LookupNamesLevel level,
uint32_t *count);
NTSTATUS rpccli_lsa_LookupSids(struct rpc_pipe_client *cli,
TALLOC_CTX *mem_ctx,
@@ -280,7 +280,7 @@ NTSTATUS rpccli_lsa_LookupNames2(struct rpc_pipe_client *cli,
struct lsa_String *names,
struct lsa_RefDomainList *domains,
struct lsa_TransSidArray2 *sids,
- uint16_t level,
+ enum lsa_LookupNamesLevel level,
uint32_t *count,
uint32_t unknown1,
uint32_t unknown2);
@@ -309,7 +309,7 @@ NTSTATUS rpccli_lsa_LookupNames3(struct rpc_pipe_client *cli,
struct lsa_String *names,
struct lsa_RefDomainList *domains,
struct lsa_TransSidArray3 *sids,
- uint16_t level,
+ enum lsa_LookupNamesLevel level,
uint32_t *count,
uint32_t unknown1,
uint32_t unknown2);
@@ -321,8 +321,12 @@ NTSTATUS rpccli_lsa_LSARGENAUDITEVENT(struct rpc_pipe_client *cli,
TALLOC_CTX *mem_ctx);
NTSTATUS rpccli_lsa_LSARUNREGISTERAUDITEVENT(struct rpc_pipe_client *cli,
TALLOC_CTX *mem_ctx);
-NTSTATUS rpccli_lsa_LSARQUERYFORESTTRUSTINFORMATION(struct rpc_pipe_client *cli,
- TALLOC_CTX *mem_ctx);
+NTSTATUS rpccli_lsa_lsaRQueryForestTrustInformation(struct rpc_pipe_client *cli,
+ TALLOC_CTX *mem_ctx,
+ struct policy_handle *handle,
+ struct lsa_String *trusted_domain_name,
+ uint16_t unknown,
+ struct lsa_ForestTrustInformation **forest_trust_info);
NTSTATUS rpccli_lsa_LSARSETFORESTTRUSTINFORMATION(struct rpc_pipe_client *cli,
TALLOC_CTX *mem_ctx);
NTSTATUS rpccli_lsa_CREDRRENAME(struct rpc_pipe_client *cli,
@@ -342,7 +346,7 @@ NTSTATUS rpccli_lsa_LookupNames4(struct rpc_pipe_client *cli,
struct lsa_String *names,
struct lsa_RefDomainList *domains,
struct lsa_TransSidArray3 *sids,
- uint16_t level,
+ enum lsa_LookupNamesLevel level,
uint32_t *count,
uint32_t unknown1,
uint32_t unknown2);
diff --git a/source3/librpc/gen_ndr/lsa.h b/source3/librpc/gen_ndr/lsa.h
index 513d17b5df..cbaa9083e4 100644
--- a/source3/librpc/gen_ndr/lsa.h
+++ b/source3/librpc/gen_ndr/lsa.h
@@ -75,9 +75,55 @@ struct lsa_AuditLogInfo {
uint32_t unknown;
};
+enum lsa_PolicyAuditPolicy
+#ifndef USE_UINT_ENUMS
+ {
+ LSA_AUDIT_POLICY_NONE=0,
+ LSA_AUDIT_POLICY_SUCCESS=1,
+ LSA_AUDIT_POLICY_FAILURE=2,
+ LSA_AUDIT_POLICY_ALL=(LSA_AUDIT_POLICY_SUCCESS|LSA_AUDIT_POLICY_FAILURE),
+ LSA_AUDIT_POLICY_CLEAR=4
+}
+#else
+ { __donnot_use_enum_lsa_PolicyAuditPolicy=0x7FFFFFFF}
+#define LSA_AUDIT_POLICY_NONE ( 0 )
+#define LSA_AUDIT_POLICY_SUCCESS ( 1 )
+#define LSA_AUDIT_POLICY_FAILURE ( 2 )
+#define LSA_AUDIT_POLICY_ALL ( (LSA_AUDIT_POLICY_SUCCESS|LSA_AUDIT_POLICY_FAILURE) )
+#define LSA_AUDIT_POLICY_CLEAR ( 4 )
+#endif
+;
+
+enum lsa_PolicyAuditEventType
+#ifndef USE_UINT_ENUMS
+ {
+ LSA_AUDIT_CATEGORY_SYSTEM=0,
+ LSA_AUDIT_CATEGORY_LOGON=1,
+ LSA_AUDIT_CATEGORY_FILE_AND_OBJECT_ACCESS=2,
+ LSA_AUDIT_CATEGORY_USE_OF_USER_RIGHTS=3,
+ LSA_AUDIT_CATEGORY_PROCCESS_TRACKING=4,
+ LSA_AUDIT_CATEGORY_SECURITY_POLICY_CHANGES=5,
+ LSA_AUDIT_CATEGORY_ACCOUNT_MANAGEMENT=6,
+ LSA_AUDIT_CATEGORY_DIRECTORY_SERVICE_ACCESS=7,
+ LSA_AUDIT_CATEGORY_ACCOUNT_LOGON=8
+}
+#else
+ { __donnot_use_enum_lsa_PolicyAuditEventType=0x7FFFFFFF}
+#define LSA_AUDIT_CATEGORY_SYSTEM ( 0 )
+#define LSA_AUDIT_CATEGORY_LOGON ( 1 )
+#define LSA_AUDIT_CATEGORY_FILE_AND_OBJECT_ACCESS ( 2 )
+#define LSA_AUDIT_CATEGORY_USE_OF_USER_RIGHTS ( 3 )
+#define LSA_AUDIT_CATEGORY_PROCCESS_TRACKING ( 4 )
+#define LSA_AUDIT_CATEGORY_SECURITY_POLICY_CHANGES ( 5 )
+#define LSA_AUDIT_CATEGORY_ACCOUNT_MANAGEMENT ( 6 )
+#define LSA_AUDIT_CATEGORY_DIRECTORY_SERVICE_ACCESS ( 7 )
+#define LSA_AUDIT_CATEGORY_ACCOUNT_LOGON ( 8 )
+#endif
+;
+
struct lsa_AuditEventsInfo {
uint32_t auditing_mode;
- uint32_t *settings;/* [unique,size_is(count)] */
+ enum lsa_PolicyAuditPolicy *settings;/* [unique,size_is(count)] */
uint32_t count;
};
@@ -240,6 +286,27 @@ struct lsa_RefDomainList {
uint32_t max_size;
};
+enum lsa_LookupNamesLevel
+#ifndef USE_UINT_ENUMS
+ {
+ LSA_LOOKUP_NAMES_ALL=1,
+ LSA_LOOKUP_NAMES_DOMAINS_ONLY=2,
+ LSA_LOOKUP_NAMES_PRIMARY_DOMAIN_ONLY=3,
+ LSA_LOOKUP_NAMES_UPLEVEL_TRUSTS_ONLY=4,
+ LSA_LOOKUP_NAMES_FOREST_TRUSTS_ONLY=5,
+ LSA_LOOKUP_NAMES_UPLEVEL_TRUSTS_ONLY2=6
+}
+#else
+ { __donnot_use_enum_lsa_LookupNamesLevel=0x7FFFFFFF}
+#define LSA_LOOKUP_NAMES_ALL ( 1 )
+#define LSA_LOOKUP_NAMES_DOMAINS_ONLY ( 2 )
+#define LSA_LOOKUP_NAMES_PRIMARY_DOMAIN_ONLY ( 3 )
+#define LSA_LOOKUP_NAMES_UPLEVEL_TRUSTS_ONLY ( 4 )
+#define LSA_LOOKUP_NAMES_FOREST_TRUSTS_ONLY ( 5 )
+#define LSA_LOOKUP_NAMES_UPLEVEL_TRUSTS_ONLY2 ( 6 )
+#endif
+;
+
struct lsa_TranslatedName {
enum lsa_SidType sid_type;
struct lsa_String name;
@@ -464,6 +531,53 @@ struct lsa_TransSidArray3 {
struct lsa_TranslatedSid3 *sids;/* [unique,size_is(count)] */
};
+struct lsa_ForestTrustBinaryData {
+ uint32_t length;/* [range(0 131072)] */
+ uint8_t *data;/* [unique,size_is(length)] */
+};
+
+struct lsa_ForestTrustDomainInfo {
+ struct dom_sid2 *domain_sid;/* [unique] */
+ struct lsa_StringLarge dns_domain_name;
+ struct lsa_StringLarge netbios_domain_name;
+};
+
+union lsa_ForestTrustData {
+ struct lsa_String top_level_name;/* [case(LSA_FOREST_TRUST_TOP_LEVEL_NAME)] */
+ struct lsa_StringLarge top_level_name_ex;/* [case(LSA_FOREST_TRUST_TOP_LEVEL_NAME_EX)] */
+ struct lsa_ForestTrustDomainInfo domain_info;/* [case(LSA_FOREST_TRUST_DOMAIN_INFO)] */
+ struct lsa_ForestTrustBinaryData data;/* [default] */
+}/* [switch_type(uint32)] */;
+
+enum lsa_ForestTrustRecordType
+#ifndef USE_UINT_ENUMS
+ {
+ LSA_FOREST_TRUST_TOP_LEVEL_NAME=0,
+ LSA_FOREST_TRUST_TOP_LEVEL_NAME_EX=1,
+ LSA_FOREST_TRUST_DOMAIN_INFO=2,
+ LSA_FOREST_TRUST_RECORD_TYPE_LAST=3
+}
+#else
+ { __donnot_use_enum_lsa_ForestTrustRecordType=0x7FFFFFFF}
+#define LSA_FOREST_TRUST_TOP_LEVEL_NAME ( 0 )
+#define LSA_FOREST_TRUST_TOP_LEVEL_NAME_EX ( 1 )
+#define LSA_FOREST_TRUST_DOMAIN_INFO ( 2 )
+#define LSA_FOREST_TRUST_RECORD_TYPE_LAST ( 3 )
+#endif
+;
+
+struct lsa_ForestTrustRecord {
+ uint32_t flags;
+ enum lsa_ForestTrustRecordType level;
+ uint64_t unknown;
+ union lsa_ForestTrustData forest_trust_data;/* [switch_is(level)] */
+};
+
+struct lsa_ForestTrustInformation {
+ uint32_t count;/* [range(0 4000)] */
+ struct lsa_ForestTrustRecord **entries;/* [unique,size_is(count)] */
+}/* [public] */;
+
struct lsa_Close {
struct {
@@ -636,7 +750,7 @@ struct lsa_CreateTrustedDomain {
struct lsa_EnumTrustDom {
struct {
struct policy_handle *handle;/* [ref] */
- uint32_t max_size;/* [range(0 1000)] */
+ uint32_t max_size;
uint32_t *resume_handle;/* [ref] */
} in;
@@ -654,7 +768,7 @@ struct lsa_LookupNames {
struct policy_handle *handle;/* [ref] */
uint32_t num_names;/* [range(0 1000)] */
struct lsa_String *names;/* [size_is(num_names)] */
- uint16_t level;
+ enum lsa_LookupNamesLevel level;
struct lsa_TransSidArray *sids;/* [ref] */
uint32_t *count;/* [ref] */
} in;
@@ -1241,7 +1355,7 @@ struct lsa_LookupNames2 {
struct policy_handle *handle;/* [ref] */
uint32_t num_names;/* [range(0 1000)] */
struct lsa_String *names;/* [size_is(num_names)] */
- uint16_t level;
+ enum lsa_LookupNamesLevel level;
uint32_t unknown1;
uint32_t unknown2;
struct lsa_TransSidArray2 *sids;/* [ref] */
@@ -1335,7 +1449,7 @@ struct lsa_LookupNames3 {
struct policy_handle *handle;/* [ref] */
uint32_t num_names;/* [range(0 1000)] */
struct lsa_String *names;/* [size_is(num_names)] */
- uint16_t level;
+ enum lsa_LookupNamesLevel level;
uint32_t unknown1;
uint32_t unknown2;
struct lsa_TransSidArray3 *sids;/* [ref] */
@@ -1384,8 +1498,15 @@ struct lsa_LSARUNREGISTERAUDITEVENT {
};
-struct lsa_LSARQUERYFORESTTRUSTINFORMATION {
+struct lsa_lsaRQueryForestTrustInformation {
struct {
+ struct policy_handle *handle;/* [ref] */
+ struct lsa_String *trusted_domain_name;/* [ref] */
+ uint16_t unknown;
+ } in;
+
+ struct {
+ struct lsa_ForestTrustInformation **forest_trust_info;/* [ref] */
NTSTATUS result;
} out;
@@ -1432,7 +1553,7 @@ struct lsa_LookupNames4 {
struct {
uint32_t num_names;/* [range(0 1000)] */
struct lsa_String *names;/* [size_is(num_names)] */
- uint16_t level;
+ enum lsa_LookupNamesLevel level;
uint32_t unknown1;
uint32_t unknown2;
struct lsa_TransSidArray3 *sids;/* [ref] */
diff --git a/source3/librpc/gen_ndr/ndr_lsa.c b/source3/librpc/gen_ndr/ndr_lsa.c
index eed2a8e0e3..25fa3d2129 100644
--- a/source3/librpc/gen_ndr/ndr_lsa.c
+++ b/source3/librpc/gen_ndr/ndr_lsa.c
@@ -690,6 +690,34 @@ _PUBLIC_ void ndr_print_lsa_AuditLogInfo(struct ndr_print *ndr, const char *name
ndr->depth--;
}
+static enum ndr_err_code ndr_push_lsa_PolicyAuditPolicy(struct ndr_push *ndr, int ndr_flags, enum lsa_PolicyAuditPolicy r)
+{
+ NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, r));
+ return NDR_ERR_SUCCESS;
+}
+
+static enum ndr_err_code ndr_pull_lsa_PolicyAuditPolicy(struct ndr_pull *ndr, int ndr_flags, enum lsa_PolicyAuditPolicy *r)
+{
+ uint32_t v;
+ NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &v));
+ *r = v;
+ return NDR_ERR_SUCCESS;
+}
+
+_PUBLIC_ void ndr_print_lsa_PolicyAuditPolicy(struct ndr_print *ndr, const char *name, enum lsa_PolicyAuditPolicy r)
+{
+ const char *val = NULL;
+
+ switch (r) {
+ case LSA_AUDIT_POLICY_NONE: val = "LSA_AUDIT_POLICY_NONE"; break;
+ case LSA_AUDIT_POLICY_SUCCESS: val = "LSA_AUDIT_POLICY_SUCCESS"; break;
+ case LSA_AUDIT_POLICY_FAILURE: val = "LSA_AUDIT_POLICY_FAILURE"; break;
+ case LSA_AUDIT_POLICY_ALL: val = "LSA_AUDIT_POLICY_ALL"; break;
+ case LSA_AUDIT_POLICY_CLEAR: val = "LSA_AUDIT_POLICY_CLEAR"; break;
+ }
+ ndr_print_enum(ndr, name, "ENUM", val, r);
+}
+
static enum ndr_err_code ndr_push_lsa_AuditEventsInfo(struct ndr_push *ndr, int ndr_flags, const struct lsa_AuditEventsInfo *r)
{
uint32_t cntr_settings_1;
@@ -703,7 +731,7 @@ static enum ndr_err_code ndr_push_lsa_AuditEventsInfo(struct ndr_push *ndr, int
if (r->settings) {
NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, r->count));
for (cntr_settings_1 = 0; cntr_settings_1 < r->count; cntr_settings_1++) {
- NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, r->settings[cntr_settings_1]));
+ NDR_CHECK(ndr_push_lsa_PolicyAuditPolicy(ndr, NDR_SCALARS, r->settings[cntr_settings_1]));
}
}
}
@@ -736,7 +764,7 @@ static enum ndr_err_code ndr_pull_lsa_AuditEventsInfo(struct ndr_pull *ndr, int
_mem_save_settings_1 = NDR_PULL_GET_MEM_CTX(ndr);
NDR_PULL_SET_MEM_CTX(ndr, r->settings, 0);
for (cntr_settings_1 = 0; cntr_settings_1 < r->count; cntr_settings_1++) {
- NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &r->settings[cntr_settings_1]));
+ NDR_CHECK(ndr_pull_lsa_PolicyAuditPolicy(ndr, NDR_SCALARS, &r->settings[cntr_settings_1]));
}
NDR_PULL_SET_MEM_CTX(ndr, _mem_save_settings_1, 0);
NDR_PULL_SET_MEM_CTX(ndr, _mem_save_settings_0, 0);
@@ -763,7 +791,7 @@ _PUBLIC_ void ndr_print_lsa_AuditEventsInfo(struct ndr_print *ndr, const char *n
char *idx_1=NULL;
asprintf(&idx_1, "[%d]", cntr_settings_1);
if (idx_1) {
- ndr_print_uint32(ndr, "settings", r->settings[cntr_settings_1]);
+ ndr_print_lsa_PolicyAuditPolicy(ndr, "settings", r->settings[cntr_settings_1]);
free(idx_1);
}
}
@@ -1939,6 +1967,35 @@ _PUBLIC_ void ndr_print_lsa_RefDomainList(struct ndr_print *ndr, const char *nam
ndr->depth--;
}
+static enum ndr_err_code ndr_push_lsa_LookupNamesLevel(struct ndr_push *ndr, int ndr_flags, enum lsa_LookupNamesLevel r)
+{
+ NDR_CHECK(ndr_push_uint16(ndr, NDR_SCALARS, r));
+ return NDR_ERR_SUCCESS;
+}
+
+static enum ndr_err_code ndr_pull_lsa_LookupNamesLevel(struct ndr_pull *ndr, int ndr_flags, enum lsa_LookupNamesLevel *r)
+{
+ uint16_t v;
+ NDR_CHECK(ndr_pull_uint16(ndr, NDR_SCALARS, &v));
+ *r = v;
+ return NDR_ERR_SUCCESS;
+}
+
+_PUBLIC_ void ndr_print_lsa_LookupNamesLevel(struct ndr_print *ndr, const char *name, enum lsa_LookupNamesLevel r)
+{
+ const char *val = NULL;
+
+ switch (r) {
+ case LSA_LOOKUP_NAMES_ALL: val = "LSA_LOOKUP_NAMES_ALL"; break;
+ case LSA_LOOKUP_NAMES_DOMAINS_ONLY: val = "LSA_LOOKUP_NAMES_DOMAINS_ONLY"; break;
+ case LSA_LOOKUP_NAMES_PRIMARY_DOMAIN_ONLY: val = "LSA_LOOKUP_NAMES_PRIMARY_DOMAIN_ONLY"; break;
+ case LSA_LOOKUP_NAMES_UPLEVEL_TRUSTS_ONLY: val = "LSA_LOOKUP_NAMES_UPLEVEL_TRUSTS_ONLY"; break;
+ case LSA_LOOKUP_NAMES_FOREST_TRUSTS_ONLY: val = "LSA_LOOKUP_NAMES_FOREST_TRUSTS_ONLY"; break;
+ case LSA_LOOKUP_NAMES_UPLEVEL_TRUSTS_ONLY2: val = "LSA_LOOKUP_NAMES_UPLEVEL_TRUSTS_ONLY2"; break;
+ }
+ ndr_print_enum(ndr, name, "ENUM", val, r);
+}
+
static enum ndr_err_code ndr_push_lsa_TranslatedName(struct ndr_push *ndr, int ndr_flags, const struct lsa_TranslatedName *r)
{
if (ndr_flags & NDR_SCALARS) {
@@ -4027,6 +4084,434 @@ _PUBLIC_ void ndr_print_lsa_TransSidArray3(struct ndr_print *ndr, const char *na
ndr->depth--;
}
+static enum ndr_err_code ndr_push_lsa_ForestTrustBinaryData(struct ndr_push *ndr, int ndr_flags, const struct lsa_ForestTrustBinaryData *r)
+{
+ if (ndr_flags & NDR_SCALARS) {
+ NDR_CHECK(ndr_push_align(ndr, 4));
+ NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, r->length));
+ NDR_CHECK(ndr_push_unique_ptr(ndr, r->data));
+ }
+ if (ndr_flags & NDR_BUFFERS) {
+ if (r->data) {
+ NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, r->length));
+ NDR_CHECK(ndr_push_array_uint8(ndr, NDR_SCALARS, r->data, r->length));
+ }
+ }
+ return NDR_ERR_SUCCESS;
+}
+
+static enum ndr_err_code ndr_pull_lsa_ForestTrustBinaryData(struct ndr_pull *ndr, int ndr_flags, struct lsa_ForestTrustBinaryData *r)
+{
+ uint32_t _ptr_data;
+ TALLOC_CTX *_mem_save_data_0;
+ if (ndr_flags & NDR_SCALARS) {
+ NDR_CHECK(ndr_pull_align(ndr, 4));
+ NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &r->length));
+ if (r->length < 0 || r->length > 131072) {
+ return ndr_pull_error(ndr, NDR_ERR_RANGE, "value out of range");
+ }
+ NDR_CHECK(ndr_pull_generic_ptr(ndr, &_ptr_data));
+ if (_ptr_data) {
+ NDR_PULL_ALLOC(ndr, r->data);
+ } else {
+ r->data = NULL;
+ }
+ }
+ if (ndr_flags & NDR_BUFFERS) {
+ if (r->data) {
+ _mem_save_data_0 = NDR_PULL_GET_MEM_CTX(ndr);
+ NDR_PULL_SET_MEM_CTX(ndr, r->data, 0);
+ NDR_CHECK(ndr_pull_array_size(ndr, &r->data));
+ NDR_PULL_ALLOC_N(ndr, r->data, ndr_get_array_size(ndr, &r->data));
+ NDR_CHECK(ndr_pull_array_uint8(ndr, NDR_SCALARS, r->data, ndr_get_array_size(ndr, &r->data)));
+ NDR_PULL_SET_MEM_CTX(ndr, _mem_save_data_0, 0);
+ }
+ if (r->data) {
+ NDR_CHECK(ndr_check_array_size(ndr, (void*)&r->data, r->length));
+ }
+ }
+ return NDR_ERR_SUCCESS;
+}
+
+_PUBLIC_ void ndr_print_lsa_ForestTrustBinaryData(struct ndr_print *ndr, const char *name, const struct lsa_ForestTrustBinaryData *r)
+{
+ ndr_print_struct(ndr, name, "lsa_ForestTrustBinaryData");
+ ndr->depth++;
+ ndr_print_uint32(ndr, "length", r->length);
+ ndr_print_ptr(ndr, "data", r->data);
+ ndr->depth++;
+ if (r->data) {
+ ndr_print_array_uint8(ndr, "data", r->data, r->length);
+ }
+ ndr->depth--;
+ ndr->depth--;
+}
+
+static enum ndr_err_code ndr_push_lsa_ForestTrustDomainInfo(struct ndr_push *ndr, int ndr_flags, const struct lsa_ForestTrustDomainInfo *r)
+{
+ if (ndr_flags & NDR_SCALARS) {
+ NDR_CHECK(ndr_push_align(ndr, 4));
+ NDR_CHECK(ndr_push_unique_ptr(ndr, r->domain_sid));
+ NDR_CHECK(ndr_push_lsa_StringLarge(ndr, NDR_SCALARS, &r->dns_domain_name));
+ NDR_CHECK(ndr_push_lsa_StringLarge(ndr, NDR_SCALARS, &r->netbios_domain_name));
+ }
+ if (ndr_flags & NDR_BUFFERS) {
+ if (r->domain_sid) {
+ NDR_CHECK(ndr_push_dom_sid2(ndr, NDR_SCALARS|NDR_BUFFERS, r->domain_sid));
+ }
+ NDR_CHECK(ndr_push_lsa_StringLarge(ndr, NDR_BUFFERS, &r->dns_domain_name));
+ NDR_CHECK(ndr_push_lsa_StringLarge(ndr, NDR_BUFFERS, &r->netbios_domain_name));
+ }
+ return NDR_ERR_SUCCESS;
+}
+
+static enum ndr_err_code ndr_pull_lsa_ForestTrustDomainInfo(struct ndr_pull *ndr, int ndr_flags, struct lsa_ForestTrustDomainInfo *r)
+{
+ uint32_t _ptr_domain_sid;
+ TALLOC_CTX *_mem_save_domain_sid_0;
+ if (ndr_flags & NDR_SCALARS) {
+ NDR_CHECK(ndr_pull_align(ndr, 4));
+ NDR_CHECK(ndr_pull_generic_ptr(ndr, &_ptr_domain_sid));
+ if (_ptr_domain_sid) {
+ NDR_PULL_ALLOC(ndr, r->domain_sid);
+ } else {
+ r->domain_sid = NULL;
+ }
+ NDR_CHECK(ndr_pull_lsa_StringLarge(ndr, NDR_SCALARS, &r->dns_domain_name));
+ NDR_CHECK(ndr_pull_lsa_StringLarge(ndr, NDR_SCALARS, &r->netbios_domain_name));
+ }
+ if (ndr_flags & NDR_BUFFERS) {
+ if (r->domain_sid) {
+ _mem_save_domain_sid_0 = NDR_PULL_GET_MEM_CTX(ndr);
+ NDR_PULL_SET_MEM_CTX(ndr, r->domain_sid, 0);
+ NDR_CHECK(ndr_pull_dom_sid2(ndr, NDR_SCALARS|NDR_BUFFERS, r->domain_sid));
+ NDR_PULL_SET_MEM_CTX(ndr, _mem_save_domain_sid_0, 0);
+ }
+ NDR_CHECK(ndr_pull_lsa_StringLarge(ndr, NDR_BUFFERS, &r->dns_domain_name));
+ NDR_CHECK(ndr_pull_lsa_StringLarge(ndr, NDR_BUFFERS, &r->netbios_domain_name));
+ }
+ return NDR_ERR_SUCCESS;
+}
+
+_PUBLIC_ void ndr_print_lsa_ForestTrustDomainInfo(struct ndr_print *ndr, const char *name, const struct lsa_ForestTrustDomainInfo *r)
+{
+ ndr_print_struct(ndr, name, "lsa_ForestTrustDomainInfo");
+ ndr->depth++;
+ ndr_print_ptr(ndr, "domain_sid", r->domain_sid);
+ ndr->depth++;
+ if (r->domain_sid) {
+ ndr_print_dom_sid2(ndr, "domain_sid", r->domain_sid);
+ }
+ ndr->depth--;
+ ndr_print_lsa_StringLarge(ndr, "dns_domain_name", &r->dns_domain_name);
+ ndr_print_lsa_StringLarge(ndr, "netbios_domain_name", &r->netbios_domain_name);
+ ndr->depth--;
+}
+
+static enum ndr_err_code ndr_push_lsa_ForestTrustData(struct ndr_push *ndr, int ndr_flags, const union lsa_ForestTrustData *r)
+{
+ if (ndr_flags & NDR_SCALARS) {
+ int level = ndr_push_get_switch_value(ndr, r);
+ NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, level));
+ switch (level) {
+ case LSA_FOREST_TRUST_TOP_LEVEL_NAME:
+ NDR_CHECK(ndr_push_lsa_String(ndr, NDR_SCALARS, &r->top_level_name));
+ break;
+
+ case LSA_FOREST_TRUST_TOP_LEVEL_NAME_EX:
+ NDR_CHECK(ndr_push_lsa_StringLarge(ndr, NDR_SCALARS, &r->top_level_name_ex));
+ break;
+
+ case LSA_FOREST_TRUST_DOMAIN_INFO:
+ NDR_CHECK(ndr_push_lsa_ForestTrustDomainInfo(ndr, NDR_SCALARS, &r->domain_info));
+ break;
+
+ default:
+ NDR_CHECK(ndr_push_lsa_ForestTrustBinaryData(ndr, NDR_SCALARS, &r->data));
+ break;
+
+ }
+ }
+ if (ndr_flags & NDR_BUFFERS) {
+ int level = ndr_push_get_switch_value(ndr, r);
+ switch (level) {
+ case LSA_FOREST_TRUST_TOP_LEVEL_NAME:
+ NDR_CHECK(ndr_push_lsa_String(ndr, NDR_BUFFERS, &r->top_level_name));
+ break;
+
+ case LSA_FOREST_TRUST_TOP_LEVEL_NAME_EX:
+ NDR_CHECK(ndr_push_lsa_StringLarge(ndr, NDR_BUFFERS, &r->top_level_name_ex));
+ break;
+
+ case LSA_FOREST_TRUST_DOMAIN_INFO:
+ NDR_CHECK(ndr_push_lsa_ForestTrustDomainInfo(ndr, NDR_BUFFERS, &r->domain_info));
+ break;
+
+ default:
+ NDR_CHECK(ndr_push_lsa_ForestTrustBinaryData(ndr, NDR_BUFFERS, &r->data));
+ break;
+
+ }
+ }
+ return NDR_ERR_SUCCESS;
+}
+
+static enum ndr_err_code ndr_pull_lsa_ForestTrustData(struct ndr_pull *ndr, int ndr_flags, union lsa_ForestTrustData *r)
+{
+ int level;
+ uint32_t _level;
+ level = ndr_pull_get_switch_value(ndr, r);
+ if (ndr_flags & NDR_SCALARS) {
+ NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &_level));
+ if (_level != level) {
+ return ndr_pull_error(ndr, NDR_ERR_BAD_SWITCH, "Bad switch value %u for r", _level);
+ }
+ switch (level) {
+ case LSA_FOREST_TRUST_TOP_LEVEL_NAME: {
+ NDR_CHECK(ndr_pull_lsa_String(ndr, NDR_SCALARS, &r->top_level_name));
+ break; }
+
+ case LSA_FOREST_TRUST_TOP_LEVEL_NAME_EX: {
+ NDR_CHECK(ndr_pull_lsa_StringLarge(ndr, NDR_SCALARS, &r->top_level_name_ex));
+ break; }
+
+ case LSA_FOREST_TRUST_DOMAIN_INFO: {
+ NDR_CHECK(ndr_pull_lsa_ForestTrustDomainInfo(ndr, NDR_SCALARS, &r->domain_info));
+ break; }
+
+ default: {
+ NDR_CHECK(ndr_pull_lsa_ForestTrustBinaryData(ndr, NDR_SCALARS, &r->data));
+ break; }
+
+ }
+ }
+ if (ndr_flags & NDR_BUFFERS) {
+ switch (level) {
+ case LSA_FOREST_TRUST_TOP_LEVEL_NAME:
+ NDR_CHECK(ndr_pull_lsa_String(ndr, NDR_BUFFERS, &r->top_level_name));
+ break;
+
+ case LSA_FOREST_TRUST_TOP_LEVEL_NAME_EX:
+ NDR_CHECK(ndr_pull_lsa_StringLarge(ndr, NDR_BUFFERS, &r->top_level_name_ex));
+ break;
+
+ case LSA_FOREST_TRUST_DOMAIN_INFO:
+ NDR_CHECK(ndr_pull_lsa_ForestTrustDomainInfo(ndr, NDR_BUFFERS, &r->domain_info));
+ break;
+
+ default:
+ NDR_CHECK(ndr_pull_lsa_ForestTrustBinaryData(ndr, NDR_BUFFERS, &r->data));
+ break;
+
+ }
+ }
+ return NDR_ERR_SUCCESS;
+}
+
+_PUBLIC_ void ndr_print_lsa_ForestTrustData(struct ndr_print *ndr, const char *name, const union lsa_ForestTrustData *r)
+{
+ int level;
+ level = ndr_print_get_switch_value(ndr, r);
+ ndr_print_union(ndr, name, level, "lsa_ForestTrustData");
+ switch (level) {
+ case LSA_FOREST_TRUST_TOP_LEVEL_NAME:
+ ndr_print_lsa_String(ndr, "top_level_name", &r->top_level_name);
+ break;
+
+ case LSA_FOREST_TRUST_TOP_LEVEL_NAME_EX:
+ ndr_print_lsa_StringLarge(ndr, "top_level_name_ex", &r->top_level_name_ex);
+ break;
+
+ case LSA_FOREST_TRUST_DOMAIN_INFO:
+ ndr_print_lsa_ForestTrustDomainInfo(ndr, "domain_info", &r->domain_info);
+ break;
+
+ default:
+ ndr_print_lsa_ForestTrustBinaryData(ndr, "data", &r->data);
+ break;
+
+ }
+}
+
+static enum ndr_err_code ndr_push_lsa_ForestTrustRecordType(struct ndr_push *ndr, int ndr_flags, enum lsa_ForestTrustRecordType r)
+{
+ NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, r));
+ return NDR_ERR_SUCCESS;
+}
+
+static enum ndr_err_code ndr_pull_lsa_ForestTrustRecordType(struct ndr_pull *ndr, int ndr_flags, enum lsa_ForestTrustRecordType *r)
+{
+ uint32_t v;
+ NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &v));
+ *r = v;
+ return NDR_ERR_SUCCESS;
+}
+
+_PUBLIC_ void ndr_print_lsa_ForestTrustRecordType(struct ndr_print *ndr, const char *name, enum lsa_ForestTrustRecordType r)
+{
+ const char *val = NULL;
+
+ switch (r) {
+ case LSA_FOREST_TRUST_TOP_LEVEL_NAME: val = "LSA_FOREST_TRUST_TOP_LEVEL_NAME"; break;
+ case LSA_FOREST_TRUST_TOP_LEVEL_NAME_EX: val = "LSA_FOREST_TRUST_TOP_LEVEL_NAME_EX"; break;
+ case LSA_FOREST_TRUST_DOMAIN_INFO: val = "LSA_FOREST_TRUST_DOMAIN_INFO"; break;
+ case LSA_FOREST_TRUST_RECORD_TYPE_LAST: val = "LSA_FOREST_TRUST_RECORD_TYPE_LAST"; break;
+ }
+ ndr_print_enum(ndr, name, "ENUM", val, r);
+}
+
+static enum ndr_err_code ndr_push_lsa_ForestTrustRecord(struct ndr_push *ndr, int ndr_flags, const struct lsa_ForestTrustRecord *r)
+{
+ if (ndr_flags & NDR_SCALARS) {
+ NDR_CHECK(ndr_push_align(ndr, 8));
+ NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, r->flags));
+ NDR_CHECK(ndr_push_lsa_ForestTrustRecordType(ndr, NDR_SCALARS, r->level));
+ NDR_CHECK(ndr_push_hyper(ndr, NDR_SCALARS, r->unknown));
+ NDR_CHECK(ndr_push_set_switch_value(ndr, &r->forest_trust_data, r->level));
+ NDR_CHECK(ndr_push_lsa_ForestTrustData(ndr, NDR_SCALARS, &r->forest_trust_data));
+ }
+ if (ndr_flags & NDR_BUFFERS) {
+ NDR_CHECK(ndr_push_lsa_ForestTrustData(ndr, NDR_BUFFERS, &r->forest_trust_data));
+ }
+ return NDR_ERR_SUCCESS;
+}
+
+static enum ndr_err_code ndr_pull_lsa_ForestTrustRecord(struct ndr_pull *ndr, int ndr_flags, struct lsa_ForestTrustRecord *r)
+{
+ if (ndr_flags & NDR_SCALARS) {
+ NDR_CHECK(ndr_pull_align(ndr, 8));
+ NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &r->flags));
+ NDR_CHECK(ndr_pull_lsa_ForestTrustRecordType(ndr, NDR_SCALARS, &r->level));
+ NDR_CHECK(ndr_pull_hyper(ndr, NDR_SCALARS, &r->unknown));
+ NDR_CHECK(ndr_pull_set_switch_value(ndr, &r->forest_trust_data, r->level));
+ NDR_CHECK(ndr_pull_lsa_ForestTrustData(ndr, NDR_SCALARS, &r->forest_trust_data));
+ }
+ if (ndr_flags & NDR_BUFFERS) {
+ NDR_CHECK(ndr_pull_lsa_ForestTrustData(ndr, NDR_BUFFERS, &r->forest_trust_data));
+ }
+ return NDR_ERR_SUCCESS;
+}
+
+_PUBLIC_ void ndr_print_lsa_ForestTrustRecord(struct ndr_print *ndr, const char *name, const struct lsa_ForestTrustRecord *r)
+{
+ ndr_print_struct(ndr, name, "lsa_ForestTrustRecord");
+ ndr->depth++;
+ ndr_print_uint32(ndr, "flags", r->flags);
+ ndr_print_lsa_ForestTrustRecordType(ndr, "level", r->level);
+ ndr_print_hyper(ndr, "unknown", r->unknown);
+ ndr_print_set_switch_value(ndr, &r->forest_trust_data, r->level);
+ ndr_print_lsa_ForestTrustData(ndr, "forest_trust_data", &r->forest_trust_data);
+ ndr->depth--;
+}
+
+_PUBLIC_ enum ndr_err_code ndr_push_lsa_ForestTrustInformation(struct ndr_push *ndr, int ndr_flags, const struct lsa_ForestTrustInformation *r)
+{
+ uint32_t cntr_entries_1;
+ if (ndr_flags & NDR_SCALARS) {
+ NDR_CHECK(ndr_push_align(ndr, 4));
+ NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, r->count));
+ NDR_CHECK(ndr_push_unique_ptr(ndr, r->entries));
+ }
+ if (ndr_flags & NDR_BUFFERS) {
+ if (r->entries) {
+ NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, r->count));
+ for (cntr_entries_1 = 0; cntr_entries_1 < r->count; cntr_entries_1++) {
+ NDR_CHECK(ndr_push_unique_ptr(ndr, r->entries[cntr_entries_1]));
+ }
+ for (cntr_entries_1 = 0; cntr_entries_1 < r->count; cntr_entries_1++) {
+ if (r->entries[cntr_entries_1]) {
+ NDR_CHECK(ndr_push_lsa_ForestTrustRecord(ndr, NDR_SCALARS|NDR_BUFFERS, r->entries[cntr_entries_1]));
+ }
+ }
+ }
+ }
+ return NDR_ERR_SUCCESS;
+}
+
+_PUBLIC_ enum ndr_err_code ndr_pull_lsa_ForestTrustInformation(struct ndr_pull *ndr, int ndr_flags, struct lsa_ForestTrustInformation *r)
+{
+ uint32_t _ptr_entries;
+ uint32_t cntr_entries_1;
+ TALLOC_CTX *_mem_save_entries_0;
+ TALLOC_CTX *_mem_save_entries_1;
+ TALLOC_CTX *_mem_save_entries_2;
+ if (ndr_flags & NDR_SCALARS) {
+ NDR_CHECK(ndr_pull_align(ndr, 4));
+ NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &r->count));
+ if (r->count < 0 || r->count > 4000) {
+ return ndr_pull_error(ndr, NDR_ERR_RANGE, "value out of range");
+ }
+ NDR_CHECK(ndr_pull_generic_ptr(ndr, &_ptr_entries));
+ if (_ptr_entries) {
+ NDR_PULL_ALLOC(ndr, r->entries);
+ } else {
+ r->entries = NULL;
+ }
+ }
+ if (ndr_flags & NDR_BUFFERS) {
+ if (r->entries) {
+ _mem_save_entries_0 = NDR_PULL_GET_MEM_CTX(ndr);
+ NDR_PULL_SET_MEM_CTX(ndr, r->entries, 0);
+ NDR_CHECK(ndr_pull_array_size(ndr, &r->entries));
+ NDR_PULL_ALLOC_N(ndr, r->entries, ndr_get_array_size(ndr, &r->entries));
+ _mem_save_entries_1 = NDR_PULL_GET_MEM_CTX(ndr);
+ NDR_PULL_SET_MEM_CTX(ndr, r->entries, 0);
+ for (cntr_entries_1 = 0; cntr_entries_1 < r->count; cntr_entries_1++) {
+ NDR_CHECK(ndr_pull_generic_ptr(ndr, &_ptr_entries));
+ if (_ptr_entries) {
+ NDR_PULL_ALLOC(ndr, r->entries[cntr_entries_1]);
+ } else {
+ r->entries[cntr_entries_1] = NULL;
+ }
+ }
+ for (cntr_entries_1 = 0; cntr_entries_1 < r->count; cntr_entries_1++) {
+ if (r->entries[cntr_entries_1]) {
+ _mem_save_entries_2 = NDR_PULL_GET_MEM_CTX(ndr);
+ NDR_PULL_SET_MEM_CTX(ndr, r->entries[cntr_entries_1], 0);
+ NDR_CHECK(ndr_pull_lsa_ForestTrustRecord(ndr, NDR_SCALARS|NDR_BUFFERS, r->entries[cntr_entries_1]));
+ NDR_PULL_SET_MEM_CTX(ndr, _mem_save_entries_2, 0);
+ }
+ }
+ NDR_PULL_SET_MEM_CTX(ndr, _mem_save_entries_1, 0);
+ NDR_PULL_SET_MEM_CTX(ndr, _mem_save_entries_0, 0);
+ }
+ if (r->entries) {
+ NDR_CHECK(ndr_check_array_size(ndr, (void*)&r->entries, r->count));
+ }
+ }
+ return NDR_ERR_SUCCESS;
+}
+
+_PUBLIC_ void ndr_print_lsa_ForestTrustInformation(struct ndr_print *ndr, const char *name, const struct lsa_ForestTrustInformation *r)
+{
+ uint32_t cntr_entries_1;
+ ndr_print_struct(ndr, name, "lsa_ForestTrustInformation");
+ ndr->depth++;
+ ndr_print_uint32(ndr, "count", r->count);
+ ndr_print_ptr(ndr, "entries", r->entries);
+ ndr->depth++;
+ if (r->entries) {
+ ndr->print(ndr, "%s: ARRAY(%d)", "entries", r->count);
+ ndr->depth++;
+ for (cntr_entries_1=0;cntr_entries_1<r->count;cntr_entries_1++) {
+ char *idx_1=NULL;
+ asprintf(&idx_1, "[%d]", cntr_entries_1);
+ if (idx_1) {
+ ndr_print_ptr(ndr, "entries", r->entries[cntr_entries_1]);
+ ndr->depth++;
+ if (r->entries[cntr_entries_1]) {
+ ndr_print_lsa_ForestTrustRecord(ndr, "entries", r->entries[cntr_entries_1]);
+ }
+ ndr->depth--;
+ free(idx_1);
+ }
+ }
+ ndr->depth--;
+ }
+ ndr->depth--;
+ ndr->depth--;
+}
+
static enum ndr_err_code ndr_push_lsa_Close(struct ndr_push *ndr, int flags, const struct lsa_Close *r)
{
if (flags & NDR_IN) {
@@ -4103,7 +4588,7 @@ _PUBLIC_ void ndr_print_lsa_Close(struct ndr_print *ndr, const char *name, int f
ndr->depth--;
}
-static enum ndr_err_code ndr_push_lsa_Delete(struct ndr_push *ndr, int flags, const struct lsa_Delete *r)
+_PUBLIC_ enum ndr_err_code ndr_push_lsa_Delete(struct ndr_push *ndr, int flags, const struct lsa_Delete *r)
{
if (flags & NDR_IN) {
if (r->in.handle == NULL) {
@@ -4117,7 +4602,7 @@ static enum ndr_err_code ndr_push_lsa_Delete(struct ndr_push *ndr, int flags, co
return NDR_ERR_SUCCESS;
}
-static enum ndr_err_code ndr_pull_lsa_Delete(struct ndr_pull *ndr, int flags, struct lsa_Delete *r)
+_PUBLIC_ enum ndr_err_code ndr_pull_lsa_Delete(struct ndr_pull *ndr, int flags, struct lsa_Delete *r)
{
TALLOC_CTX *_mem_save_handle_0;
if (flags & NDR_IN) {
@@ -4160,7 +4645,7 @@ _PUBLIC_ void ndr_print_lsa_Delete(struct ndr_print *ndr, const char *name, int
ndr->depth--;
}
-static enum ndr_err_code ndr_push_lsa_EnumPrivs(struct ndr_push *ndr, int flags, const struct lsa_EnumPrivs *r)
+_PUBLIC_ enum ndr_err_code ndr_push_lsa_EnumPrivs(struct ndr_push *ndr, int flags, const struct lsa_EnumPrivs *r)
{
if (flags & NDR_IN) {
if (r->in.handle == NULL) {
@@ -4187,7 +4672,7 @@ static enum ndr_err_code ndr_push_lsa_EnumPrivs(struct ndr_push *ndr, int flags,
return NDR_ERR_SUCCESS;
}
-static enum ndr_err_code ndr_pull_lsa_EnumPrivs(struct ndr_pull *ndr, int flags, struct lsa_EnumPrivs *r)
+_PUBLIC_ enum ndr_err_code ndr_pull_lsa_EnumPrivs(struct ndr_pull *ndr, int flags, struct lsa_EnumPrivs *r)
{
TALLOC_CTX *_mem_save_handle_0;
TALLOC_CTX *_mem_save_resume_handle_0;
@@ -4441,7 +4926,7 @@ _PUBLIC_ void ndr_print_lsa_ChangePassword(struct ndr_print *ndr, const char *na
ndr->depth--;
}
-static enum ndr_err_code ndr_push_lsa_OpenPolicy(struct ndr_push *ndr, int flags, const struct lsa_OpenPolicy *r)
+_PUBLIC_ enum ndr_err_code ndr_push_lsa_OpenPolicy(struct ndr_push *ndr, int flags, const struct lsa_OpenPolicy *r)
{
if (flags & NDR_IN) {
NDR_CHECK(ndr_push_unique_ptr(ndr, r->in.system_name));
@@ -4464,7 +4949,7 @@ static enum ndr_err_code ndr_push_lsa_OpenPolicy(struct ndr_push *ndr, int flags
return NDR_ERR_SUCCESS;
}
-static enum ndr_err_code ndr_pull_lsa_OpenPolicy(struct ndr_pull *ndr, int flags, struct lsa_OpenPolicy *r)
+_PUBLIC_ enum ndr_err_code ndr_pull_lsa_OpenPolicy(struct ndr_pull *ndr, int flags, struct lsa_OpenPolicy *r)
{
uint32_t _ptr_system_name;
TALLOC_CTX *_mem_save_system_name_0;
@@ -4754,7 +5239,7 @@ _PUBLIC_ void ndr_print_lsa_ClearAuditLog(struct ndr_print *ndr, const char *nam
ndr->depth--;
}
-static enum ndr_err_code ndr_push_lsa_CreateAccount(struct ndr_push *ndr, int flags, const struct lsa_CreateAccount *r)
+_PUBLIC_ enum ndr_err_code ndr_push_lsa_CreateAccount(struct ndr_push *ndr, int flags, const struct lsa_CreateAccount *r)
{
if (flags & NDR_IN) {
if (r->in.handle == NULL) {
@@ -4777,7 +5262,7 @@ static enum ndr_err_code ndr_push_lsa_CreateAccount(struct ndr_push *ndr, int fl
return NDR_ERR_SUCCESS;
}
-static enum ndr_err_code ndr_pull_lsa_CreateAccount(struct ndr_pull *ndr, int flags, struct lsa_CreateAccount *r)
+_PUBLIC_ enum ndr_err_code ndr_pull_lsa_CreateAccount(struct ndr_pull *ndr, int flags, struct lsa_CreateAccount *r)
{
TALLOC_CTX *_mem_save_handle_0;
TALLOC_CTX *_mem_save_sid_0;
@@ -4850,7 +5335,7 @@ _PUBLIC_ void ndr_print_lsa_CreateAccount(struct ndr_print *ndr, const char *nam
ndr->depth--;
}
-static enum ndr_err_code ndr_push_lsa_EnumAccounts(struct ndr_push *ndr, int flags, const struct lsa_EnumAccounts *r)
+_PUBLIC_ enum ndr_err_code ndr_push_lsa_EnumAccounts(struct ndr_push *ndr, int flags, const struct lsa_EnumAccounts *r)
{
if (flags & NDR_IN) {
if (r->in.handle == NULL) {
@@ -4877,7 +5362,7 @@ static enum ndr_err_code ndr_push_lsa_EnumAccounts(struct ndr_push *ndr, int fla
return NDR_ERR_SUCCESS;
}
-static enum ndr_err_code ndr_pull_lsa_EnumAccounts(struct ndr_pull *ndr, int flags, struct lsa_EnumAccounts *r)
+_PUBLIC_ enum ndr_err_code ndr_pull_lsa_EnumAccounts(struct ndr_pull *ndr, int flags, struct lsa_EnumAccounts *r)
{
TALLOC_CTX *_mem_save_handle_0;
TALLOC_CTX *_mem_save_resume_handle_0;
@@ -4966,7 +5451,7 @@ _PUBLIC_ void ndr_print_lsa_EnumAccounts(struct ndr_print *ndr, const char *name
ndr->depth--;
}
-static enum ndr_err_code ndr_push_lsa_CreateTrustedDomain(struct ndr_push *ndr, int flags, const struct lsa_CreateTrustedDomain *r)
+_PUBLIC_ enum ndr_err_code ndr_push_lsa_CreateTrustedDomain(struct ndr_push *ndr, int flags, const struct lsa_CreateTrustedDomain *r)
{
if (flags & NDR_IN) {
if (r->in.handle == NULL) {
@@ -4989,7 +5474,7 @@ static enum ndr_err_code ndr_push_lsa_CreateTrustedDomain(struct ndr_push *ndr,
return NDR_ERR_SUCCESS;
}
-static enum ndr_err_code ndr_pull_lsa_CreateTrustedDomain(struct ndr_pull *ndr, int flags, struct lsa_CreateTrustedDomain *r)
+_PUBLIC_ enum ndr_err_code ndr_pull_lsa_CreateTrustedDomain(struct ndr_pull *ndr, int flags, struct lsa_CreateTrustedDomain *r)
{
TALLOC_CTX *_mem_save_handle_0;
TALLOC_CTX *_mem_save_info_0;
@@ -5112,9 +5597,6 @@ static enum ndr_err_code ndr_pull_lsa_EnumTrustDom(struct ndr_pull *ndr, int fla
NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, r->in.resume_handle));
NDR_PULL_SET_MEM_CTX(ndr, _mem_save_resume_handle_0, LIBNDR_FLAG_REF_ALLOC);
NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &r->in.max_size));
- if (r->in.max_size < 0 || r->in.max_size > 1000) {
- return ndr_pull_error(ndr, NDR_ERR_RANGE, "value out of range");
- }
NDR_PULL_ALLOC(ndr, r->out.resume_handle);
*r->out.resume_handle = *r->in.resume_handle;
NDR_PULL_ALLOC(ndr, r->out.domains);
@@ -5178,7 +5660,7 @@ _PUBLIC_ void ndr_print_lsa_EnumTrustDom(struct ndr_print *ndr, const char *name
ndr->depth--;
}
-static enum ndr_err_code ndr_push_lsa_LookupNames(struct ndr_push *ndr, int flags, const struct lsa_LookupNames *r)
+_PUBLIC_ enum ndr_err_code ndr_push_lsa_LookupNames(struct ndr_push *ndr, int flags, const struct lsa_LookupNames *r)
{
uint32_t cntr_names_0;
if (flags & NDR_IN) {
@@ -5198,7 +5680,7 @@ static enum ndr_err_code ndr_push_lsa_LookupNames(struct ndr_push *ndr, int flag
return ndr_push_error(ndr, NDR_ERR_INVALID_POINTER, "NULL [ref] pointer");
}
NDR_CHECK(ndr_push_lsa_TransSidArray(ndr, NDR_SCALARS|NDR_BUFFERS, r->in.sids));
- NDR_CHECK(ndr_push_uint16(ndr, NDR_SCALARS, r->in.level));
+ NDR_CHECK(ndr_push_lsa_LookupNamesLevel(ndr, NDR_SCALARS, r->in.level));
if (r->in.count == NULL) {
return ndr_push_error(ndr, NDR_ERR_INVALID_POINTER, "NULL [ref] pointer");
}
@@ -5222,7 +5704,7 @@ static enum ndr_err_code ndr_push_lsa_LookupNames(struct ndr_push *ndr, int flag
return NDR_ERR_SUCCESS;
}
-static enum ndr_err_code ndr_pull_lsa_LookupNames(struct ndr_pull *ndr, int flags, struct lsa_LookupNames *r)
+_PUBLIC_ enum ndr_err_code ndr_pull_lsa_LookupNames(struct ndr_pull *ndr, int flags, struct lsa_LookupNames *r)
{
uint32_t cntr_names_0;
uint32_t _ptr_domains;
@@ -5263,7 +5745,7 @@ static enum ndr_err_code ndr_pull_lsa_LookupNames(struct ndr_pull *ndr, int flag
NDR_PULL_SET_MEM_CTX(ndr, r->in.sids, LIBNDR_FLAG_REF_ALLOC);
NDR_CHECK(ndr_pull_lsa_TransSidArray(ndr, NDR_SCALARS|NDR_BUFFERS, r->in.sids));
NDR_PULL_SET_MEM_CTX(ndr, _mem_save_sids_0, LIBNDR_FLAG_REF_ALLOC);
- NDR_CHECK(ndr_pull_uint16(ndr, NDR_SCALARS, &r->in.level));
+ NDR_CHECK(ndr_pull_lsa_LookupNamesLevel(ndr, NDR_SCALARS, &r->in.level));
if (ndr->flags & LIBNDR_FLAG_REF_ALLOC) {
NDR_PULL_ALLOC(ndr, r->in.count);
}
@@ -5342,7 +5824,7 @@ _PUBLIC_ void ndr_print_lsa_LookupNames(struct ndr_print *ndr, const char *name,
ndr->depth++;
ndr_print_lsa_TransSidArray(ndr, "sids", r->in.sids);
ndr->depth--;
- ndr_print_uint16(ndr, "level", r->in.level);
+ ndr_print_lsa_LookupNamesLevel(ndr, "level", r->in.level);
ndr_print_ptr(ndr, "count", r->in.count);
ndr->depth++;
ndr_print_uint32(ndr, "count", *r->in.count);
@@ -5372,7 +5854,7 @@ _PUBLIC_ void ndr_print_lsa_LookupNames(struct ndr_print *ndr, const char *name,
ndr->depth--;
}
-static enum ndr_err_code ndr_push_lsa_LookupSids(struct ndr_push *ndr, int flags, const struct lsa_LookupSids *r)
+_PUBLIC_ enum ndr_err_code ndr_push_lsa_LookupSids(struct ndr_push *ndr, int flags, const struct lsa_LookupSids *r)
{
if (flags & NDR_IN) {
if (r->in.handle == NULL) {
@@ -5411,7 +5893,7 @@ static enum ndr_err_code ndr_push_lsa_LookupSids(struct ndr_push *ndr, int flags
return NDR_ERR_SUCCESS;
}
-static enum ndr_err_code ndr_pull_lsa_LookupSids(struct ndr_pull *ndr, int flags, struct lsa_LookupSids *r)
+_PUBLIC_ enum ndr_err_code ndr_pull_lsa_LookupSids(struct ndr_pull *ndr, int flags, struct lsa_LookupSids *r)
{
uint32_t _ptr_domains;
TALLOC_CTX *_mem_save_handle_0;
@@ -5540,7 +6022,7 @@ _PUBLIC_ void ndr_print_lsa_LookupSids(struct ndr_print *ndr, const char *name,
ndr->depth--;
}
-static enum ndr_err_code ndr_push_lsa_CreateSecret(struct ndr_push *ndr, int flags, const struct lsa_CreateSecret *r)
+_PUBLIC_ enum ndr_err_code ndr_push_lsa_CreateSecret(struct ndr_push *ndr, int flags, const struct lsa_CreateSecret *r)
{
if (flags & NDR_IN) {
if (r->in.handle == NULL) {
@@ -5560,7 +6042,7 @@ static enum ndr_err_code ndr_push_lsa_CreateSecret(struct ndr_push *ndr, int fla
return NDR_ERR_SUCCESS;
}
-static enum ndr_err_code ndr_pull_lsa_CreateSecret(struct ndr_pull *ndr, int flags, struct lsa_CreateSecret *r)
+_PUBLIC_ enum ndr_err_code ndr_pull_lsa_CreateSecret(struct ndr_pull *ndr, int flags, struct lsa_CreateSecret *r)
{
TALLOC_CTX *_mem_save_handle_0;
TALLOC_CTX *_mem_save_sec_handle_0;
@@ -6349,7 +6831,7 @@ _PUBLIC_ void ndr_print_lsa_SetInformationTrustedDomain(struct ndr_print *ndr, c
ndr->depth--;
}
-static enum ndr_err_code ndr_push_lsa_OpenSecret(struct ndr_push *ndr, int flags, const struct lsa_OpenSecret *r)
+_PUBLIC_ enum ndr_err_code ndr_push_lsa_OpenSecret(struct ndr_push *ndr, int flags, const struct lsa_OpenSecret *r)
{
if (flags & NDR_IN) {
if (r->in.handle == NULL) {
@@ -6369,7 +6851,7 @@ static enum ndr_err_code ndr_push_lsa_OpenSecret(struct ndr_push *ndr, int flags
return NDR_ERR_SUCCESS;
}
-static enum ndr_err_code ndr_pull_lsa_OpenSecret(struct ndr_pull *ndr, int flags, struct lsa_OpenSecret *r)
+_PUBLIC_ enum ndr_err_code ndr_pull_lsa_OpenSecret(struct ndr_pull *ndr, int flags, struct lsa_OpenSecret *r)
{
TALLOC_CTX *_mem_save_handle_0;
TALLOC_CTX *_mem_save_sec_handle_0;
@@ -6432,7 +6914,7 @@ _PUBLIC_ void ndr_print_lsa_OpenSecret(struct ndr_print *ndr, const char *name,
ndr->depth--;
}
-static enum ndr_err_code ndr_push_lsa_SetSecret(struct ndr_push *ndr, int flags, const struct lsa_SetSecret *r)
+_PUBLIC_ enum ndr_err_code ndr_push_lsa_SetSecret(struct ndr_push *ndr, int flags, const struct lsa_SetSecret *r)
{
if (flags & NDR_IN) {
if (r->in.sec_handle == NULL) {
@@ -6454,7 +6936,7 @@ static enum ndr_err_code ndr_push_lsa_SetSecret(struct ndr_push *ndr, int flags,
return NDR_ERR_SUCCESS;
}
-static enum ndr_err_code ndr_pull_lsa_SetSecret(struct ndr_pull *ndr, int flags, struct lsa_SetSecret *r)
+_PUBLIC_ enum ndr_err_code ndr_pull_lsa_SetSecret(struct ndr_pull *ndr, int flags, struct lsa_SetSecret *r)
{
uint32_t _ptr_new_val;
uint32_t _ptr_old_val;
@@ -6537,7 +7019,7 @@ _PUBLIC_ void ndr_print_lsa_SetSecret(struct ndr_print *ndr, const char *name, i
ndr->depth--;
}
-static enum ndr_err_code ndr_push_lsa_QuerySecret(struct ndr_push *ndr, int flags, const struct lsa_QuerySecret *r)
+_PUBLIC_ enum ndr_err_code ndr_push_lsa_QuerySecret(struct ndr_push *ndr, int flags, const struct lsa_QuerySecret *r)
{
if (flags & NDR_IN) {
if (r->in.sec_handle == NULL) {
@@ -6583,7 +7065,7 @@ static enum ndr_err_code ndr_push_lsa_QuerySecret(struct ndr_push *ndr, int flag
return NDR_ERR_SUCCESS;
}
-static enum ndr_err_code ndr_pull_lsa_QuerySecret(struct ndr_pull *ndr, int flags, struct lsa_QuerySecret *r)
+_PUBLIC_ enum ndr_err_code ndr_pull_lsa_QuerySecret(struct ndr_pull *ndr, int flags, struct lsa_QuerySecret *r)
{
uint32_t _ptr_new_val;
uint32_t _ptr_new_mtime;
@@ -7824,7 +8306,7 @@ _PUBLIC_ void ndr_print_lsa_RetrievePrivateData(struct ndr_print *ndr, const cha
ndr->depth--;
}
-static enum ndr_err_code ndr_push_lsa_OpenPolicy2(struct ndr_push *ndr, int flags, const struct lsa_OpenPolicy2 *r)
+_PUBLIC_ enum ndr_err_code ndr_push_lsa_OpenPolicy2(struct ndr_push *ndr, int flags, const struct lsa_OpenPolicy2 *r)
{
if (flags & NDR_IN) {
NDR_CHECK(ndr_push_unique_ptr(ndr, r->in.system_name));
@@ -7850,7 +8332,7 @@ static enum ndr_err_code ndr_push_lsa_OpenPolicy2(struct ndr_push *ndr, int flag
return NDR_ERR_SUCCESS;
}
-static enum ndr_err_code ndr_pull_lsa_OpenPolicy2(struct ndr_pull *ndr, int flags, struct lsa_OpenPolicy2 *r)
+_PUBLIC_ enum ndr_err_code ndr_pull_lsa_OpenPolicy2(struct ndr_pull *ndr, int flags, struct lsa_OpenPolicy2 *r)
{
uint32_t _ptr_system_name;
TALLOC_CTX *_mem_save_system_name_0;
@@ -8985,7 +9467,7 @@ _PUBLIC_ void ndr_print_lsa_TestCall(struct ndr_print *ndr, const char *name, in
ndr->depth--;
}
-static enum ndr_err_code ndr_push_lsa_LookupSids2(struct ndr_push *ndr, int flags, const struct lsa_LookupSids2 *r)
+_PUBLIC_ enum ndr_err_code ndr_push_lsa_LookupSids2(struct ndr_push *ndr, int flags, const struct lsa_LookupSids2 *r)
{
if (flags & NDR_IN) {
if (r->in.handle == NULL) {
@@ -9026,7 +9508,7 @@ static enum ndr_err_code ndr_push_lsa_LookupSids2(struct ndr_push *ndr, int flag
return NDR_ERR_SUCCESS;
}
-static enum ndr_err_code ndr_pull_lsa_LookupSids2(struct ndr_pull *ndr, int flags, struct lsa_LookupSids2 *r)
+_PUBLIC_ enum ndr_err_code ndr_pull_lsa_LookupSids2(struct ndr_pull *ndr, int flags, struct lsa_LookupSids2 *r)
{
uint32_t _ptr_domains;
TALLOC_CTX *_mem_save_handle_0;
@@ -9159,7 +9641,7 @@ _PUBLIC_ void ndr_print_lsa_LookupSids2(struct ndr_print *ndr, const char *name,
ndr->depth--;
}
-static enum ndr_err_code ndr_push_lsa_LookupNames2(struct ndr_push *ndr, int flags, const struct lsa_LookupNames2 *r)
+_PUBLIC_ enum ndr_err_code ndr_push_lsa_LookupNames2(struct ndr_push *ndr, int flags, const struct lsa_LookupNames2 *r)
{
uint32_t cntr_names_0;
if (flags & NDR_IN) {
@@ -9179,7 +9661,7 @@ static enum ndr_err_code ndr_push_lsa_LookupNames2(struct ndr_push *ndr, int fla
return ndr_push_error(ndr, NDR_ERR_INVALID_POINTER, "NULL [ref] pointer");
}
NDR_CHECK(ndr_push_lsa_TransSidArray2(ndr, NDR_SCALARS|NDR_BUFFERS, r->in.sids));
- NDR_CHECK(ndr_push_uint16(ndr, NDR_SCALARS, r->in.level));
+ NDR_CHECK(ndr_push_lsa_LookupNamesLevel(ndr, NDR_SCALARS, r->in.level));
if (r->in.count == NULL) {
return ndr_push_error(ndr, NDR_ERR_INVALID_POINTER, "NULL [ref] pointer");
}
@@ -9205,7 +9687,7 @@ static enum ndr_err_code ndr_push_lsa_LookupNames2(struct ndr_push *ndr, int fla
return NDR_ERR_SUCCESS;
}
-static enum ndr_err_code ndr_pull_lsa_LookupNames2(struct ndr_pull *ndr, int flags, struct lsa_LookupNames2 *r)
+_PUBLIC_ enum ndr_err_code ndr_pull_lsa_LookupNames2(struct ndr_pull *ndr, int flags, struct lsa_LookupNames2 *r)
{
uint32_t cntr_names_0;
uint32_t _ptr_domains;
@@ -9246,7 +9728,7 @@ static enum ndr_err_code ndr_pull_lsa_LookupNames2(struct ndr_pull *ndr, int fla
NDR_PULL_SET_MEM_CTX(ndr, r->in.sids, LIBNDR_FLAG_REF_ALLOC);
NDR_CHECK(ndr_pull_lsa_TransSidArray2(ndr, NDR_SCALARS|NDR_BUFFERS, r->in.sids));
NDR_PULL_SET_MEM_CTX(ndr, _mem_save_sids_0, LIBNDR_FLAG_REF_ALLOC);
- NDR_CHECK(ndr_pull_uint16(ndr, NDR_SCALARS, &r->in.level));
+ NDR_CHECK(ndr_pull_lsa_LookupNamesLevel(ndr, NDR_SCALARS, &r->in.level));
if (ndr->flags & LIBNDR_FLAG_REF_ALLOC) {
NDR_PULL_ALLOC(ndr, r->in.count);
}
@@ -9327,7 +9809,7 @@ _PUBLIC_ void ndr_print_lsa_LookupNames2(struct ndr_print *ndr, const char *name
ndr->depth++;
ndr_print_lsa_TransSidArray2(ndr, "sids", r->in.sids);
ndr->depth--;
- ndr_print_uint16(ndr, "level", r->in.level);
+ ndr_print_lsa_LookupNamesLevel(ndr, "level", r->in.level);
ndr_print_ptr(ndr, "count", r->in.count);
ndr->depth++;
ndr_print_uint32(ndr, "count", *r->in.count);
@@ -9728,7 +10210,7 @@ _PUBLIC_ void ndr_print_lsa_CREDRPROFILELOADED(struct ndr_print *ndr, const char
ndr->depth--;
}
-static enum ndr_err_code ndr_push_lsa_LookupNames3(struct ndr_push *ndr, int flags, const struct lsa_LookupNames3 *r)
+_PUBLIC_ enum ndr_err_code ndr_push_lsa_LookupNames3(struct ndr_push *ndr, int flags, const struct lsa_LookupNames3 *r)
{
uint32_t cntr_names_0;
if (flags & NDR_IN) {
@@ -9748,7 +10230,7 @@ static enum ndr_err_code ndr_push_lsa_LookupNames3(struct ndr_push *ndr, int fla
return ndr_push_error(ndr, NDR_ERR_INVALID_POINTER, "NULL [ref] pointer");
}
NDR_CHECK(ndr_push_lsa_TransSidArray3(ndr, NDR_SCALARS|NDR_BUFFERS, r->in.sids));
- NDR_CHECK(ndr_push_uint16(ndr, NDR_SCALARS, r->in.level));
+ NDR_CHECK(ndr_push_lsa_LookupNamesLevel(ndr, NDR_SCALARS, r->in.level));
if (r->in.count == NULL) {
return ndr_push_error(ndr, NDR_ERR_INVALID_POINTER, "NULL [ref] pointer");
}
@@ -9774,7 +10256,7 @@ static enum ndr_err_code ndr_push_lsa_LookupNames3(struct ndr_push *ndr, int fla
return NDR_ERR_SUCCESS;
}
-static enum ndr_err_code ndr_pull_lsa_LookupNames3(struct ndr_pull *ndr, int flags, struct lsa_LookupNames3 *r)
+_PUBLIC_ enum ndr_err_code ndr_pull_lsa_LookupNames3(struct ndr_pull *ndr, int flags, struct lsa_LookupNames3 *r)
{
uint32_t cntr_names_0;
uint32_t _ptr_domains;
@@ -9815,7 +10297,7 @@ static enum ndr_err_code ndr_pull_lsa_LookupNames3(struct ndr_pull *ndr, int fla
NDR_PULL_SET_MEM_CTX(ndr, r->in.sids, LIBNDR_FLAG_REF_ALLOC);
NDR_CHECK(ndr_pull_lsa_TransSidArray3(ndr, NDR_SCALARS|NDR_BUFFERS, r->in.sids));
NDR_PULL_SET_MEM_CTX(ndr, _mem_save_sids_0, LIBNDR_FLAG_REF_ALLOC);
- NDR_CHECK(ndr_pull_uint16(ndr, NDR_SCALARS, &r->in.level));
+ NDR_CHECK(ndr_pull_lsa_LookupNamesLevel(ndr, NDR_SCALARS, &r->in.level));
if (ndr->flags & LIBNDR_FLAG_REF_ALLOC) {
NDR_PULL_ALLOC(ndr, r->in.count);
}
@@ -9896,7 +10378,7 @@ _PUBLIC_ void ndr_print_lsa_LookupNames3(struct ndr_print *ndr, const char *name
ndr->depth++;
ndr_print_lsa_TransSidArray3(ndr, "sids", r->in.sids);
ndr->depth--;
- ndr_print_uint16(ndr, "level", r->in.level);
+ ndr_print_lsa_LookupNamesLevel(ndr, "level", r->in.level);
ndr_print_ptr(ndr, "count", r->in.count);
ndr->depth++;
ndr_print_uint32(ndr, "count", *r->in.count);
@@ -10092,41 +10574,112 @@ _PUBLIC_ void ndr_print_lsa_LSARUNREGISTERAUDITEVENT(struct ndr_print *ndr, cons
ndr->depth--;
}
-static enum ndr_err_code ndr_push_lsa_LSARQUERYFORESTTRUSTINFORMATION(struct ndr_push *ndr, int flags, const struct lsa_LSARQUERYFORESTTRUSTINFORMATION *r)
+static enum ndr_err_code ndr_push_lsa_lsaRQueryForestTrustInformation(struct ndr_push *ndr, int flags, const struct lsa_lsaRQueryForestTrustInformation *r)
{
if (flags & NDR_IN) {
+ if (r->in.handle == NULL) {
+ return ndr_push_error(ndr, NDR_ERR_INVALID_POINTER, "NULL [ref] pointer");
+ }
+ NDR_CHECK(ndr_push_policy_handle(ndr, NDR_SCALARS|NDR_BUFFERS, r->in.handle));
+ if (r->in.trusted_domain_name == NULL) {
+ return ndr_push_error(ndr, NDR_ERR_INVALID_POINTER, "NULL [ref] pointer");
+ }
+ NDR_CHECK(ndr_push_lsa_String(ndr, NDR_SCALARS|NDR_BUFFERS, r->in.trusted_domain_name));
+ NDR_CHECK(ndr_push_uint16(ndr, NDR_SCALARS, r->in.unknown));
}
if (flags & NDR_OUT) {
+ if (r->out.forest_trust_info == NULL) {
+ return ndr_push_error(ndr, NDR_ERR_INVALID_POINTER, "NULL [ref] pointer");
+ }
+ if (*r->out.forest_trust_info == NULL) {
+ return ndr_push_error(ndr, NDR_ERR_INVALID_POINTER, "NULL [ref] pointer");
+ }
+ NDR_CHECK(ndr_push_ref_ptr(ndr));
+ NDR_CHECK(ndr_push_lsa_ForestTrustInformation(ndr, NDR_SCALARS|NDR_BUFFERS, *r->out.forest_trust_info));
NDR_CHECK(ndr_push_NTSTATUS(ndr, NDR_SCALARS, r->out.result));
}
return NDR_ERR_SUCCESS;
}
-static enum ndr_err_code ndr_pull_lsa_LSARQUERYFORESTTRUSTINFORMATION(struct ndr_pull *ndr, int flags, struct lsa_LSARQUERYFORESTTRUSTINFORMATION *r)
+static enum ndr_err_code ndr_pull_lsa_lsaRQueryForestTrustInformation(struct ndr_pull *ndr, int flags, struct lsa_lsaRQueryForestTrustInformation *r)
{
+ uint32_t _ptr_forest_trust_info;
+ TALLOC_CTX *_mem_save_handle_0;
+ TALLOC_CTX *_mem_save_trusted_domain_name_0;
+ TALLOC_CTX *_mem_save_forest_trust_info_0;
+ TALLOC_CTX *_mem_save_forest_trust_info_1;
if (flags & NDR_IN) {
+ ZERO_STRUCT(r->out);
+
+ if (ndr->flags & LIBNDR_FLAG_REF_ALLOC) {
+ NDR_PULL_ALLOC(ndr, r->in.handle);
+ }
+ _mem_save_handle_0 = NDR_PULL_GET_MEM_CTX(ndr);
+ NDR_PULL_SET_MEM_CTX(ndr, r->in.handle, LIBNDR_FLAG_REF_ALLOC);
+ NDR_CHECK(ndr_pull_policy_handle(ndr, NDR_SCALARS|NDR_BUFFERS, r->in.handle));
+ NDR_PULL_SET_MEM_CTX(ndr, _mem_save_handle_0, LIBNDR_FLAG_REF_ALLOC);
+ if (ndr->flags & LIBNDR_FLAG_REF_ALLOC) {
+ NDR_PULL_ALLOC(ndr, r->in.trusted_domain_name);
+ }
+ _mem_save_trusted_domain_name_0 = NDR_PULL_GET_MEM_CTX(ndr);
+ NDR_PULL_SET_MEM_CTX(ndr, r->in.trusted_domain_name, LIBNDR_FLAG_REF_ALLOC);
+ NDR_CHECK(ndr_pull_lsa_String(ndr, NDR_SCALARS|NDR_BUFFERS, r->in.trusted_domain_name));
+ NDR_PULL_SET_MEM_CTX(ndr, _mem_save_trusted_domain_name_0, LIBNDR_FLAG_REF_ALLOC);
+ NDR_CHECK(ndr_pull_uint16(ndr, NDR_SCALARS, &r->in.unknown));
+ NDR_PULL_ALLOC(ndr, r->out.forest_trust_info);
+ ZERO_STRUCTP(r->out.forest_trust_info);
}
if (flags & NDR_OUT) {
+ if (ndr->flags & LIBNDR_FLAG_REF_ALLOC) {
+ NDR_PULL_ALLOC(ndr, r->out.forest_trust_info);
+ }
+ _mem_save_forest_trust_info_0 = NDR_PULL_GET_MEM_CTX(ndr);
+ NDR_PULL_SET_MEM_CTX(ndr, r->out.forest_trust_info, LIBNDR_FLAG_REF_ALLOC);
+ NDR_CHECK(ndr_pull_ref_ptr(ndr, &_ptr_forest_trust_info));
+ if (ndr->flags & LIBNDR_FLAG_REF_ALLOC) {
+ NDR_PULL_ALLOC(ndr, *r->out.forest_trust_info);
+ }
+ _mem_save_forest_trust_info_1 = NDR_PULL_GET_MEM_CTX(ndr);
+ NDR_PULL_SET_MEM_CTX(ndr, *r->out.forest_trust_info, LIBNDR_FLAG_REF_ALLOC);
+ NDR_CHECK(ndr_pull_lsa_ForestTrustInformation(ndr, NDR_SCALARS|NDR_BUFFERS, *r->out.forest_trust_info));
+ NDR_PULL_SET_MEM_CTX(ndr, _mem_save_forest_trust_info_1, LIBNDR_FLAG_REF_ALLOC);
+ NDR_PULL_SET_MEM_CTX(ndr, _mem_save_forest_trust_info_0, LIBNDR_FLAG_REF_ALLOC);
NDR_CHECK(ndr_pull_NTSTATUS(ndr, NDR_SCALARS, &r->out.result));
}
return NDR_ERR_SUCCESS;
}
-_PUBLIC_ void ndr_print_lsa_LSARQUERYFORESTTRUSTINFORMATION(struct ndr_print *ndr, const char *name, int flags, const struct lsa_LSARQUERYFORESTTRUSTINFORMATION *r)
+_PUBLIC_ void ndr_print_lsa_lsaRQueryForestTrustInformation(struct ndr_print *ndr, const char *name, int flags, const struct lsa_lsaRQueryForestTrustInformation *r)
{
- ndr_print_struct(ndr, name, "lsa_LSARQUERYFORESTTRUSTINFORMATION");
+ ndr_print_struct(ndr, name, "lsa_lsaRQueryForestTrustInformation");
ndr->depth++;
if (flags & NDR_SET_VALUES) {
ndr->flags |= LIBNDR_PRINT_SET_VALUES;
}
if (flags & NDR_IN) {
- ndr_print_struct(ndr, "in", "lsa_LSARQUERYFORESTTRUSTINFORMATION");
+ ndr_print_struct(ndr, "in", "lsa_lsaRQueryForestTrustInformation");
+ ndr->depth++;
+ ndr_print_ptr(ndr, "handle", r->in.handle);
ndr->depth++;
+ ndr_print_policy_handle(ndr, "handle", r->in.handle);
+ ndr->depth--;
+ ndr_print_ptr(ndr, "trusted_domain_name", r->in.trusted_domain_name);
+ ndr->depth++;
+ ndr_print_lsa_String(ndr, "trusted_domain_name", r->in.trusted_domain_name);
+ ndr->depth--;
+ ndr_print_uint16(ndr, "unknown", r->in.unknown);
ndr->depth--;
}
if (flags & NDR_OUT) {
- ndr_print_struct(ndr, "out", "lsa_LSARQUERYFORESTTRUSTINFORMATION");
+ ndr_print_struct(ndr, "out", "lsa_lsaRQueryForestTrustInformation");
+ ndr->depth++;
+ ndr_print_ptr(ndr, "forest_trust_info", r->out.forest_trust_info);
+ ndr->depth++;
+ ndr_print_ptr(ndr, "forest_trust_info", *r->out.forest_trust_info);
ndr->depth++;
+ ndr_print_lsa_ForestTrustInformation(ndr, "forest_trust_info", *r->out.forest_trust_info);
+ ndr->depth--;
+ ndr->depth--;
ndr_print_NTSTATUS(ndr, "result", r->out.result);
ndr->depth--;
}
@@ -10215,7 +10768,7 @@ _PUBLIC_ void ndr_print_lsa_CREDRRENAME(struct ndr_print *ndr, const char *name,
ndr->depth--;
}
-static enum ndr_err_code ndr_push_lsa_LookupSids3(struct ndr_push *ndr, int flags, const struct lsa_LookupSids3 *r)
+_PUBLIC_ enum ndr_err_code ndr_push_lsa_LookupSids3(struct ndr_push *ndr, int flags, const struct lsa_LookupSids3 *r)
{
if (flags & NDR_IN) {
if (r->in.sids == NULL) {
@@ -10252,7 +10805,7 @@ static enum ndr_err_code ndr_push_lsa_LookupSids3(struct ndr_push *ndr, int flag
return NDR_ERR_SUCCESS;
}
-static enum ndr_err_code ndr_pull_lsa_LookupSids3(struct ndr_pull *ndr, int flags, struct lsa_LookupSids3 *r)
+_PUBLIC_ enum ndr_err_code ndr_pull_lsa_LookupSids3(struct ndr_pull *ndr, int flags, struct lsa_LookupSids3 *r)
{
uint32_t _ptr_domains;
TALLOC_CTX *_mem_save_sids_0;
@@ -10389,7 +10942,7 @@ static enum ndr_err_code ndr_push_lsa_LookupNames4(struct ndr_push *ndr, int fla
return ndr_push_error(ndr, NDR_ERR_INVALID_POINTER, "NULL [ref] pointer");
}
NDR_CHECK(ndr_push_lsa_TransSidArray3(ndr, NDR_SCALARS|NDR_BUFFERS, r->in.sids));
- NDR_CHECK(ndr_push_uint16(ndr, NDR_SCALARS, r->in.level));
+ NDR_CHECK(ndr_push_lsa_LookupNamesLevel(ndr, NDR_SCALARS, r->in.level));
if (r->in.count == NULL) {
return ndr_push_error(ndr, NDR_ERR_INVALID_POINTER, "NULL [ref] pointer");
}
@@ -10448,7 +11001,7 @@ static enum ndr_err_code ndr_pull_lsa_LookupNames4(struct ndr_pull *ndr, int fla
NDR_PULL_SET_MEM_CTX(ndr, r->in.sids, LIBNDR_FLAG_REF_ALLOC);
NDR_CHECK(ndr_pull_lsa_TransSidArray3(ndr, NDR_SCALARS|NDR_BUFFERS, r->in.sids));
NDR_PULL_SET_MEM_CTX(ndr, _mem_save_sids_0, LIBNDR_FLAG_REF_ALLOC);
- NDR_CHECK(ndr_pull_uint16(ndr, NDR_SCALARS, &r->in.level));
+ NDR_CHECK(ndr_pull_lsa_LookupNamesLevel(ndr, NDR_SCALARS, &r->in.level));
if (ndr->flags & LIBNDR_FLAG_REF_ALLOC) {
NDR_PULL_ALLOC(ndr, r->in.count);
}
@@ -10525,7 +11078,7 @@ _PUBLIC_ void ndr_print_lsa_LookupNames4(struct ndr_print *ndr, const char *name
ndr->depth++;
ndr_print_lsa_TransSidArray3(ndr, "sids", r->in.sids);
ndr->depth--;
- ndr_print_uint16(ndr, "level", r->in.level);
+ ndr_print_lsa_LookupNamesLevel(ndr, "level", r->in.level);
ndr_print_ptr(ndr, "count", r->in.count);
ndr->depth++;
ndr_print_uint32(ndr, "count", *r->in.count);
@@ -11307,11 +11860,11 @@ static const struct ndr_interface_call lsarpc_calls[] = {
false,
},
{
- "lsa_LSARQUERYFORESTTRUSTINFORMATION",
- sizeof(struct lsa_LSARQUERYFORESTTRUSTINFORMATION),
- (ndr_push_flags_fn_t) ndr_push_lsa_LSARQUERYFORESTTRUSTINFORMATION,
- (ndr_pull_flags_fn_t) ndr_pull_lsa_LSARQUERYFORESTTRUSTINFORMATION,
- (ndr_print_function_t) ndr_print_lsa_LSARQUERYFORESTTRUSTINFORMATION,
+ "lsa_lsaRQueryForestTrustInformation",
+ sizeof(struct lsa_lsaRQueryForestTrustInformation),
+ (ndr_push_flags_fn_t) ndr_push_lsa_lsaRQueryForestTrustInformation,
+ (ndr_pull_flags_fn_t) ndr_pull_lsa_lsaRQueryForestTrustInformation,
+ (ndr_print_function_t) ndr_print_lsa_lsaRQueryForestTrustInformation,
false,
},
{
diff --git a/source3/librpc/gen_ndr/ndr_lsa.h b/source3/librpc/gen_ndr/ndr_lsa.h
index dc100297f5..ab4043f2a1 100644
--- a/source3/librpc/gen_ndr/ndr_lsa.h
+++ b/source3/librpc/gen_ndr/ndr_lsa.h
@@ -194,6 +194,7 @@ void ndr_print_lsa_PrivArray(struct ndr_print *ndr, const char *name, const stru
void ndr_print_lsa_QosInfo(struct ndr_print *ndr, const char *name, const struct lsa_QosInfo *r);
void ndr_print_lsa_ObjectAttribute(struct ndr_print *ndr, const char *name, const struct lsa_ObjectAttribute *r);
void ndr_print_lsa_AuditLogInfo(struct ndr_print *ndr, const char *name, const struct lsa_AuditLogInfo *r);
+void ndr_print_lsa_PolicyAuditPolicy(struct ndr_print *ndr, const char *name, enum lsa_PolicyAuditPolicy r);
void ndr_print_lsa_AuditEventsInfo(struct ndr_print *ndr, const char *name, const struct lsa_AuditEventsInfo *r);
void ndr_print_lsa_DomainInfo(struct ndr_print *ndr, const char *name, const struct lsa_DomainInfo *r);
void ndr_print_lsa_PDAccountInfo(struct ndr_print *ndr, const char *name, const struct lsa_PDAccountInfo *r);
@@ -215,6 +216,7 @@ void ndr_print_lsa_SidType(struct ndr_print *ndr, const char *name, enum lsa_Sid
void ndr_print_lsa_TranslatedSid(struct ndr_print *ndr, const char *name, const struct lsa_TranslatedSid *r);
void ndr_print_lsa_TransSidArray(struct ndr_print *ndr, const char *name, const struct lsa_TransSidArray *r);
void ndr_print_lsa_RefDomainList(struct ndr_print *ndr, const char *name, const struct lsa_RefDomainList *r);
+void ndr_print_lsa_LookupNamesLevel(struct ndr_print *ndr, const char *name, enum lsa_LookupNamesLevel r);
void ndr_print_lsa_TranslatedName(struct ndr_print *ndr, const char *name, const struct lsa_TranslatedName *r);
void ndr_print_lsa_TransNameArray(struct ndr_print *ndr, const char *name, const struct lsa_TransNameArray *r);
void ndr_print_lsa_LUIDAttribute(struct ndr_print *ndr, const char *name, const struct lsa_LUIDAttribute *r);
@@ -246,22 +248,48 @@ void ndr_print_lsa_TranslatedSid2(struct ndr_print *ndr, const char *name, const
void ndr_print_lsa_TransSidArray2(struct ndr_print *ndr, const char *name, const struct lsa_TransSidArray2 *r);
void ndr_print_lsa_TranslatedSid3(struct ndr_print *ndr, const char *name, const struct lsa_TranslatedSid3 *r);
void ndr_print_lsa_TransSidArray3(struct ndr_print *ndr, const char *name, const struct lsa_TransSidArray3 *r);
+void ndr_print_lsa_ForestTrustBinaryData(struct ndr_print *ndr, const char *name, const struct lsa_ForestTrustBinaryData *r);
+void ndr_print_lsa_ForestTrustDomainInfo(struct ndr_print *ndr, const char *name, const struct lsa_ForestTrustDomainInfo *r);
+void ndr_print_lsa_ForestTrustData(struct ndr_print *ndr, const char *name, const union lsa_ForestTrustData *r);
+void ndr_print_lsa_ForestTrustRecordType(struct ndr_print *ndr, const char *name, enum lsa_ForestTrustRecordType r);
+void ndr_print_lsa_ForestTrustRecord(struct ndr_print *ndr, const char *name, const struct lsa_ForestTrustRecord *r);
+enum ndr_err_code ndr_push_lsa_ForestTrustInformation(struct ndr_push *ndr, int ndr_flags, const struct lsa_ForestTrustInformation *r);
+enum ndr_err_code ndr_pull_lsa_ForestTrustInformation(struct ndr_pull *ndr, int ndr_flags, struct lsa_ForestTrustInformation *r);
+void ndr_print_lsa_ForestTrustInformation(struct ndr_print *ndr, const char *name, const struct lsa_ForestTrustInformation *r);
void ndr_print_lsa_Close(struct ndr_print *ndr, const char *name, int flags, const struct lsa_Close *r);
+enum ndr_err_code ndr_push_lsa_Delete(struct ndr_push *ndr, int flags, const struct lsa_Delete *r);
+enum ndr_err_code ndr_pull_lsa_Delete(struct ndr_pull *ndr, int flags, struct lsa_Delete *r);
void ndr_print_lsa_Delete(struct ndr_print *ndr, const char *name, int flags, const struct lsa_Delete *r);
+enum ndr_err_code ndr_push_lsa_EnumPrivs(struct ndr_push *ndr, int flags, const struct lsa_EnumPrivs *r);
+enum ndr_err_code ndr_pull_lsa_EnumPrivs(struct ndr_pull *ndr, int flags, struct lsa_EnumPrivs *r);
void ndr_print_lsa_EnumPrivs(struct ndr_print *ndr, const char *name, int flags, const struct lsa_EnumPrivs *r);
void ndr_print_lsa_QuerySecurity(struct ndr_print *ndr, const char *name, int flags, const struct lsa_QuerySecurity *r);
void ndr_print_lsa_SetSecObj(struct ndr_print *ndr, const char *name, int flags, const struct lsa_SetSecObj *r);
void ndr_print_lsa_ChangePassword(struct ndr_print *ndr, const char *name, int flags, const struct lsa_ChangePassword *r);
+enum ndr_err_code ndr_push_lsa_OpenPolicy(struct ndr_push *ndr, int flags, const struct lsa_OpenPolicy *r);
+enum ndr_err_code ndr_pull_lsa_OpenPolicy(struct ndr_pull *ndr, int flags, struct lsa_OpenPolicy *r);
void ndr_print_lsa_OpenPolicy(struct ndr_print *ndr, const char *name, int flags, const struct lsa_OpenPolicy *r);
void ndr_print_lsa_QueryInfoPolicy(struct ndr_print *ndr, const char *name, int flags, const struct lsa_QueryInfoPolicy *r);
void ndr_print_lsa_SetInfoPolicy(struct ndr_print *ndr, const char *name, int flags, const struct lsa_SetInfoPolicy *r);
void ndr_print_lsa_ClearAuditLog(struct ndr_print *ndr, const char *name, int flags, const struct lsa_ClearAuditLog *r);
+enum ndr_err_code ndr_push_lsa_CreateAccount(struct ndr_push *ndr, int flags, const struct lsa_CreateAccount *r);
+enum ndr_err_code ndr_pull_lsa_CreateAccount(struct ndr_pull *ndr, int flags, struct lsa_CreateAccount *r);
void ndr_print_lsa_CreateAccount(struct ndr_print *ndr, const char *name, int flags, const struct lsa_CreateAccount *r);
+enum ndr_err_code ndr_push_lsa_EnumAccounts(struct ndr_push *ndr, int flags, const struct lsa_EnumAccounts *r);
+enum ndr_err_code ndr_pull_lsa_EnumAccounts(struct ndr_pull *ndr, int flags, struct lsa_EnumAccounts *r);
void ndr_print_lsa_EnumAccounts(struct ndr_print *ndr, const char *name, int flags, const struct lsa_EnumAccounts *r);
+enum ndr_err_code ndr_push_lsa_CreateTrustedDomain(struct ndr_push *ndr, int flags, const struct lsa_CreateTrustedDomain *r);
+enum ndr_err_code ndr_pull_lsa_CreateTrustedDomain(struct ndr_pull *ndr, int flags, struct lsa_CreateTrustedDomain *r);
void ndr_print_lsa_CreateTrustedDomain(struct ndr_print *ndr, const char *name, int flags, const struct lsa_CreateTrustedDomain *r);
void ndr_print_lsa_EnumTrustDom(struct ndr_print *ndr, const char *name, int flags, const struct lsa_EnumTrustDom *r);
+enum ndr_err_code ndr_push_lsa_LookupNames(struct ndr_push *ndr, int flags, const struct lsa_LookupNames *r);
+enum ndr_err_code ndr_pull_lsa_LookupNames(struct ndr_pull *ndr, int flags, struct lsa_LookupNames *r);
void ndr_print_lsa_LookupNames(struct ndr_print *ndr, const char *name, int flags, const struct lsa_LookupNames *r);
+enum ndr_err_code ndr_push_lsa_LookupSids(struct ndr_push *ndr, int flags, const struct lsa_LookupSids *r);
+enum ndr_err_code ndr_pull_lsa_LookupSids(struct ndr_pull *ndr, int flags, struct lsa_LookupSids *r);
void ndr_print_lsa_LookupSids(struct ndr_print *ndr, const char *name, int flags, const struct lsa_LookupSids *r);
+enum ndr_err_code ndr_push_lsa_CreateSecret(struct ndr_push *ndr, int flags, const struct lsa_CreateSecret *r);
+enum ndr_err_code ndr_pull_lsa_CreateSecret(struct ndr_pull *ndr, int flags, struct lsa_CreateSecret *r);
void ndr_print_lsa_CreateSecret(struct ndr_print *ndr, const char *name, int flags, const struct lsa_CreateSecret *r);
void ndr_print_lsa_OpenAccount(struct ndr_print *ndr, const char *name, int flags, const struct lsa_OpenAccount *r);
void ndr_print_lsa_EnumPrivsAccount(struct ndr_print *ndr, const char *name, int flags, const struct lsa_EnumPrivsAccount *r);
@@ -274,8 +302,14 @@ void ndr_print_lsa_SetSystemAccessAccount(struct ndr_print *ndr, const char *nam
void ndr_print_lsa_OpenTrustedDomain(struct ndr_print *ndr, const char *name, int flags, const struct lsa_OpenTrustedDomain *r);
void ndr_print_lsa_QueryTrustedDomainInfo(struct ndr_print *ndr, const char *name, int flags, const struct lsa_QueryTrustedDomainInfo *r);
void ndr_print_lsa_SetInformationTrustedDomain(struct ndr_print *ndr, const char *name, int flags, const struct lsa_SetInformationTrustedDomain *r);
+enum ndr_err_code ndr_push_lsa_OpenSecret(struct ndr_push *ndr, int flags, const struct lsa_OpenSecret *r);
+enum ndr_err_code ndr_pull_lsa_OpenSecret(struct ndr_pull *ndr, int flags, struct lsa_OpenSecret *r);
void ndr_print_lsa_OpenSecret(struct ndr_print *ndr, const char *name, int flags, const struct lsa_OpenSecret *r);
+enum ndr_err_code ndr_push_lsa_SetSecret(struct ndr_push *ndr, int flags, const struct lsa_SetSecret *r);
+enum ndr_err_code ndr_pull_lsa_SetSecret(struct ndr_pull *ndr, int flags, struct lsa_SetSecret *r);
void ndr_print_lsa_SetSecret(struct ndr_print *ndr, const char *name, int flags, const struct lsa_SetSecret *r);
+enum ndr_err_code ndr_push_lsa_QuerySecret(struct ndr_push *ndr, int flags, const struct lsa_QuerySecret *r);
+enum ndr_err_code ndr_pull_lsa_QuerySecret(struct ndr_pull *ndr, int flags, struct lsa_QuerySecret *r);
void ndr_print_lsa_QuerySecret(struct ndr_print *ndr, const char *name, int flags, const struct lsa_QuerySecret *r);
void ndr_print_lsa_LookupPrivValue(struct ndr_print *ndr, const char *name, int flags, const struct lsa_LookupPrivValue *r);
void ndr_print_lsa_LookupPrivName(struct ndr_print *ndr, const char *name, int flags, const struct lsa_LookupPrivName *r);
@@ -290,6 +324,8 @@ void ndr_print_lsa_SetTrustedDomainInfo(struct ndr_print *ndr, const char *name,
void ndr_print_lsa_DeleteTrustedDomain(struct ndr_print *ndr, const char *name, int flags, const struct lsa_DeleteTrustedDomain *r);
void ndr_print_lsa_StorePrivateData(struct ndr_print *ndr, const char *name, int flags, const struct lsa_StorePrivateData *r);
void ndr_print_lsa_RetrievePrivateData(struct ndr_print *ndr, const char *name, int flags, const struct lsa_RetrievePrivateData *r);
+enum ndr_err_code ndr_push_lsa_OpenPolicy2(struct ndr_push *ndr, int flags, const struct lsa_OpenPolicy2 *r);
+enum ndr_err_code ndr_pull_lsa_OpenPolicy2(struct ndr_pull *ndr, int flags, struct lsa_OpenPolicy2 *r);
void ndr_print_lsa_OpenPolicy2(struct ndr_print *ndr, const char *name, int flags, const struct lsa_OpenPolicy2 *r);
void ndr_print_lsa_GetUserName(struct ndr_print *ndr, const char *name, int flags, const struct lsa_GetUserName *r);
void ndr_print_lsa_QueryInfoPolicy2(struct ndr_print *ndr, const char *name, int flags, const struct lsa_QueryInfoPolicy2 *r);
@@ -303,7 +339,11 @@ void ndr_print_lsa_QueryDomainInformationPolicy(struct ndr_print *ndr, const cha
void ndr_print_lsa_SetDomainInformationPolicy(struct ndr_print *ndr, const char *name, int flags, const struct lsa_SetDomainInformationPolicy *r);
void ndr_print_lsa_OpenTrustedDomainByName(struct ndr_print *ndr, const char *name, int flags, const struct lsa_OpenTrustedDomainByName *r);
void ndr_print_lsa_TestCall(struct ndr_print *ndr, const char *name, int flags, const struct lsa_TestCall *r);
+enum ndr_err_code ndr_push_lsa_LookupSids2(struct ndr_push *ndr, int flags, const struct lsa_LookupSids2 *r);
+enum ndr_err_code ndr_pull_lsa_LookupSids2(struct ndr_pull *ndr, int flags, struct lsa_LookupSids2 *r);
void ndr_print_lsa_LookupSids2(struct ndr_print *ndr, const char *name, int flags, const struct lsa_LookupSids2 *r);
+enum ndr_err_code ndr_push_lsa_LookupNames2(struct ndr_push *ndr, int flags, const struct lsa_LookupNames2 *r);
+enum ndr_err_code ndr_pull_lsa_LookupNames2(struct ndr_pull *ndr, int flags, struct lsa_LookupNames2 *r);
void ndr_print_lsa_LookupNames2(struct ndr_print *ndr, const char *name, int flags, const struct lsa_LookupNames2 *r);
void ndr_print_lsa_CreateTrustedDomainEx2(struct ndr_print *ndr, const char *name, int flags, const struct lsa_CreateTrustedDomainEx2 *r);
void ndr_print_lsa_CREDRWRITE(struct ndr_print *ndr, const char *name, int flags, const struct lsa_CREDRWRITE *r);
@@ -314,14 +354,18 @@ void ndr_print_lsa_CREDRREADDOMAINCREDENTIALS(struct ndr_print *ndr, const char
void ndr_print_lsa_CREDRDELETE(struct ndr_print *ndr, const char *name, int flags, const struct lsa_CREDRDELETE *r);
void ndr_print_lsa_CREDRGETTARGETINFO(struct ndr_print *ndr, const char *name, int flags, const struct lsa_CREDRGETTARGETINFO *r);
void ndr_print_lsa_CREDRPROFILELOADED(struct ndr_print *ndr, const char *name, int flags, const struct lsa_CREDRPROFILELOADED *r);
+enum ndr_err_code ndr_push_lsa_LookupNames3(struct ndr_push *ndr, int flags, const struct lsa_LookupNames3 *r);
+enum ndr_err_code ndr_pull_lsa_LookupNames3(struct ndr_pull *ndr, int flags, struct lsa_LookupNames3 *r);
void ndr_print_lsa_LookupNames3(struct ndr_print *ndr, const char *name, int flags, const struct lsa_LookupNames3 *r);
void ndr_print_lsa_CREDRGETSESSIONTYPES(struct ndr_print *ndr, const char *name, int flags, const struct lsa_CREDRGETSESSIONTYPES *r);
void ndr_print_lsa_LSARREGISTERAUDITEVENT(struct ndr_print *ndr, const char *name, int flags, const struct lsa_LSARREGISTERAUDITEVENT *r);
void ndr_print_lsa_LSARGENAUDITEVENT(struct ndr_print *ndr, const char *name, int flags, const struct lsa_LSARGENAUDITEVENT *r);
void ndr_print_lsa_LSARUNREGISTERAUDITEVENT(struct ndr_print *ndr, const char *name, int flags, const struct lsa_LSARUNREGISTERAUDITEVENT *r);
-void ndr_print_lsa_LSARQUERYFORESTTRUSTINFORMATION(struct ndr_print *ndr, const char *name, int flags, const struct lsa_LSARQUERYFORESTTRUSTINFORMATION *r);
+void ndr_print_lsa_lsaRQueryForestTrustInformation(struct ndr_print *ndr, const char *name, int flags, const struct lsa_lsaRQueryForestTrustInformation *r);
void ndr_print_lsa_LSARSETFORESTTRUSTINFORMATION(struct ndr_print *ndr, const char *name, int flags, const struct lsa_LSARSETFORESTTRUSTINFORMATION *r);
void ndr_print_lsa_CREDRRENAME(struct ndr_print *ndr, const char *name, int flags, const struct lsa_CREDRRENAME *r);
+enum ndr_err_code ndr_push_lsa_LookupSids3(struct ndr_push *ndr, int flags, const struct lsa_LookupSids3 *r);
+enum ndr_err_code ndr_pull_lsa_LookupSids3(struct ndr_pull *ndr, int flags, struct lsa_LookupSids3 *r);
void ndr_print_lsa_LookupSids3(struct ndr_print *ndr, const char *name, int flags, const struct lsa_LookupSids3 *r);
void ndr_print_lsa_LookupNames4(struct ndr_print *ndr, const char *name, int flags, const struct lsa_LookupNames4 *r);
void ndr_print_lsa_LSAROPENPOLICYSCE(struct ndr_print *ndr, const char *name, int flags, const struct lsa_LSAROPENPOLICYSCE *r);
diff --git a/source3/librpc/gen_ndr/srv_lsa.c b/source3/librpc/gen_ndr/srv_lsa.c
index 68dc32cef5..8f8f985650 100644
--- a/source3/librpc/gen_ndr/srv_lsa.c
+++ b/source3/librpc/gen_ndr/srv_lsa.c
@@ -5579,18 +5579,18 @@ static bool api_lsa_LSARUNREGISTERAUDITEVENT(pipes_struct *p)
return true;
}
-static bool api_lsa_LSARQUERYFORESTTRUSTINFORMATION(pipes_struct *p)
+static bool api_lsa_lsaRQueryForestTrustInformation(pipes_struct *p)
{
const struct ndr_interface_call *call;
struct ndr_pull *pull;
struct ndr_push *push;
enum ndr_err_code ndr_err;
DATA_BLOB blob;
- struct lsa_LSARQUERYFORESTTRUSTINFORMATION *r;
+ struct lsa_lsaRQueryForestTrustInformation *r;
call = &ndr_table_lsarpc.calls[NDR_LSA_LSARQUERYFORESTTRUSTINFORMATION];
- r = talloc(NULL, struct lsa_LSARQUERYFORESTTRUSTINFORMATION);
+ r = talloc(NULL, struct lsa_lsaRQueryForestTrustInformation);
if (r == NULL) {
return false;
}
@@ -5614,10 +5614,17 @@ static bool api_lsa_LSARQUERYFORESTTRUSTINFORMATION(pipes_struct *p)
}
if (DEBUGLEVEL >= 10) {
- NDR_PRINT_IN_DEBUG(lsa_LSARQUERYFORESTTRUSTINFORMATION, r);
+ NDR_PRINT_IN_DEBUG(lsa_lsaRQueryForestTrustInformation, r);
}
- r->out.result = _lsa_LSARQUERYFORESTTRUSTINFORMATION(p, r);
+ ZERO_STRUCT(r->out);
+ r->out.forest_trust_info = talloc_zero(r, struct lsa_ForestTrustInformation *);
+ if (r->out.forest_trust_info == NULL) {
+ talloc_free(r);
+ return false;
+ }
+
+ r->out.result = _lsa_lsaRQueryForestTrustInformation(p, r);
if (p->rng_fault_state) {
talloc_free(r);
@@ -5626,7 +5633,7 @@ static bool api_lsa_LSARQUERYFORESTTRUSTINFORMATION(pipes_struct *p)
}
if (DEBUGLEVEL >= 10) {
- NDR_PRINT_OUT_DEBUG(lsa_LSARQUERYFORESTTRUSTINFORMATION, r);
+ NDR_PRINT_OUT_DEBUG(lsa_lsaRQueryForestTrustInformation, r);
}
push = ndr_push_init_ctx(r);
@@ -6331,7 +6338,7 @@ static struct api_struct api_lsarpc_cmds[] =
{"LSA_LSARREGISTERAUDITEVENT", NDR_LSA_LSARREGISTERAUDITEVENT, api_lsa_LSARREGISTERAUDITEVENT},
{"LSA_LSARGENAUDITEVENT", NDR_LSA_LSARGENAUDITEVENT, api_lsa_LSARGENAUDITEVENT},
{"LSA_LSARUNREGISTERAUDITEVENT", NDR_LSA_LSARUNREGISTERAUDITEVENT, api_lsa_LSARUNREGISTERAUDITEVENT},
- {"LSA_LSARQUERYFORESTTRUSTINFORMATION", NDR_LSA_LSARQUERYFORESTTRUSTINFORMATION, api_lsa_LSARQUERYFORESTTRUSTINFORMATION},
+ {"LSA_LSARQUERYFORESTTRUSTINFORMATION", NDR_LSA_LSARQUERYFORESTTRUSTINFORMATION, api_lsa_lsaRQueryForestTrustInformation},
{"LSA_LSARSETFORESTTRUSTINFORMATION", NDR_LSA_LSARSETFORESTTRUSTINFORMATION, api_lsa_LSARSETFORESTTRUSTINFORMATION},
{"LSA_CREDRRENAME", NDR_LSA_CREDRRENAME, api_lsa_CREDRRENAME},
{"LSA_LOOKUPSIDS3", NDR_LSA_LOOKUPSIDS3, api_lsa_LookupSids3},
diff --git a/source3/librpc/gen_ndr/srv_lsa.h b/source3/librpc/gen_ndr/srv_lsa.h
index e3decb2862..223ee5e970 100644
--- a/source3/librpc/gen_ndr/srv_lsa.h
+++ b/source3/librpc/gen_ndr/srv_lsa.h
@@ -74,7 +74,7 @@ NTSTATUS _lsa_CREDRGETSESSIONTYPES(pipes_struct *p, struct lsa_CREDRGETSESSIONTY
NTSTATUS _lsa_LSARREGISTERAUDITEVENT(pipes_struct *p, struct lsa_LSARREGISTERAUDITEVENT *r);
NTSTATUS _lsa_LSARGENAUDITEVENT(pipes_struct *p, struct lsa_LSARGENAUDITEVENT *r);
NTSTATUS _lsa_LSARUNREGISTERAUDITEVENT(pipes_struct *p, struct lsa_LSARUNREGISTERAUDITEVENT *r);
-NTSTATUS _lsa_LSARQUERYFORESTTRUSTINFORMATION(pipes_struct *p, struct lsa_LSARQUERYFORESTTRUSTINFORMATION *r);
+NTSTATUS _lsa_lsaRQueryForestTrustInformation(pipes_struct *p, struct lsa_lsaRQueryForestTrustInformation *r);
NTSTATUS _lsa_LSARSETFORESTTRUSTINFORMATION(pipes_struct *p, struct lsa_LSARSETFORESTTRUSTINFORMATION *r);
NTSTATUS _lsa_CREDRRENAME(pipes_struct *p, struct lsa_CREDRRENAME *r);
NTSTATUS _lsa_LookupSids3(pipes_struct *p, struct lsa_LookupSids3 *r);
diff --git a/source3/librpc/idl/lsa.idl b/source3/librpc/idl/lsa.idl
index 7daf648a63..8d26ec0aad 100644
--- a/source3/librpc/idl/lsa.idl
+++ b/source3/librpc/idl/lsa.idl
@@ -47,7 +47,7 @@ import "security.idl";
/******************/
/* Function: 0x01 */
- NTSTATUS lsa_Delete (
+ [public] NTSTATUS lsa_Delete (
[in] policy_handle *handle
);
@@ -69,7 +69,7 @@ import "security.idl";
[size_is(count)] lsa_PrivEntry *privs;
} lsa_PrivArray;
- NTSTATUS lsa_EnumPrivs (
+ [public] NTSTATUS lsa_EnumPrivs (
[in] policy_handle *handle,
[in,out] uint32 *resume_handle,
[in] uint32 max_count,
@@ -116,7 +116,7 @@ import "security.idl";
/* notice the screwup with the system_name - thats why MS created
OpenPolicy2 */
- NTSTATUS lsa_OpenPolicy (
+ [public] NTSTATUS lsa_OpenPolicy (
[in,unique] uint16 *system_name,
[in] lsa_ObjectAttribute *attr,
[in] uint32 access_mask,
@@ -138,9 +138,29 @@ import "security.idl";
uint32 unknown;
} lsa_AuditLogInfo;
+ typedef [v1_enum] enum {
+ LSA_AUDIT_POLICY_NONE=0,
+ LSA_AUDIT_POLICY_SUCCESS=1,
+ LSA_AUDIT_POLICY_FAILURE=2,
+ LSA_AUDIT_POLICY_ALL=(LSA_AUDIT_POLICY_SUCCESS|LSA_AUDIT_POLICY_FAILURE),
+ LSA_AUDIT_POLICY_CLEAR=4
+ } lsa_PolicyAuditPolicy;
+
+ typedef enum {
+ LSA_AUDIT_CATEGORY_SYSTEM = 0,
+ LSA_AUDIT_CATEGORY_LOGON = 1,
+ LSA_AUDIT_CATEGORY_FILE_AND_OBJECT_ACCESS = 2,
+ LSA_AUDIT_CATEGORY_USE_OF_USER_RIGHTS = 3,
+ LSA_AUDIT_CATEGORY_PROCCESS_TRACKING = 4,
+ LSA_AUDIT_CATEGORY_SECURITY_POLICY_CHANGES = 5,
+ LSA_AUDIT_CATEGORY_ACCOUNT_MANAGEMENT = 6,
+ LSA_AUDIT_CATEGORY_DIRECTORY_SERVICE_ACCESS = 7, /* only in win2k/2k3 */
+ LSA_AUDIT_CATEGORY_ACCOUNT_LOGON = 8 /* only in win2k/2k3 */
+ } lsa_PolicyAuditEventType;
+
typedef struct {
uint32 auditing_mode;
- [size_is(count)] uint32 *settings;
+ [size_is(count)] lsa_PolicyAuditPolicy *settings;
uint32 count;
} lsa_AuditEventsInfo;
@@ -251,7 +271,7 @@ import "security.idl";
/******************/
/* Function: 0x0a */
- NTSTATUS lsa_CreateAccount (
+ [public] NTSTATUS lsa_CreateAccount (
[in] policy_handle *handle,
[in] dom_sid2 *sid,
[in] uint32 access_mask,
@@ -272,7 +292,7 @@ import "security.idl";
[size_is(num_sids)] lsa_SidPtr *sids;
} lsa_SidArray;
- NTSTATUS lsa_EnumAccounts (
+ [public] NTSTATUS lsa_EnumAccounts (
[in] policy_handle *handle,
[in,out] uint32 *resume_handle,
[in,range(0,8192)] uint32 num_entries,
@@ -283,7 +303,7 @@ import "security.idl";
/*************************************************/
/* Function: 0x0c */
- NTSTATUS lsa_CreateTrustedDomain(
+ [public] NTSTATUS lsa_CreateTrustedDomain(
[in] policy_handle *handle,
[in] lsa_DomainInfo *info,
[in] uint32 access_mask,
@@ -305,7 +325,7 @@ import "security.idl";
NTSTATUS lsa_EnumTrustDom (
[in] policy_handle *handle,
[in,out] uint32 *resume_handle,
- [in,range(0,1000)] uint32 max_size,
+ [in] uint32 max_size,
[out] lsa_DomainList *domains
);
@@ -343,13 +363,30 @@ import "security.idl";
uint32 max_size;
} lsa_RefDomainList;
- NTSTATUS lsa_LookupNames (
+ /* Level 1: Ask everywhere
+ * Level 2: Ask domain and trusted domains, no builtin and wkn
+ * Level 3: Only ask domain
+ * Level 4: W2k3ad: Only ask AD trusts
+ * Level 5: Only ask transitive forest trusts
+ * Level 6: Like 4
+ */
+
+ typedef enum {
+ LSA_LOOKUP_NAMES_ALL = 1,
+ LSA_LOOKUP_NAMES_DOMAINS_ONLY = 2,
+ LSA_LOOKUP_NAMES_PRIMARY_DOMAIN_ONLY = 3,
+ LSA_LOOKUP_NAMES_UPLEVEL_TRUSTS_ONLY = 4,
+ LSA_LOOKUP_NAMES_FOREST_TRUSTS_ONLY = 5,
+ LSA_LOOKUP_NAMES_UPLEVEL_TRUSTS_ONLY2 = 6
+ } lsa_LookupNamesLevel;
+
+ [public] NTSTATUS lsa_LookupNames (
[in] policy_handle *handle,
[in,range(0,1000)] uint32 num_names,
[in,size_is(num_names)] lsa_String names[],
[out,unique] lsa_RefDomainList *domains,
[in,out] lsa_TransSidArray *sids,
- [in] uint16 level,
+ [in] lsa_LookupNamesLevel level,
[in,out] uint32 *count
);
@@ -368,7 +405,7 @@ import "security.idl";
[size_is(count)] lsa_TranslatedName *names;
} lsa_TransNameArray;
- NTSTATUS lsa_LookupSids (
+ [public] NTSTATUS lsa_LookupSids (
[in] policy_handle *handle,
[in] lsa_SidArray *sids,
[out,unique] lsa_RefDomainList *domains,
@@ -379,7 +416,7 @@ import "security.idl";
/* Function: 0x10 */
- NTSTATUS lsa_CreateSecret(
+ [public] NTSTATUS lsa_CreateSecret(
[in] policy_handle *handle,
[in] lsa_String name,
[in] uint32 access_mask,
@@ -559,7 +596,7 @@ import "security.idl";
NTSTATUS lsa_SetInformationTrustedDomain();
/* Function: 0x1c */
- NTSTATUS lsa_OpenSecret(
+ [public] NTSTATUS lsa_OpenSecret(
[in] policy_handle *handle,
[in] lsa_String name,
[in] uint32 access_mask,
@@ -568,7 +605,7 @@ import "security.idl";
/* Function: 0x1d */
- NTSTATUS lsa_SetSecret(
+ [public] NTSTATUS lsa_SetSecret(
[in] policy_handle *sec_handle,
[in,unique] lsa_DATA_BUF *new_val,
[in,unique] lsa_DATA_BUF *old_val
@@ -579,7 +616,7 @@ import "security.idl";
} lsa_DATA_BUF_PTR;
/* Function: 0x1e */
- NTSTATUS lsa_QuerySecret (
+ [public] NTSTATUS lsa_QuerySecret (
[in] policy_handle *sec_handle,
[in,out,unique] lsa_DATA_BUF_PTR *new_val,
[in,out,unique] NTTIME_hyper *new_mtime,
@@ -685,7 +722,7 @@ import "security.idl";
/**********************/
/* Function: 0x2c */
- NTSTATUS lsa_OpenPolicy2 (
+ [public] NTSTATUS lsa_OpenPolicy2 (
[in,unique] [string,charset(UTF16)] uint16 *system_name,
[in] lsa_ObjectAttribute *attr,
[in] uint32 access_mask,
@@ -832,7 +869,7 @@ import "security.idl";
[size_is(count)] lsa_TranslatedName2 *names;
} lsa_TransNameArray2;
- NTSTATUS lsa_LookupSids2(
+ [public] NTSTATUS lsa_LookupSids2(
[in] policy_handle *handle,
[in] lsa_SidArray *sids,
[out,unique] lsa_RefDomainList *domains,
@@ -858,13 +895,13 @@ import "security.idl";
[size_is(count)] lsa_TranslatedSid2 *sids;
} lsa_TransSidArray2;
- NTSTATUS lsa_LookupNames2 (
+ [public] NTSTATUS lsa_LookupNames2 (
[in] policy_handle *handle,
[in,range(0,1000)] uint32 num_names,
[in,size_is(num_names)] lsa_String names[],
[out,unique] lsa_RefDomainList *domains,
[in,out] lsa_TransSidArray2 *sids,
- [in] uint16 level,
+ [in] lsa_LookupNamesLevel level,
[in,out] uint32 *count,
[in] uint32 unknown1,
[in] uint32 unknown2
@@ -911,13 +948,13 @@ import "security.idl";
[size_is(count)] lsa_TranslatedSid3 *sids;
} lsa_TransSidArray3;
- NTSTATUS lsa_LookupNames3 (
+ [public] NTSTATUS lsa_LookupNames3 (
[in] policy_handle *handle,
[in,range(0,1000)] uint32 num_names,
[in,size_is(num_names)] lsa_String names[],
[out,unique] lsa_RefDomainList *domains,
[in,out] lsa_TransSidArray3 *sids,
- [in] uint16 level,
+ [in] lsa_LookupNamesLevel level,
[in,out] uint32 *count,
[in] uint32 unknown1,
[in] uint32 unknown2
@@ -936,7 +973,49 @@ import "security.idl";
NTSTATUS lsa_LSARUNREGISTERAUDITEVENT();
/* Function 0x49 */
- NTSTATUS lsa_LSARQUERYFORESTTRUSTINFORMATION();
+ typedef struct {
+ [range(0,131072)] uint32 length;
+ [size_is(length)] uint8 *data;
+ } lsa_ForestTrustBinaryData;
+
+ typedef struct {
+ dom_sid2 *domain_sid;
+ lsa_StringLarge dns_domain_name;
+ lsa_StringLarge netbios_domain_name;
+ } lsa_ForestTrustDomainInfo;
+
+ typedef [switch_type(uint32)] union {
+ [case(LSA_FOREST_TRUST_TOP_LEVEL_NAME)] lsa_String top_level_name;
+ [case(LSA_FOREST_TRUST_TOP_LEVEL_NAME_EX)] lsa_StringLarge top_level_name_ex;
+ [case(LSA_FOREST_TRUST_DOMAIN_INFO)] lsa_ForestTrustDomainInfo domain_info;
+ [default] lsa_ForestTrustBinaryData data;
+ } lsa_ForestTrustData;
+
+ typedef [v1_enum] enum {
+ LSA_FOREST_TRUST_TOP_LEVEL_NAME = 0,
+ LSA_FOREST_TRUST_TOP_LEVEL_NAME_EX = 1,
+ LSA_FOREST_TRUST_DOMAIN_INFO = 2,
+ LSA_FOREST_TRUST_RECORD_TYPE_LAST = 3
+ } lsa_ForestTrustRecordType;
+
+ typedef struct {
+ uint32 flags;
+ lsa_ForestTrustRecordType level;
+ hyper unknown;
+ [switch_is(level)] lsa_ForestTrustData forest_trust_data;
+ } lsa_ForestTrustRecord;
+
+ typedef [public] struct {
+ [range(0,4000)] uint32 count;
+ [size_is(count)] lsa_ForestTrustRecord **entries;
+ } lsa_ForestTrustInformation;
+
+ NTSTATUS lsa_lsaRQueryForestTrustInformation(
+ [in] policy_handle *handle,
+ [in,ref] lsa_String *trusted_domain_name,
+ [in] uint16 unknown, /* level ? */
+ [out,ref] lsa_ForestTrustInformation **forest_trust_info
+ );
/* Function 0x4a */
NTSTATUS lsa_LSARSETFORESTTRUSTINFORMATION();
@@ -947,7 +1026,7 @@ import "security.idl";
/*****************/
/* Function 0x4c */
- NTSTATUS lsa_LookupSids3(
+ [public] NTSTATUS lsa_LookupSids3(
[in] lsa_SidArray *sids,
[out,unique] lsa_RefDomainList *domains,
[in,out] lsa_TransNameArray2 *names,
@@ -963,7 +1042,7 @@ import "security.idl";
[in,size_is(num_names)] lsa_String names[],
[out,unique] lsa_RefDomainList *domains,
[in,out] lsa_TransSidArray3 *sids,
- [in] uint16 level,
+ [in] lsa_LookupNamesLevel level,
[in,out] uint32 *count,
[in] uint32 unknown1,
[in] uint32 unknown2
diff --git a/source3/libsmb/namequery.c b/source3/libsmb/namequery.c
index ad999b34b4..ad16452e3e 100644
--- a/source3/libsmb/namequery.c
+++ b/source3/libsmb/namequery.c
@@ -1299,11 +1299,11 @@ static NTSTATUS resolve_hosts(const char *name, int name_type,
Resolve via "ADS" method.
*********************************************************/
-NTSTATUS resolve_ads(const char *name,
- int name_type,
- const char *sitename,
- struct ip_service **return_iplist,
- int *return_count)
+static NTSTATUS resolve_ads(const char *name,
+ int name_type,
+ const char *sitename,
+ struct ip_service **return_iplist,
+ int *return_count)
{
int i, j;
NTSTATUS status;
diff --git a/source3/locking/brlock.c b/source3/locking/brlock.c
index eb42d081fe..4191871bb1 100644
--- a/source3/locking/brlock.c
+++ b/source3/locking/brlock.c
@@ -41,11 +41,11 @@ static struct db_context *brlock_db;
static void print_lock_struct(unsigned int i, struct lock_struct *pls)
{
- DEBUG(10,("[%u]: smbpid = %u, tid = %u, pid = %s, ",
+ DEBUG(10,("[%u]: smbpid = %u, tid = %u, pid = %u, ",
i,
(unsigned int)pls->context.smbpid,
(unsigned int)pls->context.tid,
- procid_str_static(&pls->context.pid) ));
+ (unsigned int)procid_to_pid(&pls->context.pid) ));
DEBUG(10,("start = %.0f, size = %.0f, fnum = %d, %s %s\n",
(double)pls->start,
@@ -263,10 +263,9 @@ void brl_init(bool read_only)
if (brlock_db) {
return;
}
- brlock_db = db_open(NULL, lock_path("brlock.tdb"), 0,
- TDB_DEFAULT
- |TDB_VOLATILE
- |(read_only?0x0:TDB_CLEAR_IF_FIRST),
+ brlock_db = db_open(NULL, lock_path("brlock.tdb"),
+ lp_open_files_db_hash_size(),
+ TDB_DEFAULT | TDB_CLEAR_IF_FIRST,
read_only?O_RDONLY:(O_RDWR|O_CREAT), 0644 );
if (!brlock_db) {
DEBUG(0,("Failed to open byte range locking database %s\n",
@@ -1495,14 +1494,16 @@ static int traverse_fn(struct db_record *rec, void *state)
}
}
- for ( i=0; i<num_locks; i++) {
- cb->fn(*key,
- locks[i].context.pid,
- locks[i].lock_type,
- locks[i].lock_flav,
- locks[i].start,
- locks[i].size,
- cb->private_data);
+ if (cb->fn) {
+ for ( i=0; i<num_locks; i++) {
+ cb->fn(*key,
+ locks[i].context.pid,
+ locks[i].lock_type,
+ locks[i].lock_flav,
+ locks[i].start,
+ locks[i].size,
+ cb->private_data);
+ }
}
SAFE_FREE(locks);
diff --git a/source3/modules/gpfs.c b/source3/modules/gpfs.c
index 300e90fa69..590dbac26f 100644
--- a/source3/modules/gpfs.c
+++ b/source3/modules/gpfs.c
@@ -22,9 +22,11 @@
#ifdef HAVE_GPFS
#include "gpfs_gpl.h"
+#include "vfs_gpfs.h"
static void *libgpfs_handle = NULL;
static bool gpfs_share_modes;
+static bool gpfs_leases;
static int (*gpfs_set_share_fn)(int fd, unsigned int allow, unsigned int deny);
static int (*gpfs_set_lease_fn)(int fd, unsigned int leaseType);
@@ -42,7 +44,7 @@ bool set_gpfs_sharemode(files_struct *fsp, uint32 access_mask,
if (!gpfs_share_modes) {
return True;
}
-
+
if (gpfs_set_share_fn == NULL) {
return False;
}
@@ -88,7 +90,7 @@ int set_gpfs_lease(int fd, int leasetype)
{
int gpfs_type = GPFS_LEASE_NONE;
- if (!gpfs_share_modes) {
+ if (!gpfs_leases) {
return True;
}
@@ -103,6 +105,13 @@ int set_gpfs_lease(int fd, int leasetype)
if (leasetype == F_WRLCK) {
gpfs_type = GPFS_LEASE_WRITE;
}
+
+ /* we unconditionally set CAP_LEASE, rather than looking for
+ -1/EACCES as there is a bug in some versions of
+ libgpfs_gpl.so which results in a leaked fd on /dev/ss0
+ each time we try this with the wrong capabilities set
+ */
+ linux_set_lease_capability();
return gpfs_set_lease_fn(fd, gpfs_type);
}
@@ -172,11 +181,8 @@ void init_gpfs(void)
goto failed;
}
- if (lp_parm_bool(-1, "gpfs", "sharemodes", True)) {
- gpfs_share_modes = True;
- } else {
- gpfs_share_modes = False;
- }
+ gpfs_share_modes = lp_parm_bool(-1, "gpfs", "sharemodes", True);
+ gpfs_leases = lp_parm_bool(-1, "gpfs", "leases", True);
return;
diff --git a/source3/modules/nfs4_acls.c b/source3/modules/nfs4_acls.c
index 52d3983fff..0c3d010dcd 100644
--- a/source3/modules/nfs4_acls.c
+++ b/source3/modules/nfs4_acls.c
@@ -20,6 +20,9 @@
#include "includes.h"
#include "nfs4_acls.h"
+#undef DBGC_CLASS
+#define DBGC_CLASS DBGC_ACLS
+
#define SMBACL4_PARAM_TYPE_NAME "nfs4"
#define SMB_ACE4_INT_MAGIC 0x76F8A967
@@ -352,6 +355,7 @@ typedef struct _smbacl4_vfs_params {
enum smbacl4_mode_enum mode;
bool do_chown;
enum smbacl4_acedup_enum acedup;
+ struct db_context *sid_mapping_table;
} smbacl4_vfs_params;
/*
@@ -451,8 +455,65 @@ static SMB_ACE4PROP_T *smbacl4_find_equal_special(
return NULL;
}
-static int smbacl4_fill_ace4(
+static bool nfs4_map_sid(smbacl4_vfs_params *params, const DOM_SID *src,
+ DOM_SID *dst)
+{
+ static struct db_context *mapping_db = NULL;
+ TDB_DATA data;
+
+ if (mapping_db == NULL) {
+ const char *dbname = lp_parm_const_string(
+ -1, SMBACL4_PARAM_TYPE_NAME, "sidmap", NULL);
+
+ if (dbname == NULL) {
+ DEBUG(10, ("%s:sidmap not defined\n",
+ SMBACL4_PARAM_TYPE_NAME));
+ return False;
+ }
+
+ become_root();
+ mapping_db = db_open(NULL, dbname, 0, TDB_DEFAULT,
+ O_RDONLY, 0600);
+ unbecome_root();
+
+ if (mapping_db == NULL) {
+ DEBUG(1, ("could not open sidmap: %s\n",
+ strerror(errno)));
+ return False;
+ }
+ }
+
+ if (mapping_db->fetch(mapping_db, NULL,
+ string_term_tdb_data(sid_string_tos(src)),
+ &data) == -1) {
+ DEBUG(10, ("could not find mapping for SID %s\n",
+ sid_string_dbg(src)));
+ return False;
+ }
+
+ if ((data.dptr == NULL) || (data.dsize <= 0)
+ || (data.dptr[data.dsize-1] != '\0')) {
+ DEBUG(5, ("invalid mapping for SID %s\n",
+ sid_string_dbg(src)));
+ TALLOC_FREE(data.dptr);
+ return False;
+ }
+
+ if (!string_to_sid(dst, (char *)data.dptr)) {
+ DEBUG(1, ("invalid mapping %s for SID %s\n",
+ (char *)data.dptr, sid_string_dbg(src)));
+ TALLOC_FREE(data.dptr);
+ return False;
+ }
+
+ TALLOC_FREE(data.dptr);
+
+ return True;
+}
+
+static bool smbacl4_fill_ace4(
TALLOC_CTX *mem_ctx,
+ const char *filename,
smbacl4_vfs_params *params,
uid_t ownerUID,
gid_t ownerGID,
@@ -460,11 +521,6 @@ static int smbacl4_fill_ace4(
SMB_ACE4PROP_T *ace_v4 /* output */
)
{
- const char *dom, *name;
- enum lsa_SidType type;
- uid_t uid;
- gid_t gid;
-
DEBUG(10, ("got ace for %s\n", sid_string_dbg(&ace_nt->trustee)));
memset(ace_v4, 0, sizeof(SMB_ACE4PROP_T));
@@ -485,18 +541,46 @@ static int smbacl4_fill_ace4(
ace_v4->who.special_id = SMB_ACE4_WHO_EVERYONE;
ace_v4->flags |= SMB_ACE4_ID_SPECIAL;
} else {
- if (!lookup_sid(mem_ctx, &ace_nt->trustee, &dom, &name, &type)) {
- DEBUG(8, ("Could not find %s' type\n",
- sid_string_dbg(&ace_nt->trustee)));
- errno = EINVAL;
- return -1;
+ const char *dom, *name;
+ enum lsa_SidType type;
+ uid_t uid;
+ gid_t gid;
+ DOM_SID sid;
+
+ sid_copy(&sid, &ace_nt->trustee);
+
+ if (!lookup_sid(mem_ctx, &sid, &dom, &name, &type)) {
+
+ DOM_SID mapped;
+
+ if (!nfs4_map_sid(params, &sid, &mapped)) {
+ DEBUG(1, ("nfs4_acls.c: file [%s]: SID %s "
+ "unknown\n", filename, sid_string_dbg(&sid)));
+ errno = EINVAL;
+ return False;
+ }
+
+ DEBUG(2, ("nfs4_acls.c: file [%s]: mapped SID %s "
+ "to %s\n", filename, sid_string_dbg(&sid), sid_string_dbg(&mapped)));
+
+ if (!lookup_sid(mem_ctx, &mapped, &dom,
+ &name, &type)) {
+ DEBUG(1, ("nfs4_acls.c: file [%s]: SID %s "
+ "mapped from %s is unknown\n",
+ filename, sid_string_dbg(&mapped), sid_string_dbg(&sid)));
+ errno = EINVAL;
+ return False;
+ }
+
+ sid_copy(&sid, &mapped);
}
-
+
if (type == SID_NAME_USER) {
- if (!sid_to_uid(&ace_nt->trustee, &uid)) {
- DEBUG(2, ("Could not convert %s to uid\n",
- sid_string_dbg(&ace_nt->trustee)));
- return -1;
+ if (!sid_to_uid(&sid, &uid)) {
+ DEBUG(1, ("nfs4_acls.c: file [%s]: could not "
+ "convert %s to uid\n", filename,
+ sid_string_dbg(&sid)));
+ return False;
}
if (params->mode==e_special && uid==ownerUID) {
@@ -506,11 +590,13 @@ static int smbacl4_fill_ace4(
ace_v4->who.uid = uid;
}
} else { /* else group? - TODO check it... */
- if (!sid_to_gid(&ace_nt->trustee, &gid)) {
- DEBUG(2, ("Could not convert %s to gid\n",
- sid_string_dbg(&ace_nt->trustee)));
- return -1;
+ if (!sid_to_gid(&sid, &gid)) {
+ DEBUG(1, ("nfs4_acls.c: file [%s]: could not "
+ "convert %s to gid\n", filename,
+ sid_string_dbg(&sid)));
+ return False;
}
+
ace_v4->aceFlags |= SMB_ACE4_IDENTIFIER_GROUP;
if (params->mode==e_special && gid==ownerGID) {
@@ -522,7 +608,7 @@ static int smbacl4_fill_ace4(
}
}
- return 0; /* OK */
+ return True; /* OK */
}
static int smbacl4_MergeIgnoreReject(
@@ -560,6 +646,7 @@ static int smbacl4_MergeIgnoreReject(
}
static SMB4ACL_T *smbacl4_win2nfs4(
+ const char *filename,
SEC_ACL *dacl,
smbacl4_vfs_params *pparams,
uid_t ownerUID,
@@ -580,9 +667,14 @@ static SMB4ACL_T *smbacl4_win2nfs4(
SMB_ACE4PROP_T ace_v4;
bool addNewACE = True;
- if (smbacl4_fill_ace4(mem_ctx, pparams, ownerUID, ownerGID,
- dacl->aces + i, &ace_v4))
- return NULL;
+ if (!smbacl4_fill_ace4(mem_ctx, filename, pparams,
+ ownerUID, ownerGID,
+ dacl->aces + i, &ace_v4)) {
+ DEBUG(3, ("Could not fill ace for file %s, SID %s\n",
+ filename,
+ sid_string_dbg(&((dacl->aces+i)->trustee))));
+ continue;
+ }
if (pparams->acedup!=e_dontcare) {
if (smbacl4_MergeIgnoreReject(pparams->acedup, acl,
@@ -607,6 +699,7 @@ NTSTATUS smb_set_nt_acl_nfs4(files_struct *fsp,
bool result;
SMB_STRUCT_STAT sbuf;
+ bool need_chown = False;
uid_t newUID = (uid_t)-1;
gid_t newGID = (gid_t)-1;
@@ -635,25 +728,33 @@ NTSTATUS smb_set_nt_acl_nfs4(files_struct *fsp,
return status;
}
if (((newUID != (uid_t)-1) && (sbuf.st_uid != newUID)) ||
- ((newGID != (gid_t)-1) && (sbuf.st_gid != newGID))) {
- if(try_chown(fsp->conn, fsp->fsp_name, newUID, newGID)) {
- DEBUG(3,("chown %s, %u, %u failed. Error = %s.\n",
- fsp->fsp_name, (unsigned int)newUID, (unsigned int)newGID, strerror(errno) ));
- if (errno == EPERM) {
- return NT_STATUS_INVALID_OWNER;
+ ((newGID != (gid_t)-1) && (sbuf.st_gid != newGID))) {
+ need_chown = True;
+ }
+ if (need_chown) {
+ if ((newUID == (uid_t)-1 || newUID == current_user.ut.uid)) {
+ if(try_chown(fsp->conn, fsp->fsp_name, newUID, newGID)) {
+ DEBUG(3,("chown %s, %u, %u failed. Error = %s.\n",
+ fsp->fsp_name, (unsigned int)newUID, (unsigned int)newGID,
+ strerror(errno)));
+ return map_nt_error_from_unix(errno);
}
- return map_nt_error_from_unix(errno);
+
+ DEBUG(10,("chown %s, %u, %u succeeded.\n",
+ fsp->fsp_name, (unsigned int)newUID, (unsigned int)newGID));
+ if (smbacl4_GetFileOwner(fsp->conn, fsp->fsp_name, &sbuf))
+ return map_nt_error_from_unix(errno);
+ need_chown = False;
+ } else { /* chown is needed, but _after_ changing acl */
+ sbuf.st_uid = newUID; /* OWNER@ in case of e_special */
+ sbuf.st_gid = newGID; /* GROUP@ in case of e_special */
}
- DEBUG(10,("chown %s, %u, %u succeeded.\n",
- fsp->fsp_name, (unsigned int)newUID, (unsigned int)newGID));
- if (smbacl4_fGetFileOwner(fsp, &sbuf))
- return map_nt_error_from_unix(errno);
}
}
if ((security_info_sent & DACL_SECURITY_INFORMATION)!=0 && psd->dacl!=NULL)
{
- acl = smbacl4_win2nfs4(psd->dacl, &params, sbuf.st_uid, sbuf.st_gid);
+ acl = smbacl4_win2nfs4(fsp->fsp_name, psd->dacl, &params, sbuf.st_uid, sbuf.st_gid);
if (!acl)
return map_nt_error_from_unix(errno);
@@ -668,6 +769,20 @@ NTSTATUS smb_set_nt_acl_nfs4(files_struct *fsp,
} else
DEBUG(10, ("no dacl found; security_info_sent = 0x%x\n", security_info_sent));
+ /* Any chown pending? */
+ if (need_chown) {
+ DEBUG(3,("chown#2 %s. uid = %u, gid = %u.\n",
+ fsp->fsp_name, (unsigned int)newUID, (unsigned int)newGID));
+ if (try_chown(fsp->conn, fsp->fsp_name, newUID, newGID)) {
+ DEBUG(2,("chown#2 %s, %u, %u failed. Error = %s.\n",
+ fsp->fsp_name, (unsigned int)newUID, (unsigned int)newGID,
+ strerror(errno)));
+ return map_nt_error_from_unix(errno);
+ }
+ DEBUG(10,("chown#2 %s, %u, %u succeeded.\n",
+ fsp->fsp_name, (unsigned int)newUID, (unsigned int)newGID));
+ }
+
DEBUG(10, ("smb_set_nt_acl_nfs4 succeeded\n"));
return NT_STATUS_OK;
}
diff --git a/source3/modules/vfs_default.c b/source3/modules/vfs_default.c
index e21136ccee..3e78c69a5e 100644
--- a/source3/modules/vfs_default.c
+++ b/source3/modules/vfs_default.c
@@ -1225,6 +1225,38 @@ static int vfswrap_aio_suspend(struct vfs_handle_struct *handle, struct files_st
return sys_aio_suspend(aiocb, n, timeout);
}
+static int vfswrap_aio_force(struct vfs_handle_struct *handle, struct files_struct *fsp)
+{
+ return False;
+}
+
+static int vfswrap_is_offline(struct vfs_handle_struct *handle, struct connection_struct *conn, const char *path, SMB_STRUCT_STAT *sbuf, bool *offline)
+{
+ if (ISDOT(path) || ISDOTDOT(path)) {
+ return 1;
+ }
+
+ if (!lp_dmapi_support(SNUM(conn)) || !dmapi_have_session()) {
+ return -1;
+ }
+
+ *offline = (dmapi_file_flags(path) & FILE_ATTRIBUTE_OFFLINE) != 0;
+ return 0;
+}
+
+static int vfswrap_set_offline(struct vfs_handle_struct *handle, struct connection_struct *conn, const char *path)
+{
+ /* We don't know how to set offline bit by default, needs to be overriden in the vfs modules */
+ return -1;
+}
+
+static bool vfswrap_is_remotestorage(struct vfs_handle_struct *handle, struct connection_struct *conn, const char *path)
+{
+ /* We don't know how to detect that volume is remote storage. VFS modules should redefine it. */
+ return False;
+}
+
+
static vfs_op_tuple vfs_default_ops[] = {
/* Disk operations */
@@ -1442,6 +1474,16 @@ static vfs_op_tuple vfs_default_ops[] = {
{SMB_VFS_OP(vfswrap_aio_suspend),SMB_VFS_OP_AIO_SUSPEND,
SMB_VFS_LAYER_OPAQUE},
+ {SMB_VFS_OP(vfswrap_aio_force), SMB_VFS_OP_AIO_FORCE,
+ SMB_VFS_LAYER_OPAQUE},
+
+ {SMB_VFS_OP(vfswrap_is_offline),SMB_VFS_OP_IS_OFFLINE,
+ SMB_VFS_LAYER_OPAQUE},
+ {SMB_VFS_OP(vfswrap_set_offline),SMB_VFS_OP_SET_OFFLINE,
+ SMB_VFS_LAYER_OPAQUE},
+ {SMB_VFS_OP(vfswrap_is_remotestorage),SMB_VFS_OP_IS_REMOTESTORAGE,
+ SMB_VFS_LAYER_OPAQUE},
+
/* Finish VFS operations definition */
{SMB_VFS_OP(NULL), SMB_VFS_OP_NOOP,
diff --git a/source3/modules/vfs_gpfs.c b/source3/modules/vfs_gpfs.c
index bcf61f3bc7..d10906dfb1 100644
--- a/source3/modules/vfs_gpfs.c
+++ b/source3/modules/vfs_gpfs.c
@@ -30,7 +30,7 @@
#include <gpfs_gpl.h>
#include "nfs4_acls.h"
-
+#include "vfs_gpfs.h"
static int vfs_gpfs_kernel_flock(vfs_handle_struct *handle, files_struct *fsp,
uint32 share_mode)
@@ -153,7 +153,7 @@ static int gpfs_get_nfs4_acl(const char *fname, SMB4ACL_T **ppacl)
DEBUG(10, ("gpfs_get_nfs4_acl invoked for %s\n", fname));
/* First get the real acl length */
- gacl = gpfs_getacl_alloc(fname, GPFS_ACL_TYPE_NFS4);
+ gacl = gpfs_getacl_alloc(fname, 0);
if (gacl == NULL) {
DEBUG(9, ("gpfs_getacl failed for %s with %s\n",
fname, strerror(errno)));
@@ -208,10 +208,10 @@ static int gpfs_get_nfs4_acl(const char *fname, SMB4ACL_T **ppacl)
if (i > 0 && gace->aceType == SMB_ACE4_ACCESS_DENIED_ACE_TYPE) {
struct gpfs_ace_v4 *prev = &gacl->ace_v4[i-1];
if (prev->aceType == SMB_ACE4_ACCESS_ALLOWED_ACE_TYPE &&
- prev->aceFlags == gace->aceFlags &&
- prev->aceIFlags == gace->aceIFlags &&
- (gace->aceMask & prev->aceMask) == 0 &&
- gace->aceWho == prev->aceWho) {
+ prev->aceFlags == gace->aceFlags &&
+ prev->aceIFlags == gace->aceIFlags &&
+ (gace->aceMask & prev->aceMask) == 0 &&
+ gace->aceWho == prev->aceWho) {
/* its redundent - skip it */
continue;
}
@@ -256,7 +256,7 @@ static NTSTATUS gpfsacl_get_nt_acl(vfs_handle_struct *handle,
int result;
*ppdesc = NULL;
- result = gpfs_get_nfs4_acl(fsp->fsp_name, &pacl);
+ result = gpfs_get_nfs4_acl(name, &pacl);
if (result == 0)
return smb_get_nt_acl_nfs4(handle->conn, name, security_info, ppdesc, pacl);
@@ -301,8 +301,31 @@ static bool gpfsacl_process_smbacl(files_struct *fsp, SMB4ACL_T *smbacl)
gace->aceType = aceprop->aceType;
gace->aceFlags = aceprop->aceFlags;
gace->aceMask = aceprop->aceMask;
+
+ /*
+ * GPFS can't distinguish between WRITE and APPEND on
+ * files, so one being set without the other is an
+ * error. Sorry for the many ()'s :-)
+ */
+
+ if (!fsp->is_directory
+ &&
+ ((((gace->aceMask & ACE4_MASK_WRITE) == 0)
+ && ((gace->aceMask & ACE4_MASK_APPEND) != 0))
+ ||
+ (((gace->aceMask & ACE4_MASK_WRITE) != 0)
+ && ((gace->aceMask & ACE4_MASK_APPEND) == 0)))
+ &&
+ lp_parm_bool(fsp->conn->params->service, "gpfs",
+ "merge_writeappend", True)) {
+ DEBUG(2, ("vfs_gpfs.c: file [%s]: ACE contains "
+ "WRITE^APPEND, setting WRITE|APPEND\n",
+ fsp->fsp_name));
+ gace->aceMask |= ACE4_MASK_WRITE|ACE4_MASK_APPEND;
+ }
+
gace->aceIFlags = (aceprop->flags&SMB_ACE4_ID_SPECIAL) ? ACE4_IFLAG_SPECIAL_ID : 0;
-
+
if (aceprop->flags&SMB_ACE4_ID_SPECIAL)
{
switch(aceprop->who.special_id)
@@ -347,7 +370,7 @@ static NTSTATUS gpfsacl_set_nt_acl_internal(files_struct *fsp, uint32 security_i
struct gpfs_acl *acl;
NTSTATUS result = NT_STATUS_ACCESS_DENIED;
- acl = gpfs_getacl_alloc(fsp->fsp_name, GPFS_ACL_TYPE_ACCESS);
+ acl = gpfs_getacl_alloc(fsp->fsp_name, 0);
if (acl == NULL)
return result;
@@ -628,75 +651,225 @@ int gpfsacl_sys_acl_delete_def_file(vfs_handle_struct *handle,
return -1;
}
+/*
+ * Assumed: mode bits are shiftable and standard
+ * Output: the new aceMask field for an smb nfs4 ace
+ */
+static uint32 gpfsacl_mask_filter(uint32 aceType, uint32 aceMask, uint32 rwx)
+{
+ const uint32 posix_nfs4map[3] = {
+ SMB_ACE4_EXECUTE, /* execute */
+ SMB_ACE4_WRITE_DATA | SMB_ACE4_APPEND_DATA, /* write; GPFS specific */
+ SMB_ACE4_READ_DATA /* read */
+ };
+ int i;
+ uint32_t posix_mask = 0x01;
+ uint32_t posix_bit;
+ uint32_t nfs4_bits;
+
+ for(i=0; i<3; i++) {
+ nfs4_bits = posix_nfs4map[i];
+ posix_bit = rwx & posix_mask;
+
+ if (aceType==SMB_ACE4_ACCESS_ALLOWED_ACE_TYPE) {
+ if (posix_bit)
+ aceMask |= nfs4_bits;
+ else
+ aceMask &= ~nfs4_bits;
+ } else {
+ /* add deny bits when suitable */
+ if (!posix_bit)
+ aceMask |= nfs4_bits;
+ else
+ aceMask &= ~nfs4_bits;
+ } /* other ace types are unexpected */
+
+ posix_mask <<= 1;
+ }
+
+ return aceMask;
+}
+
+static int gpfsacl_emu_chmod(const char *path, mode_t mode)
+{
+ SMB4ACL_T *pacl = NULL;
+ int result;
+ bool haveAllowEntry[SMB_ACE4_WHO_EVERYONE + 1] = {False, False, False, False};
+ int i;
+ files_struct fake_fsp; /* TODO: rationalize parametrization */
+ SMB4ACE_T *smbace;
+
+ DEBUG(10, ("gpfsacl_emu_chmod invoked for %s mode %o\n", path, mode));
+
+ result = gpfs_get_nfs4_acl(path, &pacl);
+ if (result)
+ return result;
+
+ if (mode & ~(S_IRWXU | S_IRWXG | S_IRWXO)) {
+ DEBUG(2, ("WARNING: cutting extra mode bits %o on %s\n", mode, path));
+ }
+
+ for (smbace=smb_first_ace4(pacl); smbace!=NULL; smbace = smb_next_ace4(smbace)) {
+ SMB_ACE4PROP_T *ace = smb_get_ace4(smbace);
+ uint32_t specid = ace->who.special_id;
+
+ if (ace->flags&SMB_ACE4_ID_SPECIAL &&
+ ace->aceType<=SMB_ACE4_ACCESS_DENIED_ACE_TYPE &&
+ specid <= SMB_ACE4_WHO_EVERYONE) {
+
+ uint32_t newMask;
+
+ if (ace->aceType==SMB_ACE4_ACCESS_ALLOWED_ACE_TYPE)
+ haveAllowEntry[specid] = True;
+
+ /* mode >> 6 for @owner, mode >> 3 for @group,
+ * mode >> 0 for @everyone */
+ newMask = gpfsacl_mask_filter(ace->aceType, ace->aceMask,
+ mode >> ((SMB_ACE4_WHO_EVERYONE - specid) * 3));
+ if (ace->aceMask!=newMask) {
+ DEBUG(10, ("ace changed for %s (%o -> %o) id=%d\n",
+ path, ace->aceMask, newMask, specid));
+ }
+ ace->aceMask = newMask;
+ }
+ }
+
+ /* make sure we have at least ALLOW entries
+ * for all the 3 special ids (@EVERYONE, @OWNER, @GROUP)
+ * - if necessary
+ */
+ for(i = SMB_ACE4_WHO_OWNER; i<=SMB_ACE4_WHO_EVERYONE; i++) {
+ SMB_ACE4PROP_T ace;
+
+ if (haveAllowEntry[i]==True)
+ continue;
+
+ memset(&ace, 0, sizeof(SMB_ACE4PROP_T));
+ ace.aceType = SMB_ACE4_ACCESS_ALLOWED_ACE_TYPE;
+ ace.flags |= SMB_ACE4_ID_SPECIAL;
+ ace.who.special_id = i;
+
+ if (i==SMB_ACE4_WHO_GROUP) /* not sure it's necessary... */
+ ace.aceFlags |= SMB_ACE4_IDENTIFIER_GROUP;
+
+ ace.aceMask = gpfsacl_mask_filter(ace.aceType, ace.aceMask,
+ mode >> ((SMB_ACE4_WHO_EVERYONE - i) * 3));
+
+ /* don't add unnecessary aces */
+ if (!ace.aceMask)
+ continue;
+
+ /* we add it to the END - as windows expects allow aces */
+ smb_add_ace4(pacl, &ace);
+ DEBUG(10, ("Added ALLOW ace for %s, mode=%o, id=%d, aceMask=%x\n",
+ path, mode, i, ace.aceMask));
+ }
+
+ /* don't add complementary DENY ACEs here */
+ memset(&fake_fsp, 0, sizeof(struct files_struct));
+ fake_fsp.fsp_name = (char *)path; /* no file_new is needed here */
+
+ /* put the acl */
+ if (gpfsacl_process_smbacl(&fake_fsp, pacl) == False)
+ return -1;
+ return 0; /* ok for [f]chmod */
+}
+
static int vfs_gpfs_chmod(vfs_handle_struct *handle, const char *path, mode_t mode)
{
SMB_STRUCT_STAT st;
+ int rc;
+
if (SMB_VFS_NEXT_STAT(handle, path, &st) != 0) {
- return -1;
+ return -1;
}
+
/* avoid chmod() if possible, to preserve acls */
if ((st.st_mode & ~S_IFMT) == mode) {
- return 0;
+ return 0;
}
- return SMB_VFS_NEXT_CHMOD(handle, path, mode);
+
+ rc = gpfsacl_emu_chmod(path, mode);
+ if (rc == 1)
+ return SMB_VFS_NEXT_CHMOD(handle, path, mode);
+ return rc;
}
static int vfs_gpfs_fchmod(vfs_handle_struct *handle, files_struct *fsp, mode_t mode)
{
SMB_STRUCT_STAT st;
+ int rc;
+
if (SMB_VFS_NEXT_FSTAT(handle, fsp, &st) != 0) {
- return -1;
+ return -1;
}
+
/* avoid chmod() if possible, to preserve acls */
if ((st.st_mode & ~S_IFMT) == mode) {
- return 0;
+ return 0;
}
- return SMB_VFS_NEXT_FCHMOD(handle, fsp, mode);
+
+ rc = gpfsacl_emu_chmod(fsp->fsp_name, mode);
+ if (rc == 1)
+ return SMB_VFS_NEXT_FCHMOD(handle, fsp, mode);
+ return rc;
}
/* VFS operations structure */
static vfs_op_tuple gpfs_op_tuples[] = {
-
- { SMB_VFS_OP(vfs_gpfs_kernel_flock), SMB_VFS_OP_KERNEL_FLOCK,
- SMB_VFS_LAYER_OPAQUE },
-
- { SMB_VFS_OP(vfs_gpfs_setlease), SMB_VFS_OP_LINUX_SETLEASE,
- SMB_VFS_LAYER_OPAQUE },
-
- { SMB_VFS_OP(gpfsacl_fget_nt_acl), SMB_VFS_OP_FGET_NT_ACL,
- SMB_VFS_LAYER_TRANSPARENT },
-
- { SMB_VFS_OP(gpfsacl_get_nt_acl), SMB_VFS_OP_GET_NT_ACL,
- SMB_VFS_LAYER_TRANSPARENT },
-
- { SMB_VFS_OP(gpfsacl_fset_nt_acl), SMB_VFS_OP_FSET_NT_ACL,
- SMB_VFS_LAYER_TRANSPARENT },
-
- { SMB_VFS_OP(gpfsacl_set_nt_acl), SMB_VFS_OP_SET_NT_ACL,
- SMB_VFS_LAYER_TRANSPARENT },
-
- { SMB_VFS_OP(gpfsacl_sys_acl_get_file), SMB_VFS_OP_SYS_ACL_GET_FILE,
- SMB_VFS_LAYER_TRANSPARENT },
-
- { SMB_VFS_OP(gpfsacl_sys_acl_get_fd), SMB_VFS_OP_SYS_ACL_GET_FD,
- SMB_VFS_LAYER_TRANSPARENT },
-
- { SMB_VFS_OP(gpfsacl_sys_acl_set_file), SMB_VFS_OP_SYS_ACL_SET_FILE,
- SMB_VFS_LAYER_TRANSPARENT },
-
- { SMB_VFS_OP(gpfsacl_sys_acl_set_fd), SMB_VFS_OP_SYS_ACL_SET_FD,
- SMB_VFS_LAYER_TRANSPARENT },
-
+
+ { SMB_VFS_OP(vfs_gpfs_kernel_flock),
+ SMB_VFS_OP_KERNEL_FLOCK,
+ SMB_VFS_LAYER_OPAQUE },
+
+ { SMB_VFS_OP(vfs_gpfs_setlease),
+ SMB_VFS_OP_LINUX_SETLEASE,
+ SMB_VFS_LAYER_OPAQUE },
+
+ { SMB_VFS_OP(gpfsacl_fget_nt_acl),
+ SMB_VFS_OP_FGET_NT_ACL,
+ SMB_VFS_LAYER_TRANSPARENT },
+
+ { SMB_VFS_OP(gpfsacl_get_nt_acl),
+ SMB_VFS_OP_GET_NT_ACL,
+ SMB_VFS_LAYER_TRANSPARENT },
+
+ { SMB_VFS_OP(gpfsacl_fset_nt_acl),
+ SMB_VFS_OP_FSET_NT_ACL,
+ SMB_VFS_LAYER_TRANSPARENT },
+
+ { SMB_VFS_OP(gpfsacl_set_nt_acl),
+ SMB_VFS_OP_SET_NT_ACL,
+ SMB_VFS_LAYER_TRANSPARENT },
+
+ { SMB_VFS_OP(gpfsacl_sys_acl_get_file),
+ SMB_VFS_OP_SYS_ACL_GET_FILE,
+ SMB_VFS_LAYER_TRANSPARENT },
+
+ { SMB_VFS_OP(gpfsacl_sys_acl_get_fd),
+ SMB_VFS_OP_SYS_ACL_GET_FD,
+ SMB_VFS_LAYER_TRANSPARENT },
+
+ { SMB_VFS_OP(gpfsacl_sys_acl_set_file),
+ SMB_VFS_OP_SYS_ACL_SET_FILE,
+ SMB_VFS_LAYER_TRANSPARENT },
+
+ { SMB_VFS_OP(gpfsacl_sys_acl_set_fd),
+ SMB_VFS_OP_SYS_ACL_SET_FD,
+ SMB_VFS_LAYER_TRANSPARENT },
+
{ SMB_VFS_OP(gpfsacl_sys_acl_delete_def_file),
- SMB_VFS_OP_SYS_ACL_DELETE_DEF_FILE,
- SMB_VFS_LAYER_TRANSPARENT },
-
- { SMB_VFS_OP(vfs_gpfs_chmod), SMB_VFS_OP_CHMOD,
- SMB_VFS_LAYER_TRANSPARENT },
-
- { SMB_VFS_OP(vfs_gpfs_fchmod), SMB_VFS_OP_FCHMOD,
- SMB_VFS_LAYER_TRANSPARENT },
+ SMB_VFS_OP_SYS_ACL_DELETE_DEF_FILE,
+ SMB_VFS_LAYER_TRANSPARENT },
+
+ { SMB_VFS_OP(vfs_gpfs_chmod),
+ SMB_VFS_OP_CHMOD,
+ SMB_VFS_LAYER_TRANSPARENT },
+
+ { SMB_VFS_OP(vfs_gpfs_fchmod),
+ SMB_VFS_OP_FCHMOD,
+ SMB_VFS_LAYER_TRANSPARENT },
{ SMB_VFS_OP(NULL), SMB_VFS_OP_NOOP, SMB_VFS_LAYER_NOOP }
diff --git a/source3/modules/vfs_gpfs.h b/source3/modules/vfs_gpfs.h
new file mode 100644
index 0000000000..3c499b0850
--- /dev/null
+++ b/source3/modules/vfs_gpfs.h
@@ -0,0 +1,32 @@
+/*
+ Unix SMB/CIFS implementation.
+ Wrap gpfs calls in vfs functions.
+
+ Copyright (C) Christian Ambach <cambach1@de.ibm.com> 2006
+
+ Major code contributions by Chetan Shringarpure <chetan.sh@in.ibm.com>
+ and Gomati Mohanan <gomati.mohanan@in.ibm.com>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+
+*/
+
+bool set_gpfs_sharemode(files_struct *fsp, uint32 access_mask,
+ uint32 share_access);
+int set_gpfs_lease(int fd, int leasetype);
+int smbd_gpfs_getacl(char *pathname, int flags, void *acl);
+int smbd_gpfs_putacl(char *pathname, int flags, void *acl);
+void init_gpfs(void);
diff --git a/source3/modules/vfs_prealloc.c b/source3/modules/vfs_prealloc.c
index 2d64bc0184..cb3508dc30 100644
--- a/source3/modules/vfs_prealloc.c
+++ b/source3/modules/vfs_prealloc.c
@@ -47,11 +47,16 @@
#define lock_type struct flock64
#endif
+#ifdef HAVE_GPFS
+#include "gpfs_gpl.h"
+#endif
+
#define MODULE "prealloc"
static int module_debug;
static int preallocate_space(int fd, SMB_OFF_T size)
{
+#ifndef HAVE_GPFS
lock_type fl = {0};
int err;
@@ -78,6 +83,9 @@ static int preallocate_space(int fd, SMB_OFF_T size)
err = -1;
errno = ENOSYS;
#endif
+#else /* GPFS uses completely different interface */
+ err = gpfs_prealloc(fd, (gpfs_off64_t)0, (gpfs_off64_t)size);
+#endif
if (err) {
DEBUG(module_debug,
diff --git a/source3/modules/vfs_shadow_copy2.c b/source3/modules/vfs_shadow_copy2.c
new file mode 100644
index 0000000000..54fc672b9c
--- /dev/null
+++ b/source3/modules/vfs_shadow_copy2.c
@@ -0,0 +1,637 @@
+/*
+ * implementation of an Shadow Copy module - version 2
+ *
+ * Copyright (C) Andrew Tridgell 2007
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include "includes.h"
+
+/*
+
+ This is a 2nd implemetation of a shadow copy module for exposing
+ snapshots to windows clients as shadow copies. This version has the
+ following features:
+
+ 1) you don't need to populate your shares with symlinks to the
+ snapshots. This can be very important when you have thousands of
+ shares, or use [homes]
+
+ 2) the inode number of the files is altered so it is different
+ from the original. This allows the 'restore' button to work
+ without a sharing violation
+
+ Module options:
+
+ shadow:snapdir = <directory where snapshots are kept>
+
+ This is the directory containing the @GMT-* snapshot directories. If it is an absolute
+ path it is used as-is. If it is a relative path, then it is taken relative to the mount
+ point of the filesystem that the root of this share is on
+
+ shadow:basedir = <base directory that snapshots are from>
+
+ This is an optional parameter that specifies the directory that
+ the snapshots are relative to. It defaults to the filesystem
+ mount point
+
+ shadow:fixinodes = yes/no
+
+ If you enable shadow:fixinodes then this module will modify the
+ apparent inode number of files in the snapshot directories using
+ a hash of the files path. This is needed for snapshot systems
+ where the snapshots have the same device:inode number as the
+ original files (such as happens with GPFS snapshots). If you
+ don't set this option then the 'restore' button in the shadow
+ copy UI will fail with a sharing violation.
+
+ Note that the directory names in the snapshot directory must take the form
+ @GMT-YYYY.MM.DD-HH.MM.SS
+
+ The following command would generate a correctly formatted directory name:
+ date -u +@GMT-%Y.%m.%d-%H.%M.%S
+
+ */
+
+static int vfs_shadow_copy2_debug_level = DBGC_VFS;
+
+#undef DBGC_CLASS
+#define DBGC_CLASS vfs_shadow_copy2_debug_level
+
+#define GMT_NAME_LEN 24 /* length of a @GMT- name */
+
+/*
+ make very sure it is one of our special names
+ */
+static inline bool shadow_copy2_match_name(const char *name)
+{
+ unsigned year, month, day, hr, min, sec;
+ if (name[0] != '@') return False;
+ if (strncmp(name, "@GMT-", 5) != 0) return False;
+ if (sscanf(name, "@GMT-%04u.%02u.%02u-%02u.%02u.%02u", &year, &month,
+ &day, &hr, &min, &sec) != 6) {
+ return False;
+ }
+ if (name[24] != 0 && name[24] != '/') {
+ return False;
+ }
+ return True;
+}
+
+/*
+ convert a name to the shadow directory
+ */
+
+#define _SHADOW2_NEXT(op, args, rtype, eret, extra) do { \
+ const char *name = fname; \
+ if (shadow_copy2_match_name(fname)) { \
+ char *name2; \
+ rtype ret; \
+ name2 = convert_shadow2_name(handle, fname); \
+ if (name2 == NULL) { \
+ errno = EINVAL; \
+ return eret; \
+ } \
+ name = name2; \
+ ret = SMB_VFS_NEXT_ ## op args; \
+ talloc_free(name2); \
+ if (ret != eret) extra; \
+ return ret; \
+ } else { \
+ return SMB_VFS_NEXT_ ## op args; \
+ } \
+} while (0)
+
+/*
+ convert a name to the shadow directory: NTSTATUS-specific handling
+ */
+
+#define _SHADOW2_NTSTATUS_NEXT(op, args, eret, extra) do { \
+ const char *name = fname; \
+ if (shadow_copy2_match_name(fname)) { \
+ char *name2; \
+ NTSTATUS ret; \
+ name2 = convert_shadow2_name(handle, fname); \
+ if (name2 == NULL) { \
+ errno = EINVAL; \
+ return eret; \
+ } \
+ name = name2; \
+ ret = SMB_VFS_NEXT_ ## op args; \
+ talloc_free(name2); \
+ if (!NT_STATUS_EQUAL(ret, eret)) extra; \
+ return ret; \
+ } else { \
+ return SMB_VFS_NEXT_ ## op args; \
+ } \
+} while (0)
+
+#define SHADOW2_NTSTATUS_NEXT(op, args, eret) _SHADOW2_NTSTATUS_NEXT(op, args, eret, )
+
+#define SHADOW2_NEXT(op, args, rtype, eret) _SHADOW2_NEXT(op, args, rtype, eret, )
+
+#define SHADOW2_NEXT2(op, args) do { \
+ if (shadow_copy2_match_name(oldname) || shadow_copy2_match_name(newname)) { \
+ errno = EROFS; \
+ return -1; \
+ } else { \
+ return SMB_VFS_NEXT_ ## op args; \
+ } \
+} while (0)
+
+
+/*
+ find the mount point of a filesystem
+ */
+static char *find_mount_point(TALLOC_CTX *mem_ctx, vfs_handle_struct *handle)
+{
+ char *path = talloc_strdup(mem_ctx, handle->conn->connectpath);
+ dev_t dev;
+ struct stat st;
+ char *p;
+
+ if (stat(path, &st) != 0) {
+ talloc_free(path);
+ return NULL;
+ }
+
+ dev = st.st_dev;
+
+ while ((p = strrchr(path, '/')) && p > path) {
+ *p = 0;
+ if (stat(path, &st) != 0) {
+ talloc_free(path);
+ return NULL;
+ }
+ if (st.st_dev != dev) {
+ *p = '/';
+ break;
+ }
+ }
+
+ return path;
+}
+
+/*
+ work out the location of the snapshot for this share
+ */
+static const char *shadow_copy2_find_snapdir(TALLOC_CTX *mem_ctx, vfs_handle_struct *handle)
+{
+ const char *snapdir;
+ char *mount_point;
+ const char *ret;
+
+ snapdir = lp_parm_const_string(SNUM(handle->conn), "shadow", "snapdir", NULL);
+ if (snapdir == NULL) {
+ return NULL;
+ }
+ /* if its an absolute path, we're done */
+ if (*snapdir == '/') {
+ return snapdir;
+ }
+
+ /* other its relative to the filesystem mount point */
+ mount_point = find_mount_point(mem_ctx, handle);
+ if (mount_point == NULL) {
+ return NULL;
+ }
+
+ ret = talloc_asprintf(mem_ctx, "%s/%s", mount_point, snapdir);
+ talloc_free(mount_point);
+ return ret;
+}
+
+/*
+ work out the location of the base directory for snapshots of this share
+ */
+static const char *shadow_copy2_find_basedir(TALLOC_CTX *mem_ctx, vfs_handle_struct *handle)
+{
+ const char *basedir = lp_parm_const_string(SNUM(handle->conn), "shadow", "basedir", NULL);
+
+ /* other its the filesystem mount point */
+ if (basedir == NULL) {
+ basedir = find_mount_point(mem_ctx, handle);
+ }
+
+ return basedir;
+}
+
+/*
+ convert a filename from a share relative path, to a path in the
+ snapshot directory
+ */
+static char *convert_shadow2_name(vfs_handle_struct *handle, const char *fname)
+{
+ TALLOC_CTX *tmp_ctx = talloc_new(handle->data);
+ const char *snapdir, *relpath, *baseoffset, *basedir;
+ size_t baselen;
+ char *ret;
+
+ snapdir = shadow_copy2_find_snapdir(tmp_ctx, handle);
+ if (snapdir == NULL) {
+ DEBUG(2,("no snapdir found for share at %s\n", handle->conn->connectpath));
+ talloc_free(tmp_ctx);
+ return NULL;
+ }
+
+ basedir = shadow_copy2_find_basedir(tmp_ctx, handle);
+ if (basedir == NULL) {
+ DEBUG(2,("no basedir found for share at %s\n", handle->conn->connectpath));
+ talloc_free(tmp_ctx);
+ return NULL;
+ }
+
+ relpath = fname + GMT_NAME_LEN;
+ baselen = strlen(basedir);
+ baseoffset = handle->conn->connectpath + baselen;
+
+ /* some sanity checks */
+ if (strncmp(basedir, handle->conn->connectpath, baselen) != 0 ||
+ (handle->conn->connectpath[baselen] != 0 && handle->conn->connectpath[baselen] != '/')) {
+ DEBUG(0,("convert_shadow2_name: basedir %s is not a parent of %s\n",
+ basedir, handle->conn->connectpath));
+ talloc_free(tmp_ctx);
+ return NULL;
+ }
+
+ if (*relpath == '/') relpath++;
+ if (*baseoffset == '/') baseoffset++;
+
+ ret = talloc_asprintf(handle->data, "%s/%.*s/%s/%s",
+ snapdir,
+ GMT_NAME_LEN, fname,
+ baseoffset,
+ relpath);
+ DEBUG(6,("convert_shadow2_name: '%s' -> '%s'\n", fname, ret));
+ talloc_free(tmp_ctx);
+ return ret;
+}
+
+
+/*
+ simple string hash
+ */
+static uint32 string_hash(const char *s)
+{
+ uint32 n = 0;
+ while (*s) {
+ n = ((n << 5) + n) ^ (uint32)(*s++);
+ }
+ return n;
+}
+
+/*
+ modify a sbuf return to ensure that inodes in the shadow directory
+ are different from those in the main directory
+ */
+static void convert_sbuf(vfs_handle_struct *handle, const char *fname, SMB_STRUCT_STAT *sbuf)
+{
+ if (lp_parm_bool(SNUM(handle->conn), "shadow", "fixinodes", False)) {
+ /* some snapshot systems, like GPFS, return the name
+ device:inode for the snapshot files as the current
+ files. That breaks the 'restore' button in the shadow copy
+ GUI, as the client gets a sharing violation.
+
+ This is a crude way of allowing both files to be
+ open at once. It has a slight chance of inode
+ number collision, but I can't see a better approach
+ without significant VFS changes
+ */
+ uint32_t shash = string_hash(fname) & 0xFF000000;
+ if (shash == 0) {
+ shash = 1;
+ }
+ sbuf->st_ino ^= shash;
+ }
+}
+
+static int shadow_copy2_rename(vfs_handle_struct *handle,
+ const char *oldname, const char *newname)
+{
+ SHADOW2_NEXT2(RENAME, (handle, oldname, newname));
+}
+
+static int shadow_copy2_symlink(vfs_handle_struct *handle,
+ const char *oldname, const char *newname)
+{
+ SHADOW2_NEXT2(SYMLINK, (handle, oldname, newname));
+}
+
+static int shadow_copy2_link(vfs_handle_struct *handle,
+ const char *oldname, const char *newname)
+{
+ SHADOW2_NEXT2(LINK, (handle, oldname, newname));
+}
+
+static int shadow_copy2_open(vfs_handle_struct *handle,
+ const char *fname, files_struct *fsp, int flags, mode_t mode)
+{
+ SHADOW2_NEXT(OPEN, (handle, name, fsp, flags, mode), int, -1);
+}
+
+static SMB_STRUCT_DIR *shadow_copy2_opendir(vfs_handle_struct *handle,
+ const char *fname, const char *mask, uint32 attr)
+{
+ SHADOW2_NEXT(OPENDIR, (handle, name, mask, attr), void*, NULL);
+}
+
+static int shadow_copy2_stat(vfs_handle_struct *handle,
+ const char *fname, SMB_STRUCT_STAT *sbuf)
+{
+ _SHADOW2_NEXT(STAT, (handle, name, sbuf), int, -1, convert_sbuf(handle, fname, sbuf));
+}
+
+static int shadow_copy2_lstat(vfs_handle_struct *handle,
+ const char *fname, SMB_STRUCT_STAT *sbuf)
+{
+ _SHADOW2_NEXT(LSTAT, (handle, name, sbuf), int, -1, convert_sbuf(handle, fname, sbuf));
+}
+
+static int shadow_copy2_fstat(vfs_handle_struct *handle, files_struct *fsp, SMB_STRUCT_STAT *sbuf)
+{
+ int ret = SMB_VFS_NEXT_FSTAT(handle, fsp, sbuf);
+ if (ret == 0 && shadow_copy2_match_name(fsp->fsp_name)) {
+ convert_sbuf(handle, fsp->fsp_name, sbuf);
+ }
+ return ret;
+}
+
+static int shadow_copy2_unlink(vfs_handle_struct *handle, const char *fname)
+{
+ SHADOW2_NEXT(UNLINK, (handle, name), int, -1);
+}
+
+static int shadow_copy2_chmod(vfs_handle_struct *handle,
+ const char *fname, mode_t mode)
+{
+ SHADOW2_NEXT(CHMOD, (handle, name, mode), int, -1);
+}
+
+static int shadow_copy2_chown(vfs_handle_struct *handle,
+ const char *fname, uid_t uid, gid_t gid)
+{
+ SHADOW2_NEXT(CHOWN, (handle, name, uid, gid), int, -1);
+}
+
+static int shadow_copy2_chdir(vfs_handle_struct *handle,
+ const char *fname)
+{
+ SHADOW2_NEXT(CHDIR, (handle, name), int, -1);
+}
+
+static int shadow_copy2_ntimes(vfs_handle_struct *handle,
+ const char *fname, const struct timespec ts[2])
+{
+ SHADOW2_NEXT(NTIMES, (handle, name, ts), int, -1);
+}
+
+static int shadow_copy2_readlink(vfs_handle_struct *handle,
+ const char *fname, char *buf, size_t bufsiz)
+{
+ SHADOW2_NEXT(READLINK, (handle, name, buf, bufsiz), int, -1);
+}
+
+static int shadow_copy2_mknod(vfs_handle_struct *handle,
+ const char *fname, mode_t mode, SMB_DEV_T dev)
+{
+ SHADOW2_NEXT(MKNOD, (handle, name, mode, dev), int, -1);
+}
+
+static char *shadow_copy2_realpath(vfs_handle_struct *handle,
+ const char *fname, char *resolved_path)
+{
+ SHADOW2_NEXT(REALPATH, (handle, name, resolved_path), void*, NULL);
+}
+
+static NTSTATUS shadow_copy2_get_nt_acl(vfs_handle_struct *handle,
+ const char *fname, uint32 security_info,
+ struct security_descriptor **ppdesc)
+{
+ SHADOW2_NTSTATUS_NEXT(GET_NT_ACL, (handle, name, security_info, ppdesc), NT_STATUS_ACCESS_DENIED);
+}
+
+static NTSTATUS shadow_copy2_set_nt_acl(vfs_handle_struct *handle, files_struct *fsp,
+ const char *fname, uint32 security_info_sent,
+ struct security_descriptor *psd)
+{
+ SHADOW2_NTSTATUS_NEXT(SET_NT_ACL, (handle, fsp, name, security_info_sent, psd), NT_STATUS_ACCESS_DENIED);
+}
+
+static int shadow_copy2_mkdir(vfs_handle_struct *handle, const char *fname, mode_t mode)
+{
+ SHADOW2_NEXT(MKDIR, (handle, name, mode), int, -1);
+}
+
+static int shadow_copy2_rmdir(vfs_handle_struct *handle, const char *fname)
+{
+ SHADOW2_NEXT(RMDIR, (handle, name), int, -1);
+}
+
+static int shadow_copy2_chflags(vfs_handle_struct *handle, const char *fname, int flags)
+{
+ SHADOW2_NEXT(CHFLAGS, (handle, name, flags), int, -1);
+}
+
+static ssize_t shadow_copy2_getxattr(vfs_handle_struct *handle,
+ const char *fname, const char *aname, void *value, size_t size)
+{
+ SHADOW2_NEXT(GETXATTR, (handle, name, aname, value, size), ssize_t, -1);
+}
+
+static ssize_t shadow_copy2_lgetxattr(vfs_handle_struct *handle,
+ const char *fname, const char *aname, void *value, size_t size)
+{
+ SHADOW2_NEXT(LGETXATTR, (handle, name, aname, value, size), ssize_t, -1);
+}
+
+static ssize_t shadow_copy2_listxattr(struct vfs_handle_struct *handle, const char *fname,
+ char *list, size_t size)
+{
+ SHADOW2_NEXT(LISTXATTR, (handle, name, list, size), ssize_t, -1);
+}
+
+static int shadow_copy2_removexattr(struct vfs_handle_struct *handle, const char *fname,
+ const char *aname)
+{
+ SHADOW2_NEXT(REMOVEXATTR, (handle, name, aname), int, -1);
+}
+
+static int shadow_copy2_lremovexattr(struct vfs_handle_struct *handle, const char *fname,
+ const char *aname)
+{
+ SHADOW2_NEXT(LREMOVEXATTR, (handle, name, aname), int, -1);
+}
+
+static int shadow_copy2_setxattr(struct vfs_handle_struct *handle, const char *fname,
+ const char *aname, const void *value, size_t size, int flags)
+{
+ SHADOW2_NEXT(SETXATTR, (handle, name, aname, value, size, flags), int, -1);
+}
+
+static int shadow_copy2_lsetxattr(struct vfs_handle_struct *handle, const char *fname,
+ const char *aname, const void *value, size_t size, int flags)
+{
+ SHADOW2_NEXT(LSETXATTR, (handle, name, aname, value, size, flags), int, -1);
+}
+
+static int shadow_copy2_chmod_acl(vfs_handle_struct *handle,
+ const char *fname, mode_t mode)
+{
+ /* If the underlying VFS doesn't have ACL support... */
+ if (!handle->vfs_next.ops.chmod_acl) {
+ errno = ENOSYS;
+ return -1;
+ }
+ SHADOW2_NEXT(CHMOD_ACL, (handle, name, mode), int, -1);
+}
+
+static int shadow_copy2_get_shadow_copy2_data(vfs_handle_struct *handle,
+ files_struct *fsp,
+ SHADOW_COPY_DATA *shadow_copy2_data,
+ bool labels)
+{
+ SMB_STRUCT_DIR *p;
+ const char *snapdir;
+ SMB_STRUCT_DIRENT *d;
+ TALLOC_CTX *tmp_ctx = talloc_new(handle->data);
+
+ snapdir = shadow_copy2_find_snapdir(tmp_ctx, handle);
+ if (snapdir == NULL) {
+ DEBUG(0,("shadow:snapdir not found for %s in get_shadow_copy_data\n",
+ handle->conn->connectpath));
+ errno = EINVAL;
+ talloc_free(tmp_ctx);
+ return -1;
+ }
+
+ p = SMB_VFS_NEXT_OPENDIR(handle, snapdir, NULL, 0);
+
+ if (!p) {
+ DEBUG(0,("shadow_copy2: SMB_VFS_NEXT_OPENDIR() failed for '%s' - %s\n",
+ snapdir, strerror(errno)));
+ talloc_free(tmp_ctx);
+ return -1;
+ }
+
+ talloc_free(tmp_ctx);
+
+ shadow_copy2_data->num_volumes = 0;
+ shadow_copy2_data->labels = NULL;
+
+ while ((d = SMB_VFS_NEXT_READDIR(handle, p))) {
+ SHADOW_COPY_LABEL *tlabels;
+
+ /* ignore names not of the right form in the snapshot directory */
+ if (!shadow_copy2_match_name(d->d_name)) {
+ continue;
+ }
+
+ if (!labels) {
+ /* the caller doesn't want the labels */
+ shadow_copy2_data->num_volumes++;
+ continue;
+ }
+
+ tlabels = talloc_realloc(shadow_copy2_data->mem_ctx,
+ shadow_copy2_data->labels,
+ SHADOW_COPY_LABEL, shadow_copy2_data->num_volumes+1);
+ if (tlabels == NULL) {
+ DEBUG(0,("shadow_copy2: out of memory\n"));
+ SMB_VFS_NEXT_CLOSEDIR(handle, p);
+ return -1;
+ }
+
+ strlcpy(tlabels[shadow_copy2_data->num_volumes], d->d_name, sizeof(*tlabels));
+ shadow_copy2_data->num_volumes++;
+ shadow_copy2_data->labels = tlabels;
+ }
+
+ SMB_VFS_NEXT_CLOSEDIR(handle,p);
+ return 0;
+}
+
+/* VFS operations structure */
+
+static vfs_op_tuple shadow_copy2_ops[] = {
+ {SMB_VFS_OP(shadow_copy2_opendir), SMB_VFS_OP_OPENDIR, SMB_VFS_LAYER_TRANSPARENT},
+
+ /* directory operations */
+ {SMB_VFS_OP(shadow_copy2_mkdir), SMB_VFS_OP_MKDIR, SMB_VFS_LAYER_TRANSPARENT},
+ {SMB_VFS_OP(shadow_copy2_rmdir), SMB_VFS_OP_RMDIR, SMB_VFS_LAYER_TRANSPARENT},
+
+ /* xattr and flags operations */
+ {SMB_VFS_OP(shadow_copy2_chflags), SMB_VFS_OP_CHFLAGS, SMB_VFS_LAYER_TRANSPARENT},
+ {SMB_VFS_OP(shadow_copy2_getxattr), SMB_VFS_OP_GETXATTR, SMB_VFS_LAYER_TRANSPARENT},
+ {SMB_VFS_OP(shadow_copy2_lgetxattr), SMB_VFS_OP_LGETXATTR, SMB_VFS_LAYER_TRANSPARENT},
+ {SMB_VFS_OP(shadow_copy2_listxattr), SMB_VFS_OP_LISTXATTR, SMB_VFS_LAYER_TRANSPARENT},
+ {SMB_VFS_OP(shadow_copy2_removexattr), SMB_VFS_OP_REMOVEXATTR, SMB_VFS_LAYER_TRANSPARENT},
+ {SMB_VFS_OP(shadow_copy2_lremovexattr),SMB_VFS_OP_LREMOVEXATTR,SMB_VFS_LAYER_TRANSPARENT},
+ {SMB_VFS_OP(shadow_copy2_setxattr), SMB_VFS_OP_SETXATTR, SMB_VFS_LAYER_TRANSPARENT},
+ {SMB_VFS_OP(shadow_copy2_lsetxattr), SMB_VFS_OP_LSETXATTR, SMB_VFS_LAYER_TRANSPARENT},
+
+ /* File operations */
+ {SMB_VFS_OP(shadow_copy2_open), SMB_VFS_OP_OPEN, SMB_VFS_LAYER_TRANSPARENT},
+ {SMB_VFS_OP(shadow_copy2_rename), SMB_VFS_OP_RENAME, SMB_VFS_LAYER_TRANSPARENT},
+ {SMB_VFS_OP(shadow_copy2_stat), SMB_VFS_OP_STAT, SMB_VFS_LAYER_TRANSPARENT},
+ {SMB_VFS_OP(shadow_copy2_lstat), SMB_VFS_OP_LSTAT, SMB_VFS_LAYER_TRANSPARENT},
+ {SMB_VFS_OP(shadow_copy2_fstat), SMB_VFS_OP_FSTAT, SMB_VFS_LAYER_TRANSPARENT},
+ {SMB_VFS_OP(shadow_copy2_unlink), SMB_VFS_OP_UNLINK, SMB_VFS_LAYER_TRANSPARENT},
+ {SMB_VFS_OP(shadow_copy2_chmod), SMB_VFS_OP_CHMOD, SMB_VFS_LAYER_TRANSPARENT},
+ {SMB_VFS_OP(shadow_copy2_chown), SMB_VFS_OP_CHOWN, SMB_VFS_LAYER_TRANSPARENT},
+ {SMB_VFS_OP(shadow_copy2_chdir), SMB_VFS_OP_CHDIR, SMB_VFS_LAYER_TRANSPARENT},
+ {SMB_VFS_OP(shadow_copy2_ntimes), SMB_VFS_OP_NTIMES, SMB_VFS_LAYER_TRANSPARENT},
+ {SMB_VFS_OP(shadow_copy2_symlink), SMB_VFS_OP_SYMLINK, SMB_VFS_LAYER_TRANSPARENT},
+ {SMB_VFS_OP(shadow_copy2_readlink), SMB_VFS_OP_READLINK, SMB_VFS_LAYER_TRANSPARENT},
+ {SMB_VFS_OP(shadow_copy2_link), SMB_VFS_OP_LINK, SMB_VFS_LAYER_TRANSPARENT},
+ {SMB_VFS_OP(shadow_copy2_mknod), SMB_VFS_OP_MKNOD, SMB_VFS_LAYER_TRANSPARENT},
+ {SMB_VFS_OP(shadow_copy2_realpath), SMB_VFS_OP_REALPATH, SMB_VFS_LAYER_TRANSPARENT},
+
+ /* NT File ACL operations */
+ {SMB_VFS_OP(shadow_copy2_get_nt_acl), SMB_VFS_OP_GET_NT_ACL, SMB_VFS_LAYER_TRANSPARENT},
+ {SMB_VFS_OP(shadow_copy2_set_nt_acl), SMB_VFS_OP_SET_NT_ACL, SMB_VFS_LAYER_TRANSPARENT},
+
+ /* POSIX ACL operations */
+ {SMB_VFS_OP(shadow_copy2_chmod_acl), SMB_VFS_OP_CHMOD_ACL, SMB_VFS_LAYER_TRANSPARENT},
+
+ /* special shadown copy op */
+ {SMB_VFS_OP(shadow_copy2_get_shadow_copy2_data),
+ SMB_VFS_OP_GET_SHADOW_COPY_DATA,SMB_VFS_LAYER_OPAQUE},
+
+ {SMB_VFS_OP(NULL), SMB_VFS_OP_NOOP, SMB_VFS_LAYER_NOOP}
+};
+
+NTSTATUS vfs_shadow_copy2_init(void);
+NTSTATUS vfs_shadow_copy2_init(void)
+{
+ NTSTATUS ret;
+
+ ret = smb_register_vfs(SMB_VFS_INTERFACE_VERSION, "shadow_copy2", shadow_copy2_ops);
+
+ if (!NT_STATUS_IS_OK(ret))
+ return ret;
+
+ vfs_shadow_copy2_debug_level = debug_add_class("shadow_copy2");
+ if (vfs_shadow_copy2_debug_level == -1) {
+ vfs_shadow_copy2_debug_level = DBGC_VFS;
+ DEBUG(0, ("%s: Couldn't register custom debugging class!\n",
+ "vfs_shadow_copy2_init"));
+ } else {
+ DEBUG(10, ("%s: Debug class number of '%s': %d\n",
+ "vfs_shadow_copy2_init","shadow_copy2",vfs_shadow_copy2_debug_level));
+ }
+
+ return ret;
+}
diff --git a/source3/modules/vfs_tsmsm.c b/source3/modules/vfs_tsmsm.c
new file mode 100644
index 0000000000..fe791b24bf
--- /dev/null
+++ b/source3/modules/vfs_tsmsm.c
@@ -0,0 +1,338 @@
+/*
+ Unix SMB/CIFS implementation.
+ Samba VFS module for handling offline files
+ with Tivoli Storage Manager Space Management
+
+ (c) Alexander Bokovoy, 2007
+ (c) Andrew Tridgell, 2007
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+/*
+ This VFS module accepts following options:
+ tsmsm: hsm script = <path to hsm script> (/bin/true by default, i.e. does nothing)
+ hsm script should point to a shell script which accepts two arguments:
+ <operation> <filepath>
+ where <operation> is currently 'offline' to set offline status of the <filepath>
+
+ tsmsm: online ratio = ratio to check reported size against actual file size (0.5 by default)
+
+ The TSMSM VFS module tries to avoid calling expensive DMAPI calls with some heuristics
+ based on the fact that number of blocks reported of a file multiplied by 512 will be
+ bigger than 'online ratio' of actual size for online (non-migrated) files.
+
+ If checks fail, we call DMAPI and ask for specific IBM attribute which present for
+ offline (migrated) files. If this attribute presents, we consider file offline.
+ */
+
+#include "includes.h"
+
+#ifndef USE_DMAPI
+#error "This module requires DMAPI support!"
+#endif
+
+#ifdef HAVE_XFS_DMAPI_H
+#include <xfs/dmapi.h>
+#elif defined(HAVE_SYS_DMI_H)
+#include <sys/dmi.h>
+#elif defined(HAVE_SYS_JFSDMAPI_H)
+#include <sys/jfsdmapi.h>
+#elif defined(HAVE_SYS_DMAPI_H)
+#include <sys/dmapi.h>
+#elif defined(HAVE_DMAPI_H)
+#include <dmapi.h>
+#endif
+
+#ifndef _ISOC99_SOURCE
+#define _ISOC99_SOURCE
+#endif
+
+#include <math.h>
+
+/* optimisation tunables - used to avoid the DMAPI slow path */
+#define FILE_IS_ONLINE_RATIO 0.5
+#define DM_ATTRIB_OBJECT "IBMObj"
+#define DM_ATTRIB_MIGRATED "IBMMig"
+
+struct tsmsm_struct {
+ dm_sessid_t sid;
+ float online_ratio;
+ char *hsmscript;
+};
+
+#define TSM_STRINGIFY(a) #a
+#define TSM_TOSTRING(a) TSM_STRINGIFY(a)
+
+static void tsmsm_free_data(void **pptr) {
+ struct tsmsm_struct **tsmd = (struct tsmsm_struct **)pptr;
+ if(!tsmd) return;
+ TALLOC_FREE(*tsmd);
+}
+
+static int tsmsm_connect(struct vfs_handle_struct *handle,
+ const char *service,
+ const char *user) {
+ struct tsmsm_struct *tsmd = TALLOC_ZERO_P(handle, struct tsmsm_struct);
+ const char *hsmscript, *tsmname;
+ const char *fres;
+
+ if (!tsmd) {
+ DEBUG(0,("tsmsm_connect: out of memory!\n"));
+ return -1;
+ }
+
+ tsmd->sid = *(dm_sessid_t*) dmapi_get_current_session();
+
+ if (tsmd->sid == DM_NO_SESSION) {
+ DEBUG(0,("tsmsm_connect: no DMAPI session for Samba is available!\n"));
+ TALLOC_FREE(tsmd);
+ return -1;
+ }
+
+ tsmname = (handle->param ? handle->param : "tsmsm");
+ hsmscript = lp_parm_const_string(SNUM(handle->conn), tsmname,
+ "hsm script", NULL);
+ if (hsmscript) {
+ tsmd->hsmscript = talloc_strdup(tsmd, hsmscript);
+ if(!tsmd->hsmscript) {
+ DEBUG(1, ("tsmsm_connect: can't allocate memory for hsm script path"));
+ TALLOC_FREE(tsmd);
+ return -1;
+ }
+ } else {
+ DEBUG(1, ("tsmsm_connect: can't call hsm script because it "
+ "is not set to anything in the smb.conf\n"
+ "Use %s: 'hsm script = path' to set it\n",
+ tsmname));
+ TALLOC_FREE(tsmd);
+ return -1;
+ }
+
+ fres = lp_parm_const_string(SNUM(handle->conn), tsmname,
+ "online ratio", TSM_TOSTRING(FILE_IS_ONLINE_RATIO));
+ tsmd->online_ratio = strtof(fres, NULL);
+ if((tsmd->online_ratio == (float)0) || ((errno == ERANGE) &&
+ ((tsmd->online_ratio == HUGE_VALF) ||
+ (tsmd->online_ratio == HUGE_VALL)))) {
+ DEBUG(1, ("tsmsm_connect: error while getting online ratio from smb.conf."
+ "Default to %s.\n", TSM_TOSTRING(FILE_IS_ONLINE_RATIO)));
+ tsmd->online_ratio = FILE_IS_ONLINE_RATIO;
+ }
+
+ /* Store the private data. */
+ SMB_VFS_HANDLE_SET_DATA(handle, tsmd, tsmsm_free_data,
+ struct tsmsm_struct, return -1);
+ return SMB_VFS_NEXT_CONNECT(handle, service, user);
+}
+
+static int tsmsm_is_offline(struct vfs_handle_struct *handle,
+ struct connection_struct *conn,
+ const char *path,
+ SMB_STRUCT_STAT *stbuf,
+ bool *offline) {
+ struct tsmsm_struct *tsmd = (struct tsmsm_struct *) handle->data;
+ void *dmhandle = NULL;
+ size_t dmhandle_len = 0;
+ size_t rlen;
+ dm_attrname_t dmname;
+ int ret;
+
+ /* if the file has more than FILE_IS_ONLINE_RATIO of blocks available,
+ then assume it is not offline (it may not be 100%, as it could be sparse) */
+ if (512 * (off_t)stbuf->st_blocks >= stbuf->st_size * tsmd->online_ratio) {
+ *offline = false;
+ DEBUG(10,("%s not offline: st_blocks=%ld st_size=%ld online_ratio=%.2f\n",
+ path, stbuf->st_blocks, stbuf->st_size, tsmd->online_ratio));
+ return 0;
+ }
+
+ /* using POSIX capabilities does not work here. It's a slow path, so
+ * become_root() is just as good anyway (tridge)
+ */
+
+ /* Also, AIX has DMAPI but no POSIX capablities support. In this case,
+ * we need to be root to do DMAPI manipulations.
+ */
+ become_root();
+
+ /* go the slow DMAPI route */
+ if (dm_path_to_handle((char*)path, &dmhandle, &dmhandle_len) != 0) {
+ ret = -1;
+ DEBUG(2,("dm_path_to_handle failed - assuming offline (%s) - %s\n",
+ path, strerror(errno)));
+ *offline = True;
+ goto done;
+ }
+
+ memset(&dmname, 0, sizeof(dmname));
+ strlcpy((char *)&dmname.an_chars[0], DM_ATTRIB_OBJECT, sizeof(dmname.an_chars));
+
+ ret = dm_get_dmattr(tsmd->sid, dmhandle, dmhandle_len,
+ DM_NO_TOKEN, &dmname, 0, NULL, &rlen);
+
+ /* its offline if the IBMObj attribute exists */
+ *offline = (ret == 0 || (ret == -1 && errno == E2BIG));
+
+ DEBUG(10,("dm_get_dmattr %s ret=%d (%s)\n", path, ret, strerror(errno)));
+
+ ret = 0;
+
+ dm_handle_free(dmhandle, dmhandle_len);
+
+done:
+ unbecome_root();
+ return ret;
+}
+
+
+static bool tsmsm_aio_force(struct vfs_handle_struct *handle, struct files_struct *fsp)
+{
+ SMB_STRUCT_STAT sbuf;
+ struct tsmsm_struct *tsmd = (struct tsmsm_struct *) handle->data;
+ /* see if the file might be offline. This is called before each IO
+ to ensure we use AIO if the file is offline. We don't do the full dmapi
+ call as that would be too slow, instead we err on the side of using AIO
+ if the file might be offline
+ */
+ if(SMB_VFS_FSTAT(fsp, &sbuf) == 0) {
+ DEBUG(10,("tsmsm_aio_force st_blocks=%ld st_size=%ld online_ratio=%.2f\n",
+ sbuf.st_blocks, sbuf.st_size, tsmd->online_ratio));
+ return !(512 * (off_t)sbuf.st_blocks >= sbuf.st_size * tsmd->online_ratio);
+ }
+ return False;
+}
+
+static ssize_t tsmsm_aio_return(struct vfs_handle_struct *handle, struct files_struct *fsp,
+ SMB_STRUCT_AIOCB *aiocb)
+{
+ ssize_t result;
+
+ result = SMB_VFS_NEXT_AIO_RETURN(handle, fsp, aiocb);
+ if(result >= 0) {
+ notify_fname(handle->conn, NOTIFY_ACTION_MODIFIED,
+ FILE_NOTIFY_CHANGE_ATTRIBUTES,
+ fsp->fsp_name);
+ }
+
+ return result;
+}
+
+static ssize_t tsmsm_sendfile(vfs_handle_struct *handle, int tofd, files_struct *fsp, const DATA_BLOB *hdr,
+ SMB_OFF_T offset, size_t n)
+{
+ bool file_online = tsmsm_aio_force(handle, fsp);
+
+ if(!file_online)
+ return ENOSYS;
+
+ return SMB_VFS_NEXT_SENDFILE(handle, tofd, fsp, hdr, offset, n);
+}
+
+/* We do overload pread to allow notification when file becomes online after offline status */
+/* We don't intercept SMB_VFS_READ here because all file I/O now goes through SMB_VFS_PREAD instead */
+static ssize_t tsmsm_pread(struct vfs_handle_struct *handle, struct files_struct *fsp,
+ void *data, size_t n, SMB_OFF_T offset) {
+ ssize_t result;
+ bool notify_online = tsmsm_aio_force(handle, fsp);
+
+ result = SMB_VFS_NEXT_PREAD(handle, fsp, data, n, offset);
+ if((result != -1) && notify_online) {
+ /* We can't actually force AIO at this point (came here not from reply_read_and_X)
+ what we can do is to send notification that file became online
+ */
+ notify_fname(handle->conn, NOTIFY_ACTION_MODIFIED,
+ FILE_NOTIFY_CHANGE_ATTRIBUTES,
+ fsp->fsp_name);
+ }
+
+ return result;
+}
+
+static ssize_t tsmsm_pwrite(struct vfs_handle_struct *handle, struct files_struct *fsp,
+ void *data, size_t n, SMB_OFF_T offset) {
+ ssize_t result;
+ bool notify_online = tsmsm_aio_force(handle, fsp);
+
+ result = SMB_VFS_NEXT_PWRITE(handle, fsp, data, n, offset);
+ if((result != -1) && notify_online) {
+ /* We can't actually force AIO at this point (came here not from reply_read_and_X)
+ what we can do is to send notification that file became online
+ */
+ notify_fname(handle->conn, NOTIFY_ACTION_MODIFIED,
+ FILE_NOTIFY_CHANGE_ATTRIBUTES,
+ fsp->fsp_name);
+ }
+
+ return result;
+}
+
+static int tsmsm_set_offline(struct vfs_handle_struct *handle, struct connection_struct *conn,
+ const char *path) {
+ struct tsmsm_struct *tsmd = (struct tsmsm_struct *) handle->data;
+ int result = 0;
+ char *command;
+
+ /* Now, call the script */
+ command = talloc_asprintf(tsmd, "%s offline \"%s\"", tsmd->hsmscript, path);
+ if(!command) {
+ DEBUG(1, ("tsmsm_set_offline: can't allocate memory to run hsm script"));
+ return -1;
+ }
+ DEBUG(10, ("tsmsm_set_offline: Running [%s]\n", command));
+ if((result = smbrun(command, NULL)) != 0) {
+ DEBUG(1,("tsmsm_set_offline: Running [%s] returned %d\n", command, result));
+ }
+ TALLOC_FREE(command);
+ return result;
+}
+
+static bool tsmsm_is_remotestorage(struct vfs_handle_struct *handle, struct connection_struct *conn, const char *path) {
+ return True;
+}
+
+static vfs_op_tuple vfs_tsmsm_ops[] = {
+
+ /* Disk operations */
+
+ {SMB_VFS_OP(tsmsm_connect), SMB_VFS_OP_CONNECT,
+ SMB_VFS_LAYER_TRANSPARENT},
+ {SMB_VFS_OP(tsmsm_aio_force), SMB_VFS_OP_AIO_FORCE,
+ SMB_VFS_LAYER_TRANSPARENT},
+ {SMB_VFS_OP(tsmsm_aio_return), SMB_VFS_OP_AIO_RETURN,
+ SMB_VFS_LAYER_TRANSPARENT},
+ {SMB_VFS_OP(tsmsm_pread), SMB_VFS_OP_PREAD,
+ SMB_VFS_LAYER_TRANSPARENT},
+ {SMB_VFS_OP(tsmsm_pwrite), SMB_VFS_OP_PWRITE,
+ SMB_VFS_LAYER_TRANSPARENT},
+ {SMB_VFS_OP(tsmsm_sendfile), SMB_VFS_OP_SENDFILE,
+ SMB_VFS_LAYER_TRANSPARENT},
+ {SMB_VFS_OP(tsmsm_is_offline),SMB_VFS_OP_IS_OFFLINE,
+ SMB_VFS_LAYER_OPAQUE},
+ {SMB_VFS_OP(tsmsm_set_offline),SMB_VFS_OP_SET_OFFLINE,
+ SMB_VFS_LAYER_OPAQUE},
+ {SMB_VFS_OP(tsmsm_is_remotestorage),SMB_VFS_OP_IS_REMOTESTORAGE,
+ SMB_VFS_LAYER_OPAQUE},
+
+ /* Finish VFS operations definition */
+
+ {SMB_VFS_OP(NULL), SMB_VFS_OP_NOOP,
+ SMB_VFS_LAYER_NOOP}
+};
+
+NTSTATUS vfs_tsmsm_init(void);
+NTSTATUS vfs_tsmsm_init(void)
+{
+ return smb_register_vfs(SMB_VFS_INTERFACE_VERSION,
+ "tsmsm", vfs_tsmsm_ops);
+}
diff --git a/source3/param/loadparm.c b/source3/param/loadparm.c
index eaf19b746a..0d3fbbf77c 100644
--- a/source3/param/loadparm.c
+++ b/source3/param/loadparm.c
@@ -9,6 +9,7 @@
Copyright (C) Alexander Bokovoy 2002
Copyright (C) Stefan (metze) Metzmacher 2002
Copyright (C) Jim McDonough <jmcd@us.ibm.com> 2003
+ Copyright (C) Michael Adam 2008
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -70,16 +71,12 @@ extern userdom_struct current_user_info;
#define HOMES_NAME "homes"
#endif
-/* the special value for the include parameter
- * to be interpreted not as a file name but to
- * trigger loading of the global smb.conf options
- * from registry. */
-#ifndef INCLUDE_REGISTRY_NAME
-#define INCLUDE_REGISTRY_NAME "registry"
-#endif
-
static int regdb_last_seqnum = 0;
-static bool include_registry_globals = False;
+
+#define CONFIG_BACKEND_FILE 0
+#define CONFIG_BACKEND_REGISTRY 1
+
+static int config_backend = CONFIG_BACKEND_FILE;
/* some helpful bits */
#define LP_SNUM_OK(i) (((i) >= 0) && ((i) < iNumServices) && (ServicePtrs != NULL) && ServicePtrs[(i)]->valid)
@@ -104,6 +101,7 @@ struct _param_opt_struct {
* This structure describes global (ie., server-wide) parameters.
*/
typedef struct {
+ int ConfigBackend;
char *smb_ports;
char *dos_charset;
char *unix_charset;
@@ -842,6 +840,14 @@ static const struct enum_list enum_map_to_guest[] = {
{-1, NULL}
};
+/* Config backend options */
+
+static const struct enum_list enum_config_backend[] = {
+ {CONFIG_BACKEND_FILE, "file"},
+ {CONFIG_BACKEND_REGISTRY, "registry"},
+ {-1, NULL}
+};
+
/* Note: We do not initialise the defaults union - it is not allowed in ANSI C
*
* The FLAG_HIDE is explicit. Paramters set this way do NOT appear in any edit
@@ -880,6 +886,8 @@ static struct parm_struct parm_table[] = {
{"interfaces", P_LIST, P_GLOBAL, &Globals.szInterfaces, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD},
{"bind interfaces only", P_BOOL, P_GLOBAL, &Globals.bBindInterfacesOnly, NULL, NULL, FLAG_ADVANCED | FLAG_WIZARD},
+ {"config backend", P_ENUM, P_GLOBAL, &Globals.ConfigBackend, NULL, enum_config_backend, FLAG_ADVANCED},
+
{N_("Security Options"), P_SEP, P_SEPARATOR},
{"security", P_ENUM, P_GLOBAL, &Globals.security, NULL, enum_security, FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD},
@@ -1215,14 +1223,14 @@ static struct parm_struct parm_table[] = {
{"ldap page size", P_INTEGER, P_GLOBAL, &Globals.ldap_page_size, NULL, NULL, FLAG_ADVANCED},
{"ldap user suffix", P_STRING, P_GLOBAL, &Globals.szLdapUserSuffix, NULL, NULL, FLAG_ADVANCED},
+ {N_("EventLog Options"), P_SEP, P_SEPARATOR},
+ {"eventlog list", P_LIST, P_GLOBAL, &Globals.szEventLogs, NULL, NULL, FLAG_ADVANCED | FLAG_GLOBAL | FLAG_SHARE},
+
{N_("Miscellaneous Options"), P_SEP, P_SEPARATOR},
{"add share command", P_STRING, P_GLOBAL, &Globals.szAddShareCommand, NULL, NULL, FLAG_ADVANCED},
{"change share command", P_STRING, P_GLOBAL, &Globals.szChangeShareCommand, NULL, NULL, FLAG_ADVANCED},
{"delete share command", P_STRING, P_GLOBAL, &Globals.szDeleteShareCommand, NULL, NULL, FLAG_ADVANCED},
- {N_("EventLog Options"), P_SEP, P_SEPARATOR},
- {"eventlog list", P_LIST, P_GLOBAL, &Globals.szEventLogs, NULL, NULL, FLAG_ADVANCED | FLAG_GLOBAL | FLAG_SHARE},
-
{"config file", P_STRING, P_GLOBAL, &Globals.szConfigFile, NULL, NULL, FLAG_HIDE},
{"preload", P_STRING, P_GLOBAL, &Globals.szAutoServices, NULL, NULL, FLAG_ADVANCED},
{"auto services", P_STRING, P_GLOBAL, &Globals.szAutoServices, NULL, NULL, FLAG_ADVANCED},
@@ -1294,6 +1302,8 @@ static struct parm_struct parm_table[] = {
{"vfs object", P_LIST, P_LOCAL, &sDefault.szVfsObjects, NULL, NULL, FLAG_HIDE},
+ {N_("MSDFS options"), P_SEP, P_SEPARATOR},
+
{"msdfs root", P_BOOL, P_LOCAL, &sDefault.bMSDfsRoot, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE},
{"msdfs proxy", P_STRING, P_LOCAL, &sDefault.szMSDfsProxy, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE},
{"host msdfs", P_BOOL, P_GLOBAL, &Globals.bHostMSDfs, NULL, NULL, FLAG_ADVANCED},
@@ -1527,6 +1537,8 @@ static void init_globals(bool first_time_only)
Globals.bLoadPrinters = True;
Globals.PrintcapCacheTime = 750; /* 12.5 minutes */
+ Globals.ConfigBackend = config_backend;
+
/* Was 65535 (0xFFFF). 0x4101 matches W2K and causes major speed improvements... */
/* Discovered by 2 days of pain by Don McCall @ HP :-). */
Globals.max_xmit = 0x4104;
@@ -2046,6 +2058,7 @@ FN_GLOBAL_INTEGER(lp_oplock_break_wait_time, &Globals.oplock_break_wait_time)
FN_GLOBAL_INTEGER(lp_lock_spin_time, &Globals.iLockSpinTime)
FN_GLOBAL_INTEGER(lp_usershare_max_shares, &Globals.iUsershareMaxShares)
FN_GLOBAL_CONST_STRING(lp_socket_options, &Globals.szSocketOptions)
+FN_GLOBAL_INTEGER(lp_config_backend, &Globals.ConfigBackend);
FN_LOCAL_STRING(lp_preexec, szPreExec)
FN_LOCAL_STRING(lp_postexec, szPostExec)
@@ -3422,8 +3435,6 @@ static bool process_registry_globals(bool (*pfunc)(const char *, const char *))
char * valstr;
struct registry_value *value = NULL;
- include_registry_globals = True;
-
ZERO_STRUCT(data);
reg_tdb = lp_regdb_open();
@@ -3536,8 +3547,6 @@ static bool process_registry_globals(bool (*pfunc)(const char *, const char *))
smb_panic("Failed to create talloc context!");
}
- include_registry_globals = True;
-
if (!registry_init_regdb()) {
DEBUG(1, ("Error initializing the registry.\n"));
goto done;
@@ -3637,9 +3646,12 @@ static void add_to_file_list(const char *fname, const char *subfname)
}
}
-bool lp_include_registry_globals(void)
+/**
+ * Utility function for outsiders to check if we're running on registry.
+ */
+bool lp_config_backend_is_registry(void)
{
- return include_registry_globals;
+ return (lp_config_backend() == CONFIG_BACKEND_REGISTRY);
}
/*******************************************************************
@@ -3653,7 +3665,7 @@ bool lp_file_list_changed(void)
DEBUG(6, ("lp_file_list_changed()\n"));
- if (include_registry_globals) {
+ if (lp_config_backend() == CONFIG_BACKEND_REGISTRY) {
reg_tdb = lp_regdb_open();
if (reg_tdb && (regdb_last_seqnum != tdb_get_seqnum(reg_tdb->tdb)))
{
@@ -3661,6 +3673,15 @@ bool lp_file_list_changed(void)
regdb_last_seqnum, tdb_get_seqnum(reg_tdb->tdb)));
TALLOC_FREE(reg_tdb);
return true;
+ } else {
+ /*
+ * Don't check files when config_backend is registry.
+ * Remove this to obtain checking of files even with
+ * registry config backend. That would enable switching
+ * off registry configuration by changing smb.conf even
+ * without restarting smbd.
+ */
+ return false;
}
}
@@ -3696,6 +3717,7 @@ bool lp_file_list_changed(void)
return (False);
}
+
/***************************************************************************
Run standard_sub_basic on netbios name... needed because global_myname
is not accessed through any lp_ macro.
@@ -3765,17 +3787,6 @@ static bool handle_include(int snum, const char *pszParmValue, char **ptr)
{
char *fname;
- if (strequal(pszParmValue, INCLUDE_REGISTRY_NAME)) {
- if (bInGlobalSection) {
- return process_registry_globals(do_parameter);
- }
- else {
- DEBUG(1, ("\"include = registry\" only effective "
- "in %s section\n", GLOBAL_NAME));
- return false;
- }
- }
-
fname = alloc_sub_basic(get_current_username(),
current_user_info.domain,
pszParmValue);
@@ -5654,15 +5665,6 @@ bool lp_load(const char *pszFname,
bool bRetval;
param_opt_struct *data, *pdata;
- n2 = alloc_sub_basic(get_current_username(),
- current_user_info.domain,
- pszFname);
- if (!n2) {
- smb_panic("lp_load: out of memory");
- }
-
- add_to_file_list(pszFname, n2);
-
bRetval = False;
DEBUG(3, ("lp_load: refreshing parameters\n"));
@@ -5691,17 +5693,47 @@ bool lp_load(const char *pszFname,
Globals.param_opt = NULL;
}
- /* We get sections first, so have to start 'behind' to make up */
- iServiceIndex = -1;
- bRetval = pm_process(n2, do_section, do_parameter);
- SAFE_FREE(n2);
+ if (lp_config_backend() == CONFIG_BACKEND_FILE) {
+ n2 = alloc_sub_basic(get_current_username(),
+ current_user_info.domain,
+ pszFname);
+ if (!n2) {
+ smb_panic("lp_load: out of memory");
+ }
+
+ add_to_file_list(pszFname, n2);
- /* finish up the last section */
- DEBUG(4, ("pm_process() returned %s\n", BOOLSTR(bRetval)));
- if (bRetval) {
- if (iServiceIndex >= 0) {
- bRetval = service_ok(iServiceIndex);
+ /* We get sections first, so have to start 'behind' to make up */
+ iServiceIndex = -1;
+ bRetval = pm_process(n2, do_section, do_parameter);
+ SAFE_FREE(n2);
+
+ /* finish up the last section */
+ DEBUG(4, ("pm_process() returned %s\n", BOOLSTR(bRetval)));
+ if (bRetval) {
+ if (iServiceIndex >= 0) {
+ bRetval = service_ok(iServiceIndex);
+ }
+ }
+
+ if (lp_config_backend() == CONFIG_BACKEND_REGISTRY) {
+ /*
+ * We need to use this extra global variable here to
+ * survive restart: init_globals usese this as a default
+ * for ConfigBackend. Otherwise, init_globals would
+ * send us into an endless loop here.
+ */
+ config_backend = CONFIG_BACKEND_REGISTRY;
+ /* start over */
+ return lp_load(pszFname, global_only, save_defaults,
+ add_ipc, initialize_globals);
}
+ } else if (lp_config_backend() == CONFIG_BACKEND_REGISTRY) {
+ bRetval = process_registry_globals(do_parameter);
+ } else {
+ DEBUG(0, ("Illegal config backend given: %d\n",
+ lp_config_backend()));
+ bRetval = false;
}
lp_add_auto_services(lp_auto_services());
diff --git a/source3/rpc_server/srv_lsa_nt.c b/source3/rpc_server/srv_lsa_nt.c
index 1b78772a79..20cafbd0af 100644
--- a/source3/rpc_server/srv_lsa_nt.c
+++ b/source3/rpc_server/srv_lsa_nt.c
@@ -2583,7 +2583,7 @@ NTSTATUS _lsa_LSARUNREGISTERAUDITEVENT(pipes_struct *p, struct lsa_LSARUNREGISTE
return NT_STATUS_NOT_IMPLEMENTED;
}
-NTSTATUS _lsa_LSARQUERYFORESTTRUSTINFORMATION(pipes_struct *p, struct lsa_LSARQUERYFORESTTRUSTINFORMATION *r)
+NTSTATUS _lsa_lsaRQueryForestTrustInformation(pipes_struct *p, struct lsa_lsaRQueryForestTrustInformation *r)
{
p->rng_fault_state = True;
return NT_STATUS_NOT_IMPLEMENTED;
diff --git a/source3/smbd/connection.c b/source3/smbd/connection.c
index 016c8adb1b..d7063c9989 100644
--- a/source3/smbd/connection.c
+++ b/source3/smbd/connection.c
@@ -118,6 +118,15 @@ int count_current_connections( const char *sharename, bool clear )
}
/****************************************************************************
+ Count the number of connections open across all shares.
+****************************************************************************/
+
+int count_all_current_connections(void)
+{
+ return count_current_connections(NULL, True /* clear stale entries */);
+}
+
+/****************************************************************************
Claim an entry in the connections database.
****************************************************************************/
diff --git a/source3/smbd/dmapi.c b/source3/smbd/dmapi.c
index 05e9138ea9..620baf199e 100644
--- a/source3/smbd/dmapi.c
+++ b/source3/smbd/dmapi.c
@@ -46,7 +46,7 @@ bool dmapi_have_session(void) { return False; }
#define DMAPI_SESSION_NAME "samba"
#define DMAPI_TRACE 10
-static dm_sessid_t dmapi_session = DM_NO_SESSION;
+static dm_sessid_t samba_dmapi_session = DM_NO_SESSION;
/* Initialise the DMAPI interface. Make sure that we only end up initialising
* once per process to avoid resource leaks across different DMAPI
@@ -75,7 +75,7 @@ static int init_dmapi_service(void)
bool dmapi_have_session(void)
{
- return dmapi_session != DM_NO_SESSION;
+ return samba_dmapi_session != DM_NO_SESSION;
}
static dm_sessid_t *realloc_session_list(dm_sessid_t * sessions, int count)
@@ -110,7 +110,7 @@ int dmapi_init_session(void)
*/
SMB_WARN(getuid() == 0, "dmapi_init_session must be called as root");
- dmapi_session = DM_NO_SESSION;
+ samba_dmapi_session = DM_NO_SESSION;
if (init_dmapi_service() < 0) {
return -1;
}
@@ -139,7 +139,7 @@ retry:
err = dm_query_session(sessions[i], sizeof(buf), buf, &buflen);
buf[sizeof(buf) - 1] = '\0';
if (err == 0 && strcmp(DMAPI_SESSION_NAME, buf) == 0) {
- dmapi_session = sessions[i];
+ samba_dmapi_session = sessions[i];
DEBUGADD(DMAPI_TRACE,
("attached to existing DMAPI session "
"named '%s'\n", buf));
@@ -150,16 +150,15 @@ retry:
TALLOC_FREE(sessions);
/* No session already defined. */
- if (dmapi_session == DM_NO_SESSION) {
- err = dm_create_session(DM_NO_SESSION,
- CONST_DISCARD(char *,
- DMAPI_SESSION_NAME),
- &dmapi_session);
+ if (samba_dmapi_session == DM_NO_SESSION) {
+ err = dm_create_session(DM_NO_SESSION,
+ CONST_DISCARD(char *, DMAPI_SESSION_NAME),
+ &samba_dmapi_session);
if (err < 0) {
DEBUGADD(DMAPI_TRACE,
("failed to create new DMAPI session: %s\n",
strerror(errno)));
- dmapi_session = DM_NO_SESSION;
+ samba_dmapi_session = DM_NO_SESSION;
return -1;
}
@@ -185,22 +184,22 @@ static int reattach_dmapi_session(void)
char buf[DM_SESSION_INFO_LEN];
size_t buflen;
- if (dmapi_session != DM_NO_SESSION ) {
+ if (samba_dmapi_session != DM_NO_SESSION ) {
become_root();
/* NOTE: On Linux, this call opens /dev/dmapi, costing us a
* file descriptor. Ideally, we would close this when we fork.
*/
if (init_dmapi_service() < 0) {
- dmapi_session = DM_NO_SESSION;
+ samba_dmapi_session = DM_NO_SESSION;
unbecome_root();
return -1;
}
- if (dm_query_session(dmapi_session, sizeof(buf),
+ if (dm_query_session(samba_dmapi_session, sizeof(buf),
buf, &buflen) < 0) {
/* Session is stale. Disable DMAPI. */
- dmapi_session = DM_NO_SESSION;
+ samba_dmapi_session = DM_NO_SESSION;
unbecome_root();
return -1;
}
@@ -214,33 +213,42 @@ static int reattach_dmapi_session(void)
return 0;
}
-uint32 dmapi_file_flags(const char * const path)
+/* If a DMAPI session has been initialised, then we need to make sure
+ * we are attached to it and have the correct privileges. This is
+ * necessary to be able to do DMAPI operations across a fork(2). If
+ * it fails, there is no likelihood of that failure being transient.
+ *
+ * Note that this use of the static attached flag relies on the fact
+ * that dmapi_file_flags() is never called prior to forking the
+ * per-client server process.
+ */
+const void * dmapi_get_current_session(void)
{
static int attached = 0;
+ if (dmapi_have_session() && !attached) {
+ attached++;
+ if (reattach_dmapi_session() < 0) {
+ return DM_NO_SESSION;
+ }
+ }
+ return &samba_dmapi_session;
+}
+uint32 dmapi_file_flags(const char * const path)
+{
+ dm_sessid_t dmapi_session;
int err;
dm_eventset_t events = {0};
uint nevents;
- void *dm_handle;
- size_t dm_handle_len;
+ void *dm_handle = NULL;
+ size_t dm_handle_len = 0;
uint32 flags = 0;
- /* If a DMAPI session has been initialised, then we need to make sure
- * we are attached to it and have the correct privileges. This is
- * necessary to be able to do DMAPI operations across a fork(2). If
- * it fails, there is no liklihood of that failure being transient.
- *
- * Note that this use of the static attached flag relies on the fact
- * that dmapi_file_flags() is never called prior to forking the
- * per-client server process.
- */
- if (dmapi_have_session() && !attached) {
- attached++;
- if (reattach_dmapi_session() < 0) {
- return 0;
- }
+ dmapi_session = *(dm_sessid_t*) dmapi_get_current_session();
+ if (dmapi_session == DM_NO_SESSION) {
+ return 0;
}
/* AIX has DMAPI but no POSIX capablities support. In this case,
@@ -313,4 +321,5 @@ done:
return flags;
}
+
#endif /* USE_DMAPI */
diff --git a/source3/smbd/dosmode.c b/source3/smbd/dosmode.c
index d3813f9b41..2021621dfa 100644
--- a/source3/smbd/dosmode.c
+++ b/source3/smbd/dosmode.c
@@ -31,23 +31,6 @@ static int set_sparse_flag(const SMB_STRUCT_STAT * const sbuf)
}
/****************************************************************************
- Work out whether this file is offline
-****************************************************************************/
-
-static uint32 set_offline_flag(connection_struct *conn, const char *const path)
-{
- if (ISDOT(path) || ISDOTDOT(path)) {
- return 0;
- }
-
- if (!lp_dmapi_support(SNUM(conn)) || !dmapi_have_session()) {
- return 0;
- }
-
- return dmapi_file_flags(path);
-}
-
-/****************************************************************************
Change a dos mode to a unix mode.
Base permission for files:
if creating file and inheriting (i.e. parent_dir != NULL)
@@ -366,6 +349,8 @@ uint32 dos_mode_msdfs(connection_struct *conn, const char *path,SMB_STRUCT_STAT
uint32 dos_mode(connection_struct *conn, const char *path,SMB_STRUCT_STAT *sbuf)
{
uint32 result = 0;
+ bool offline;
+ int ret;
DEBUG(8,("dos_mode: %s\n", path));
@@ -395,8 +380,10 @@ uint32 dos_mode(connection_struct *conn, const char *path,SMB_STRUCT_STAT *sbuf)
result |= dos_mode_from_sbuf(conn, path, sbuf);
}
- if (S_ISREG(sbuf->st_mode)) {
- result |= set_offline_flag(conn, path);
+
+ ret = SMB_VFS_IS_OFFLINE(conn, path, sbuf, &offline);
+ if (S_ISREG(sbuf->st_mode) && (ret == 0) && offline) {
+ result |= FILE_ATTRIBUTE_OFFLINE;
}
/* Optimization : Only call is_hidden_path if it's not already
@@ -432,7 +419,7 @@ int file_set_dosmode(connection_struct *conn, const char *fname,
int mask=0;
mode_t tmp;
mode_t unixmode;
- int ret = -1;
+ int ret = -1, lret = -1;
/* We only allow READONLY|HIDDEN|SYSTEM|DIRECTORY|ARCHIVE here. */
dosmode &= SAMBA_ATTRIBUTES_MASK;
@@ -505,10 +492,21 @@ int file_set_dosmode(connection_struct *conn, const char *fname,
unixmode |= (st->st_mode & (S_IWUSR|S_IWGRP|S_IWOTH));
}
- if ((ret = SMB_VFS_CHMOD(conn,fname,unixmode)) == 0) {
- if (!newfile) {
+ if (dosmode & FILE_ATTRIBUTE_OFFLINE) {
+ lret = SMB_VFS_SET_OFFLINE(conn, fname);
+ if (lret == -1) {
+ DEBUG(0, ("set_dos_mode: client has asked to set "
+ "FILE_ATTRIBUTE_OFFLINE to %s/%s but there was "
+ "an error while setting it or it is not supported.\n",
+ parent_dir, fname));
+ }
+ }
+
+ ret = SMB_VFS_CHMOD(conn, fname, unixmode);
+ if (ret == 0) {
+ if(!newfile || (lret != -1)) {
notify_fname(conn, NOTIFY_ACTION_MODIFIED,
- FILE_NOTIFY_CHANGE_ATTRIBUTES, fname);
+ FILE_NOTIFY_CHANGE_ATTRIBUTES, fname);
}
st->st_mode = unixmode;
return 0;
diff --git a/source3/smbd/oplock_linux.c b/source3/smbd/oplock_linux.c
index 05021b6c74..fa7cb42bc6 100644
--- a/source3/smbd/oplock_linux.c
+++ b/source3/smbd/oplock_linux.c
@@ -93,17 +93,27 @@ static void set_capability(unsigned capability)
return;
}
- data.effective |= (1<<capability);
+ if (0 == (data.effective & (1<<capability))) {
+ data.effective |= (1<<capability);
- if (capset(&header, &data) == -1) {
- DEBUG(3,("Unable to set %d capability (%s)\n",
- capability, strerror(errno)));
+ if (capset(&header, &data) == -1) {
+ DEBUG(3,("Unable to set %d capability (%s)\n",
+ capability, strerror(errno)));
+ }
}
}
/*
- Call to set the kernel lease signal handler
-*/
+ * public function to get linux lease capability. Needed by some VFS modules (eg. gpfs.c)
+ */
+void linux_set_lease_capability(void)
+{
+ set_capability(CAP_LEASE);
+}
+
+/*
+ * Call to set the kernel lease signal handler
+ */
int linux_set_lease_sighandler(int fd)
{
if (fcntl(fd, F_SETSIG, RT_SIGNAL_LEASE) == -1) {
diff --git a/source3/smbd/posix_acls.c b/source3/smbd/posix_acls.c
index 5f18615f66..6cec39f9c0 100644
--- a/source3/smbd/posix_acls.c
+++ b/source3/smbd/posix_acls.c
@@ -3413,6 +3413,9 @@ NTSTATUS set_nt_acl(files_struct *fsp, uint32 security_info_sent, SEC_DESC *psd)
bool acl_perms = False;
mode_t orig_mode = (mode_t)0;
NTSTATUS status;
+ uid_t orig_uid;
+ gid_t orig_gid;
+ bool need_chown = False;
DEBUG(10,("set_nt_acl: called for file %s\n", fsp->fsp_name ));
@@ -3435,6 +3438,8 @@ NTSTATUS set_nt_acl(files_struct *fsp, uint32 security_info_sent, SEC_DESC *psd)
/* Save the original elements we check against. */
orig_mode = sbuf.st_mode;
+ orig_uid = sbuf.st_uid;
+ orig_gid = sbuf.st_gid;
/*
* Unpack the user/group/world id's.
@@ -3449,7 +3454,11 @@ NTSTATUS set_nt_acl(files_struct *fsp, uint32 security_info_sent, SEC_DESC *psd)
* Do we need to chown ?
*/
- if (((user != (uid_t)-1) && (sbuf.st_uid != user)) || (( grp != (gid_t)-1) && (sbuf.st_gid != grp))) {
+ if (((user != (uid_t)-1) && (orig_uid != user)) || (( grp != (gid_t)-1) && (orig_gid != grp))) {
+ need_chown = True;
+ }
+
+ if (need_chown && (user == (uid_t)-1 || user == current_user.ut.uid)) {
DEBUG(3,("set_nt_acl: chown %s. uid = %u, gid = %u.\n",
fsp->fsp_name, (unsigned int)user, (unsigned int)grp ));
@@ -3487,6 +3496,11 @@ NTSTATUS set_nt_acl(files_struct *fsp, uint32 security_info_sent, SEC_DESC *psd)
/* Save the original elements we check against. */
orig_mode = sbuf.st_mode;
+ orig_uid = sbuf.st_uid;
+ orig_gid = sbuf.st_gid;
+
+ /* We did chown already, drop the flag */
+ need_chown = False;
}
create_file_sids(&sbuf, &file_owner_sid, &file_grp_sid);
@@ -3630,6 +3644,21 @@ NTSTATUS set_nt_acl(files_struct *fsp, uint32 security_info_sent, SEC_DESC *psd)
free_canon_ace_list(dir_ace_list);
}
+ /* Any chown pending? */
+ if (need_chown) {
+ DEBUG(3,("set_nt_acl: chown %s. uid = %u, gid = %u.\n",
+ fsp->fsp_name, (unsigned int)user, (unsigned int)grp ));
+
+ if(try_chown( fsp->conn, fsp->fsp_name, user, grp) == -1) {
+ DEBUG(3,("set_nt_acl: chown %s, %u, %u failed. Error = %s.\n",
+ fsp->fsp_name, (unsigned int)user, (unsigned int)grp, strerror(errno) ));
+ if (errno == EPERM) {
+ return NT_STATUS_INVALID_OWNER;
+ }
+ return map_nt_error_from_unix(errno);
+ }
+ }
+
return NT_STATUS_OK;
}
diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c
index e2316ef120..381ddfe151 100644
--- a/source3/smbd/reply.c
+++ b/source3/smbd/reply.c
@@ -3329,8 +3329,12 @@ void reply_read_and_X(struct smb_request *req)
return;
}
- if (!big_readX
- && schedule_aio_read_and_X(conn, req, fsp, startpos, smb_maxcnt)) {
+ /* It is possible for VFS modules to selectively decide whether Async I/O should be used
+ for the file or not.
+ */
+ if ((SMB_VFS_AIO_FORCE(fsp)) &&
+ !big_readX &&
+ schedule_aio_read_and_X(conn, req, fsp, startpos, smb_maxcnt)) {
END_PROFILE(SMBreadX);
return;
}
@@ -4001,13 +4005,16 @@ void reply_write_and_X(struct smb_request *req)
nwritten = 0;
} else {
- if (req->unread_bytes == 0 &&
- schedule_aio_write_and_X(conn, req, fsp, data,
- startpos, numtowrite)) {
+ /* It is possible for VFS modules to selectively decide whether Async I/O
+ should be used for the file or not.
+ */
+ if ((SMB_VFS_AIO_FORCE(fsp)) && (req->unread_bytes == 0) &&
+ schedule_aio_write_and_X(conn, req, fsp, data, startpos,
+ numtowrite)) {
END_PROFILE(SMBwriteX);
return;
}
-
+
nwritten = write_file(req,fsp,data,startpos,numtowrite);
}
diff --git a/source3/smbd/server.c b/source3/smbd/server.c
index 8371d17f10..db241103ed 100644
--- a/source3/smbd/server.c
+++ b/source3/smbd/server.c
@@ -268,10 +268,20 @@ static void add_child_pid(pid_t pid)
num_children += 1;
}
-static void remove_child_pid(pid_t pid)
+static void remove_child_pid(pid_t pid, bool unclean_shutdown)
{
struct child_pid *child;
+ if (unclean_shutdown) {
+ /* a child terminated uncleanly so tickle all processes to see
+ if they can grab any of the pending locks
+ */
+ messaging_send_buf(smbd_messaging_context(), procid_self(),
+ MSG_SMB_BRL_VALIDATE, NULL, 0);
+ message_send_all(smbd_messaging_context(),
+ MSG_SMB_UNLOCK, NULL, 0, NULL);
+ }
+
if (lp_max_smbd_processes() == 0) {
/* Don't bother with the child list if we don't care anyway */
return;
@@ -560,10 +570,27 @@ static bool open_sockets_smbd(bool is_daemon, bool interactive, const char *smb_
if (got_sig_cld) {
pid_t pid;
+ int status;
+
got_sig_cld = False;
- while ((pid = sys_waitpid(-1, NULL, WNOHANG)) > 0) {
- remove_child_pid(pid);
+ while ((pid = sys_waitpid(-1, &status, WNOHANG)) > 0) {
+ bool unclean_shutdown = False;
+
+ /* If the child terminated normally, assume
+ it was an unclean shutdown unless the
+ status is 0
+ */
+ if (WIFEXITED(status)) {
+ unclean_shutdown = WEXITSTATUS(status);
+ }
+ /* If the child terminated due to a signal
+ we always assume it was unclean.
+ */
+ if (WIFSIGNALED(status)) {
+ unclean_shutdown = True;
+ }
+ remove_child_pid(pid, unclean_shutdown);
}
}
@@ -603,6 +630,15 @@ static bool open_sockets_smbd(bool is_daemon, bool interactive, const char *smb_
continue;
}
+
+
+ /* If the idle timeout fired and we don't have any connected
+ * users, exit gracefully. We should be running under a process
+ * controller that will restart us if necessry.
+ */
+ if (num == 0 && count_all_current_connections() == 0) {
+ exit_server_cleanly("idle timeout");
+ }
/* process pending nDNS responses */
if (dns_register_smbd_reply(dns_reg, &r_fds, &idle_timeout)) {
@@ -906,6 +942,29 @@ void exit_server_fault(void)
exit_server("critical server fault");
}
+
+/****************************************************************************
+received when we should release a specific IP
+****************************************************************************/
+static void msg_release_ip(struct messaging_context *msg_ctx, void *private_data,
+ uint32_t msg_type, struct server_id server_id, DATA_BLOB *data)
+{
+ const char *ip = (const char *)data->data;
+ char addr[INET6_ADDRSTRLEN];
+
+ if (strcmp(client_socket_addr(get_client_fd(),addr,sizeof(addr)), ip) == 0) {
+ /* we can't afford to do a clean exit - that involves
+ database writes, which would potentially mean we
+ are still running after the failover has finished -
+ we have to get rid of this process ID straight
+ away */
+ DEBUG(0,("Got release IP message for our IP %s - exiting immediately\n",
+ ip));
+ _exit(0);
+ }
+}
+
+
/****************************************************************************
Initialise connect, service and file structs.
****************************************************************************/
@@ -1305,6 +1364,8 @@ extern void build_options(bool screen);
/* register our message handlers */
messaging_register(smbd_messaging_context(), NULL,
MSG_SMB_FORCE_TDIS, msg_force_tdis);
+ messaging_register(smbd_messaging_context(), NULL,
+ MSG_SMB_RELEASE_IP, msg_release_ip);
if ((lp_keepalive() != 0)
&& !(event_add_idle(smbd_event_context(), NULL,
diff --git a/source3/smbd/service.c b/source3/smbd/service.c
index 2588a66b8b..ed8061e2f7 100644
--- a/source3/smbd/service.c
+++ b/source3/smbd/service.c
@@ -219,44 +219,6 @@ bool set_current_service(connection_struct *conn, uint16 flags, bool do_chdir)
return(True);
}
-/****************************************************************************
- Add a home service. Returns the new service number or -1 if fail.
-****************************************************************************/
-
-int add_home_service(const char *service, const char *username, const char *homedir)
-{
- int iHomeService;
-
- if (!service || !homedir)
- return -1;
-
- if ((iHomeService = lp_servicenumber(HOMES_NAME)) < 0)
- return -1;
-
- /*
- * If this is a winbindd provided username, remove
- * the domain component before adding the service.
- * Log a warning if the "path=" parameter does not
- * include any macros.
- */
-
- {
- const char *p = strchr(service,*lp_winbind_separator());
-
- /* We only want the 'user' part of the string */
- if (p) {
- service = p + 1;
- }
- }
-
- if (!lp_add_home(service, iHomeService, username, homedir)) {
- return -1;
- }
-
- return lp_servicenumber(service);
-
-}
-
static int load_registry_service(const char *servicename)
{
struct registry_key *key;
@@ -348,6 +310,47 @@ void load_registry_shares(void)
return;
}
+/****************************************************************************
+ Add a home service. Returns the new service number or -1 if fail.
+****************************************************************************/
+
+int add_home_service(const char *service, const char *username, const char *homedir)
+{
+ int iHomeService;
+
+ if (!service || !homedir)
+ return -1;
+
+ if ((iHomeService = lp_servicenumber(HOMES_NAME)) < 0) {
+ if ((iHomeService = load_registry_service(HOMES_NAME)) < 0) {
+ return -1;
+ }
+ }
+
+ /*
+ * If this is a winbindd provided username, remove
+ * the domain component before adding the service.
+ * Log a warning if the "path=" parameter does not
+ * include any macros.
+ */
+
+ {
+ const char *p = strchr(service,*lp_winbind_separator());
+
+ /* We only want the 'user' part of the string */
+ if (p) {
+ service = p + 1;
+ }
+ }
+
+ if (!lp_add_home(service, iHomeService, username, homedir)) {
+ return -1;
+ }
+
+ return lp_servicenumber(service);
+
+}
+
/**
* Find a service entry.
*
@@ -386,7 +389,10 @@ int find_service(fstring service)
if (iService < 0) {
int iPrinterService;
- if ((iPrinterService = lp_servicenumber(PRINTERS_NAME)) >= 0) {
+ if ((iPrinterService = lp_servicenumber(PRINTERS_NAME)) < 0) {
+ iPrinterService = load_registry_service(PRINTERS_NAME);
+ }
+ if (iPrinterService) {
DEBUG(3,("checking whether %s is a valid printer name...\n", service));
if (pcap_printername_ok(service)) {
DEBUG(3,("%s is a valid printer name\n", service));
diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c
index bf6802f2a6..5729ab5349 100644
--- a/source3/smbd/trans2.c
+++ b/source3/smbd/trans2.c
@@ -2373,8 +2373,8 @@ static void call_trans2qfsinfo(connection_struct *conn,
const char *vname = volume_label(SNUM(conn));
int snum = SNUM(conn);
char *fstype = lp_fstype(SNUM(conn));
- int quota_flag = 0;
-
+ uint32 additional_flags = 0;
+
if (total_params < 2) {
reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
return;
@@ -2487,16 +2487,23 @@ cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_dev, (unsi
case SMB_QUERY_FS_ATTRIBUTE_INFO:
case SMB_FS_ATTRIBUTE_INFORMATION:
-
+ additional_flags = 0;
#if defined(HAVE_SYS_QUOTAS)
- quota_flag = FILE_VOLUME_QUOTAS;
+ additional_flags |= FILE_VOLUME_QUOTAS;
#endif
+ if(lp_nt_acl_support(SNUM(conn))) {
+ additional_flags |= FILE_PERSISTENT_ACLS;
+ }
+
+ if(SMB_VFS_IS_REMOTESTORAGE(conn, lp_pathname(SNUM(conn)))) {
+ additional_flags |= FILE_SUPPORTS_REMOTE_STORAGE;
+ additional_flags |= FILE_SUPPORTS_REPARSE_POINTS;
+ }
+
SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
- (lp_nt_acl_support(SNUM(conn)) ? FILE_PERSISTENT_ACLS : 0)|
- FILE_SUPPORTS_OBJECT_IDS|
- FILE_UNICODE_ON_DISK|
- quota_flag); /* FS ATTRIBUTES */
+ FILE_SUPPORTS_OBJECT_IDS|FILE_UNICODE_ON_DISK|
+ additional_flags); /* FS ATTRIBUTES */
SIVAL(pdata,4,255); /* Max filename component length */
/* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
diff --git a/source3/winbindd/idmap_tdb2.c b/source3/winbindd/idmap_tdb2.c
new file mode 100644
index 0000000000..ab89e615f7
--- /dev/null
+++ b/source3/winbindd/idmap_tdb2.c
@@ -0,0 +1,1017 @@
+/*
+ Unix SMB/CIFS implementation.
+
+ idmap TDB2 backend, used for clustered Samba setups.
+
+ This uses 2 tdb files. One is permanent, and is in shared storage
+ on the cluster (using "tdb:idmap2.tdb =" in smb.conf). The other is a
+ temporary cache tdb on local storage.
+
+ Copyright (C) Andrew Tridgell 2007
+
+ This is heavily based upon idmap_tdb.c, which is:
+
+ Copyright (C) Tim Potter 2000
+ Copyright (C) Jim McDonough <jmcd@us.ibm.com> 2003
+ Copyright (C) Jeremy Allison 2006
+ Copyright (C) Simo Sorce 2003-2006
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#include "includes.h"
+#include "winbindd.h"
+
+#undef DBGC_CLASS
+#define DBGC_CLASS DBGC_IDMAP
+
+/* High water mark keys */
+#define HWM_GROUP "GROUP HWM"
+#define HWM_USER "USER HWM"
+
+static struct idmap_tdb2_state {
+ /* User and group id pool */
+ uid_t low_uid, high_uid; /* Range of uids to allocate */
+ gid_t low_gid, high_gid; /* Range of gids to allocate */
+ const char *idmap_script;
+} idmap_tdb2_state;
+
+
+
+/* tdb context for the local cache tdb */
+static TDB_CONTEXT *idmap_tdb2_tmp;
+
+/* handle to the permanent tdb */
+static struct db_context *idmap_tdb2_perm;
+
+/*
+ open the cache tdb
+ */
+static NTSTATUS idmap_tdb2_open_cache_db(void)
+{
+ const char *db_path;
+
+ if (idmap_tdb2_tmp) {
+ /* its already open */
+ return NT_STATUS_OK;
+ }
+
+ db_path = lock_path("idmap2_cache.tdb");
+
+ /* Open idmap repository */
+ if (!(idmap_tdb2_tmp = tdb_open_log(db_path, 0, TDB_CLEAR_IF_FIRST, O_RDWR|O_CREAT, 0644))) {
+ DEBUG(0, ("Unable to open cache idmap database '%s'\n", db_path));
+ return NT_STATUS_UNSUCCESSFUL;
+ }
+
+ return NT_STATUS_OK;
+}
+
+
+static NTSTATUS idmap_tdb2_alloc_load(void);
+
+/*
+ open the permanent tdb
+ */
+static NTSTATUS idmap_tdb2_open_perm_db(void)
+{
+ char *db_path;
+
+ if (idmap_tdb2_perm) {
+ /* its already open */
+ return NT_STATUS_OK;
+ }
+
+ db_path = lp_parm_talloc_string(-1, "tdb", "idmap2.tdb", NULL);
+ if (db_path == NULL) {
+ /* fall back to the private directory, which, despite
+ its name, is usually on shared storage */
+ db_path = talloc_asprintf(NULL, "%s/idmap2.tdb", lp_private_dir());
+ }
+ NT_STATUS_HAVE_NO_MEMORY(db_path);
+
+ /* Open idmap repository */
+ idmap_tdb2_perm = db_open(NULL, db_path, 0, TDB_DEFAULT,
+ O_RDWR|O_CREAT, 0644);
+ TALLOC_FREE(db_path);
+
+ if (idmap_tdb2_perm == NULL) {
+ DEBUG(0, ("Unable to open permanent idmap database '%s'\n",
+ db_path));
+ return NT_STATUS_UNSUCCESSFUL;
+ }
+
+ /* load the ranges and high/low water marks */
+ return idmap_tdb2_alloc_load();
+}
+
+
+/*
+ load the idmap allocation ranges and high/low water marks
+*/
+static NTSTATUS idmap_tdb2_alloc_load(void)
+{
+ const char *range;
+ uid_t low_uid = 0;
+ uid_t high_uid = 0;
+ gid_t low_gid = 0;
+ gid_t high_gid = 0;
+
+ /* load ranges */
+ idmap_tdb2_state.low_uid = 0;
+ idmap_tdb2_state.high_uid = 0;
+ idmap_tdb2_state.low_gid = 0;
+ idmap_tdb2_state.high_gid = 0;
+
+ /* see if a idmap script is configured */
+ idmap_tdb2_state.idmap_script = lp_parm_const_string(-1, "idmap", "script", NULL);
+
+ if (idmap_tdb2_state.idmap_script) {
+ DEBUG(1, ("using idmap script '%s'\n", idmap_tdb2_state.idmap_script));
+ }
+
+ range = lp_parm_const_string(-1, "idmap alloc config", "range", NULL);
+ if (range && range[0]) {
+ unsigned low_id, high_id;
+ if (sscanf(range, "%u - %u", &low_id, &high_id) == 2) {
+ if (low_id < high_id) {
+ idmap_tdb2_state.low_gid = idmap_tdb2_state.low_uid = low_id;
+ idmap_tdb2_state.high_gid = idmap_tdb2_state.high_uid = high_id;
+ } else {
+ DEBUG(1, ("ERROR: invalid idmap alloc range [%s]", range));
+ }
+ } else {
+ DEBUG(1, ("ERROR: invalid syntax for idmap alloc config:range [%s]", range));
+ }
+ }
+
+ /* Create high water marks for group and user id */
+ if (lp_idmap_uid(&low_uid, &high_uid)) {
+ idmap_tdb2_state.low_uid = low_uid;
+ idmap_tdb2_state.high_uid = high_uid;
+ }
+
+ if (lp_idmap_gid(&low_gid, &high_gid)) {
+ idmap_tdb2_state.low_gid = low_gid;
+ idmap_tdb2_state.high_gid = high_gid;
+ }
+
+ if (idmap_tdb2_state.high_uid <= idmap_tdb2_state.low_uid) {
+ DEBUG(1, ("idmap uid range missing or invalid\n"));
+ DEBUGADD(1, ("idmap will be unable to map foreign SIDs\n"));
+ return NT_STATUS_UNSUCCESSFUL;
+ } else {
+ uint32 low_id;
+
+ if (((low_id = dbwrap_fetch_int32(idmap_tdb2_perm,
+ HWM_USER)) == -1) ||
+ (low_id < idmap_tdb2_state.low_uid)) {
+ if (dbwrap_store_int32(
+ idmap_tdb2_perm, HWM_USER,
+ idmap_tdb2_state.low_uid) == -1) {
+ DEBUG(0, ("Unable to initialise user hwm in idmap database\n"));
+ return NT_STATUS_INTERNAL_DB_ERROR;
+ }
+ }
+ }
+
+ if (idmap_tdb2_state.high_gid <= idmap_tdb2_state.low_gid) {
+ DEBUG(1, ("idmap gid range missing or invalid\n"));
+ DEBUGADD(1, ("idmap will be unable to map foreign SIDs\n"));
+ return NT_STATUS_UNSUCCESSFUL;
+ } else {
+ uint32 low_id;
+
+ if (((low_id = dbwrap_fetch_int32(idmap_tdb2_perm,
+ HWM_GROUP)) == -1) ||
+ (low_id < idmap_tdb2_state.low_gid)) {
+ if (dbwrap_store_int32(
+ idmap_tdb2_perm, HWM_GROUP,
+ idmap_tdb2_state.low_gid) == -1) {
+ DEBUG(0, ("Unable to initialise group hwm in idmap database\n"));
+ return NT_STATUS_INTERNAL_DB_ERROR;
+ }
+ }
+ }
+
+ return NT_STATUS_OK;
+}
+
+
+/*
+ Initialise idmap alloc database.
+*/
+static NTSTATUS idmap_tdb2_alloc_init(const char *params)
+{
+ /* nothing to do - we want to avoid opening the permanent
+ database if possible. Instead we load the params when we
+ first need it. */
+ return NT_STATUS_OK;
+}
+
+
+/*
+ Allocate a new id.
+*/
+static NTSTATUS idmap_tdb2_allocate_id(struct unixid *xid)
+{
+ bool ret;
+ const char *hwmkey;
+ const char *hwmtype;
+ uint32_t high_hwm;
+ uint32_t hwm;
+ NTSTATUS status;
+
+ status = idmap_tdb2_open_perm_db();
+ NT_STATUS_NOT_OK_RETURN(status);
+
+ /* Get current high water mark */
+ switch (xid->type) {
+
+ case ID_TYPE_UID:
+ hwmkey = HWM_USER;
+ hwmtype = "UID";
+ high_hwm = idmap_tdb2_state.high_uid;
+ break;
+
+ case ID_TYPE_GID:
+ hwmkey = HWM_GROUP;
+ hwmtype = "GID";
+ high_hwm = idmap_tdb2_state.high_gid;
+ break;
+
+ default:
+ DEBUG(2, ("Invalid ID type (0x%x)\n", xid->type));
+ return NT_STATUS_INVALID_PARAMETER;
+ }
+
+ if ((hwm = dbwrap_fetch_int32(idmap_tdb2_perm, hwmkey)) == -1) {
+ return NT_STATUS_INTERNAL_DB_ERROR;
+ }
+
+ /* check it is in the range */
+ if (hwm > high_hwm) {
+ DEBUG(1, ("Fatal Error: %s range full!! (max: %lu)\n",
+ hwmtype, (unsigned long)high_hwm));
+ return NT_STATUS_UNSUCCESSFUL;
+ }
+
+ /* fetch a new id and increment it */
+ ret = dbwrap_change_uint32_atomic(idmap_tdb2_perm, hwmkey, &hwm, 1);
+ if (ret == -1) {
+ DEBUG(1, ("Fatal error while fetching a new %s value\n!", hwmtype));
+ return NT_STATUS_UNSUCCESSFUL;
+ }
+
+ /* recheck it is in the range */
+ if (hwm > high_hwm) {
+ DEBUG(1, ("Fatal Error: %s range full!! (max: %lu)\n",
+ hwmtype, (unsigned long)high_hwm));
+ return NT_STATUS_UNSUCCESSFUL;
+ }
+
+ xid->id = hwm;
+ DEBUG(10,("New %s = %d\n", hwmtype, hwm));
+
+ return NT_STATUS_OK;
+}
+
+/*
+ Get current highest id.
+*/
+static NTSTATUS idmap_tdb2_get_hwm(struct unixid *xid)
+{
+ const char *hwmkey;
+ const char *hwmtype;
+ uint32_t hwm;
+ uint32_t high_hwm;
+
+ /* Get current high water mark */
+ switch (xid->type) {
+
+ case ID_TYPE_UID:
+ hwmkey = HWM_USER;
+ hwmtype = "UID";
+ high_hwm = idmap_tdb2_state.high_uid;
+ break;
+
+ case ID_TYPE_GID:
+ hwmkey = HWM_GROUP;
+ hwmtype = "GID";
+ high_hwm = idmap_tdb2_state.high_gid;
+ break;
+
+ default:
+ return NT_STATUS_INVALID_PARAMETER;
+ }
+
+ if ((hwm = dbwrap_fetch_int32(idmap_tdb2_perm, hwmkey)) == -1) {
+ return NT_STATUS_INTERNAL_DB_ERROR;
+ }
+
+ xid->id = hwm;
+
+ /* Warn if it is out of range */
+ if (hwm >= high_hwm) {
+ DEBUG(0, ("Warning: %s range full!! (max: %lu)\n",
+ hwmtype, (unsigned long)high_hwm));
+ }
+
+ return NT_STATUS_OK;
+}
+
+/*
+ Set high id.
+*/
+static NTSTATUS idmap_tdb2_set_hwm(struct unixid *xid)
+{
+ /* not supported, or we would invalidate the cache tdb on
+ other nodes */
+ DEBUG(0,("idmap_tdb2_set_hwm not supported\n"));
+ return NT_STATUS_NOT_SUPPORTED;
+}
+
+/*
+ Close the alloc tdb
+*/
+static NTSTATUS idmap_tdb2_alloc_close(void)
+{
+ /* don't actually close it */
+ return NT_STATUS_OK;
+}
+
+/*
+ IDMAP MAPPING TDB BACKEND
+*/
+struct idmap_tdb2_context {
+ uint32_t filter_low_id;
+ uint32_t filter_high_id;
+};
+
+/*
+ try fetching from the cache tdb, and if that fails then
+ fetch from the permanent tdb
+ */
+static TDB_DATA tdb2_fetch_bystring(TALLOC_CTX *mem_ctx, const char *keystr)
+{
+ TDB_DATA ret;
+ NTSTATUS status;
+
+ ret = tdb_fetch_bystring(idmap_tdb2_tmp, keystr);
+ if (ret.dptr != NULL) {
+ /* got it from cache */
+ unsigned char *tmp;
+
+ tmp = (unsigned char *)talloc_memdup(mem_ctx, ret.dptr,
+ ret.dsize);
+ SAFE_FREE(ret.dptr);
+ ret.dptr = tmp;
+
+ if (ret.dptr == NULL) {
+ return make_tdb_data(NULL, 0);
+ }
+ return ret;
+ }
+
+ status = idmap_tdb2_open_perm_db();
+ if (!NT_STATUS_IS_OK(status)) {
+ return ret;
+ }
+
+ /* fetch from the permanent tdb */
+ return dbwrap_fetch_bystring(idmap_tdb2_perm, mem_ctx, keystr);
+}
+
+/*
+ store into both databases
+ */
+static NTSTATUS tdb2_store_bystring(const char *keystr, TDB_DATA data, int flags)
+{
+ NTSTATUS ret;
+ NTSTATUS status = idmap_tdb2_open_perm_db();
+ if (!NT_STATUS_IS_OK(status)) {
+ return NT_STATUS_UNSUCCESSFUL;
+ }
+ ret = dbwrap_store_bystring(idmap_tdb2_perm, keystr, data, flags);
+ if (!NT_STATUS_IS_OK(ret)) {
+ ret = tdb_store_bystring(idmap_tdb2_tmp, keystr, data, flags) ? NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL;
+ }
+ return ret;
+}
+
+/*
+ delete from both databases
+ */
+static NTSTATUS tdb2_delete_bystring(const char *keystr)
+{
+ NTSTATUS ret;
+ NTSTATUS status = idmap_tdb2_open_perm_db();
+ if (!NT_STATUS_IS_OK(status)) {
+ return NT_STATUS_UNSUCCESSFUL;
+ }
+ ret = dbwrap_delete_bystring(idmap_tdb2_perm, keystr);
+ if (!NT_STATUS_IS_OK(ret)) {
+ ret = tdb_delete_bystring(idmap_tdb2_tmp, keystr) ? NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL;
+ }
+ return ret;
+}
+
+/*
+ Initialise idmap database.
+*/
+static NTSTATUS idmap_tdb2_db_init(struct idmap_domain *dom)
+{
+ NTSTATUS ret;
+ struct idmap_tdb2_context *ctx;
+ char *config_option = NULL;
+ const char *range;
+ NTSTATUS status;
+
+ status = idmap_tdb2_open_cache_db();
+ NT_STATUS_NOT_OK_RETURN(status);
+
+ ctx = talloc(dom, struct idmap_tdb2_context);
+ if ( ! ctx) {
+ DEBUG(0, ("Out of memory!\n"));
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ config_option = talloc_asprintf(ctx, "idmap config %s", dom->name);
+ if ( ! config_option) {
+ DEBUG(0, ("Out of memory!\n"));
+ ret = NT_STATUS_NO_MEMORY;
+ goto failed;
+ }
+
+ range = lp_parm_const_string(-1, config_option, "range", NULL);
+ if (( ! range) ||
+ (sscanf(range, "%u - %u", &ctx->filter_low_id, &ctx->filter_high_id) != 2) ||
+ (ctx->filter_low_id > ctx->filter_high_id)) {
+ ctx->filter_low_id = 0;
+ ctx->filter_high_id = 0;
+ }
+
+ dom->private_data = ctx;
+ dom->initialized = True;
+
+ talloc_free(config_option);
+ return NT_STATUS_OK;
+
+failed:
+ talloc_free(ctx);
+ return ret;
+}
+
+
+/*
+ run a script to perform a mapping
+
+ The script should the following command lines:
+
+ SIDTOID S-1-xxxx
+ IDTOSID UID xxxx
+ IDTOSID GID xxxx
+
+ and should return one of the following as a single line of text
+ UID:xxxx
+ GID:xxxx
+ SID:xxxx
+ ERR:xxxx
+ */
+static NTSTATUS idmap_tdb2_script(struct idmap_tdb2_context *ctx, struct id_map *map,
+ const char *fmt, ...)
+{
+ va_list ap;
+ char *cmd;
+ FILE *p;
+ char line[64];
+ unsigned long v;
+
+ cmd = talloc_asprintf(ctx, "%s ", idmap_tdb2_state.idmap_script);
+ NT_STATUS_HAVE_NO_MEMORY(cmd);
+
+ va_start(ap, fmt);
+ cmd = talloc_vasprintf_append(cmd, fmt, ap);
+ va_end(ap);
+ NT_STATUS_HAVE_NO_MEMORY(cmd);
+
+ p = popen(cmd, "r");
+ talloc_free(cmd);
+ if (p == NULL) {
+ return NT_STATUS_NONE_MAPPED;
+ }
+
+ if (fgets(line, sizeof(line)-1, p) == NULL) {
+ pclose(p);
+ return NT_STATUS_NONE_MAPPED;
+ }
+ pclose(p);
+
+ DEBUG(10,("idmap script gave: %s\n", line));
+
+ if (sscanf(line, "UID:%lu", &v) == 1) {
+ map->xid.id = v;
+ map->xid.type = ID_TYPE_UID;
+ } else if (sscanf(line, "GID:%lu", &v) == 1) {
+ map->xid.id = v;
+ map->xid.type = ID_TYPE_GID;
+ } else if (strncmp(line, "SID:S-", 6) == 0) {
+ if (!string_to_sid(map->sid, &line[4])) {
+ DEBUG(0,("Bad SID in '%s' from idmap script %s\n",
+ line, idmap_tdb2_state.idmap_script));
+ return NT_STATUS_NONE_MAPPED;
+ }
+ } else {
+ DEBUG(0,("Bad reply '%s' from idmap script %s\n",
+ line, idmap_tdb2_state.idmap_script));
+ return NT_STATUS_NONE_MAPPED;
+ }
+
+ return NT_STATUS_OK;
+}
+
+
+
+/*
+ Single id to sid lookup function.
+*/
+static NTSTATUS idmap_tdb2_id_to_sid(struct idmap_tdb2_context *ctx, struct id_map *map)
+{
+ NTSTATUS ret;
+ TDB_DATA data;
+ char *keystr;
+
+ if (!ctx || !map) {
+ return NT_STATUS_INVALID_PARAMETER;
+ }
+
+ /* apply filters before checking */
+ if ((ctx->filter_low_id && (map->xid.id < ctx->filter_low_id)) ||
+ (ctx->filter_high_id && (map->xid.id > ctx->filter_high_id))) {
+ DEBUG(5, ("Requested id (%u) out of range (%u - %u). Filtered!\n",
+ map->xid.id, ctx->filter_low_id, ctx->filter_high_id));
+ return NT_STATUS_NONE_MAPPED;
+ }
+
+ switch (map->xid.type) {
+
+ case ID_TYPE_UID:
+ keystr = talloc_asprintf(ctx, "UID %lu", (unsigned long)map->xid.id);
+ break;
+
+ case ID_TYPE_GID:
+ keystr = talloc_asprintf(ctx, "GID %lu", (unsigned long)map->xid.id);
+ break;
+
+ default:
+ DEBUG(2, ("INVALID unix ID type: 0x02%x\n", map->xid.type));
+ return NT_STATUS_INVALID_PARAMETER;
+ }
+
+ /* final SAFE_FREE safe */
+ data.dptr = NULL;
+
+ if (keystr == NULL) {
+ DEBUG(0, ("Out of memory!\n"));
+ ret = NT_STATUS_NO_MEMORY;
+ goto done;
+ }
+
+ DEBUG(10,("Fetching record %s\n", keystr));
+
+ /* Check if the mapping exists */
+ data = tdb2_fetch_bystring(keystr, keystr);
+
+ if (!data.dptr) {
+ fstring sidstr;
+
+ DEBUG(10,("Record %s not found\n", keystr));
+ if (idmap_tdb2_state.idmap_script == NULL) {
+ ret = NT_STATUS_NONE_MAPPED;
+ goto done;
+ }
+
+ ret = idmap_tdb2_script(ctx, map, "IDTOSID %s", keystr);
+
+ /* store it on shared storage */
+ if (!NT_STATUS_IS_OK(ret)) {
+ goto done;
+ }
+
+ if (sid_to_fstring(sidstr, map->sid)) {
+ /* both forward and reverse mappings */
+ tdb2_store_bystring(keystr,
+ string_term_tdb_data(sidstr),
+ TDB_REPLACE);
+ tdb2_store_bystring(sidstr,
+ string_term_tdb_data(keystr),
+ TDB_REPLACE);
+ }
+ goto done;
+ }
+
+ if (!string_to_sid(map->sid, (const char *)data.dptr)) {
+ DEBUG(10,("INVALID SID (%s) in record %s\n",
+ (const char *)data.dptr, keystr));
+ ret = NT_STATUS_INTERNAL_DB_ERROR;
+ goto done;
+ }
+
+ DEBUG(10,("Found record %s -> %s\n", keystr, (const char *)data.dptr));
+ ret = NT_STATUS_OK;
+
+done:
+ talloc_free(keystr);
+ return ret;
+}
+
+
+/*
+ Single sid to id lookup function.
+*/
+static NTSTATUS idmap_tdb2_sid_to_id(struct idmap_tdb2_context *ctx, struct id_map *map)
+{
+ NTSTATUS ret;
+ TDB_DATA data;
+ char *keystr;
+ unsigned long rec_id = 0;
+
+ if ((keystr = sid_string_talloc(ctx, map->sid)) == NULL) {
+ DEBUG(0, ("Out of memory!\n"));
+ ret = NT_STATUS_NO_MEMORY;
+ goto done;
+ }
+
+ DEBUG(10,("Fetching record %s\n", keystr));
+
+ /* Check if sid is present in database */
+ data = tdb2_fetch_bystring(keystr, keystr);
+ if (!data.dptr) {
+ fstring idstr;
+
+ DEBUG(10,(__location__ " Record %s not found\n", keystr));
+
+ if (idmap_tdb2_state.idmap_script == NULL) {
+ ret = NT_STATUS_NONE_MAPPED;
+ goto done;
+ }
+
+ ret = idmap_tdb2_script(ctx, map, "SIDTOID %s", keystr);
+ /* store it on shared storage */
+ if (!NT_STATUS_IS_OK(ret)) {
+ goto done;
+ }
+
+ snprintf(idstr, sizeof(idstr), "%cID %lu",
+ map->xid.type == ID_TYPE_UID?'U':'G',
+ (unsigned long)map->xid.id);
+ /* store both forward and reverse mappings */
+ tdb2_store_bystring(keystr, string_term_tdb_data(idstr),
+ TDB_REPLACE);
+ tdb2_store_bystring(idstr, string_term_tdb_data(keystr),
+ TDB_REPLACE);
+ goto done;
+ }
+
+ /* What type of record is this ? */
+ if (sscanf((const char *)data.dptr, "UID %lu", &rec_id) == 1) { /* Try a UID record. */
+ map->xid.id = rec_id;
+ map->xid.type = ID_TYPE_UID;
+ DEBUG(10,("Found uid record %s -> %s \n", keystr, (const char *)data.dptr ));
+ ret = NT_STATUS_OK;
+
+ } else if (sscanf((const char *)data.dptr, "GID %lu", &rec_id) == 1) { /* Try a GID record. */
+ map->xid.id = rec_id;
+ map->xid.type = ID_TYPE_GID;
+ DEBUG(10,("Found gid record %s -> %s \n", keystr, (const char *)data.dptr ));
+ ret = NT_STATUS_OK;
+
+ } else { /* Unknown record type ! */
+ DEBUG(2, ("Found INVALID record %s -> %s\n", keystr, (const char *)data.dptr));
+ ret = NT_STATUS_INTERNAL_DB_ERROR;
+ }
+
+ /* apply filters before returning result */
+ if ((ctx->filter_low_id && (map->xid.id < ctx->filter_low_id)) ||
+ (ctx->filter_high_id && (map->xid.id > ctx->filter_high_id))) {
+ DEBUG(5, ("Requested id (%u) out of range (%u - %u). Filtered!\n",
+ map->xid.id, ctx->filter_low_id, ctx->filter_high_id));
+ ret = NT_STATUS_NONE_MAPPED;
+ }
+
+done:
+ talloc_free(keystr);
+ return ret;
+}
+
+/*
+ lookup a set of unix ids.
+*/
+static NTSTATUS idmap_tdb2_unixids_to_sids(struct idmap_domain *dom, struct id_map **ids)
+{
+ struct idmap_tdb2_context *ctx;
+ NTSTATUS ret;
+ int i;
+
+ /* make sure we initialized */
+ if ( ! dom->initialized) {
+ ret = idmap_tdb2_db_init(dom);
+ if ( ! NT_STATUS_IS_OK(ret)) {
+ return ret;
+ }
+ }
+
+ ctx = talloc_get_type(dom->private_data, struct idmap_tdb2_context);
+
+ for (i = 0; ids[i]; i++) {
+ ret = idmap_tdb2_id_to_sid(ctx, ids[i]);
+ if ( ! NT_STATUS_IS_OK(ret)) {
+
+ /* if it is just a failed mapping continue */
+ if (NT_STATUS_EQUAL(ret, NT_STATUS_NONE_MAPPED)) {
+
+ /* make sure it is marked as unmapped */
+ ids[i]->status = ID_UNMAPPED;
+ continue;
+ }
+
+ /* some fatal error occurred, return immediately */
+ goto done;
+ }
+
+ /* all ok, id is mapped */
+ ids[i]->status = ID_MAPPED;
+ }
+
+ ret = NT_STATUS_OK;
+
+done:
+ return ret;
+}
+
+/*
+ lookup a set of sids.
+*/
+static NTSTATUS idmap_tdb2_sids_to_unixids(struct idmap_domain *dom, struct id_map **ids)
+{
+ struct idmap_tdb2_context *ctx;
+ NTSTATUS ret;
+ int i;
+
+ /* make sure we initialized */
+ if ( ! dom->initialized) {
+ ret = idmap_tdb2_db_init(dom);
+ if ( ! NT_STATUS_IS_OK(ret)) {
+ return ret;
+ }
+ }
+
+ ctx = talloc_get_type(dom->private_data, struct idmap_tdb2_context);
+
+ for (i = 0; ids[i]; i++) {
+ ret = idmap_tdb2_sid_to_id(ctx, ids[i]);
+ if ( ! NT_STATUS_IS_OK(ret)) {
+
+ /* if it is just a failed mapping continue */
+ if (NT_STATUS_EQUAL(ret, NT_STATUS_NONE_MAPPED)) {
+
+ /* make sure it is marked as unmapped */
+ ids[i]->status = ID_UNMAPPED;
+ continue;
+ }
+
+ /* some fatal error occurred, return immediately */
+ goto done;
+ }
+
+ /* all ok, id is mapped */
+ ids[i]->status = ID_MAPPED;
+ }
+
+ ret = NT_STATUS_OK;
+
+done:
+ return ret;
+}
+
+
+/*
+ set a mapping.
+*/
+static NTSTATUS idmap_tdb2_set_mapping(struct idmap_domain *dom, const struct id_map *map)
+{
+ struct idmap_tdb2_context *ctx;
+ NTSTATUS ret;
+ TDB_DATA data;
+ char *ksidstr, *kidstr;
+ struct db_record *update_lock = NULL;
+ struct db_record *rec = NULL;
+
+ /* make sure we initialized */
+ if ( ! dom->initialized) {
+ ret = idmap_tdb2_db_init(dom);
+ if ( ! NT_STATUS_IS_OK(ret)) {
+ return ret;
+ }
+ }
+
+ if (!map || !map->sid) {
+ return NT_STATUS_INVALID_PARAMETER;
+ }
+
+ ksidstr = kidstr = NULL;
+ data.dptr = NULL;
+
+ /* TODO: should we filter a set_mapping using low/high filters ? */
+
+ ctx = talloc_get_type(dom->private_data, struct idmap_tdb2_context);
+
+ switch (map->xid.type) {
+
+ case ID_TYPE_UID:
+ kidstr = talloc_asprintf(ctx, "UID %lu", (unsigned long)map->xid.id);
+ break;
+
+ case ID_TYPE_GID:
+ kidstr = talloc_asprintf(ctx, "GID %lu", (unsigned long)map->xid.id);
+ break;
+
+ default:
+ DEBUG(2, ("INVALID unix ID type: 0x02%x\n", map->xid.type));
+ return NT_STATUS_INVALID_PARAMETER;
+ }
+
+ if (kidstr == NULL) {
+ DEBUG(0, ("ERROR: Out of memory!\n"));
+ ret = NT_STATUS_NO_MEMORY;
+ goto done;
+ }
+
+ if (!(ksidstr = sid_string_talloc(ctx, map->sid))) {
+ DEBUG(0, ("Out of memory!\n"));
+ ret = NT_STATUS_NO_MEMORY;
+ goto done;
+ }
+
+ DEBUG(10, ("Storing %s <-> %s map\n", ksidstr, kidstr));
+
+ /*
+ * Get us the update lock. This is necessary to get the lock orders
+ * right, we need to deal with two records under a lock.
+ */
+
+ if (!(update_lock = idmap_tdb2_perm->fetch_locked(
+ idmap_tdb2_perm, ctx,
+ string_term_tdb_data("UPDATELOCK")))) {
+ DEBUG(10,("Failed to lock record %s\n", ksidstr));
+ ret = NT_STATUS_UNSUCCESSFUL;
+ goto done;
+ }
+
+ /*
+ * *DELETE* previous mappings if any. *
+ */
+
+ /* First delete indexed on SID */
+
+ if (((rec = idmap_tdb2_perm->fetch_locked(
+ idmap_tdb2_perm, update_lock,
+ string_term_tdb_data(ksidstr))) != NULL)
+ && (rec->value.dsize != 0)) {
+ struct db_record *rec2;
+
+ if ((rec2 = idmap_tdb2_perm->fetch_locked(
+ idmap_tdb2_perm, update_lock, rec->value))
+ != NULL) {
+ rec2->delete_rec(rec2);
+ TALLOC_FREE(rec2);
+ }
+
+ rec->delete_rec(rec);
+
+ tdb_delete(idmap_tdb2_tmp, rec->key);
+ tdb_delete(idmap_tdb2_tmp, rec->value);
+ }
+ TALLOC_FREE(rec);
+
+ /* Now delete indexed on unix ID */
+
+ if (((rec = idmap_tdb2_perm->fetch_locked(
+ idmap_tdb2_perm, update_lock,
+ string_term_tdb_data(kidstr))) != NULL)
+ && (rec->value.dsize != 0)) {
+ struct db_record *rec2;
+
+ if ((rec2 = idmap_tdb2_perm->fetch_locked(
+ idmap_tdb2_perm, update_lock, rec->value))
+ != NULL) {
+ rec2->delete_rec(rec2);
+ TALLOC_FREE(rec2);
+ }
+
+ rec->delete_rec(rec);
+
+ tdb_delete(idmap_tdb2_tmp, rec->key);
+ tdb_delete(idmap_tdb2_tmp, rec->value);
+ }
+ TALLOC_FREE(rec);
+
+ if (!NT_STATUS_IS_OK(tdb2_store_bystring(ksidstr, string_term_tdb_data(kidstr),
+ TDB_INSERT))) {
+ DEBUG(0, ("Error storing SID -> ID\n"));
+ ret = NT_STATUS_UNSUCCESSFUL;
+ goto done;
+ }
+ if (!NT_STATUS_IS_OK(tdb2_store_bystring(kidstr, string_term_tdb_data(ksidstr),
+ TDB_INSERT))) {
+ DEBUG(0, ("Error storing ID -> SID\n"));
+ /* try to remove the previous stored SID -> ID map */
+ tdb2_delete_bystring(ksidstr);
+ ret = NT_STATUS_UNSUCCESSFUL;
+ goto done;
+ }
+
+ DEBUG(10,("Stored %s <-> %s\n", ksidstr, kidstr));
+ ret = NT_STATUS_OK;
+
+done:
+ talloc_free(ksidstr);
+ talloc_free(kidstr);
+ SAFE_FREE(data.dptr);
+ TALLOC_FREE(update_lock);
+ return ret;
+}
+
+/*
+ remove a mapping.
+*/
+static NTSTATUS idmap_tdb2_remove_mapping(struct idmap_domain *dom, const struct id_map *map)
+{
+ /* not supported as it would invalidate the cache tdb on other
+ nodes */
+ DEBUG(0,("idmap_tdb2_remove_mapping not supported\n"));
+ return NT_STATUS_NOT_SUPPORTED;
+}
+
+/*
+ Close the idmap tdb instance
+*/
+static NTSTATUS idmap_tdb2_close(struct idmap_domain *dom)
+{
+ /* don't do anything */
+ return NT_STATUS_OK;
+}
+
+
+/*
+ Dump all mappings out
+*/
+static NTSTATUS idmap_tdb2_dump_data(struct idmap_domain *dom, struct id_map **maps, int *num_maps)
+{
+ DEBUG(0,("idmap_tdb2_dump_data not supported\n"));
+ return NT_STATUS_NOT_SUPPORTED;
+}
+
+static struct idmap_methods db_methods = {
+ .init = idmap_tdb2_db_init,
+ .unixids_to_sids = idmap_tdb2_unixids_to_sids,
+ .sids_to_unixids = idmap_tdb2_sids_to_unixids,
+ .set_mapping = idmap_tdb2_set_mapping,
+ .remove_mapping = idmap_tdb2_remove_mapping,
+ .dump_data = idmap_tdb2_dump_data,
+ .close_fn = idmap_tdb2_close
+};
+
+static struct idmap_alloc_methods db_alloc_methods = {
+ .init = idmap_tdb2_alloc_init,
+ .allocate_id = idmap_tdb2_allocate_id,
+ .get_id_hwm = idmap_tdb2_get_hwm,
+ .set_id_hwm = idmap_tdb2_set_hwm,
+ .close_fn = idmap_tdb2_alloc_close
+};
+
+NTSTATUS idmap_tdb2_init(void)
+{
+ NTSTATUS ret;
+
+ /* register both backends */
+ ret = smb_register_idmap_alloc(SMB_IDMAP_INTERFACE_VERSION, "tdb2", &db_alloc_methods);
+ if (! NT_STATUS_IS_OK(ret)) {
+ DEBUG(0, ("Unable to register idmap alloc tdb2 module: %s\n", get_friendly_nt_error_msg(ret)));
+ return ret;
+ }
+
+ return smb_register_idmap(SMB_IDMAP_INTERFACE_VERSION, "tdb2", &db_methods);
+}