diff options
author | Alexander Bokovoy <ab@samba.org> | 2008-01-16 23:24:44 +0300 |
---|---|---|
committer | Alexander Bokovoy <ab@samba.org> | 2008-01-16 23:24:44 +0300 |
commit | fd03ea4a903b79a0a7894315b3b43fb08108f938 (patch) | |
tree | 0dbce899aca9e727977b2a0becbcc78c6c2de6a4 /source3 | |
parent | e2ffd5110173c6c7d9c15853646988e536331ed0 (diff) | |
parent | 60c3ec3fca08b7d36df760cd6093adb5a807afa0 (diff) | |
download | samba-fd03ea4a903b79a0a7894315b3b43fb08108f938.tar.gz samba-fd03ea4a903b79a0a7894315b3b43fb08108f938.tar.bz2 samba-fd03ea4a903b79a0a7894315b3b43fb08108f938.zip |
Merge branch 'v3-2-test' of ssh://git.samba.org/data/git/samba into v3-2-test
(This used to be commit b01f34141509c90b12003786957790866c286cba)
Diffstat (limited to 'source3')
97 files changed, 6109 insertions, 1053 deletions
diff --git a/source3/Makefile.in b/source3/Makefile.in index c34f3283db..265d14547c 100644 --- a/source3/Makefile.in +++ b/source3/Makefile.in @@ -268,7 +268,8 @@ LIBNDR_GEN_OBJ = librpc/gen_ndr/ndr_wkssvc.o \ librpc/gen_ndr/ndr_srvsvc.o \ librpc/gen_ndr/ndr_svcctl.o \ librpc/gen_ndr/ndr_eventlog.o \ - librpc/gen_ndr/ndr_notify.o + librpc/gen_ndr/ndr_notify.o \ + librpc/gen_ndr/ndr_libnet_join.o RPC_PARSE_OBJ0 = rpc_parse/parse_prs.o rpc_parse/parse_misc.o @@ -307,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 \ @@ -340,13 +341,13 @@ LIBADDNS_OBJ0 = libaddns/dnsrecord.o libaddns/dnsutils.o libaddns/dnssock.o \ libaddns/dnsgss.o libaddns/dnsmarshall.o LIBADDNS_OBJ = $(LIBADDNS_OBJ0) $(TALLOC_OBJ) -LIBWBCLIENT_OBJ = nsswitch/libwbclient/wbclient.o \ +LIBWBCLIENT_OBJ0 = nsswitch/libwbclient/wbclient.o \ nsswitch/libwbclient/wbc_util.o \ nsswitch/libwbclient/wbc_pwd.o \ nsswitch/libwbclient/wbc_idmap.o \ nsswitch/libwbclient/wbc_sid.o \ nsswitch/libwbclient/wbc_pam.o - +LIBWBCLIENT_OBJ = $(LIBWBCLIENT_OBJ0) $(WBCOMMON_OBJ) $(TALLOC_OBJ) $(LIBREPLACE_OBJ) LIBGPO_OBJ0 = libgpo/gpo_ldap.o libgpo/gpo_ini.o libgpo/gpo_util.o \ libgpo/gpo_fetch.o libgpo/gpo_filesync.o libgpo/gpo_sec.o @@ -502,7 +503,9 @@ 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 VFS_AIXACL_OBJ = modules/vfs_aixacl.o modules/vfs_aixacl_util.o VFS_AIXACL2_OBJ = modules/vfs_aixacl2.o modules/vfs_aixacl_util.o modules/nfs4_acls.o @@ -518,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 @@ -671,7 +675,7 @@ RPCCLIENT_OBJ = $(RPCCLIENT_OBJ1) \ $(SMBLDAP_OBJ) $(DCUTIL_OBJ) $(LDB_OBJ) PAM_WINBIND_OBJ = nsswitch/pam_winbind.o $(WBCOMMON_OBJ) \ - $(LIBREPLACE_OBJ) $(SOCKET_WRAPPER_OBJ) @BUILD_INIPARSER@ + $(LIBREPLACE_OBJ) @BUILD_INIPARSER@ LIBSMBCLIENT_OBJ = libsmb/libsmbclient.o libsmb/libsmb_compat.o \ libsmb/libsmb_cache.o \ @@ -928,7 +932,7 @@ WBINFO_OBJ = nsswitch/wbinfo.o $(LIBSAMBA_OBJ) $(PARAM_OBJ) $(LIB_NONSMBD_OBJ) \ $(SECRETS_OBJ) $(POPT_LIB_OBJ) $(AFS_SETTOKEN_OBJ) $(RPC_PARSE_OBJ1) \ $(DOSERR_OBJ) lib/winbind_util.o @LIBWBCLIENT_STATIC@ -WINBIND_NSS_OBJ = $(WBCOMMON_OBJ) $(LIBREPLACE_OBJ) $(SOCKET_WRAPPER_OBJ) @WINBIND_NSS_EXTRA_OBJS@ +WINBIND_NSS_OBJ = $(WBCOMMON_OBJ) $(LIBREPLACE_OBJ) @WINBIND_NSS_EXTRA_OBJS@ LDB_COMMON_OBJ=lib/ldb/common/ldb.o lib/ldb/common/ldb_ldif.o \ lib/ldb/common/ldb_parse.o lib/ldb/common/ldb_msg.o lib/ldb/common/ldb_utf8.o \ @@ -966,7 +970,7 @@ LDBDEL_OBJ = $(LDB_CMDLINE_OBJ) lib/ldb/tools/ldbdel.o LDBMODIFY_OBJ = $(LDB_CMDLINE_OBJ) lib/ldb/tools/ldbmodify.o WINBIND_KRB5_LOCATOR_OBJ1 = nsswitch/winbind_krb5_locator.o -WINBIND_KRB5_LOCATOR_OBJ = $(WINBIND_KRB5_LOCATOR_OBJ1) $(WBCOMMON_OBJ) $(LIBREPLACE_OBJ) $(SOCKET_WRAPPER_OBJ) +WINBIND_KRB5_LOCATOR_OBJ = $(WINBIND_KRB5_LOCATOR_OBJ1) $(WBCOMMON_OBJ) $(LIBREPLACE_OBJ) POPT_OBJ=popt/findme.o popt/popt.o popt/poptconfig.o \ popt/popthelp.o popt/poptparse.o @@ -1060,7 +1064,7 @@ modules: SHOWFLAGS $(MODULES) ## Perl IDL Compiler IDL_FILES = unixinfo.idl lsa.idl dfs.idl echo.idl winreg.idl initshutdown.idl \ srvsvc.idl svcctl.idl eventlog.idl wkssvc.idl netlogon.idl notify.idl \ - epmapper.idl messaging.idl + epmapper.idl messaging.idl xattr.idl idl: @IDL_FILES="$(IDL_FILES)" CPP="$(CPP)" PERL="$(PERL)" \ @@ -1396,15 +1400,15 @@ bin/ldbdel: $(BINARY_PREREQS) $(LDBDEL_OBJ) @BUILD_POPT@ @LIBWBCLIENT_SHARED@ @POPTLIBS@ $(KRB5LIBS) $(UUID_LIBS) $(LDAP_LIBS) $(PASSDB_LIBS) \ $(TERMLDFLAGS) $(TERMLIBS) $(NSCD_LIBS) @WINBIND_LIBS@ -bin/libwbclient.@SHLIBEXT@: $(BINARY_PREREQS) $(LIBWBCLIENT_OBJ) nsswitch/wb_common.o $(LIBSAMBAUTIL_OBJ) +bin/libwbclient.@SHLIBEXT@: $(BINARY_PREREQS) $(LIBWBCLIENT_OBJ) @echo Linking shared library $@ - @$(SHLD_DSO) $(LIBWBCLIENT_OBJ) nsswitch/wb_common.o $(LIBSAMBAUTIL_OBJ) \ + @$(SHLD_DSO) $(LIBWBCLIENT_OBJ) \ @SONAMEFLAG@`basename $@`.$(SONAME_VER) @ln -s -f `basename $@` $@.$(SONAME_VER) -bin/libwbclient.a: $(BINARY_PREREQS) $(LIBWBCLIENT_OBJ) +bin/libwbclient.a: $(BINARY_PREREQS) $(LIBWBCLIENT_OBJ0) @echo Linking non-shared library $@ - @-$(AR) -rc $@ $(LIBWBCLIENT_OBJ) + @-$(AR) -rc $@ $(LIBWBCLIENT_OBJ0) bin/libaddns.@SHLIBEXT@: $(BINARY_PREREQS) $(LIBADDNS_OBJ) @echo Linking shared library $@ @@ -1609,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 @@ -1668,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) @@ -1684,6 +1696,10 @@ bin/afsacl.@SHLIBEXT@: $(BINARY_PREREQS) $(VFS_AFSACL_OBJ) @echo "Building plugin $@" @$(SHLD_MODULE) $(VFS_AFSACL_OBJ) +bin/xattr_tdb.@SHLIBEXT@: $(BINARY_PREREQS) $(VFS_XATTR_TDB_OBJ) + @echo "Building plugin $@" + @$(SHLD_MODULE) $(VFS_XATTR_TDB_OBJ) + bin/posixacl.@SHLIBEXT@: $(BINARY_PREREQS) $(VFS_POSIXACL_OBJ) @echo "Building plugin $@" @$(SHLD_MODULE) $(VFS_POSIXACL_OBJ) @@ -1744,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) @@ -1884,9 +1904,10 @@ installlibaddns: installdirs libaddns -$(INSTALLLIBCMD_A) bin/libaddns.a $(DESTDIR)$(LIBDIR) installlibwbclient: installdirs libwbclient - @$(SHELL) $(srcdir)/script/installdirs.sh $(INSTALLPERMS_BIN) $(DESTDIR) $(LIBDIR) $(INCLUDEDIR)/samba + @$(SHELL) $(srcdir)/script/installdirs.sh $(INSTALLPERMS_BIN) $(DESTDIR) $(LIBDIR) -$(INSTALLLIBCMD_SH) bin/libwbclient.@SHLIBEXT@ $(DESTDIR)$(LIBDIR) - -$(INSTALLCMD) -m $(INSTALLPERMS_DATA) $(srcdir)/nsswitch/libwbclient/wbclient.h $(DESTDIR)${prefix}/include/samba + @$(SHELL) $(srcdir)/script/installdirs.sh $(INSTALLPERMS_BIN) $(DESTDIR) ${prefix}/include + -$(INSTALLCMD) -m $(INSTALLPERMS_DATA) $(srcdir)/nsswitch/libwbclient/wbclient.h $(DESTDIR)${prefix}/include installlibnetapi: installdirs libnetapi @$(SHELL) $(srcdir)/script/installdirs.sh $(INSTALLPERMS_BIN) $(DESTDIR) $(LIBDIR) diff --git a/source3/client/cifs.spnego.c b/source3/client/cifs.spnego.c index caa22276c4..d10d19da96 100644 --- a/source3/client/cifs.spnego.c +++ b/source3/client/cifs.spnego.c @@ -3,11 +3,13 @@ * Copyright (C) Igor Mammedov (niallain@gmail.com) 2007 * * Used by /sbin/request-key for handling -* cifs upcall for kerberos authorization of access to share. +* cifs upcall for kerberos authorization of access to share and +* cifs upcall for DFS srver name resolving (IPv4/IPv6 aware). * You should have keyutils installed and add following line to * /etc/request-key.conf file create cifs.spnego * * /usr/local/sbin/cifs.spnego [-v][-c] %k +create cifs.resolver * * /usr/local/sbin/cifs.spnego [-v] %k * 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 @@ -27,7 +29,7 @@ create cifs.spnego * * /usr/local/sbin/cifs.spnego [-v][-c] %k #include "cifs_spnego.h" -const char* CIFSSPNEGO_VERSION="1.0"; +const char *CIFSSPNEGO_VERSION = "1.1"; static const char *prog = "cifs.spnego"; typedef enum _secType { KRB5, @@ -146,6 +148,58 @@ int decode_key_description(const char *desc, int *ver, secType_t * sec, return retval; } +int cifs_resolver(const key_serial_t key, const char *key_descr) +{ + int c; + struct addrinfo *addr; + char ip[INET6_ADDRSTRLEN]; + void *p; + const char *keyend = key_descr; + /* skip next 4 ';' delimiters to get to description */ + for (c = 1; c <= 4; c++) { + keyend = index(keyend+1, ';'); + if (!keyend) { + syslog(LOG_WARNING, "invalid key description: %s", + key_descr); + return 1; + } + } + keyend++; + + /* resolve name to ip */ + c = getaddrinfo(keyend, NULL, NULL, &addr); + if (c) { + syslog(LOG_WARNING, "unable to resolve hostname: %s [%s]", + keyend, gai_strerror(c)); + return 1; + } + + /* conver ip to string form */ + if (addr->ai_family == AF_INET) { + p = &(((struct sockaddr_in *)addr->ai_addr)->sin_addr); + } else { + p = &(((struct sockaddr_in6 *)addr->ai_addr)->sin6_addr); + } + if (!inet_ntop(addr->ai_family, p, ip, sizeof(ip))) { + syslog(LOG_WARNING, "%s: inet_ntop: %s", + __FUNCTION__, strerror(errno)); + freeaddrinfo(addr); + return 1; + } + + /* setup key */ + c = keyctl_instantiate(key, ip, strlen(ip)+1, 0); + if (c == -1) { + syslog(LOG_WARNING, "%s: keyctl_instantiate: %s", + __FUNCTION__, strerror(errno)); + freeaddrinfo(addr); + return 1; + } + + freeaddrinfo(addr); + return 0; +} + int main(const int argc, char *const argv[]) { struct cifs_spnego_msg *keydata = NULL; @@ -199,6 +253,11 @@ int main(const int argc, char *const argv[]) goto out; } + if (strncmp(buf, "cifs.resolver", sizeof("cifs.resolver")-1) == 0) { + rc = cifs_resolver(key, buf); + goto out; + } + rc = decode_key_description(buf, &kernel_upcall_version, §ype, &hostname, &uid); if ((rc & DKD_MUSTHAVE_SET) != DKD_MUSTHAVE_SET) { diff --git a/source3/configure.in b/source3/configure.in index 4222d93227..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" +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,7 +6495,9 @@ 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) SMB_MODULE(vfs_aixacl, \$(VFS_AIXACL_OBJ), "bin/aixacl.$SHLIBEXT", VFS) SMB_MODULE(vfs_aixacl2, \$(VFS_AIXACL2_OBJ), "bin/aixacl2.$SHLIBEXT", VFS) @@ -6502,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) @@ -6656,7 +6666,10 @@ AC_SUBST(SMBD_LIBS) AC_OUTPUT(Makefile library-versions script/findsmb smbadduser script/gen-8bit-gap.sh script/installbin.sh script/uninstallbin.sh lib/netapi/examples/Makefile - pkgconfig/smbclient.pc pkgconfig/netapi.pc pkgconfig/smbsharemodes.pc + pkgconfig/smbclient.pc + pkgconfig/wbclient.pc + pkgconfig/netapi.pc + pkgconfig/smbsharemodes.pc ) ################################################# diff --git a/source3/groupdb/mapping_ldb.c b/source3/groupdb/mapping_ldb.c index 05056eabd2..454fe467a9 100644 --- a/source3/groupdb/mapping_ldb.c +++ b/source3/groupdb/mapping_ldb.c @@ -492,7 +492,7 @@ static NTSTATUS enum_aliasmem(const DOM_SID *alias, DOM_SID **sids, size_t *num) NULL }; int ret, i; - NTSTATUS status; + NTSTATUS status = NT_STATUS_OK; struct ldb_result *res=NULL; struct ldb_dn *dn; struct ldb_message_element *el; diff --git a/source3/groupdb/mapping_tdb.c b/source3/groupdb/mapping_tdb.c index 21a4f95383..67e377c338 100644 --- a/source3/groupdb/mapping_tdb.c +++ b/source3/groupdb/mapping_tdb.c @@ -394,7 +394,7 @@ static NTSTATUS one_alias_membership(const DOM_SID *member, char *string_sid; TDB_DATA dbuf; const char *p; - NTSTATUS status; + NTSTATUS status = NT_STATUS_OK; TALLOC_CTX *frame; slprintf(key, sizeof(key), "%s%s", MEMBEROF_PREFIX, 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/libsmbclient.h b/source3/include/libsmbclient.h index 9175b33d60..07242f7956 100644 --- a/source3/include/libsmbclient.h +++ b/source3/include/libsmbclient.h @@ -1961,7 +1961,7 @@ int smbc_fremovexattr(int fd, * extended attributes * * @note This function always returns all attribute names supported - * by NT file systems, regardless of wether the referenced + * by NT file systems, regardless of whether the referenced * file system supports extended attributes (e.g. a Windows * 2000 machine supports extended attributes if NTFS is used, * but not if FAT is used, and Windows 98 doesn't support 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/smb.h b/source3/include/smb.h index 49245eaa83..744acd719f 100644 --- a/source3/include/smb.h +++ b/source3/include/smb.h @@ -322,6 +322,8 @@ struct id_map { #include "librpc/gen_ndr/wkssvc.h" #include "librpc/gen_ndr/echo.h" #include "librpc/gen_ndr/svcctl.h" +#include "librpc/gen_ndr/libnet_join.h" + struct lsa_dom_info { bool valid; 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/tdb/common/open.c b/source3/lib/tdb/common/open.c index 94140a4baa..b19e4cea29 100644 --- a/source3/lib/tdb/common/open.c +++ b/source3/lib/tdb/common/open.c @@ -179,7 +179,7 @@ struct tdb_context *tdb_open_ex(const char *name, int hash_size, int tdb_flags, tdb->page_size = 0x2000; } - tdb->max_dead_records = (open_flags & TDB_VOLATILE) ? 5 : 0; + tdb->max_dead_records = (tdb_flags & TDB_VOLATILE) ? 5 : 0; if ((open_flags & O_ACCMODE) == O_WRONLY) { TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_open_ex: can't open tdb %s write-only\n", @@ -227,6 +227,7 @@ struct tdb_context *tdb_open_ex(const char *name, int hash_size, int tdb_flags, /* we need to zero database if we are the only one with it open */ if ((tdb_flags & TDB_CLEAR_IF_FIRST) && + (!tdb->read_only) && (locked = (tdb->methods->tdb_brlock(tdb, ACTIVE_LOCK, F_WRLCK, F_SETLK, 0, 1) == 0))) { open_flags |= O_CREAT; if (ftruncate(tdb->fd, 0) == -1) { diff --git a/source3/lib/tdb/common/tdb_private.h b/source3/lib/tdb/common/tdb_private.h index 63a6d04e72..dd69903015 100644 --- a/source3/lib/tdb/common/tdb_private.h +++ b/source3/lib/tdb/common/tdb_private.h @@ -178,6 +178,7 @@ struct tdb_context { int tdb_munmap(struct tdb_context *tdb); void tdb_mmap(struct tdb_context *tdb); int tdb_lock(struct tdb_context *tdb, int list, int ltype); +int tdb_lock_nonblock(struct tdb_context *tdb, int list, int ltype); int tdb_unlock(struct tdb_context *tdb, int list, int ltype); int tdb_brlock(struct tdb_context *tdb, tdb_off_t offset, int rw_type, int lck_type, int probe, size_t len); int tdb_transaction_lock(struct tdb_context *tdb, int ltype); diff --git a/source3/lib/tdb/common/transaction.c b/source3/lib/tdb/common/transaction.c index 0ecfb9b7ff..c3e7a4e2c0 100644 --- a/source3/lib/tdb/common/transaction.c +++ b/source3/lib/tdb/common/transaction.c @@ -219,9 +219,12 @@ static int transaction_write(struct tdb_context *tdb, tdb_off_t off, uint8_t **new_blocks; /* expand the blocks array */ if (tdb->transaction->blocks == NULL) { - new_blocks = malloc((blk+1)*sizeof(uint8_t *)); + new_blocks = (uint8_t **)malloc( + (blk+1)*sizeof(uint8_t *)); } else { - new_blocks = realloc(tdb->transaction->blocks, (blk+1)*sizeof(uint8_t *)); + new_blocks = (uint8_t **)realloc( + tdb->transaction->blocks, + (blk+1)*sizeof(uint8_t *)); } if (new_blocks == NULL) { tdb->ecode = TDB_ERR_OOM; @@ -316,25 +319,15 @@ static int transaction_write_existing(struct tdb_context *tdb, tdb_off_t off, return 0; } - /* overwrite part of an existing block */ - if (buf == NULL) { - memset(tdb->transaction->blocks[blk] + off, 0, len); - } else { - memcpy(tdb->transaction->blocks[blk] + off, buf, len); - } - if (blk == tdb->transaction->num_blocks-1) { - if (len + off > tdb->transaction->last_block_size) { - tdb->transaction->last_block_size = len + off; - } + if (blk == tdb->transaction->num_blocks-1 && + off + len > tdb->transaction->last_block_size) { + len = tdb->transaction->last_block_size - off; } - return 0; + /* overwrite part of an existing block */ + memcpy(tdb->transaction->blocks[blk] + off, buf, len); -fail: - TDB_LOG((tdb, TDB_DEBUG_FATAL, "transaction_write: failed at off=%d len=%d\n", - (blk*tdb->transaction->block_size) + off, len)); - tdb->transaction->transaction_error = 1; - return -1; + return 0; } 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.h b/source3/libnet/libnet.h index d6238ca982..97e720f617 100644 --- a/source3/libnet/libnet.h +++ b/source3/libnet/libnet.h @@ -20,7 +20,7 @@ #ifndef __LIBNET_H__ #define __LIBNET_H__ -#include "libnet/libnet_join.h" +#include "librpc/gen_ndr/libnet_join.h" #include "libnet/libnet_conf.h" #include "libnet/libnet_proto.h" diff --git a/source3/libnet/libnet_join.c b/source3/libnet/libnet_join.c index eaf851ccec..a9978ba4b8 100644 --- a/source3/libnet/libnet_join.c +++ b/source3/libnet/libnet_join.c @@ -24,6 +24,35 @@ /**************************************************************** ****************************************************************/ +#define LIBNET_JOIN_DUMP_CTX(ctx, r, f) \ + do { \ + char *str = NULL; \ + str = NDR_PRINT_FUNCTION_STRING(ctx, libnet_JoinCtx, f, r); \ + DEBUG(1,("libnet_Join:\n%s", str)); \ + talloc_free(str); \ + } while (0) + +#define LIBNET_JOIN_IN_DUMP_CTX(ctx, r) \ + LIBNET_JOIN_DUMP_CTX(ctx, r, NDR_IN | NDR_SET_VALUES) +#define LIBNET_JOIN_OUT_DUMP_CTX(ctx, r) \ + LIBNET_JOIN_DUMP_CTX(ctx, r, NDR_OUT) + +#define LIBNET_UNJOIN_DUMP_CTX(ctx, r, f) \ + do { \ + char *str = NULL; \ + str = NDR_PRINT_FUNCTION_STRING(ctx, libnet_UnjoinCtx, f, r); \ + DEBUG(1,("libnet_Unjoin:\n%s", str)); \ + talloc_free(str); \ + } while (0) + +#define LIBNET_UNJOIN_IN_DUMP_CTX(ctx, r) \ + LIBNET_UNJOIN_DUMP_CTX(ctx, r, NDR_IN | NDR_SET_VALUES) +#define LIBNET_UNJOIN_OUT_DUMP_CTX(ctx, r) \ + LIBNET_UNJOIN_DUMP_CTX(ctx, r, NDR_OUT) + +/**************************************************************** +****************************************************************/ + static void libnet_join_set_error_string(TALLOC_CTX *mem_ctx, struct libnet_JoinCtx *r, const char *format, ...) @@ -107,10 +136,6 @@ static ADS_STATUS libnet_join_connect_ads(TALLOC_CTX *mem_ctx, { ADS_STATUS status; - if (r->in.ads) { - ads_destroy(&r->in.ads); - } - status = libnet_connect_ads(r->in.domain_name, r->in.domain_name, r->in.dc_name, @@ -134,10 +159,6 @@ static ADS_STATUS libnet_unjoin_connect_ads(TALLOC_CTX *mem_ctx, { ADS_STATUS status; - if (r->in.ads) { - ads_destroy(&r->in.ads); - } - status = libnet_connect_ads(r->in.domain_name, r->in.domain_name, r->in.dc_name, @@ -244,7 +265,6 @@ static ADS_STATUS libnet_join_find_machine_acct(TALLOC_CTX *mem_ctx, goto done; } - TALLOC_FREE(r->out.dn); r->out.dn = talloc_strdup(mem_ctx, dn); if (!r->out.dn) { status = ADS_ERROR_LDAP(LDAP_NO_MEMORY); @@ -1013,6 +1033,58 @@ static WERROR do_UnjoinConfig(struct libnet_UnjoinCtx *r) /**************************************************************** ****************************************************************/ +static WERROR libnet_join_pre_processing(TALLOC_CTX *mem_ctx, + struct libnet_JoinCtx *r) +{ + + if (!r->in.domain_name) { + return WERR_INVALID_PARAM; + } + + if (r->in.modify_config && !lp_config_backend_is_registry()) { + return WERR_NOT_SUPPORTED; + } + + if (IS_DC) { + return WERR_SETUP_DOMAIN_CONTROLLER; + } + + if (!secrets_init()) { + libnet_join_set_error_string(mem_ctx, r, + "Unable to open secrets database"); + return WERR_CAN_NOT_COMPLETE; + } + + return WERR_OK; +} + +/**************************************************************** +****************************************************************/ + +static WERROR libnet_join_post_processing(TALLOC_CTX *mem_ctx, + struct libnet_JoinCtx *r) +{ + WERROR werr; + + if (!W_ERROR_IS_OK(r->out.result)) { + return r->out.result; + } + + werr = do_JoinConfig(r); + if (!W_ERROR_IS_OK(werr)) { + return werr; + } + + if (r->in.join_flags & WKSSVC_JOIN_FLAGS_JOIN_TYPE) { + saf_store(r->in.domain_name, r->in.dc_name); + } + + return WERR_OK; +} + +/**************************************************************** +****************************************************************/ + static int libnet_destroy_JoinCtx(struct libnet_JoinCtx *r) { if (r->in.ads) { @@ -1104,8 +1176,9 @@ static WERROR libnet_DomainJoin(TALLOC_CTX *mem_ctx, &info); if (!NT_STATUS_IS_OK(status)) { libnet_join_set_error_string(mem_ctx, r, - "failed to find DC: %s", - nt_errstr(status)); + "failed to find DC for domain %s", + r->in.domain_name, + get_friendly_nt_error_msg(status)); return WERR_DOMAIN_CONTROLLER_NOT_FOUND; } @@ -1139,7 +1212,7 @@ static WERROR libnet_DomainJoin(TALLOC_CTX *mem_ctx, if (!NT_STATUS_IS_OK(status)) { libnet_join_set_error_string(mem_ctx, r, "failed to join domain over rpc: %s", - nt_errstr(status)); + get_friendly_nt_error_msg(status)); if (NT_STATUS_EQUAL(status, NT_STATUS_USER_EXISTS)) { return WERR_SETUP_ALREADY_JOINED; } @@ -1170,30 +1243,32 @@ WERROR libnet_Join(TALLOC_CTX *mem_ctx, { WERROR werr; - if (!r->in.domain_name) { - return WERR_INVALID_PARAM; + if (r->in.debug) { + LIBNET_JOIN_IN_DUMP_CTX(mem_ctx, r); } - if (r->in.modify_config && !lp_include_registry_globals()) { - return WERR_NOT_SUPPORTED; - } - - if (IS_DC) { - return WERR_SETUP_DOMAIN_CONTROLLER; + werr = libnet_join_pre_processing(mem_ctx, r); + if (!W_ERROR_IS_OK(werr)) { + goto done; } if (r->in.join_flags & WKSSVC_JOIN_FLAGS_JOIN_TYPE) { werr = libnet_DomainJoin(mem_ctx, r); if (!W_ERROR_IS_OK(werr)) { - return werr; + goto done; } } - werr = do_JoinConfig(r); + werr = libnet_join_post_processing(mem_ctx, r); if (!W_ERROR_IS_OK(werr)) { - return werr; + goto done; } + done: + r->out.result = werr; + if (r->in.debug) { + LIBNET_JOIN_OUT_DUMP_CTX(mem_ctx, r); + } return werr; } @@ -1205,11 +1280,46 @@ static WERROR libnet_DomainUnjoin(TALLOC_CTX *mem_ctx, { NTSTATUS status; + if (!r->in.domain_sid) { + struct dom_sid sid; + if (!secrets_fetch_domain_sid(lp_workgroup(), &sid)) { + libnet_unjoin_set_error_string(mem_ctx, r, + "Unable to fetch domain sid: are we joined?"); + return WERR_SETUP_NOT_JOINED; + } + r->in.domain_sid = sid_dup_talloc(mem_ctx, &sid); + W_ERROR_HAVE_NO_MEMORY(r->in.domain_sid); + } + + if (!r->in.dc_name) { + struct DS_DOMAIN_CONTROLLER_INFO *info; + status = dsgetdcname(mem_ctx, + NULL, + r->in.domain_name, + NULL, + NULL, + DS_DIRECTORY_SERVICE_REQUIRED | + DS_WRITABLE_REQUIRED | + DS_RETURN_DNS_NAME, + &info); + if (!NT_STATUS_IS_OK(status)) { + libnet_unjoin_set_error_string(mem_ctx, r, + "failed to find DC for domain %s", + r->in.domain_name, + get_friendly_nt_error_msg(status)); + return WERR_DOMAIN_CONTROLLER_NOT_FOUND; + } + + r->in.dc_name = talloc_strdup(mem_ctx, + info->domain_controller_name); + W_ERROR_HAVE_NO_MEMORY(r->in.dc_name); + } + status = libnet_join_unjoindomain_rpc(mem_ctx, r); if (!NT_STATUS_IS_OK(status)) { libnet_unjoin_set_error_string(mem_ctx, r, - "failed to unjoin domain: %s", - nt_errstr(status)); + "failed to disable machine account via rpc: %s", + get_friendly_nt_error_msg(status)); if (NT_STATUS_EQUAL(status, NT_STATUS_NO_SUCH_USER)) { return WERR_SETUP_NOT_JOINED; } @@ -1237,26 +1347,57 @@ 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_config_backend_is_registry()) { + return WERR_NOT_SUPPORTED; + } + + if (!secrets_init()) { + libnet_unjoin_set_error_string(mem_ctx, r, + "Unable to open secrets database"); + return WERR_CAN_NOT_COMPLETE; + } + + return WERR_OK; +} + + +/**************************************************************** +****************************************************************/ + WERROR libnet_Unjoin(TALLOC_CTX *mem_ctx, struct libnet_UnjoinCtx *r) { WERROR werr; - if (r->in.modify_config && !lp_include_registry_globals()) { - return WERR_NOT_SUPPORTED; + if (r->in.debug) { + LIBNET_UNJOIN_IN_DUMP_CTX(mem_ctx, r); + } + + werr = libnet_unjoin_pre_processing(mem_ctx, r); + if (!W_ERROR_IS_OK(werr)) { + goto done; } if (r->in.unjoin_flags & WKSSVC_JOIN_FLAGS_JOIN_TYPE) { werr = libnet_DomainUnjoin(mem_ctx, r); if (!W_ERROR_IS_OK(werr)) { - do_UnjoinConfig(r); - return werr; + goto done; } } werr = do_UnjoinConfig(r); if (!W_ERROR_IS_OK(werr)) { - return werr; + goto done; + } + + done: + r->out.result = werr; + + if (r->in.debug) { + LIBNET_UNJOIN_OUT_DUMP_CTX(mem_ctx, r); } return werr; diff --git a/source3/libnet/libnet_join.h b/source3/libnet/libnet_join.h deleted file mode 100644 index c47e8d934c..0000000000 --- a/source3/libnet/libnet_join.h +++ /dev/null @@ -1,75 +0,0 @@ -/* - * Unix SMB/CIFS implementation. - * libnet Join Support - * Copyright (C) Guenther Deschner 2007-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 - * 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/>. - */ - -#ifndef __LIBNET_JOIN_H__ -#define __LIBNET_JOIN_H__ - -struct libnet_JoinCtx { - struct { - const char *dc_name; - const char *machine_name; - const char *domain_name; - const char *account_ou; - const char *admin_account; - const char *admin_password; - const char *machine_password; - uint32_t join_flags; - const char *os_version; - const char *os_name; - bool create_upn; - const char *upn; - bool modify_config; - struct ads_struct *ads; - bool debug; - } in; - - struct { - char *account_name; - char *netbios_domain_name; - char *dns_domain_name; - char *dn; - struct dom_sid *domain_sid; - bool modified_config; - WERROR result; - char *error_string; - bool domain_is_ad; - } out; -}; - -struct libnet_UnjoinCtx { - struct { - const char *dc_name; - const char *machine_name; - const char *domain_name; - const char *admin_account; - const char *admin_password; - uint32_t unjoin_flags; - bool modify_config; - struct dom_sid *domain_sid; - struct ads_struct *ads; - } in; - - struct { - bool modified_config; - WERROR result; - char *error_string; - } out; -}; - -#endif 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/libnet_join.h b/source3/librpc/gen_ndr/libnet_join.h new file mode 100644 index 0000000000..40759cb489 --- /dev/null +++ b/source3/librpc/gen_ndr/libnet_join.h @@ -0,0 +1,73 @@ +/* header auto-generated by pidl */ + +#include <stdint.h> + +#include "librpc/gen_ndr/wkssvc.h" +#include "librpc/gen_ndr/security.h" +#ifndef _HEADER_libnetjoin +#define _HEADER_libnetjoin + +; + + +struct libnet_JoinCtx { + struct { + const char * dc_name; + const char * machine_name; + const char * domain_name;/* [ref] */ + const char * account_ou; + const char * admin_account; + const char * admin_password; + const char * machine_password; + uint32_t join_flags; + const char * os_version; + const char * os_name; + uint8_t create_upn; + const char * upn; + uint8_t modify_config; + struct ads_struct *ads;/* [ref] */ + uint8_t debug; + } in; + + struct { + const char * account_name; + const char * netbios_domain_name; + const char * dns_domain_name; + const char * dn; + struct dom_sid *domain_sid;/* [ref] */ + uint8_t modified_config; + const char * error_string; + uint8_t domain_is_ad; + WERROR result; + } out; + +}; + + +struct libnet_UnjoinCtx { + struct { + const char * dc_name; + const char * machine_name; + const char * domain_name; + const char * account_ou; + const char * admin_account; + const char * admin_password; + const char * machine_password; + uint32_t unjoin_flags; + uint8_t modify_config; + struct dom_sid *domain_sid;/* [ref] */ + struct ads_struct *ads;/* [ref] */ + uint8_t debug; + } in; + + struct { + const char * netbios_domain_name; + const char * dns_domain_name; + uint8_t modified_config; + const char * error_string; + WERROR result; + } out; + +}; + +#endif /* _HEADER_libnetjoin */ 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_libnet_join.c b/source3/librpc/gen_ndr/ndr_libnet_join.c new file mode 100644 index 0000000000..5345bc0ad4 --- /dev/null +++ b/source3/librpc/gen_ndr/ndr_libnet_join.c @@ -0,0 +1,103 @@ +/* parser auto-generated by pidl */ + +#include "includes.h" +#include "librpc/gen_ndr/ndr_libnet_join.h" + +#include "librpc/gen_ndr/ndr_wkssvc.h" +#include "librpc/gen_ndr/ndr_security.h" +_PUBLIC_ void ndr_print_libnet_JoinCtx(struct ndr_print *ndr, const char *name, int flags, const struct libnet_JoinCtx *r) +{ + ndr_print_struct(ndr, name, "libnet_JoinCtx"); + ndr->depth++; + if (flags & NDR_SET_VALUES) { + ndr->flags |= LIBNDR_PRINT_SET_VALUES; + } + if (flags & NDR_IN) { + ndr_print_struct(ndr, "in", "libnet_JoinCtx"); + ndr->depth++; + ndr_print_string(ndr, "dc_name", r->in.dc_name); + ndr_print_string(ndr, "machine_name", r->in.machine_name); + ndr_print_ptr(ndr, "domain_name", r->in.domain_name); + ndr->depth++; + ndr_print_string(ndr, "domain_name", r->in.domain_name); + ndr->depth--; + ndr_print_string(ndr, "account_ou", r->in.account_ou); + ndr_print_string(ndr, "admin_account", r->in.admin_account); + ndr_print_string(ndr, "admin_password", r->in.admin_password); + ndr_print_string(ndr, "machine_password", r->in.machine_password); + ndr_print_wkssvc_joinflags(ndr, "join_flags", r->in.join_flags); + ndr_print_string(ndr, "os_version", r->in.os_version); + ndr_print_string(ndr, "os_name", r->in.os_name); + ndr_print_uint8(ndr, "create_upn", r->in.create_upn); + ndr_print_string(ndr, "upn", r->in.upn); + ndr_print_uint8(ndr, "modify_config", r->in.modify_config); + ndr_print_ptr(ndr, "ads", r->in.ads); + ndr->depth++; + ndr_print_ads_struct(ndr, "ads", r->in.ads); + ndr->depth--; + ndr_print_uint8(ndr, "debug", r->in.debug); + ndr->depth--; + } + if (flags & NDR_OUT) { + ndr_print_struct(ndr, "out", "libnet_JoinCtx"); + ndr->depth++; + ndr_print_string(ndr, "account_name", r->out.account_name); + ndr_print_string(ndr, "netbios_domain_name", r->out.netbios_domain_name); + ndr_print_string(ndr, "dns_domain_name", r->out.dns_domain_name); + ndr_print_string(ndr, "dn", r->out.dn); + ndr_print_ptr(ndr, "domain_sid", r->out.domain_sid); + ndr->depth++; + ndr_print_dom_sid(ndr, "domain_sid", r->out.domain_sid); + ndr->depth--; + ndr_print_uint8(ndr, "modified_config", r->out.modified_config); + ndr_print_string(ndr, "error_string", r->out.error_string); + ndr_print_uint8(ndr, "domain_is_ad", r->out.domain_is_ad); + ndr_print_WERROR(ndr, "result", r->out.result); + ndr->depth--; + } + ndr->depth--; +} + +_PUBLIC_ void ndr_print_libnet_UnjoinCtx(struct ndr_print *ndr, const char *name, int flags, const struct libnet_UnjoinCtx *r) +{ + ndr_print_struct(ndr, name, "libnet_UnjoinCtx"); + ndr->depth++; + if (flags & NDR_SET_VALUES) { + ndr->flags |= LIBNDR_PRINT_SET_VALUES; + } + if (flags & NDR_IN) { + ndr_print_struct(ndr, "in", "libnet_UnjoinCtx"); + ndr->depth++; + ndr_print_string(ndr, "dc_name", r->in.dc_name); + ndr_print_string(ndr, "machine_name", r->in.machine_name); + ndr_print_string(ndr, "domain_name", r->in.domain_name); + ndr_print_string(ndr, "account_ou", r->in.account_ou); + ndr_print_string(ndr, "admin_account", r->in.admin_account); + ndr_print_string(ndr, "admin_password", r->in.admin_password); + ndr_print_string(ndr, "machine_password", r->in.machine_password); + ndr_print_wkssvc_joinflags(ndr, "unjoin_flags", r->in.unjoin_flags); + ndr_print_uint8(ndr, "modify_config", r->in.modify_config); + ndr_print_ptr(ndr, "domain_sid", r->in.domain_sid); + ndr->depth++; + ndr_print_dom_sid(ndr, "domain_sid", r->in.domain_sid); + ndr->depth--; + ndr_print_ptr(ndr, "ads", r->in.ads); + ndr->depth++; + ndr_print_ads_struct(ndr, "ads", r->in.ads); + ndr->depth--; + ndr_print_uint8(ndr, "debug", r->in.debug); + ndr->depth--; + } + if (flags & NDR_OUT) { + ndr_print_struct(ndr, "out", "libnet_UnjoinCtx"); + ndr->depth++; + ndr_print_string(ndr, "netbios_domain_name", r->out.netbios_domain_name); + ndr_print_string(ndr, "dns_domain_name", r->out.dns_domain_name); + ndr_print_uint8(ndr, "modified_config", r->out.modified_config); + ndr_print_string(ndr, "error_string", r->out.error_string); + ndr_print_WERROR(ndr, "result", r->out.result); + ndr->depth--; + } + ndr->depth--; +} + diff --git a/source3/librpc/gen_ndr/ndr_libnet_join.h b/source3/librpc/gen_ndr/ndr_libnet_join.h new file mode 100644 index 0000000000..4a5fdf0d50 --- /dev/null +++ b/source3/librpc/gen_ndr/ndr_libnet_join.h @@ -0,0 +1,20 @@ +/* header auto-generated by pidl */ + +#include "librpc/ndr/libndr.h" +#include "librpc/gen_ndr/libnet_join.h" + +#ifndef _HEADER_NDR_libnetjoin +#define _HEADER_NDR_libnetjoin + +#define NDR_LIBNET_JOINCTX (0x00) + +#define NDR_LIBNET_UNJOINCTX (0x01) + +#define NDR_LIBNETJOIN_CALL_COUNT (2) +enum ndr_err_code ndr_push_libnet_JoinCtx(struct ndr_push *ndr, int flags, const struct libnet_JoinCtx *r); +enum ndr_err_code ndr_pull_libnet_JoinCtx(struct ndr_pull *ndr, int flags, struct libnet_JoinCtx *r); +void ndr_print_libnet_JoinCtx(struct ndr_print *ndr, const char *name, int flags, const struct libnet_JoinCtx *r); +enum ndr_err_code ndr_push_libnet_UnjoinCtx(struct ndr_push *ndr, int flags, const struct libnet_UnjoinCtx *r); +enum ndr_err_code ndr_pull_libnet_UnjoinCtx(struct ndr_pull *ndr, int flags, struct libnet_UnjoinCtx *r); +void ndr_print_libnet_UnjoinCtx(struct ndr_print *ndr, const char *name, int flags, const struct libnet_UnjoinCtx *r); +#endif /* _HEADER_NDR_libnetjoin */ 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/ndr_xattr.c b/source3/librpc/gen_ndr/ndr_xattr.c new file mode 100644 index 0000000000..29a31a12b2 --- /dev/null +++ b/source3/librpc/gen_ndr/ndr_xattr.c @@ -0,0 +1,102 @@ +/* parser auto-generated by pidl */ + +#include "includes.h" +#include "librpc/gen_ndr/ndr_xattr.h" + +_PUBLIC_ enum ndr_err_code ndr_push_tdb_xattr(struct ndr_push *ndr, int ndr_flags, const struct tdb_xattr *r) +{ + if (ndr_flags & NDR_SCALARS) { + NDR_CHECK(ndr_push_align(ndr, 4)); + { + uint32_t _flags_save_string = ndr->flags; + ndr_set_flags(&ndr->flags, LIBNDR_FLAG_STR_UTF8|LIBNDR_FLAG_STR_NULLTERM); + NDR_CHECK(ndr_push_string(ndr, NDR_SCALARS, r->name)); + ndr->flags = _flags_save_string; + } + NDR_CHECK(ndr_push_DATA_BLOB(ndr, NDR_SCALARS, r->value)); + } + if (ndr_flags & NDR_BUFFERS) { + } + return NDR_ERR_SUCCESS; +} + +_PUBLIC_ enum ndr_err_code ndr_pull_tdb_xattr(struct ndr_pull *ndr, int ndr_flags, struct tdb_xattr *r) +{ + if (ndr_flags & NDR_SCALARS) { + NDR_CHECK(ndr_pull_align(ndr, 4)); + { + uint32_t _flags_save_string = ndr->flags; + ndr_set_flags(&ndr->flags, LIBNDR_FLAG_STR_UTF8|LIBNDR_FLAG_STR_NULLTERM); + NDR_CHECK(ndr_pull_string(ndr, NDR_SCALARS, &r->name)); + ndr->flags = _flags_save_string; + } + NDR_CHECK(ndr_pull_DATA_BLOB(ndr, NDR_SCALARS, &r->value)); + } + if (ndr_flags & NDR_BUFFERS) { + } + return NDR_ERR_SUCCESS; +} + +_PUBLIC_ void ndr_print_tdb_xattr(struct ndr_print *ndr, const char *name, const struct tdb_xattr *r) +{ + ndr_print_struct(ndr, name, "tdb_xattr"); + ndr->depth++; + ndr_print_string(ndr, "name", r->name); + ndr_print_DATA_BLOB(ndr, "value", r->value); + ndr->depth--; +} + +_PUBLIC_ enum ndr_err_code ndr_push_tdb_xattrs(struct ndr_push *ndr, int ndr_flags, const struct tdb_xattrs *r) +{ + uint32_t cntr_xattrs_0; + if (ndr_flags & NDR_SCALARS) { + NDR_CHECK(ndr_push_align(ndr, 4)); + NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, r->num_xattrs)); + for (cntr_xattrs_0 = 0; cntr_xattrs_0 < r->num_xattrs; cntr_xattrs_0++) { + NDR_CHECK(ndr_push_tdb_xattr(ndr, NDR_SCALARS, &r->xattrs[cntr_xattrs_0])); + } + } + if (ndr_flags & NDR_BUFFERS) { + } + return NDR_ERR_SUCCESS; +} + +_PUBLIC_ enum ndr_err_code ndr_pull_tdb_xattrs(struct ndr_pull *ndr, int ndr_flags, struct tdb_xattrs *r) +{ + uint32_t cntr_xattrs_0; + TALLOC_CTX *_mem_save_xattrs_0; + if (ndr_flags & NDR_SCALARS) { + NDR_CHECK(ndr_pull_align(ndr, 4)); + NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &r->num_xattrs)); + NDR_PULL_ALLOC_N(ndr, r->xattrs, r->num_xattrs); + _mem_save_xattrs_0 = NDR_PULL_GET_MEM_CTX(ndr); + NDR_PULL_SET_MEM_CTX(ndr, r->xattrs, 0); + for (cntr_xattrs_0 = 0; cntr_xattrs_0 < r->num_xattrs; cntr_xattrs_0++) { + NDR_CHECK(ndr_pull_tdb_xattr(ndr, NDR_SCALARS, &r->xattrs[cntr_xattrs_0])); + } + NDR_PULL_SET_MEM_CTX(ndr, _mem_save_xattrs_0, 0); + } + if (ndr_flags & NDR_BUFFERS) { + } + return NDR_ERR_SUCCESS; +} + +_PUBLIC_ void ndr_print_tdb_xattrs(struct ndr_print *ndr, const char *name, const struct tdb_xattrs *r) +{ + uint32_t cntr_xattrs_0; + ndr_print_struct(ndr, name, "tdb_xattrs"); + ndr->depth++; + ndr_print_uint32(ndr, "num_xattrs", r->num_xattrs); + ndr->print(ndr, "%s: ARRAY(%d)", "xattrs", r->num_xattrs); + ndr->depth++; + for (cntr_xattrs_0=0;cntr_xattrs_0<r->num_xattrs;cntr_xattrs_0++) { + char *idx_0=NULL; + asprintf(&idx_0, "[%d]", cntr_xattrs_0); + if (idx_0) { + ndr_print_tdb_xattr(ndr, "xattrs", &r->xattrs[cntr_xattrs_0]); + free(idx_0); + } + } + ndr->depth--; + ndr->depth--; +} diff --git a/source3/librpc/gen_ndr/ndr_xattr.h b/source3/librpc/gen_ndr/ndr_xattr.h new file mode 100644 index 0000000000..a18477f347 --- /dev/null +++ b/source3/librpc/gen_ndr/ndr_xattr.h @@ -0,0 +1,16 @@ +/* header auto-generated by pidl */ + +#include "librpc/ndr/libndr.h" +#include "librpc/gen_ndr/xattr.h" + +#ifndef _HEADER_NDR_xattr +#define _HEADER_NDR_xattr + +#define NDR_XATTR_CALL_COUNT (0) +enum ndr_err_code ndr_push_tdb_xattr(struct ndr_push *ndr, int ndr_flags, const struct tdb_xattr *r); +enum ndr_err_code ndr_pull_tdb_xattr(struct ndr_pull *ndr, int ndr_flags, struct tdb_xattr *r); +void ndr_print_tdb_xattr(struct ndr_print *ndr, const char *name, const struct tdb_xattr *r); +enum ndr_err_code ndr_push_tdb_xattrs(struct ndr_push *ndr, int ndr_flags, const struct tdb_xattrs *r); +enum ndr_err_code ndr_pull_tdb_xattrs(struct ndr_pull *ndr, int ndr_flags, struct tdb_xattrs *r); +void ndr_print_tdb_xattrs(struct ndr_print *ndr, const char *name, const struct tdb_xattrs *r); +#endif /* _HEADER_NDR_xattr */ 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/gen_ndr/xattr.h b/source3/librpc/gen_ndr/xattr.h new file mode 100644 index 0000000000..ee30376be8 --- /dev/null +++ b/source3/librpc/gen_ndr/xattr.h @@ -0,0 +1,18 @@ +/* header auto-generated by pidl */ + +#include <stdint.h> + +#ifndef _HEADER_xattr +#define _HEADER_xattr + +struct tdb_xattr { + const char * name;/* [flag(LIBNDR_FLAG_STR_UTF8|LIBNDR_FLAG_STR_NULLTERM)] */ + DATA_BLOB value; +}/* [public] */; + +struct tdb_xattrs { + uint32_t num_xattrs; + struct tdb_xattr *xattrs; +}/* [public] */; + +#endif /* _HEADER_xattr */ diff --git a/source3/librpc/idl/libnet_join.idl b/source3/librpc/idl/libnet_join.idl new file mode 100644 index 0000000000..2741b7bd7b --- /dev/null +++ b/source3/librpc/idl/libnet_join.idl @@ -0,0 +1,60 @@ +#include "idl_types.h" + +import "wkssvc.idl", "security.idl"; + +/* + libnetjoin interface definition +*/ + +[ + pointer_default(unique) +] +interface libnetjoin +{ + typedef bitmap wkssvc_joinflags wkssvc_joinflags; + + [nopush,nopull] WERROR libnet_JoinCtx( + [in] string dc_name, + [in] string machine_name, + [in,ref] string *domain_name, + [in] string account_ou, + [in] string admin_account, + [in] string admin_password, + [in] string machine_password, + [in] wkssvc_joinflags join_flags, + [in] string os_version, + [in] string os_name, + [in] boolean8 create_upn, + [in] string upn, + [in] boolean8 modify_config, + [in] ads_struct *ads, + [in] boolean8 debug, + [out] string account_name, + [out] string netbios_domain_name, + [out] string dns_domain_name, + [out] string dn, + [out] dom_sid *domain_sid, + [out] boolean8 modified_config, + [out] string error_string, + [out] boolean8 domain_is_ad + ); + + [nopush,nopull] WERROR libnet_UnjoinCtx( + [in] string dc_name, + [in] string machine_name, + [in] string domain_name, + [in] string account_ou, + [in] string admin_account, + [in] string admin_password, + [in] string machine_password, + [in] wkssvc_joinflags unjoin_flags, + [in] boolean8 modify_config, + [in] dom_sid *domain_sid, + [in] ads_struct *ads, + [in] boolean8 debug, + [out] string netbios_domain_name, + [out] string dns_domain_name, + [out] boolean8 modified_config, + [out] string error_string + ); +} 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/librpc/idl/xattr.idl b/source3/librpc/idl/xattr.idl new file mode 100644 index 0000000000..ec230a4efb --- /dev/null +++ b/source3/librpc/idl/xattr.idl @@ -0,0 +1,23 @@ +#include "idl_types.h" + +/* + IDL structures for xattrs +*/ + +[ + pointer_default(unique) +] +interface xattr +{ + /* xattrs for file systems that don't have any */ + + typedef [public] struct { + utf8string name; + DATA_BLOB value; + } tdb_xattr; + + typedef [public] struct { + uint32 num_xattrs; + tdb_xattr xattrs[num_xattrs]; + } tdb_xattrs; +} diff --git a/source3/librpc/ndr/libndr.h b/source3/librpc/ndr/libndr.h index 6341e20b65..d0c2c74db9 100644 --- a/source3/librpc/ndr/libndr.h +++ b/source3/librpc/ndr/libndr.h @@ -149,7 +149,7 @@ struct ndr_print { /* set to avoid recursion in ndr_size_*() calculation */ #define LIBNDR_FLAG_NO_NDR_SIZE (1<<31) -/* useful macro for debugging */ +/* useful macro for debugging with DEBUG */ #define NDR_PRINT_DEBUG(type, p) ndr_print_debug((ndr_print_fn_t)ndr_print_ ##type, #p, p) #define NDR_PRINT_UNION_DEBUG(type, level, p) ndr_print_union_debug((ndr_print_fn_t)ndr_print_ ##type, #p, level, p) #define NDR_PRINT_FUNCTION_DEBUG(type, flags, p) ndr_print_function_debug((ndr_print_function_t)ndr_print_ ##type, #type, flags, p) @@ -157,6 +157,14 @@ struct ndr_print { #define NDR_PRINT_OUT_DEBUG(type, p) NDR_PRINT_FUNCTION_DEBUG(type, NDR_OUT, p) #define NDR_PRINT_IN_DEBUG(type, p) NDR_PRINT_FUNCTION_DEBUG(type, NDR_IN | NDR_SET_VALUES, p) +/* useful macro for debugging in strings */ +#define NDR_PRINT_STRUCT_STRING(ctx, type, p) ndr_print_struct_string(ctx, (ndr_print_fn_t)ndr_print_ ##type, #p, p) +#define NDR_PRINT_UNION_STRING(ctx, type, level, p) ndr_print_union_string(ctx, (ndr_print_fn_t)ndr_print_ ##type, #p, level, p) +#define NDR_PRINT_FUNCTION_STRING(ctx, type, flags, p) ndr_print_function_string(ctx, (ndr_print_function_t)ndr_print_ ##type, #type, flags, p) +#define NDR_PRINT_BOTH_STRING(ctx, type, p) NDR_PRINT_FUNCTION_STRING(ctx, type, NDR_BOTH, p) +#define NDR_PRINT_OUT_STRING(ctx, type, p) NDR_PRINT_FUNCTION_STRING(ctx, type, NDR_OUT, p) +#define NDR_PRINT_IN_STRING(ctx, type, p) NDR_PRINT_FUNCTION_STRING(ctx, type, NDR_IN | NDR_SET_VALUES, p) + #define NDR_BE(ndr) (((ndr)->flags & (LIBNDR_FLAG_BIGENDIAN|LIBNDR_FLAG_LITTLE_ENDIAN)) == LIBNDR_FLAG_BIGENDIAN) enum ndr_err_code { diff --git a/source3/librpc/ndr/ndr_basic.c b/source3/librpc/ndr/ndr_basic.c index 0ef78a2a54..54397c9469 100644 --- a/source3/librpc/ndr/ndr_basic.c +++ b/source3/librpc/ndr/ndr_basic.c @@ -847,3 +847,14 @@ _PUBLIC_ uint32_t ndr_size_DATA_BLOB(int ret, const DATA_BLOB *data, int flags) if (!data) return ret; return ret + data->length; } + +_PUBLIC_ void ndr_print_bool(struct ndr_print *ndr, const char *name, const bool b) +{ + ndr->print(ndr, "%-25s: %s", name, b?"true":"false"); +} + +_PUBLIC_ void ndr_print_sockaddr_storage(struct ndr_print *ndr, const char *name, const struct sockaddr_storage *ss) +{ + char addr[INET6_ADDRSTRLEN]; + ndr->print(ndr, "%-25s: %s", name, print_sockaddr(addr, sizeof(addr), ss)); +} diff --git a/source3/librpc/ndr/ndr_misc.c b/source3/librpc/ndr/ndr_misc.c index 2ca0cf08e8..245ba45215 100644 --- a/source3/librpc/ndr/ndr_misc.c +++ b/source3/librpc/ndr/ndr_misc.c @@ -153,3 +153,84 @@ void ndr_print_server_id(struct ndr_print *ndr, const char *name, const struct s #endif ndr->depth--; } + +void ndr_print_ads_struct(struct ndr_print *ndr, const char *name, const struct ads_struct *r) +{ + if (!r) { return; } + + ndr_print_struct(ndr, name, "ads_struct"); + ndr->depth++; + ndr_print_bool(ndr, "is_mine", r->is_mine); + ndr_print_struct(ndr, name, "server"); + ndr->depth++; + ndr_print_string(ndr, "realm", r->server.realm); + ndr_print_string(ndr, "workgroup", r->server.workgroup); + ndr_print_string(ndr, "ldap_server", r->server.ldap_server); + ndr_print_bool(ndr, "foreign", r->server.foreign); + ndr->depth--; + ndr_print_struct(ndr, name, "auth"); + ndr->depth++; + ndr_print_string(ndr, "realm", r->auth.realm); +#ifdef DEBUG_PASSWORD + ndr_print_string(ndr, "password", r->auth.password); +#else + ndr_print_string(ndr, "password", "(PASSWORD ommited)"); +#endif + ndr_print_string(ndr, "user_name", r->auth.user_name); + ndr_print_string(ndr, "kdc_server", r->auth.kdc_server); + ndr_print_uint32(ndr, "flags", r->auth.flags); + ndr_print_uint32(ndr, "time_offset", r->auth.time_offset); + ndr_print_time_t(ndr, "tgt_expire", r->auth.tgt_expire); + ndr_print_time_t(ndr, "tgs_expire", r->auth.tgs_expire); + ndr_print_time_t(ndr, "renewable", r->auth.renewable); + ndr->depth--; + ndr_print_struct(ndr, name, "config"); + ndr->depth++; + ndr_print_uint32(ndr, "flags", r->config.flags); + ndr_print_string(ndr, "realm", r->config.realm); + ndr_print_string(ndr, "bind_path", r->config.bind_path); + ndr_print_string(ndr, "ldap_server_name", r->config.ldap_server_name); + ndr_print_string(ndr, "server_site_name", r->config.server_site_name); + ndr_print_string(ndr, "client_site_name", r->config.client_site_name); + ndr_print_time_t(ndr, "current_time", r->config.current_time); + ndr_print_bool(ndr, "tried_closest_dc", r->config.tried_closest_dc); + ndr_print_string(ndr, "schema_path", r->config.schema_path); + ndr_print_string(ndr, "config_path", r->config.config_path); + ndr->depth--; +#ifdef HAVE_LDAP + ndr_print_struct(ndr, name, "ldap"); + ndr->depth++; + ndr_print_ptr(ndr, "ld", r->ldap.ld); + ndr_print_sockaddr_storage(ndr, "ss", &r->ldap.ss); + ndr_print_time_t(ndr, "last_attempt", r->ldap.last_attempt); + ndr_print_uint32(ndr, "port", r->ldap.port); + ndr_print_uint16(ndr, "wrap_type", r->ldap.wrap_type); +#ifdef HAVE_LDAP_SASL_WRAPPING + ndr_print_ptr(ndr, "sbiod", r->ldap.sbiod); +#endif /* HAVE_LDAP_SASL_WRAPPING */ + ndr_print_ptr(ndr, "mem_ctx", r->ldap.mem_ctx); + ndr_print_ptr(ndr, "wrap_ops", r->ldap.wrap_ops); + ndr_print_ptr(ndr, "wrap_private_data", r->ldap.wrap_private_data); + ndr_print_struct(ndr, name, "in"); + ndr->depth++; + ndr_print_uint32(ndr, "ofs", r->ldap.in.ofs); + ndr_print_uint32(ndr, "needed", r->ldap.in.needed); + ndr_print_uint32(ndr, "left", r->ldap.in.left); + ndr_print_uint32(ndr, "max_wrapped", r->ldap.in.max_wrapped); + ndr_print_uint32(ndr, "min_wrapped", r->ldap.in.min_wrapped); + ndr_print_uint32(ndr, "size", r->ldap.in.size); + ndr_print_array_uint8(ndr, "buf", r->ldap.in.buf, r->ldap.in.size); + ndr->depth--; + ndr_print_struct(ndr, name, "out"); + ndr->depth++; + ndr_print_uint32(ndr, "ofs", r->ldap.out.ofs); + ndr_print_uint32(ndr, "left", r->ldap.out.left); + ndr_print_uint32(ndr, "max_unwrapped", r->ldap.out.max_unwrapped); + ndr_print_uint32(ndr, "sig_size", r->ldap.out.sig_size); + ndr_print_uint32(ndr, "size", r->ldap.out.size); + ndr_print_array_uint8(ndr, "buf", r->ldap.out.buf, r->ldap.out.size); + ndr->depth--; + ndr->depth--; +#endif /* HAVE_LDAP */ + ndr->depth--; +} diff --git a/source3/libsmb/clireadwrite.c b/source3/libsmb/clireadwrite.c index 0b33e43563..6b39a885f0 100644 --- a/source3/libsmb/clireadwrite.c +++ b/source3/libsmb/clireadwrite.c @@ -404,6 +404,9 @@ ssize_t cli_write(struct cli_state *cli, mpx = 1; } + /* Default (small) writesize. */ + writesize = (cli->max_xmit - (smb_size+32)) & ~1023; + if (write_mode == 0 && !client_is_signing_on(cli) && !cli_encryption_on(cli) && @@ -415,11 +418,11 @@ ssize_t cli_write(struct cli_state *cli, } else if (cli->capabilities & CAP_LARGE_WRITEX) { if (cli->is_samba) { writesize = CLI_SAMBA_MAX_LARGE_WRITEX_SIZE; - } else { + } else if (!client_is_signing_on(cli)) { + /* Windows restricts signed writes to max_xmit. + * Found by Volker. */ writesize = CLI_WINDOWS_MAX_LARGE_WRITEX_SIZE; } - } else { - writesize = (cli->max_xmit - (smb_size+32)) & ~1023; } blocks = (size + (writesize-1)) / writesize; diff --git a/source3/libsmb/libsmbclient.c b/source3/libsmb/libsmbclient.c index da8f1e332b..fb04d143a5 100644 --- a/source3/libsmb/libsmbclient.c +++ b/source3/libsmb/libsmbclient.c @@ -592,13 +592,58 @@ smbc_remove_unused_server(SMBCCTX * context, return 0; } +/**************************************************************** + * Call the auth_fn with fixed size (fstring) buffers. + ***************************************************************/ + +static void call_auth_fn(TALLOC_CTX *ctx, + SMBCCTX *context, + const char *server, + const char *share, + char **pp_workgroup, + char **pp_username, + char **pp_password) +{ + fstring workgroup; + fstring username; + fstring password; + + strlcpy(workgroup, *pp_workgroup, sizeof(workgroup)); + strlcpy(username, *pp_username, sizeof(username)); + strlcpy(password, *pp_password, sizeof(password)); + + if (context->internal->_auth_fn_with_context != NULL) { + (context->internal->_auth_fn_with_context)( + context, + server, share, + workgroup, sizeof(workgroup), + username, sizeof(username), + password, sizeof(password)); + } else { + (context->callbacks.auth_fn)( + server, share, + workgroup, sizeof(workgroup), + username, sizeof(username), + password, sizeof(password)); + } + + TALLOC_FREE(*pp_workgroup); + TALLOC_FREE(*pp_username); + TALLOC_FREE(*pp_password); + + *pp_workgroup = talloc_strdup(ctx, workgroup); + *pp_username = talloc_strdup(ctx, username); + *pp_password = talloc_strdup(ctx, password); +} + static SMBCSRV * -find_server(SMBCCTX *context, +find_server(TALLOC_CTX *ctx, + SMBCCTX *context, const char *server, const char *share, - char *workgroup, - char *username, - char *password) + char **pp_workgroup, + char **pp_username, + char **pp_password) { SMBCSRV *srv; int auth_called = 0; @@ -606,22 +651,15 @@ find_server(SMBCCTX *context, check_server_cache: srv = (context->callbacks.get_cached_srv_fn)(context, server, share, - workgroup, username); - - if (!auth_called && !srv && (!username[0] || !password[0])) { - if (context->internal->_auth_fn_with_context != NULL) { - (context->internal->_auth_fn_with_context)( - context, - server, share, - workgroup, strlen(workgroup)+1, - username, strlen(username)+1, - password, strlen(password)+1); - } else { - (context->callbacks.auth_fn)( - server, share, - workgroup, strlen(workgroup)+1, - username, strlen(username)+1, - password, strlen(password)+1); + *pp_workgroup, *pp_username); + + if (!auth_called && !srv && (!*pp_username || !(*pp_username)[0] || + !*pp_password || !(*pp_password)[0])) { + call_auth_fn(ctx, context, server, share, + pp_workgroup, pp_username, pp_password); + + if (!pp_workgroup || !pp_username || !pp_password) { + return NULL; } /* @@ -652,12 +690,12 @@ find_server(SMBCCTX *context, (context->callbacks.remove_cached_srv_fn)(context, srv); } - + /* * Maybe there are more cached connections to this * server */ - goto check_server_cache; + goto check_server_cache; } return srv; @@ -678,13 +716,14 @@ find_server(SMBCCTX *context, */ static SMBCSRV * -smbc_server(SMBCCTX *context, +smbc_server(TALLOC_CTX *ctx, + SMBCCTX *context, bool connect_if_not_found, const char *server, const char *share, - char *workgroup, - char *username, - char *password) + char **pp_workgroup, + char **pp_username, + char **pp_password) { SMBCSRV *srv=NULL; struct cli_state *c; @@ -706,8 +745,8 @@ smbc_server(SMBCCTX *context, } /* Look for a cached connection */ - srv = find_server(context, server, share, - workgroup, username, password); + srv = find_server(ctx, context, server, share, + pp_workgroup, pp_username, pp_password); /* * If we found a connection and we're only allowed one share per @@ -725,20 +764,17 @@ smbc_server(SMBCCTX *context, */ if (srv->cli->cnum == (uint16) -1) { /* Ensure we have accurate auth info */ - if (context->internal->_auth_fn_with_context != NULL) { - (context->internal->_auth_fn_with_context)( - context, - server, share, - workgroup, strlen(workgroup)+1, - username, strlen(username)+1, - password, strlen(password)+1); - } else { - (context->callbacks.auth_fn)( - server, share, - workgroup, strlen(workgroup)+1, - username, strlen(username)+1, - password, strlen(password)+1); - } + call_auth_fn(ctx, context, server, share, + pp_workgroup, pp_username, pp_password); + + if (!*pp_workgroup || !*pp_username || !*pp_password) { + errno = ENOMEM; + cli_shutdown(srv->cli); + srv->cli = NULL; + (context->callbacks.remove_cached_srv_fn)(context, + srv); + return NULL; + } /* * We don't need to renegotiate encryption @@ -746,8 +782,9 @@ smbc_server(SMBCCTX *context, * tid. */ - if (! cli_send_tconX(srv->cli, share, "?????", - password, strlen(password)+1)) { + if (!cli_send_tconX(srv->cli, share, "?????", + *pp_password, + strlen(*pp_password)+1)) { errno = smbc_errno(context, srv->cli); cli_shutdown(srv->cli); @@ -781,6 +818,11 @@ smbc_server(SMBCCTX *context, return NULL; } + if (!*pp_workgroup || !*pp_username || !*pp_password) { + errno = ENOMEM; + return NULL; + } + make_nmb_name(&calling, context->netbios_name, 0x0); make_nmb_name(&called , server, 0x20); @@ -877,21 +919,21 @@ smbc_server(SMBCCTX *context, return NULL; } - username_used = username; + username_used = *pp_username; if (!NT_STATUS_IS_OK(cli_session_setup(c, username_used, - password, strlen(password), - password, strlen(password), - workgroup))) { + *pp_password, strlen(*pp_password), + *pp_password, strlen(*pp_password), + *pp_workgroup))) { /* Failed. Try an anonymous login, if allowed by flags. */ username_used = ""; if ((context->flags & SMBCCTX_FLAG_NO_AUTO_ANONYMOUS_LOGON) || !NT_STATUS_IS_OK(cli_session_setup(c, username_used, - password, 1, - password, 0, - workgroup))) { + *pp_password, 1, + *pp_password, 0, + *pp_workgroup))) { cli_shutdown(c); errno = EPERM; @@ -902,7 +944,7 @@ smbc_server(SMBCCTX *context, DEBUG(4,(" session setup ok\n")); if (!cli_send_tconX(c, share, "?????", - password, strlen(password)+1)) { + *pp_password, strlen(*pp_password)+1)) { errno = smbc_errno(context, c); cli_shutdown(c); return NULL; @@ -914,8 +956,8 @@ smbc_server(SMBCCTX *context, /* Attempt UNIX smb encryption. */ if (!NT_STATUS_IS_OK(cli_force_encryption(c, username_used, - password, - workgroup))) { + *pp_password, + *pp_workgroup))) { /* * context->internal->_smb_encryption_level == 1 @@ -956,8 +998,9 @@ smbc_server(SMBCCTX *context, /* Let the cache function set errno if it wants to */ errno = 0; if ((context->callbacks.add_cached_srv_fn)(context, srv, - server, share, - workgroup, username)) { + server, share, + *pp_workgroup, + *pp_username)) { int saved_errno = errno; DEBUG(3, (" Failed to add server to cache\n")); errno = saved_errno; @@ -988,13 +1031,14 @@ smbc_server(SMBCCTX *context, * connection. This works similarly to smbc_server(). */ static SMBCSRV * -smbc_attr_server(SMBCCTX *context, - const char *server, - const char *share, - char *workgroup, - char *username, - char *password, - POLICY_HND *pol) +smbc_attr_server(TALLOC_CTX *ctx, + SMBCCTX *context, + const char *server, + const char *share, + char **pp_workgroup, + char **pp_username, + char **pp_password, + POLICY_HND *pol) { int flags; struct sockaddr_storage ss; @@ -1008,27 +1052,19 @@ smbc_attr_server(SMBCCTX *context, * our "special" share name '*IPC$', which is an impossible real share * name due to the leading asterisk. */ - ipc_srv = find_server(context, server, "*IPC$", - workgroup, username, password); + ipc_srv = find_server(ctx, context, server, "*IPC$", + pp_workgroup, pp_username, pp_password); if (!ipc_srv) { /* We didn't find a cached connection. Get the password */ - if (*password == '\0') { + if (!*pp_password || (*pp_password)[0] == '\0') { /* ... then retrieve it now. */ - if (context->internal->_auth_fn_with_context != NULL) { - (context->internal->_auth_fn_with_context)( - context, - server, share, - workgroup, strlen(workgroup)+1, - username, strlen(username)+1, - password, strlen(password)+1); - } else { - (context->callbacks.auth_fn)( - server, share, - workgroup, strlen(workgroup)+1, - username, strlen(username)+1, - password, strlen(password)+1); - } + call_auth_fn(ctx, context, server, share, + pp_workgroup, pp_username, pp_password); + if (!*pp_workgroup || !*pp_username || !*pp_password) { + errno = ENOMEM; + return NULL; + } } flags = 0; @@ -1038,11 +1074,13 @@ smbc_attr_server(SMBCCTX *context, zero_addr(&ss); nt_status = cli_full_connection(&ipc_cli, - global_myname(), server, - &ss, 0, "IPC$", "?????", - username, workgroup, - password, flags, - Undefined, NULL); + global_myname(), server, + &ss, 0, "IPC$", "?????", + *pp_username, + *pp_workgroup, + *pp_password, + flags, + Undefined, NULL); if (! NT_STATUS_IS_OK(nt_status)) { DEBUG(1,("cli_full_connection failed! (%s)\n", nt_errstr(nt_status))); @@ -1053,9 +1091,9 @@ smbc_attr_server(SMBCCTX *context, if (context->internal->_smb_encryption_level) { /* Attempt UNIX smb encryption. */ if (!NT_STATUS_IS_OK(cli_force_encryption(ipc_cli, - username, - password, - workgroup))) { + *pp_username, + *pp_password, + *pp_workgroup))) { /* * context->internal->_smb_encryption_level == 1 @@ -1101,14 +1139,14 @@ smbc_attr_server(SMBCCTX *context, * SEC_RIGHTS_MAXIMUM_ALLOWED, but NT sends 0x2000000 * so we might as well do it too. */ - + nt_status = rpccli_lsa_open_policy( pipe_hnd, talloc_tos(), - True, + True, GENERIC_EXECUTE_ACCESS, pol); - + if (!NT_STATUS_IS_OK(nt_status)) { errno = smbc_errno(context, ipc_srv->cli); cli_shutdown(ipc_srv->cli); @@ -1120,10 +1158,10 @@ smbc_attr_server(SMBCCTX *context, errno = 0; /* let cache function set errno if it likes */ if ((context->callbacks.add_cached_srv_fn)(context, ipc_srv, - server, - "*IPC$", - workgroup, - username)) { + server, + "*IPC$", + *pp_workgroup, + *pp_username)) { DEBUG(3, (" Failed to add server to cache\n")); if (errno == 0) { errno = ENOMEM; @@ -1149,10 +1187,10 @@ smbc_open_ctx(SMBCCTX *context, int flags, mode_t mode) { - char *server, *share, *user, *password, *workgroup; - char *path; + char *server = NULL, *share = NULL, *user = NULL, *password = NULL, *workgroup = NULL; + char *path = NULL; char *targetpath = NULL; - struct cli_state *targetcli; + struct cli_state *targetcli = NULL; SMBCSRV *srv = NULL; SMBCFILE *file = NULL; int fd; @@ -1199,8 +1237,8 @@ smbc_open_ctx(SMBCCTX *context, } } - srv = smbc_server(context, True, - server, share, workgroup, user, password); + srv = smbc_server(frame, context, True, + server, share, &workgroup, &user, &password); if (!srv) { if (errno == EPERM) errno = EACCES; @@ -1343,10 +1381,10 @@ smbc_read_ctx(SMBCCTX *context, size_t count) { int ret; - char *server, *share, *user, *password; - char *path; + char *server = NULL, *share = NULL, *user = NULL, *password = NULL; + char *path = NULL; char *targetpath = NULL; - struct cli_state *targetcli; + struct cli_state *targetcli = NULL; TALLOC_CTX *frame = talloc_stackframe(); /* @@ -1444,10 +1482,10 @@ smbc_write_ctx(SMBCCTX *context, { int ret; off_t offset; - char *server, *share, *user, *password; - char *path; + char *server = NULL, *share = NULL, *user = NULL, *password = NULL; + char *path = NULL; char *targetpath = NULL; - struct cli_state *targetcli; + struct cli_state *targetcli = NULL; TALLOC_CTX *frame = talloc_stackframe(); /* First check all pointers before dereferencing them */ @@ -1526,10 +1564,10 @@ smbc_close_ctx(SMBCCTX *context, SMBCFILE *file) { SMBCSRV *srv; - char *server, *share, *user, *password; - char *path; + char *server = NULL, *share = NULL, *user = NULL, *password = NULL; + char *path = NULL; char *targetpath = NULL; - struct cli_state *targetcli; + struct cli_state *targetcli = NULL; TALLOC_CTX *frame = talloc_stackframe(); if (!context || !context->internal || @@ -1618,9 +1656,9 @@ smbc_getatr(SMBCCTX * context, struct timespec *change_time_ts, SMB_INO_T *ino) { - char *fixedpath; + char *fixedpath = NULL; char *targetpath = NULL; - struct cli_state *targetcli; + struct cli_state *targetcli = NULL; time_t write_time; TALLOC_CTX *frame = talloc_stackframe(); @@ -1689,11 +1727,11 @@ smbc_getatr(SMBCCTX * context, if (create_time_ts != NULL) { *create_time_ts = w_time_ts; } - + if (access_time_ts != NULL) { *access_time_ts = w_time_ts; } - + if (change_time_ts != NULL) { *change_time_ts = w_time_ts; } @@ -1804,10 +1842,10 @@ static int smbc_unlink_ctx(SMBCCTX *context, const char *fname) { - char *server, *share, *user, *password, *workgroup; - char *path; - char *targetpath; - struct cli_state *targetcli; + char *server = NULL, *share = NULL, *user = NULL, *password = NULL, *workgroup = NULL; + char *path = NULL; + char *targetpath = NULL; + struct cli_state *targetcli = NULL; SMBCSRV *srv = NULL; TALLOC_CTX *frame = talloc_stackframe(); @@ -1850,8 +1888,8 @@ smbc_unlink_ctx(SMBCCTX *context, } } - srv = smbc_server(context, True, - server, share, workgroup, user, password); + srv = smbc_server(frame, context, True, + server, share, &workgroup, &user, &password); if (!srv) { TALLOC_FREE(frame); @@ -1926,21 +1964,21 @@ smbc_rename_ctx(SMBCCTX *ocontext, SMBCCTX *ncontext, const char *nname) { - char *server1; - char *share1; - char *server2; - char *share2; - char *user1; - char *user2; - char *password1; - char *password2; - char *workgroup; - char *path1; - char *path2; - char *targetpath1; - char *targetpath2; - struct cli_state *targetcli1; - struct cli_state *targetcli2; + char *server1 = NULL; + char *share1 = NULL; + char *server2 = NULL; + char *share2 = NULL; + char *user1 = NULL; + char *user2 = NULL; + char *password1 = NULL; + char *password2 = NULL; + char *workgroup = NULL; + char *path1 = NULL; + char *path2 = NULL; + char *targetpath1 = NULL; + char *targetpath2 = NULL; + struct cli_state *targetcli1 = NULL; + struct cli_state *targetcli2 = NULL; SMBCSRV *srv = NULL; TALLOC_CTX *frame = talloc_stackframe(); @@ -2017,8 +2055,8 @@ smbc_rename_ctx(SMBCCTX *ocontext, return -1; } - srv = smbc_server(ocontext, True, - server1, share1, workgroup, user1, password1); + srv = smbc_server(frame, ocontext, True, + server1, share1, &workgroup, &user1, &password1); if (!srv) { TALLOC_FREE(frame); return -1; @@ -2080,10 +2118,10 @@ smbc_lseek_ctx(SMBCCTX *context, int whence) { SMB_OFF_T size; - char *server, *share, *user, *password; - char *path; - char *targetpath; - struct cli_state *targetcli; + char *server = NULL, *share = NULL, *user = NULL, *password = NULL; + char *path = NULL; + char *targetpath = NULL; + struct cli_state *targetcli = NULL; TALLOC_CTX *frame = talloc_stackframe(); if (!context || !context->internal || @@ -2253,13 +2291,13 @@ smbc_stat_ctx(SMBCCTX *context, const char *fname, struct stat *st) { - SMBCSRV *srv; - char *server; - char *share; - char *user; - char *password; - char *workgroup; - char *path; + SMBCSRV *srv = NULL; + char *server = NULL; + char *share = NULL; + char *user = NULL; + char *password = NULL; + char *workgroup = NULL; + char *path = NULL; struct timespec write_time_ts; struct timespec access_time_ts; struct timespec change_time_ts; @@ -2308,8 +2346,8 @@ smbc_stat_ctx(SMBCCTX *context, } } - srv = smbc_server(context, True, - server, share, workgroup, user, password); + srv = smbc_server(frame, context, True, + server, share, &workgroup, &user, &password); if (!srv) { TALLOC_FREE(frame); @@ -2355,13 +2393,13 @@ smbc_fstat_ctx(SMBCCTX *context, struct timespec write_time_ts; SMB_OFF_T size; uint16 mode; - char *server; - char *share; - char *user; - char *password; - char *path; - char *targetpath; - struct cli_state *targetcli; + char *server = NULL; + char *share = NULL; + char *user = NULL; + char *password = NULL; + char *path = NULL; + char *targetpath = NULL; + struct cli_state *targetcli = NULL; SMB_INO_T ino = 0; TALLOC_CTX *frame = talloc_stackframe(); @@ -2743,14 +2781,14 @@ smbc_opendir_ctx(SMBCCTX *context, const char *fname) { int saved_errno; - char *server, *share, *user, *password, *options; - char *workgroup; - char *path; + char *server = NULL, *share = NULL, *user = NULL, *password = NULL, *options = NULL; + char *workgroup = NULL; + char *path = NULL; uint16 mode; - char *p; + char *p = NULL; SMBCSRV *srv = NULL; SMBCFILE *dir = NULL; - struct _smbc_callbacks *cb; + struct _smbc_callbacks *cb = NULL; struct sockaddr_storage rem_ss; TALLOC_CTX *frame = talloc_stackframe(); @@ -2939,8 +2977,8 @@ smbc_opendir_ctx(SMBCCTX *context, * workgroups/domains that it knows about. */ - srv = smbc_server(context, True, server, "IPC$", - workgroup, user, password); + srv = smbc_server(frame, context, True, server, "IPC$", + &workgroup, &user, &password); if (!srv) { continue; } @@ -2993,8 +3031,8 @@ smbc_opendir_ctx(SMBCCTX *context, * establish a connection if one does not already * exist. */ - srv = smbc_server(context, False, server, "IPC$", - workgroup, user, password); + srv = smbc_server(frame, context, False, server, "IPC$", + &workgroup, &user, &password); /* * If no existing server and not an IP addr, look for @@ -3032,9 +3070,9 @@ smbc_opendir_ctx(SMBCCTX *context, * Get a connection to IPC$ on the server if * we do not already have one */ - srv = smbc_server(context, True, + srv = smbc_server(frame, context, True, buserver, "IPC$", - workgroup, user, password); + &workgroup, &user, &password); if (!srv) { DEBUG(0, ("got no contact to IPC$\n")); if (dir) { @@ -3065,10 +3103,10 @@ smbc_opendir_ctx(SMBCCTX *context, /* If we hadn't found the server, get one now */ if (!srv) { - srv = smbc_server(context, True, + srv = smbc_server(frame, context, True, server, "IPC$", - workgroup, - user, password); + &workgroup, + &user, &password); } if (!srv) { @@ -3127,8 +3165,8 @@ smbc_opendir_ctx(SMBCCTX *context, /* We connect to the server and list the directory */ dir->dir_type = SMBC_FILE_SHARE; - srv = smbc_server(context, True, server, share, - workgroup, user, password); + srv = smbc_server(frame, context, True, server, share, + &workgroup, &user, &password); if (!srv) { if (dir) { @@ -3495,15 +3533,15 @@ smbc_mkdir_ctx(SMBCCTX *context, const char *fname, mode_t mode) { - SMBCSRV *srv; - char *server; - char *share; - char *user; - char *password; - char *workgroup; - char *path; - char *targetpath; - struct cli_state *targetcli; + SMBCSRV *srv = NULL; + char *server = NULL; + char *share = NULL; + char *user = NULL; + char *password = NULL; + char *workgroup = NULL; + char *path = NULL; + char *targetpath = NULL; + struct cli_state *targetcli = NULL; TALLOC_CTX *frame = talloc_stackframe(); if (!context || !context->internal || @@ -3545,8 +3583,8 @@ smbc_mkdir_ctx(SMBCCTX *context, } } - srv = smbc_server(context, True, - server, share, workgroup, user, password); + srv = smbc_server(frame, context, True, + server, share, &workgroup, &user, &password); if (!srv) { @@ -3603,15 +3641,15 @@ static int smbc_rmdir_ctx(SMBCCTX *context, const char *fname) { - SMBCSRV *srv; - char *server; - char *share; - char *user; - char *password; - char *workgroup; - char *path; - char *targetpath; - struct cli_state *targetcli; + SMBCSRV *srv = NULL; + char *server = NULL; + char *share = NULL; + char *user = NULL; + char *password = NULL; + char *workgroup = NULL; + char *path = NULL; + char *targetpath = NULL; + struct cli_state *targetcli = NULL; TALLOC_CTX *frame = talloc_stackframe(); if (!context || !context->internal || @@ -3653,8 +3691,8 @@ smbc_rmdir_ctx(SMBCCTX *context, } } - srv = smbc_server(context, True, - server, share, workgroup, user, password); + srv = smbc_server(frame, context, True, + server, share, &workgroup, &user, &password); if (!srv) { @@ -3888,13 +3926,13 @@ smbc_chmod_ctx(SMBCCTX *context, const char *fname, mode_t newmode) { - SMBCSRV *srv; - char *server; - char *share; - char *user; - char *password; - char *workgroup; - char *path; + SMBCSRV *srv = NULL; + char *server = NULL; + char *share = NULL; + char *user = NULL; + char *password = NULL; + char *workgroup = NULL; + char *path = NULL; uint16 mode; TALLOC_CTX *frame = talloc_stackframe(); @@ -3937,8 +3975,8 @@ smbc_chmod_ctx(SMBCCTX *context, } } - srv = smbc_server(context, True, - server, share, workgroup, user, password); + srv = smbc_server(frame, context, True, + server, share, &workgroup, &user, &password); if (!srv) { TALLOC_FREE(frame); @@ -3967,13 +4005,13 @@ smbc_utimes_ctx(SMBCCTX *context, const char *fname, struct timeval *tbuf) { - SMBCSRV *srv; - char *server; - char *share; - char *user; - char *password; - char *workgroup; - char *path; + SMBCSRV *srv = NULL; + char *server = NULL; + char *share = NULL; + char *user = NULL; + char *password = NULL; + char *workgroup = NULL; + char *path = NULL; time_t access_time; time_t write_time; TALLOC_CTX *frame = talloc_stackframe(); @@ -4043,8 +4081,8 @@ smbc_utimes_ctx(SMBCCTX *context, } } - srv = smbc_server(context, True, - server, share, workgroup, user, password); + srv = smbc_server(frame, context, True, + server, share, &workgroup, &user, &password); if (!srv) { TALLOC_FREE(frame); @@ -5679,16 +5717,16 @@ smbc_setxattr_ctx(SMBCCTX *context, { int ret; int ret2; - SMBCSRV *srv; - SMBCSRV *ipc_srv; - char *server; - char *share; - char *user; - char *password; - char *workgroup; - char *path; + SMBCSRV *srv = NULL; + SMBCSRV *ipc_srv = NULL; + char *server = NULL; + char *share = NULL; + char *user = NULL; + char *password = NULL; + char *workgroup = NULL; + char *path = NULL; POLICY_HND pol; - DOS_ATTR_DESC *dad; + DOS_ATTR_DESC *dad = NULL; struct { const char * create_time_attr; const char * access_time_attr; @@ -5737,16 +5775,16 @@ smbc_setxattr_ctx(SMBCCTX *context, } } - srv = smbc_server(context, True, - server, share, workgroup, user, password); + srv = smbc_server(frame, context, True, + server, share, &workgroup, &user, &password); if (!srv) { TALLOC_FREE(frame); return -1; /* errno set by smbc_server */ } if (! srv->no_nt_session) { - ipc_srv = smbc_attr_server(context, server, share, - workgroup, user, password, + ipc_srv = smbc_attr_server(frame, context, server, share, + &workgroup, &user, &password, &pol); if (! ipc_srv) { srv->no_nt_session = True; @@ -5977,14 +6015,14 @@ smbc_getxattr_ctx(SMBCCTX *context, size_t size) { int ret; - SMBCSRV *srv; - SMBCSRV *ipc_srv; - char *server; - char *share; - char *user; - char *password; - char *workgroup; - char *path; + SMBCSRV *srv = NULL; + SMBCSRV *ipc_srv = NULL; + char *server = NULL; + char *share = NULL; + char *user = NULL; + char *password = NULL; + char *workgroup = NULL; + char *path = NULL; POLICY_HND pol; struct { const char * create_time_attr; @@ -6033,16 +6071,16 @@ smbc_getxattr_ctx(SMBCCTX *context, } } - srv = smbc_server(context, True, - server, share, workgroup, user, password); + srv = smbc_server(frame, context, True, + server, share, &workgroup, &user, &password); if (!srv) { TALLOC_FREE(frame); return -1; /* errno set by smbc_server */ } if (! srv->no_nt_session) { - ipc_srv = smbc_attr_server(context, server, share, - workgroup, user, password, + ipc_srv = smbc_attr_server(frame, context, server, share, + &workgroup, &user, &password, &pol); if (! ipc_srv) { srv->no_nt_session = True; @@ -6119,14 +6157,14 @@ smbc_removexattr_ctx(SMBCCTX *context, const char *name) { int ret; - SMBCSRV *srv; - SMBCSRV *ipc_srv; - char *server; - char *share; - char *user; - char *password; - char *workgroup; - char *path; + SMBCSRV *srv = NULL; + SMBCSRV *ipc_srv = NULL; + char *server = NULL; + char *share = NULL; + char *user = NULL; + char *password = NULL; + char *workgroup = NULL; + char *path = NULL; POLICY_HND pol; TALLOC_CTX *frame = talloc_stackframe(); @@ -6169,16 +6207,16 @@ smbc_removexattr_ctx(SMBCCTX *context, } } - srv = smbc_server(context, True, - server, share, workgroup, user, password); + srv = smbc_server(frame, context, True, + server, share, &workgroup, &user, &password); if (!srv) { TALLOC_FREE(frame); return -1; /* errno set by smbc_server */ } if (! srv->no_nt_session) { - ipc_srv = smbc_attr_server(context, server, share, - workgroup, user, password, + ipc_srv = smbc_attr_server(frame, context, server, share, + &workgroup, &user, &password, &pol); if (! ipc_srv) { srv->no_nt_session = True; @@ -6241,6 +6279,7 @@ smbc_listxattr_ctx(SMBCCTX *context, * the complete set of attribute names, always, rather than only those * attribute names which actually exist for a file. Hmmm... */ + size_t retsize; const char supported_old[] = "system.*\0" "system.*+\0" @@ -6284,22 +6323,24 @@ smbc_listxattr_ctx(SMBCCTX *context, if (context->internal->_full_time_names) { supported = supported_new; + retsize = sizeof(supported_new); } else { supported = supported_old; + retsize = sizeof(supported_old); } if (size == 0) { - return sizeof(supported); + return retsize; } - if (sizeof(supported) > size) { + if (retsize > size) { errno = ERANGE; return -1; } /* this can't be strcpy() because there are embedded null characters */ - memcpy(list, supported, sizeof(supported)); - return sizeof(supported); + memcpy(list, supported, retsize); + return retsize; } @@ -6311,11 +6352,11 @@ static SMBCFILE * smbc_open_print_job_ctx(SMBCCTX *context, const char *fname) { - char *server; - char *share; - char *user; - char *password; - char *path; + char *server = NULL; + char *share = NULL; + char *user = NULL; + char *password = NULL; + char *path = NULL; TALLOC_CTX *frame = talloc_stackframe(); if (!context || !context->internal || @@ -6454,13 +6495,13 @@ smbc_list_print_jobs_ctx(SMBCCTX *context, const char *fname, smbc_list_print_job_fn fn) { - SMBCSRV *srv; - char *server; - char *share; - char *user; - char *password; - char *workgroup; - char *path; + SMBCSRV *srv = NULL; + char *server = NULL; + char *share = NULL; + char *user = NULL; + char *password = NULL; + char *workgroup = NULL; + char *path = NULL; TALLOC_CTX *frame = talloc_stackframe(); if (!context || !context->internal || @@ -6502,8 +6543,8 @@ smbc_list_print_jobs_ctx(SMBCCTX *context, } } - srv = smbc_server(context, True, - server, share, workgroup, user, password); + srv = smbc_server(frame, context, True, + server, share, &workgroup, &user, &password); if (!srv) { TALLOC_FREE(frame); @@ -6531,13 +6572,13 @@ smbc_unlink_print_job_ctx(SMBCCTX *context, const char *fname, int id) { - SMBCSRV *srv; - char *server; - char *share; - char *user; - char *password; - char *workgroup; - char *path; + SMBCSRV *srv = NULL; + char *server = NULL; + char *share = NULL; + char *user = NULL; + char *password = NULL; + char *workgroup = NULL; + char *path = NULL; int err; TALLOC_CTX *frame = talloc_stackframe(); @@ -6580,8 +6621,8 @@ smbc_unlink_print_job_ctx(SMBCCTX *context, } } - srv = smbc_server(context, True, - server, share, workgroup, user, password); + srv = smbc_server(frame, context, True, + server, share, &workgroup, &user, &password); if (!srv) { 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/libsmb/smbencrypt.c b/source3/libsmb/smbencrypt.c index d7f6f604f7..c547a4a003 100644 --- a/source3/libsmb/smbencrypt.c +++ b/source3/libsmb/smbencrypt.c @@ -443,7 +443,7 @@ bool SMBNTLMv2encrypt_hash(const char *user, const char *domain, const uchar nt_ the username and domain. This prevents username swapping during the auth exchange */ - if (!ntv2_owf_gen(nt_hash, user, domain, True, ntlm_v2_hash)) { + if (!ntv2_owf_gen(nt_hash, user, domain, False, ntlm_v2_hash)) { return False; } 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, ¶ms, sbuf.st_uid, sbuf.st_gid); + acl = smbacl4_win2nfs4(fsp->fsp_name, psd->dacl, ¶ms, 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..ddbc5aab18 --- /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), SMB_STRUCT_DIR *, 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), char *, 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/modules/vfs_xattr_tdb.c b/source3/modules/vfs_xattr_tdb.c new file mode 100644 index 0000000000..29864a8f94 --- /dev/null +++ b/source3/modules/vfs_xattr_tdb.c @@ -0,0 +1,737 @@ +/* + * Store posix-level xattrs in a tdb + * + * 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 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/>. + */ + +#include "includes.h" +#include "librpc/gen_ndr/xattr.h" +#include "librpc/gen_ndr/ndr_xattr.h" + +#undef DBGC_CLASS +#define DBGC_CLASS DBGC_VFS + +/* + * unmarshall tdb_xattrs + */ + +static NTSTATUS xattr_tdb_pull_attrs(TALLOC_CTX *mem_ctx, + const TDB_DATA *data, + struct tdb_xattrs **presult) +{ + DATA_BLOB blob; + enum ndr_err_code ndr_err; + struct tdb_xattrs *result; + + if (!(result = TALLOC_ZERO_P(mem_ctx, struct tdb_xattrs))) { + return NT_STATUS_NO_MEMORY; + } + + if (data->dsize == 0) { + *presult = result; + return NT_STATUS_OK; + } + + blob = data_blob_const(data->dptr, data->dsize); + + ndr_err = ndr_pull_struct_blob( + &blob, result, result, + (ndr_pull_flags_fn_t)ndr_pull_tdb_xattrs); + + if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { + DEBUG(0, ("ndr_pull_tdb_xattrs failed: %s\n", + ndr_errstr(ndr_err))); + TALLOC_FREE(result); + return ndr_map_error2ntstatus(ndr_err);; + } + + *presult = result; + return NT_STATUS_OK; +} + +/* + * marshall tdb_xattrs + */ + +static NTSTATUS xattr_tdb_push_attrs(TALLOC_CTX *mem_ctx, + const struct tdb_xattrs *attribs, + TDB_DATA *data) +{ + DATA_BLOB blob; + enum ndr_err_code ndr_err; + + ndr_err = ndr_push_struct_blob( + &blob, mem_ctx, attribs, + (ndr_push_flags_fn_t)ndr_push_tdb_xattrs); + + if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { + DEBUG(0, ("ndr_push_tdb_xattrs failed: %s\n", + ndr_errstr(ndr_err))); + return ndr_map_error2ntstatus(ndr_err);; + } + + *data = make_tdb_data(blob.data, blob.length); + return NT_STATUS_OK; +} + +/* + * Load tdb_xattrs for a file from the tdb + */ + +static NTSTATUS xattr_tdb_load_attrs(TALLOC_CTX *mem_ctx, + struct db_context *db_ctx, + const struct file_id *id, + struct tdb_xattrs **presult) +{ + uint8 id_buf[16]; + NTSTATUS status; + TDB_DATA data; + + push_file_id_16((char *)id_buf, id); + + if (db_ctx->fetch(db_ctx, mem_ctx, + make_tdb_data(id_buf, sizeof(id_buf)), + &data) == -1) { + return NT_STATUS_INTERNAL_DB_CORRUPTION; + } + + status = xattr_tdb_pull_attrs(mem_ctx, &data, presult); + TALLOC_FREE(data.dptr); + return NT_STATUS_OK; +} + +/* + * fetch_lock the tdb_ea record for a file + */ + +static struct db_record *xattr_tdb_lock_attrs(TALLOC_CTX *mem_ctx, + struct db_context *db_ctx, + const struct file_id *id) +{ + uint8 id_buf[16]; + push_file_id_16((char *)id_buf, id); + return db_ctx->fetch_locked(db_ctx, mem_ctx, + make_tdb_data(id_buf, sizeof(id_buf))); +} + +/* + * Save tdb_xattrs to a previously fetch_locked record + */ + +static NTSTATUS xattr_tdb_save_attrs(struct db_record *rec, + const struct tdb_xattrs *attribs) +{ + TDB_DATA data = tdb_null; + NTSTATUS status; + + status = xattr_tdb_push_attrs(talloc_tos(), attribs, &data); + + if (!NT_STATUS_IS_OK(status)) { + DEBUG(0, ("xattr_tdb_push_attrs failed: %s\n", + nt_errstr(status))); + return status; + } + + status = rec->store(rec, data, 0); + + TALLOC_FREE(data.dptr); + + return status; +} + +/* + * Worker routine for getxattr and fgetxattr + */ + +static ssize_t xattr_tdb_getattr(struct db_context *db_ctx, + const struct file_id *id, + const char *name, void *value, size_t size) +{ + struct tdb_xattrs *attribs; + uint32_t i; + ssize_t result = -1; + NTSTATUS status; + + status = xattr_tdb_load_attrs(talloc_tos(), db_ctx, id, &attribs); + + if (!NT_STATUS_IS_OK(status)) { + DEBUG(10, ("xattr_tdb_fetch_attrs failed: %s\n", + nt_errstr(status))); + errno = EINVAL; + return -1; + } + + for (i=0; i<attribs->num_xattrs; i++) { + if (strcmp(attribs->xattrs[i].name, name) == 0) { + break; + } + } + + if (i == attribs->num_xattrs) { + errno = ENOATTR; + goto fail; + } + + if (attribs->xattrs[i].value.length > size) { + errno = ERANGE; + goto fail; + } + + memcpy(value, attribs->xattrs[i].value.data, + attribs->xattrs[i].value.length); + result = attribs->xattrs[i].value.length; + + fail: + TALLOC_FREE(attribs); + return result; +} + +static ssize_t xattr_tdb_getxattr(struct vfs_handle_struct *handle, + const char *path, const char *name, + void *value, size_t size) +{ + SMB_STRUCT_STAT sbuf; + struct file_id id; + struct db_context *db; + + SMB_VFS_HANDLE_GET_DATA(handle, db, struct db_context, return -1); + + if (SMB_VFS_STAT(handle->conn, path, &sbuf) == -1) { + return -1; + } + + id = SMB_VFS_FILE_ID_CREATE(handle->conn, sbuf.st_dev, sbuf.st_ino); + + return xattr_tdb_getattr(db, &id, name, value, size); +} + +static ssize_t xattr_tdb_fgetxattr(struct vfs_handle_struct *handle, + struct files_struct *fsp, + const char *name, void *value, size_t size) +{ + SMB_STRUCT_STAT sbuf; + struct file_id id; + struct db_context *db; + + SMB_VFS_HANDLE_GET_DATA(handle, db, struct db_context, return -1); + + if (SMB_VFS_FSTAT(fsp, &sbuf) == -1) { + return -1; + } + + id = SMB_VFS_FILE_ID_CREATE(handle->conn, sbuf.st_dev, sbuf.st_ino); + + return xattr_tdb_getattr(db, &id, name, value, size); +} + +/* + * Worker routine for setxattr and fsetxattr + */ + +static int xattr_tdb_setattr(struct db_context *db_ctx, + const struct file_id *id, const char *name, + const void *value, size_t size, int flags) +{ + NTSTATUS status; + struct db_record *rec; + struct tdb_xattrs *attribs; + uint32_t i; + + rec = xattr_tdb_lock_attrs(talloc_tos(), db_ctx, id); + + if (rec == NULL) { + DEBUG(0, ("xattr_tdb_lock_attrs failed\n")); + errno = EINVAL; + return -1; + } + + status = xattr_tdb_pull_attrs(rec, &rec->value, &attribs); + + if (!NT_STATUS_IS_OK(status)) { + DEBUG(10, ("xattr_tdb_fetch_attrs failed: %s\n", + nt_errstr(status))); + TALLOC_FREE(rec); + return -1; + } + + for (i=0; i<attribs->num_xattrs; i++) { + if (strcmp(attribs->xattrs[i].name, name) == 0) { + break; + } + } + + if (i == attribs->num_xattrs) { + struct tdb_xattr *tmp; + + tmp = TALLOC_REALLOC_ARRAY( + attribs, attribs->xattrs, struct tdb_xattr, + attribs->num_xattrs + 1); + + if (tmp == NULL) { + DEBUG(0, ("TALLOC_REALLOC_ARRAY failed\n")); + TALLOC_FREE(rec); + errno = ENOMEM; + return -1; + } + + attribs->xattrs = tmp; + attribs->num_xattrs += 1; + } + + attribs->xattrs[i].name = name; + attribs->xattrs[i].value.data = CONST_DISCARD(uint8 *, value); + attribs->xattrs[i].value.length = size; + + status = xattr_tdb_save_attrs(rec, attribs); + + TALLOC_FREE(rec); + + if (!NT_STATUS_IS_OK(status)) { + DEBUG(1, ("save failed: %s\n", nt_errstr(status))); + return -1; + } + + return 0; +} + +static int xattr_tdb_setxattr(struct vfs_handle_struct *handle, + const char *path, const char *name, + const void *value, size_t size, int flags) +{ + SMB_STRUCT_STAT sbuf; + struct file_id id; + struct db_context *db; + + SMB_VFS_HANDLE_GET_DATA(handle, db, struct db_context, return -1); + + if (SMB_VFS_STAT(handle->conn, path, &sbuf) == -1) { + return -1; + } + + id = SMB_VFS_FILE_ID_CREATE(handle->conn, sbuf.st_dev, sbuf.st_ino); + + return xattr_tdb_setattr(db, &id, name, value, size, flags); +} + +static int xattr_tdb_fsetxattr(struct vfs_handle_struct *handle, + struct files_struct *fsp, + const char *name, const void *value, + size_t size, int flags) +{ + SMB_STRUCT_STAT sbuf; + struct file_id id; + struct db_context *db; + + SMB_VFS_HANDLE_GET_DATA(handle, db, struct db_context, return -1); + + if (SMB_VFS_FSTAT(fsp, &sbuf) == -1) { + return -1; + } + + id = SMB_VFS_FILE_ID_CREATE(handle->conn, sbuf.st_dev, sbuf.st_ino); + + return xattr_tdb_setattr(db, &id, name, value, size, flags); +} + +/* + * Worker routine for listxattr and flistxattr + */ + +static ssize_t xattr_tdb_listattr(struct db_context *db_ctx, + const struct file_id *id, char *list, + size_t size) +{ + NTSTATUS status; + struct tdb_xattrs *attribs; + uint32_t i; + size_t len = 0; + + status = xattr_tdb_load_attrs(talloc_tos(), db_ctx, id, &attribs); + + if (!NT_STATUS_IS_OK(status)) { + DEBUG(10, ("xattr_tdb_fetch_attrs failed: %s\n", + nt_errstr(status))); + errno = EINVAL; + return -1; + } + + DEBUG(10, ("xattr_tdb_listattr: Found %d xattrs\n", + attribs->num_xattrs)); + + for (i=0; i<attribs->num_xattrs; i++) { + size_t tmp; + + DEBUG(10, ("xattr_tdb_listattr: xattrs[i].name: %s\n", + attribs->xattrs[i].name)); + + tmp = strlen(attribs->xattrs[i].name); + + /* + * Try to protect against overflow + */ + + if (len + (tmp+1) < len) { + TALLOC_FREE(attribs); + errno = EINVAL; + return -1; + } + + /* + * Take care of the terminating NULL + */ + len += (tmp + 1); + } + + if (len > size) { + TALLOC_FREE(attribs); + errno = ERANGE; + return -1; + } + + len = 0; + + for (i=0; i<attribs->num_xattrs; i++) { + strlcpy(list+len, attribs->xattrs[i].name, + size-len); + len += (strlen(attribs->xattrs[i].name) + 1); + } + + TALLOC_FREE(attribs); + return len; +} + +static ssize_t xattr_tdb_listxattr(struct vfs_handle_struct *handle, + const char *path, char *list, size_t size) +{ + SMB_STRUCT_STAT sbuf; + struct file_id id; + struct db_context *db; + + SMB_VFS_HANDLE_GET_DATA(handle, db, struct db_context, return -1); + + if (SMB_VFS_STAT(handle->conn, path, &sbuf) == -1) { + return -1; + } + + id = SMB_VFS_FILE_ID_CREATE(handle->conn, sbuf.st_dev, sbuf.st_ino); + + return xattr_tdb_listattr(db, &id, list, size); +} + +static ssize_t xattr_tdb_flistxattr(struct vfs_handle_struct *handle, + struct files_struct *fsp, char *list, + size_t size) +{ + SMB_STRUCT_STAT sbuf; + struct file_id id; + struct db_context *db; + + SMB_VFS_HANDLE_GET_DATA(handle, db, struct db_context, return -1); + + if (SMB_VFS_FSTAT(fsp, &sbuf) == -1) { + return -1; + } + + id = SMB_VFS_FILE_ID_CREATE(handle->conn, sbuf.st_dev, sbuf.st_ino); + + return xattr_tdb_listattr(db, &id, list, size); +} + +/* + * Worker routine for removexattr and fremovexattr + */ + +static int xattr_tdb_removeattr(struct db_context *db_ctx, + const struct file_id *id, const char *name) +{ + NTSTATUS status; + struct db_record *rec; + struct tdb_xattrs *attribs; + uint32_t i; + + rec = xattr_tdb_lock_attrs(talloc_tos(), db_ctx, id); + + if (rec == NULL) { + DEBUG(0, ("xattr_tdb_lock_attrs failed\n")); + errno = EINVAL; + return -1; + } + + status = xattr_tdb_pull_attrs(rec, &rec->value, &attribs); + + if (!NT_STATUS_IS_OK(status)) { + DEBUG(10, ("xattr_tdb_fetch_attrs failed: %s\n", + nt_errstr(status))); + TALLOC_FREE(rec); + return -1; + } + + for (i=0; i<attribs->num_xattrs; i++) { + if (strcmp(attribs->xattrs[i].name, name) == 0) { + break; + } + } + + if (i == attribs->num_xattrs) { + TALLOC_FREE(rec); + errno = ENOATTR; + return -1; + } + + attribs->xattrs[i] = + attribs->xattrs[attribs->num_xattrs-1]; + attribs->num_xattrs -= 1; + + if (attribs->num_xattrs == 0) { + rec->delete_rec(rec); + TALLOC_FREE(rec); + return 0; + } + + status = xattr_tdb_save_attrs(rec, attribs); + + TALLOC_FREE(rec); + + if (!NT_STATUS_IS_OK(status)) { + DEBUG(1, ("save failed: %s\n", nt_errstr(status))); + return -1; + } + + return 0; +} + +static int xattr_tdb_removexattr(struct vfs_handle_struct *handle, + const char *path, const char *name) +{ + SMB_STRUCT_STAT sbuf; + struct file_id id; + struct db_context *db; + + SMB_VFS_HANDLE_GET_DATA(handle, db, struct db_context, return -1); + + if (SMB_VFS_STAT(handle->conn, path, &sbuf) == -1) { + return -1; + } + + id = SMB_VFS_FILE_ID_CREATE(handle->conn, sbuf.st_dev, sbuf.st_ino); + + return xattr_tdb_removeattr(db, &id, name); +} + +static int xattr_tdb_fremovexattr(struct vfs_handle_struct *handle, + struct files_struct *fsp, const char *name) +{ + SMB_STRUCT_STAT sbuf; + struct file_id id; + struct db_context *db; + + SMB_VFS_HANDLE_GET_DATA(handle, db, struct db_context, return -1); + + if (SMB_VFS_FSTAT(fsp, &sbuf) == -1) { + return -1; + } + + id = SMB_VFS_FILE_ID_CREATE(handle->conn, sbuf.st_dev, sbuf.st_ino); + + return xattr_tdb_removeattr(db, &id, name); +} + +/* + * Open the tdb file upon VFS_CONNECT + */ + +static bool xattr_tdb_init(int snum, struct db_context **p_db) +{ + struct db_context *db; + const char *dbname; + + dbname = lp_parm_const_string(snum, "ea", "tdb", lock_path("eas.tdb")); + + if (dbname == NULL) { + errno = ENOTSUP; + return false; + } + + become_root(); + db = db_open(NULL, dbname, 0, TDB_DEFAULT, O_RDWR|O_CREAT, 0600); + unbecome_root(); + + if (db == NULL) { + errno = ENOTSUP; + return false; + } + + *p_db = db; + return true; +} + +/* + * On unlink we need to delete the tdb record + */ +static int xattr_tdb_unlink(vfs_handle_struct *handle, const char *path) +{ + SMB_STRUCT_STAT sbuf; + struct file_id id; + struct db_context *db; + struct db_record *rec; + int ret; + + SMB_VFS_HANDLE_GET_DATA(handle, db, struct db_context, return -1); + + if (SMB_VFS_STAT(handle->conn, path, &sbuf) == -1) { + return -1; + } + + ret = SMB_VFS_NEXT_UNLINK(handle, path); + + if (ret == -1) { + return -1; + } + + id = SMB_VFS_FILE_ID_CREATE(handle->conn, sbuf.st_dev, sbuf.st_ino); + + rec = xattr_tdb_lock_attrs(talloc_tos(), db, &id); + + /* + * If rec == NULL there's not much we can do about it + */ + + if (rec != NULL) { + rec->delete_rec(rec); + TALLOC_FREE(rec); + } + + return 0; +} + +/* + * On rmdir we need to delete the tdb record + */ +static int xattr_tdb_rmdir(vfs_handle_struct *handle, const char *path) +{ + SMB_STRUCT_STAT sbuf; + struct file_id id; + struct db_context *db; + struct db_record *rec; + int ret; + + SMB_VFS_HANDLE_GET_DATA(handle, db, struct db_context, return -1); + + if (SMB_VFS_STAT(handle->conn, path, &sbuf) == -1) { + return -1; + } + + ret = SMB_VFS_NEXT_RMDIR(handle, path); + + if (ret == -1) { + return -1; + } + + id = SMB_VFS_FILE_ID_CREATE(handle->conn, sbuf.st_dev, sbuf.st_ino); + + rec = xattr_tdb_lock_attrs(talloc_tos(), db, &id); + + /* + * If rec == NULL there's not much we can do about it + */ + + if (rec != NULL) { + rec->delete_rec(rec); + TALLOC_FREE(rec); + } + + return 0; +} + +/* + * Destructor for the VFS private data + */ + +static void close_ea_db(void **data) +{ + struct db_context **p_db = (struct db_context **)data; + TALLOC_FREE(*p_db); +} + +static int xattr_tdb_connect(vfs_handle_struct *handle, const char *service, + const char *user) +{ + fstring sname; + int res, snum; + struct db_context *db; + + res = SMB_VFS_NEXT_CONNECT(handle, service, user); + if (res < 0) { + return res; + } + + fstrcpy(sname, service); + snum = find_service(sname); + if (snum == -1) { + /* + * Should not happen, but we should not fail just *here*. + */ + return 0; + } + + if (!xattr_tdb_init(snum, &db)) { + DEBUG(5, ("Could not init ea tdb\n")); + lp_do_parameter(snum, "ea support", "False"); + return 0; + } + + lp_do_parameter(snum, "ea support", "True"); + + SMB_VFS_HANDLE_SET_DATA(handle, db, close_ea_db, + struct db_context, return -1); + + return 0; +} + +/* VFS operations structure */ + +static const vfs_op_tuple xattr_tdb_ops[] = { + {SMB_VFS_OP(xattr_tdb_getxattr), SMB_VFS_OP_GETXATTR, + SMB_VFS_LAYER_TRANSPARENT}, + {SMB_VFS_OP(xattr_tdb_fgetxattr), SMB_VFS_OP_FGETXATTR, + SMB_VFS_LAYER_TRANSPARENT}, + {SMB_VFS_OP(xattr_tdb_setxattr), SMB_VFS_OP_SETXATTR, + SMB_VFS_LAYER_TRANSPARENT}, + {SMB_VFS_OP(xattr_tdb_fsetxattr), SMB_VFS_OP_FSETXATTR, + SMB_VFS_LAYER_TRANSPARENT}, + {SMB_VFS_OP(xattr_tdb_listxattr), SMB_VFS_OP_LISTXATTR, + SMB_VFS_LAYER_TRANSPARENT}, + {SMB_VFS_OP(xattr_tdb_flistxattr), SMB_VFS_OP_FLISTXATTR, + SMB_VFS_LAYER_TRANSPARENT}, + {SMB_VFS_OP(xattr_tdb_removexattr), SMB_VFS_OP_REMOVEXATTR, + SMB_VFS_LAYER_TRANSPARENT}, + {SMB_VFS_OP(xattr_tdb_fremovexattr), SMB_VFS_OP_FREMOVEXATTR, + SMB_VFS_LAYER_TRANSPARENT}, + {SMB_VFS_OP(xattr_tdb_unlink), SMB_VFS_OP_UNLINK, + SMB_VFS_LAYER_TRANSPARENT}, + {SMB_VFS_OP(xattr_tdb_rmdir), SMB_VFS_OP_RMDIR, + SMB_VFS_LAYER_TRANSPARENT}, + {SMB_VFS_OP(xattr_tdb_connect), SMB_VFS_OP_CONNECT, + SMB_VFS_LAYER_TRANSPARENT}, + {SMB_VFS_OP(NULL), SMB_VFS_OP_NOOP, SMB_VFS_LAYER_NOOP} +}; + +NTSTATUS vfs_xattr_tdb_init(void); +NTSTATUS vfs_xattr_tdb_init(void) +{ + return smb_register_vfs(SMB_VFS_INTERFACE_VERSION, "xattr_tdb", + xattr_tdb_ops); +} diff --git a/source3/nsswitch/libwbclient/wbc_err.h b/source3/nsswitch/libwbclient/wbc_err.h deleted file mode 100644 index 069f68f189..0000000000 --- a/source3/nsswitch/libwbclient/wbc_err.h +++ /dev/null @@ -1,51 +0,0 @@ -/* - Unix SMB/CIFS implementation. - - Winbind client API - - Copyright (C) Gerald (Jerry) Carter 2007 - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 3 of the License, or (at your option) any later version. - - This library 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 - Library General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. -*/ - -#ifndef _WBC_ERR_H -#define _WBC_ERR_H - - -/* Define error types */ - -/** - * @brief Status codes returned from wbc functions - **/ - -enum _wbcErrType { - WBC_ERR_SUCCESS = 0, /**< Successful completion **/ - WBC_ERR_NOT_IMPLEMENTED,/**< Function not implemented **/ - WBC_ERR_UNKNOWN_FAILURE,/**< General failure **/ - WBC_ERR_NO_MEMORY, /**< Memory allocation error **/ - WBC_ERR_INVALID_SID, /**< Invalid SID format **/ - WBC_ERR_INVALID_PARAM, /**< An Invalid parameter was supplied **/ - WBC_ERR_WINBIND_NOT_AVAILABLE, /**< Winbind daemon is not available **/ - WBC_ERR_DOMAIN_NOT_FOUND, /**< Domain is not trusted or cannot be found **/ - WBC_INVALID_RESPONSE, /**< Winbind returned an invalid response **/ - WBC_ERR_NSS_ERROR /**< NSS_STATUS error **/ -}; - -typedef enum _wbcErrType wbcErr; - -#define WBC_ERROR_IS_OK(x) ((x) == WBC_ERR_SUCCESS) - -char *wbcErrorString(wbcErr error); - -#endif /* _WBC_ERR_H */ diff --git a/source3/nsswitch/libwbclient/wbclient.h b/source3/nsswitch/libwbclient/wbclient.h index 6b85d7e8b3..0b256d343f 100644 --- a/source3/nsswitch/libwbclient/wbclient.h +++ b/source3/nsswitch/libwbclient/wbclient.h @@ -23,7 +23,32 @@ #define _WBCLIENT_H #include <pwd.h> -#include <nsswitch/libwbclient/wbc_err.h> +#include <grp.h> + +/* Define error types */ + +/** + * @brief Status codes returned from wbc functions + **/ + +enum _wbcErrType { + WBC_ERR_SUCCESS = 0, /**< Successful completion **/ + WBC_ERR_NOT_IMPLEMENTED,/**< Function not implemented **/ + WBC_ERR_UNKNOWN_FAILURE,/**< General failure **/ + WBC_ERR_NO_MEMORY, /**< Memory allocation error **/ + WBC_ERR_INVALID_SID, /**< Invalid SID format **/ + WBC_ERR_INVALID_PARAM, /**< An Invalid parameter was supplied **/ + WBC_ERR_WINBIND_NOT_AVAILABLE, /**< Winbind daemon is not available **/ + WBC_ERR_DOMAIN_NOT_FOUND, /**< Domain is not trusted or cannot be found **/ + WBC_INVALID_RESPONSE, /**< Winbind returned an invalid response **/ + WBC_ERR_NSS_ERROR /**< NSS_STATUS error **/ +}; + +typedef enum _wbcErrType wbcErr; + +#define WBC_ERROR_IS_OK(x) ((x) == WBC_ERR_SUCCESS) + +char *wbcErrorString(wbcErr error); /* * Data types used by the Winbind Client API diff --git a/source3/nsswitch/winbind_nss_config.h b/source3/nsswitch/winbind_nss_config.h index 7f0e4b92e0..64d52af771 100644 --- a/source3/nsswitch/winbind_nss_config.h +++ b/source3/nsswitch/winbind_nss_config.h @@ -27,6 +27,14 @@ #undef SIZEOF_LONG #endif +/* + * we don't need socket wrapper + * nor nss wrapper here and we don't + * want to depend on swrap_close() + * so we better disable both + */ +#define SOCKET_WRAPPER_NOT_REPLACE +#define NSS_WRAPPER_NOT_REPLACE /* Include header files from data in config.h file */ diff --git a/source3/pam_smbpass/pam_smb_acct.c b/source3/pam_smbpass/pam_smb_acct.c index 59ed4eee8b..b9bcb31091 100644 --- a/source3/pam_smbpass/pam_smb_acct.c +++ b/source3/pam_smbpass/pam_smb_acct.c @@ -78,7 +78,7 @@ int pam_sm_acct_mgmt( pam_handle_t *pamh, int flags, } if (geteuid() != 0) { - _log_err(pamh, LOG_DEBUG, "Cannot access samba password database, not running as root."); + _log_err( LOG_DEBUG, "Cannot access samba password database, not running as root."); return PAM_AUTHINFO_UNAVAIL; } diff --git a/source3/pam_smbpass/pam_smb_passwd.c b/source3/pam_smbpass/pam_smb_passwd.c index de5310761f..326a0b59e7 100644 --- a/source3/pam_smbpass/pam_smb_passwd.c +++ b/source3/pam_smbpass/pam_smb_passwd.c @@ -130,7 +130,7 @@ int pam_sm_chauthtok(pam_handle_t *pamh, int flags, } if (geteuid() != 0) { - _log_err(pamh, LOG_DEBUG, "Cannot access samba password database, not running as root."); + _log_err( LOG_DEBUG, "Cannot access samba password database, not running as root."); return PAM_AUTHINFO_UNAVAIL; } 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/pkgconfig/wbclient.pc.in b/source3/pkgconfig/wbclient.pc.in new file mode 100644 index 0000000000..158fa923d6 --- /dev/null +++ b/source3/pkgconfig/wbclient.pc.in @@ -0,0 +1,13 @@ +prefix=@prefix@ +exec_prefix=@exec_prefix@ +libdir=@libdir@ +includedir=@includedir@ + +Name: Samba libwbclient +Description: A library to access winbindd +Version: 0 +URL: http://www.samba.org/ +#Libs: -L@libdir@ -lwbclient +Libs: -lwbclient +Libs.private: -lwbclient +Cflags: -I@includedir@ diff --git a/source3/printing/nt_printing.c b/source3/printing/nt_printing.c index bba55c0e4a..d5803b711b 100644 --- a/source3/printing/nt_printing.c +++ b/source3/printing/nt_printing.c @@ -3315,8 +3315,13 @@ static WERROR nt_printer_publish_ads(ADS_STRUCT *ads, /* publish it */ ads_rc = ads_mod_printer_entry(ads, prt_dn, ctx, &mods); - if (ads_rc.err.rc == LDAP_NO_SUCH_OBJECT) + if (ads_rc.err.rc == LDAP_NO_SUCH_OBJECT) { + int i; + for (i=0; mods[i] != 0; i++) + ; + mods[i] = (LDAPMod *)-1; ads_rc = ads_add_printer_entry(ads, prt_dn, ctx, &mods); + } if (!ADS_ERR_OK(ads_rc)) DEBUG(3, ("error publishing %s: %s\n", printer->info_2->sharename, ads_errstr(ads_rc))); diff --git a/source3/registry/reg_api.c b/source3/registry/reg_api.c index 8bbdb6abd3..d1657c8cf6 100644 --- a/source3/registry/reg_api.c +++ b/source3/registry/reg_api.c @@ -1,4 +1,4 @@ -/* +/* * Unix SMB/CIFS implementation. * Virtual Windows Registry Layer * Copyright (C) Volker Lendecke 2006 @@ -7,12 +7,12 @@ * 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/>. */ @@ -140,7 +140,7 @@ static WERROR regkey_open_onelevel(TALLOC_CTX *mem_ctx, result = WERR_BADFILE; goto done; } - + /* check if the path really exists; failed is indicated by -1 */ /* if the subkey count failed, bail out */ @@ -153,7 +153,7 @@ static WERROR regkey_open_onelevel(TALLOC_CTX *mem_ctx, result = WERR_BADFILE; goto done; } - + TALLOC_FREE( subkeys ); if ( !regkey_access_check( key, access_desired, &key->access_granted, @@ -302,7 +302,7 @@ WERROR reg_enumvalue(TALLOC_CTX *mem_ctx, struct registry_key *key, SAFE_FREE(val); return WERR_NOMEM; } - + *pval = val; return WERR_OK; } @@ -494,7 +494,6 @@ WERROR reg_createkey(TALLOC_CTX *ctx, struct registry_key *parent, TALLOC_FREE(mem_ctx); return err; } - WERROR reg_deletekey(struct registry_key *parent, const char *path) { @@ -712,8 +711,8 @@ WERROR reg_open_path(TALLOC_CTX *mem_ctx, const char *orig_path, } /* - * Utility function to delete a registry key with all its subkeys. - * Note that reg_deletekey returns ACCESS_DENIED when called on a + * Utility function to delete a registry key with all its subkeys. + * Note that reg_deletekey returns ACCESS_DENIED when called on a * key that has subkeys. */ WERROR reg_deletekey_recursive_internal(TALLOC_CTX *ctx, @@ -739,11 +738,11 @@ WERROR reg_deletekey_recursive_internal(TALLOC_CTX *ctx, } while (W_ERROR_IS_OK(werr = reg_enumkey(mem_ctx, key, 0, - &subkey_name, NULL))) + &subkey_name, NULL))) { werr = reg_deletekey_recursive_internal(mem_ctx, key, subkey_name, - True); + true); if (!W_ERROR_IS_OK(werr)) { goto done; } @@ -771,12 +770,12 @@ WERROR reg_deletekey_recursive(TALLOC_CTX *ctx, struct registry_key *parent, const char *path) { - return reg_deletekey_recursive_internal(ctx, parent, path, True); + return reg_deletekey_recursive_internal(ctx, parent, path, true); } WERROR reg_deletesubkeys_recursive(TALLOC_CTX *ctx, struct registry_key *parent, const char *path) { - return reg_deletekey_recursive_internal(ctx, parent, path, False); + return reg_deletekey_recursive_internal(ctx, parent, path, false); } diff --git a/source3/rpc_client/cli_lsarpc.c b/source3/rpc_client/cli_lsarpc.c index 77ade5cba1..286cc210e2 100644 --- a/source3/rpc_client/cli_lsarpc.c +++ b/source3/rpc_client/cli_lsarpc.c @@ -542,7 +542,8 @@ NTSTATUS rpccli_lsa_query_info_policy2_new(struct rpc_pipe_client *cli, TALLOC_C NTSTATUS rpccli_lsa_query_info_policy(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, POLICY_HND *pol, uint16 info_class, - char **domain_name, DOM_SID **domain_sid) + const char **domain_name, + DOM_SID **domain_sid) { prs_struct qbuf, rbuf; LSA_Q_QUERY_INFO q; @@ -632,8 +633,9 @@ NTSTATUS rpccli_lsa_query_info_policy(struct rpc_pipe_client *cli, NTSTATUS rpccli_lsa_query_info_policy2(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, POLICY_HND *pol, uint16 info_class, - char **domain_name, char **dns_name, - char **forest_name, + const char **domain_name, + const char **dns_name, + const char **forest_name, struct GUID **domain_guid, DOM_SID **domain_sid) { 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/rpc_server/srv_wkssvc_nt.c b/source3/rpc_server/srv_wkssvc_nt.c index 849ec9c4eb..de2e33732d 100644 --- a/source3/rpc_server/srv_wkssvc_nt.c +++ b/source3/rpc_server/srv_wkssvc_nt.c @@ -287,7 +287,7 @@ WERROR _wkssvc_NetrJoinDomain2(pipes_struct *p, struct wkssvc_NetrJoinDomain2 *r { #if 0 struct libnet_JoinCtx *j = NULL; - char *pwd = NULL; + char *cleartext_pwd = NULL; char *admin_domain = NULL; char *admin_account = NULL; WERROR werr; @@ -308,12 +308,7 @@ WERROR _wkssvc_NetrJoinDomain2(pipes_struct *p, struct wkssvc_NetrJoinDomain2 *r werr = decode_wkssvc_join_password_buffer(p->mem_ctx, r->in.encrypted_password, &p->session_key, - &pwd); - if (!W_ERROR_IS_OK(werr)) { - return werr; - } - - werr = libnet_init_JoinCtx(p->mem_ctx, &j); + &cleartext_pwd); if (!W_ERROR_IS_OK(werr)) { return werr; } @@ -323,7 +318,7 @@ WERROR _wkssvc_NetrJoinDomain2(pipes_struct *p, struct wkssvc_NetrJoinDomain2 *r &admin_domain, &admin_account); - status = DsGetDcName(p->mem_ctx, + status = dsgetdcname(p->mem_ctx, NULL, r->in.domain_name, NULL, @@ -336,14 +331,18 @@ WERROR _wkssvc_NetrJoinDomain2(pipes_struct *p, struct wkssvc_NetrJoinDomain2 *r return ntstatus_to_werror(status); } - j->in.server_name = info->domain_controller_name; + werr = libnet_init_JoinCtx(p->mem_ctx, &j); + if (!W_ERROR_IS_OK(werr)) { + return werr; + } + + j->in.dc_name = info->domain_controller_name; j->in.domain_name = r->in.domain_name; j->in.account_ou = r->in.account_ou; j->in.join_flags = r->in.join_flags; - - j->in.admin_account = admin_account; - j->in.password = pwd; - j->in.modify_config = true; + j->in.admin_account = admin_account; + j->in.admin_password = cleartext_pwd; + j->in.modify_config = true; become_root(); werr = libnet_Join(p->mem_ctx, j); diff --git a/source3/rpcclient/cmd_lsarpc.c b/source3/rpcclient/cmd_lsarpc.c index 7743269ce0..05269d7711 100644 --- a/source3/rpcclient/cmd_lsarpc.c +++ b/source3/rpcclient/cmd_lsarpc.c @@ -916,7 +916,8 @@ static void display_trust_dom_info_4(struct lsa_TrustDomainInfoPassword *p, cons data_blob_free(&data_old); } -static void display_trust_dom_info(union lsa_TrustedDomainInfo *info, +static void display_trust_dom_info(TALLOC_CTX *mem_ctx, + union lsa_TrustedDomainInfo *info, enum lsa_TrustDomInfoEnum info_class, const char *pass) { @@ -924,12 +925,17 @@ static void display_trust_dom_info(union lsa_TrustedDomainInfo *info, case LSA_TRUSTED_DOMAIN_INFO_PASSWORD: display_trust_dom_info_4(&info->password, pass); break; - default: - NDR_PRINT_UNION_DEBUG(lsa_TrustedDomainInfo, - info_class, info); + default: { + const char *str = NULL; + str = NDR_PRINT_UNION_STRING(mem_ctx, + lsa_TrustedDomainInfo, + info_class, info); + if (str) { + d_printf("%s\n", str); + } break; + } } - } static NTSTATUS cmd_lsa_query_trustdominfobysid(struct rpc_pipe_client *cli, @@ -967,7 +973,7 @@ static NTSTATUS cmd_lsa_query_trustdominfobysid(struct rpc_pipe_client *cli, if (!NT_STATUS_IS_OK(result)) goto done; - display_trust_dom_info(&info, info_class, cli->pwd.password); + display_trust_dom_info(mem_ctx, &info, info_class, cli->pwd.password); done: if (&pol) @@ -1015,7 +1021,7 @@ static NTSTATUS cmd_lsa_query_trustdominfobyname(struct rpc_pipe_client *cli, if (!NT_STATUS_IS_OK(result)) goto done; - display_trust_dom_info(&info, info_class, cli->pwd.password); + display_trust_dom_info(mem_ctx, &info, info_class, cli->pwd.password); done: if (&pol) @@ -1069,7 +1075,7 @@ static NTSTATUS cmd_lsa_query_trustdominfo(struct rpc_pipe_client *cli, if (!NT_STATUS_IS_OK(result)) goto done; - display_trust_dom_info(&info, info_class, cli->pwd.password); + display_trust_dom_info(mem_ctx, &info, info_class, cli->pwd.password); done: if (&pol) diff --git a/source3/rpcclient/rpcclient.c b/source3/rpcclient/rpcclient.c index dd8b911bb8..081e0fb15e 100644 --- a/source3/rpcclient/rpcclient.c +++ b/source3/rpcclient/rpcclient.c @@ -134,7 +134,7 @@ static void fetch_machine_sid(struct cli_state *cli) POLICY_HND pol; NTSTATUS result = NT_STATUS_OK; uint32 info_class = 5; - char *domain_name = NULL; + const char *domain_name = NULL; static bool got_domain_sid; TALLOC_CTX *mem_ctx; DOM_SID *dom_sid = NULL; diff --git a/source3/script/fix_bool.pl b/source3/script/fix_bool.pl new file mode 100755 index 0000000000..c09645de7c --- /dev/null +++ b/source3/script/fix_bool.pl @@ -0,0 +1,19 @@ +#!/usr/bin/perl -w + +open(INFILE, "$ARGV[0]") || die $@; +open(OUTFILE, ">$ARGV[0].new") || die $@; + +while (<INFILE>) { + $_ =~ s/True/true/; + $_ =~ s/False/false/; + print OUTFILE "$_"; +} + +close(INFILE); +close(OUTFILE); + +rename("$ARGV[0].new", "$ARGV[0]") || die @_; + +exit(0); + + diff --git a/source3/script/tests/selftest.sh b/source3/script/tests/selftest.sh index 86abb15ed1..5a170b2117 100755 --- a/source3/script/tests/selftest.sh +++ b/source3/script/tests/selftest.sh @@ -186,6 +186,7 @@ cat >$SERVERCONFFILE<<EOF map hidden = yes map system = yes create mask = 755 + vfs objects = $BINDIR/xattr_tdb.so [hideunread] copy = tmp hide unreadable = yes diff --git a/source3/script/tests/test_posix_s3.sh b/source3/script/tests/test_posix_s3.sh index 9f672897ac..0b4a52d4b5 100755 --- a/source3/script/tests/test_posix_s3.sh +++ b/source3/script/tests/test_posix_s3.sh @@ -47,7 +47,7 @@ unix="UNIX-INFO2" tests="$base $raw $rpc $unix" skipped="BASE-CHARSET BASE-DELAYWRITE BASE-TCONDEV" -skipped="$skipped RAW-ACLS RAW-COMPOSITE RAW-CONTEXT RAW-EAS" +skipped="$skipped RAW-ACLS RAW-COMPOSITE RAW-CONTEXT" skipped="$skipped RAW-IOCTL" skipped="$skipped RAW-QFILEINFO RAW-QFSINFO RAW-SEARCH" skipped="$skipped RAW-SFILEINFO RAW-STREAMS" 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/utils/net.h b/source3/utils/net.h index 2ffa4d77b1..3a4b1da7b0 100644 --- a/source3/utils/net.h +++ b/source3/utils/net.h @@ -42,7 +42,7 @@ struct rpc_sh_ctx { struct cli_state *cli; DOM_SID *domain_sid; - char *domain_name; + const char *domain_name; const char *whoami; const char *thiscmd; diff --git a/source3/utils/net_ads.c b/source3/utils/net_ads.c index 80f6ba9001..732ba8d8b6 100644 --- a/source3/utils/net_ads.c +++ b/source3/utils/net_ads.c @@ -817,7 +817,7 @@ static int net_ads_leave(int argc, const char **argv) struct cli_state *cli = NULL; TALLOC_CTX *ctx; DOM_SID *dom_sid = NULL; - char *short_domain_name = NULL; + const char *short_domain_name = NULL; if (!secrets_init()) { DEBUG(1,("Failed to initialise secrets database\n")); @@ -961,7 +961,8 @@ static NTSTATUS check_ads_config( void ) ********************************************************************/ static NTSTATUS net_join_domain(TALLOC_CTX *ctx, const char *servername, - struct sockaddr_storage *pss, char **domain, + struct sockaddr_storage *pss, + const char **domain, DOM_SID **dom_sid, const char *password) { @@ -1294,14 +1295,13 @@ static bool net_derive_salting_principal( TALLOC_CTX *ctx, ADS_STRUCT *ads ) #if defined(WITH_DNS_UPDATES) #include "dns.h" DNS_ERROR DoDNSUpdate(char *pszServerName, - const char *pszDomainName, - const char *pszHostName, - const struct in_addr *iplist, int num_addrs ); - + const char *pszDomainName, const char *pszHostName, + const struct sockaddr_storage *sslist, + size_t num_addrs ); static NTSTATUS net_update_dns_internal(TALLOC_CTX *ctx, ADS_STRUCT *ads, const char *machine_name, - const struct in_addr *addrs, + const struct sockaddr_storage *addrs, int num_addrs) { struct dns_rr_ns *nameservers = NULL; @@ -1390,7 +1390,7 @@ done: static NTSTATUS net_update_dns(TALLOC_CTX *mem_ctx, ADS_STRUCT *ads) { int num_addrs; - struct in_addr *iplist = NULL; + struct sockaddr_storage *iplist = NULL; fstring machine_name; NTSTATUS status; @@ -1446,7 +1446,7 @@ int net_ads_join(int argc, const char **argv) ADS_STRUCT *ads = NULL; ADS_STATUS status; NTSTATUS nt_status; - char *short_domain_name = NULL; + const char *short_domain_name = NULL; char *tmp_password, *password; TALLOC_CTX *ctx = NULL; DOM_SID *domain_sid = NULL; diff --git a/source3/utils/net_dns.c b/source3/utils/net_dns.c index 44a0b46e4e..fb6644d6b2 100644 --- a/source3/utils/net_dns.c +++ b/source3/utils/net_dns.c @@ -32,7 +32,8 @@ DNS_ERROR DoDNSUpdate(char *pszServerName, const char *pszDomainName, const char *pszHostName, - const struct sockaddr_storage *sslist, size_t num_addrs ); + const struct sockaddr_storage *sslist, + size_t num_addrs ); /********************************************************************* *********************************************************************/ diff --git a/source3/utils/net_domain.c b/source3/utils/net_domain.c index 3f1908e242..da5e61caf0 100644 --- a/source3/utils/net_domain.c +++ b/source3/utils/net_domain.c @@ -157,7 +157,7 @@ int netdom_store_machine_account( const char *domain, DOM_SID *sid, const char * ********************************************************************/ NTSTATUS netdom_get_domain_sid( TALLOC_CTX *mem_ctx, struct cli_state *cli, - char **domain, DOM_SID **sid ) + const char **domain, DOM_SID **sid ) { struct rpc_pipe_client *pipe_hnd = NULL; POLICY_HND lsa_pol; diff --git a/source3/utils/net_rpc.c b/source3/utils/net_rpc.c index 2bd867fff3..677924649c 100644 --- a/source3/utils/net_rpc.c +++ b/source3/utils/net_rpc.c @@ -51,7 +51,8 @@ static bool sync_files(struct copy_clistate *cp_clistate, const char *mask); **/ NTSTATUS net_get_remote_domain_sid(struct cli_state *cli, TALLOC_CTX *mem_ctx, - DOM_SID **domain_sid, char **domain_name) + DOM_SID **domain_sid, + const char **domain_name) { struct rpc_pipe_client *lsa_pipe; POLICY_HND pol; @@ -112,7 +113,7 @@ int run_rpc_command(struct cli_state *cli_arg, TALLOC_CTX *mem_ctx; NTSTATUS nt_status; DOM_SID *domain_sid; - char *domain_name; + const char *domain_name; /* make use of cli_state handed over as an argument, if possible */ if (!cli_arg) { @@ -5607,7 +5608,7 @@ static int rpc_trustdom_establish(int argc, const char **argv) DOM_SID *domain_sid; char* domain_name; - char* domain_name_pol; + const char* domain_name_pol; char* acct_name; fstring pdc_name; char *dc_name; @@ -5917,7 +5918,7 @@ static int rpc_trustdom_vampire(int argc, const char **argv) DOM_SID *domain_sids; char **trusted_dom_names; fstring pdc_name; - char *dummy; + const char *dummy; /* * Listing trusted domains (stored in secrets.tdb, if local) @@ -6057,7 +6058,7 @@ static int rpc_trustdom_list(int argc, const char **argv) DOM_SID *domain_sids; char **trusted_dom_names; fstring pdc_name; - char *dummy; + const char *dummy; /* trusting domains listing variables */ POLICY_HND domain_hnd; diff --git a/source3/utils/net_rpc_join.c b/source3/utils/net_rpc_join.c index 0c25a53365..6e37f3c84c 100644 --- a/source3/utils/net_rpc_join.c +++ b/source3/utils/net_rpc_join.c @@ -155,7 +155,7 @@ int net_rpc_join_newstyle(int argc, const char **argv) NTSTATUS result; int retval = 1; - char *domain = NULL; + const char *domain = NULL; uint32 num_rids, *name_types, *user_rids; uint32 flags = 0x3e8; char *acct_name; @@ -413,7 +413,7 @@ int net_rpc_join_newstyle(int argc, const char **argv) /* Now store the secret in the secrets database */ - strupper_m(domain); + strupper_m(CONST_DISCARD(char *, domain)); if (!secrets_store_domain_sid(domain, domain_sid)) { DEBUG(0, ("error storing domain sid for %s\n", domain)); 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); +} diff --git a/source3/winbindd/winbindd_cm.c b/source3/winbindd/winbindd_cm.c index a9155a5763..908228717e 100644 --- a/source3/winbindd/winbindd_cm.c +++ b/source3/winbindd/winbindd_cm.c @@ -1799,9 +1799,9 @@ static void set_dc_type_and_flags_connect( struct winbindd_domain *domain ) struct rpc_pipe_client *cli; POLICY_HND pol; - char *domain_name = NULL; - char *dns_name = NULL; - char *forest_name = NULL; + const char *domain_name = NULL; + const char *dns_name = NULL; + const char *forest_name = NULL; DOM_SID *dom_sid = NULL; ZERO_STRUCT( ctr ); |