diff options
Diffstat (limited to 'source3')
148 files changed, 6703 insertions, 6485 deletions
diff --git a/source3/Makefile.in b/source3/Makefile.in index cbbf821b22..8e8932bc5f 100644 --- a/source3/Makefile.in +++ b/source3/Makefile.in @@ -19,6 +19,8 @@ datarootdir=@datarootdir@ selftest_prefix=@selftest_prefix@ selftest_shrdir=@selftest_shrdir@ smbtorture4_path=@smbtorture4_path@ +smbtorture4_option=@smbtorture4_option@ +selftest_custom_conf=@selftest_custom_conf@ LIBS=@LIBS@ CC=@CC@ @@ -129,7 +131,6 @@ INSTALLPERMS_DATA = 0644 LOGFILEBASE = @logfilebase@ CONFIGFILE = $(CONFIGDIR)/smb.conf LMHOSTSFILE = $(CONFIGDIR)/lmhosts -CTDBDIR = @ctdbdir@ NCALRPCDIR = @ncalrpcdir@ # This is where smbpasswd et al go @@ -241,6 +242,8 @@ TDB_LIB_OBJ = lib/util_tdb.o ../lib/util/util_tdb.o \ lib/dbwrap_ctdb.o \ lib/dbwrap_rbt.o @LIBTDB_STATIC@ +TDB_VALIDATE_OBJ = lib/tdb_validate.o + SMBLDAP_OBJ = @SMBLDAP@ @SMBLDAPUTIL@ VERSION_OBJ = lib/version.o @@ -277,7 +280,6 @@ LIBNDR_OBJ = ../librpc/ndr/ndr_basic.o \ ../librpc/gen_ndr/ndr_security.o \ ../librpc/ndr/ndr_sec_helper.o \ librpc/ndr/ndr_string.o \ - librpc/ndr/sid.o \ ../librpc/ndr/uuid.o \ librpc/ndr/util.o @@ -289,6 +291,9 @@ LIBNDR_GEN_OBJ0 = ../librpc/gen_ndr/ndr_samr.o \ LIBNDR_GEN_OBJ1 = ../librpc/gen_ndr/ndr_netlogon.o \ ../librpc/ndr/ndr_netlogon.o +LIBNDR_GEN_OBJ2 = ../librpc/gen_ndr/ndr_spoolss.o \ + ../librpc/ndr/ndr_spoolss_buf.o + LIBNDR_GEN_OBJ = ../librpc/gen_ndr/ndr_wkssvc.o \ $(LIBNDR_GEN_OBJ0) \ ../librpc/gen_ndr/ndr_dfs.o \ @@ -341,7 +346,7 @@ LIB_OBJ = $(LIBSAMBAUTIL_OBJ) $(UTIL_OBJ) $(CRYPTO_OBJ) \ lib/messages_ctdbd.o lib/packet.o lib/ctdbd_conn.o \ lib/interfaces.o lib/memcache.o \ lib/util_transfer_file.o ../lib/async_req/async_req.o \ - lib/async_sock.o \ + ../lib/async_req/async_sock.o ../lib/async_req/async_req_ntstatus.o \ $(TDB_LIB_OBJ) \ $(VERSION_OBJ) lib/charcnv.o lib/debug.o lib/fault.o \ lib/interface.o lib/pidfile.o \ @@ -362,7 +367,8 @@ LIB_OBJ = $(LIBSAMBAUTIL_OBJ) $(UTIL_OBJ) $(CRYPTO_OBJ) \ lib/ldap_escape.o @CHARSET_STATIC@ \ lib/secdesc.o lib/util_seaccess.o lib/secace.o lib/secacl.o \ libads/krb5_errs.o lib/system_smbd.o lib/audit.o $(LIBNDR_OBJ) \ - lib/file_id.o lib/idmap_cache.o + lib/file_id.o lib/idmap_cache.o \ + ../libcli/security/dom_sid.o LIB_DUMMY_OBJ = lib/dummysmbd.o lib/dummyroot.o LIB_NONSMBD_OBJ = $(LIB_OBJ) $(LIB_DUMMY_OBJ) @@ -527,6 +533,7 @@ REG_FULL_OBJ = $(REG_SMBCONF_OBJ) \ registry/reg_perfcount.o \ registry/reg_util_legacy.o +LIB_EVENTLOG_OBJ = rpc_server/srv_eventlog_lib.o RPC_LSA_OBJ = rpc_server/srv_lsa_nt.o ../librpc/gen_ndr/srv_lsa.o @@ -562,8 +569,8 @@ RPC_DFS_OBJ = ../librpc/gen_ndr/srv_dfs.o rpc_server/srv_dfs_nt.o RPC_SPOOLSS_OBJ = rpc_server/srv_spoolss.o rpc_server/srv_spoolss_nt.o -RPC_EVENTLOG_OBJ = rpc_server/srv_eventlog.o rpc_server/srv_eventlog_nt.o \ - rpc_server/srv_eventlog_lib.o ../librpc/gen_ndr/srv_eventlog.o +RPC_EVENTLOG_OBJ = rpc_server/srv_eventlog_nt.o \ + $(LIB_EVENTLOG_OBJ) ../librpc/gen_ndr/srv_eventlog.o RPC_PIPE_OBJ = rpc_server/srv_pipe_hnd.o \ rpc_server/srv_pipe.o rpc_server/srv_lsa_hnd.o @@ -574,10 +581,10 @@ RPC_SERVER_OBJ = @RPC_STATIC@ $(RPC_PIPE_OBJ) RPC_PARSE_OBJ = $(RPC_PARSE_OBJ2) \ rpc_parse/parse_spoolss.o \ - rpc_parse/parse_eventlog.o rpc_parse/parse_buffer.o + rpc_parse/parse_buffer.o RPC_CLIENT_OBJ = rpc_client/cli_pipe.o rpc_client/rpc_transport_np.o \ - rpc_client/rpc_transport_sock.o + rpc_client/rpc_transport_sock.o rpc_client/rpc_transport_smbd.o LOCKING_OBJ = locking/locking.o locking/brlock.o locking/posix.o @@ -893,7 +900,8 @@ NET_OBJ1 = utils/net.o utils/net_ads.o utils/net_help.o \ $(PASSWD_UTIL_OBJ) utils/net_dns.o utils/net_ads_gpo.o \ utils/net_conf.o utils/net_join.o utils/net_user.o \ utils/net_group.o utils/net_file.o utils/net_registry.o \ - auth/token_util.o utils/net_dom.o utils/net_share.o utils/net_lua.o + auth/token_util.o utils/net_dom.o utils/net_share.o utils/net_lua.o \ + utils/net_eventlog.o # these are not processed by make proto NET_OBJ2 = utils/net_registry_util.o utils/net_help_common.o @@ -911,7 +919,8 @@ NET_OBJ = $(NET_OBJ1) \ $(REG_SMBCONF_OBJ) @LIBNETAPI_STATIC@ $(LIBNET_OBJ) \ $(LIBSMBCONF_OBJ) \ @LIBWBCLIENT_STATIC@ \ - $(PRIVILEGES_BASIC_OBJ) + $(PRIVILEGES_BASIC_OBJ) @LIBLUA_STATIC@ \ + $(LIB_EVENTLOG_OBJ) CUPS_OBJ = client/smbspool.o $(PARAM_OBJ) $(LIBSMB_OBJ) \ $(LIB_NONSMBD_OBJ) $(KRBCLIENT_OBJ) $(POPT_LIB_OBJ) \ @@ -980,7 +989,9 @@ EVTLOGADM_OBJ0 = utils/eventlogadm.o EVTLOGADM_OBJ = $(EVTLOGADM_OBJ0) $(PARAM_OBJ) $(LIB_NONSMBD_OBJ) \ $(LIBSAMBA_OBJ) \ - registry/reg_eventlog.o rpc_server/srv_eventlog_lib.o + registry/reg_eventlog.o $(LIB_EVENTLOG_OBJ) \ + ../librpc/gen_ndr/ndr_eventlog.o \ + ../librpc/gen_ndr/ndr_lsa.o SHARESEC_OBJ0 = utils/sharesec.o SHARESEC_OBJ = $(SHARESEC_OBJ0) $(PARAM_OBJ) $(LIB_NONSMBD_OBJ) \ @@ -1064,7 +1075,8 @@ WINBINDD_OBJ = \ $(LIBADS_OBJ) $(KRBCLIENT_OBJ) $(POPT_LIB_OBJ) \ $(DCUTIL_OBJ) $(IDMAP_OBJ) $(NSS_INFO_OBJ) \ $(AFS_OBJ) $(AFS_SETTOKEN_OBJ) \ - $(LIBADS_SERVER_OBJ) $(SERVER_MUTEX_OBJ) $(LDB_OBJ) + $(LIBADS_SERVER_OBJ) $(SERVER_MUTEX_OBJ) $(LDB_OBJ) \ + $(TDB_VALIDATE_OBJ) WBINFO_OBJ = ../nsswitch/wbinfo.o $(LIBSAMBA_OBJ) $(PARAM_OBJ) $(LIB_NONSMBD_OBJ) \ $(POPT_LIB_OBJ) $(AFS_SETTOKEN_OBJ) \ @@ -1341,7 +1353,7 @@ bin/.dummy: bin/smbd@EXEEXT@: $(BINARY_PREREQS) $(SMBD_OBJ) @LIBTALLOC_SHARED@ @LIBTDB_SHARED@ @LIBWBCLIENT_SHARED@ @BUILD_POPT@ @echo Linking $@ - @$(CC) $(FLAGS) -o $@ $(SMBD_OBJ) $(LDFLAGS) $(LDAP_LIBS) \ + @$(CC) -o $@ $(SMBD_OBJ) $(LDFLAGS) $(LDAP_LIBS) \ $(KRB5LIBS) $(DYNEXP) $(PRINT_LIBS) $(AUTH_LIBS) \ $(ACL_LIBS) $(PASSDB_LIBS) $(LIBS) $(DNSSD_LIBS) \ $(POPT_LIBS) @SMBD_LIBS@ $(LIBTALLOC_LIBS) $(LIBTDB_LIBS) \ @@ -1349,33 +1361,33 @@ bin/smbd@EXEEXT@: $(BINARY_PREREQS) $(SMBD_OBJ) @LIBTALLOC_SHARED@ @LIBTDB_SHARE bin/nmbd@EXEEXT@: $(BINARY_PREREQS) $(NMBD_OBJ) @BUILD_POPT@ @LIBTALLOC_SHARED@ @LIBTDB_SHARED@ @echo Linking $@ - @$(CC) $(FLAGS) -o $@ $(NMBD_OBJ) $(LDFLAGS) $(DYNEXP) $(LIBS) \ + @$(CC) -o $@ $(NMBD_OBJ) $(LDFLAGS) $(DYNEXP) $(LIBS) \ $(LIBTALLOC_LIBS) $(LIBTDB_LIBS) $(POPT_LIBS) \ $(KRB5LIBS) $(LDAP_LIBS) $(ZLIB_LIBS) bin/swat@EXEEXT@: $(BINARY_PREREQS) $(SWAT_OBJ) @BUILD_POPT@ @LIBTALLOC_SHARED@ @LIBTDB_SHARED@ @LIBWBCLIENT_SHARED@ @echo Linking $@ - @$(CC) $(FLAGS) -o $@ $(SWAT_OBJ) $(LDFLAGS) $(DYNEXP) $(PRINT_LIBS) \ + @$(CC) -o $@ $(SWAT_OBJ) $(LDFLAGS) $(DYNEXP) $(PRINT_LIBS) \ $(AUTH_LIBS) $(LIBS) $(PASSDB_LIBS) $(POPT_LIBS) $(KRB5LIBS) \ $(LDAP_LIBS) $(LIBTALLOC_LIBS) $(LIBTDB_LIBS) $(WINBIND_LIBS) $(ZLIB_LIBS) bin/rpcclient@EXEEXT@: $(BINARY_PREREQS) $(RPCCLIENT_OBJ) @BUILD_POPT@ @LIBTALLOC_SHARED@ @LIBTDB_SHARED@ @LIBWBCLIENT_SHARED@ @echo Linking $@ - @$(CC) $(FLAGS) -o $@ $(LDFLAGS) $(PASSDB_LIBS) $(RPCCLIENT_OBJ) \ + @$(CC) -o $@ $(LDFLAGS) $(PASSDB_LIBS) $(RPCCLIENT_OBJ) \ $(DYNEXP) $(TERMLDFLAGS) $(TERMLIBS) $(LIBS) $(POPT_LIBS) \ $(KRB5LIBS) $(LDAP_LIBS) $(LIBTALLOC_LIBS) $(LIBTDB_LIBS) \ $(WINBIND_LIBS) $(ZLIB_LIBS) bin/smbclient@EXEEXT@: $(BINARY_PREREQS) $(CLIENT_OBJ) @BUILD_POPT@ @LIBTALLOC_SHARED@ @LIBTDB_SHARED@ @LIBWBCLIENT_SHARED@ @echo Linking $@ - @$(CC) $(FLAGS) -o $@ $(CLIENT_OBJ) $(LDFLAGS) $(DYNEXP) \ + @$(CC) -o $@ $(CLIENT_OBJ) $(LDFLAGS) $(DYNEXP) \ $(TERMLDFLAGS) $(TERMLIBS) $(LIBS) $(POPT_LIBS) \ $(KRB5LIBS) $(LDAP_LIBS) $(NSCD_LIBS) $(DNSSD_LIBS) \ $(LIBTALLOC_LIBS) $(LIBTDB_LIBS) $(WINBIND_LIBS) $(ZLIB_LIBS) bin/net@EXEEXT@: $(BINARY_PREREQS) $(NET_OBJ) @BUILD_POPT@ @LIBTALLOC_SHARED@ @LIBTDB_SHARED@ @LIBWBCLIENT_SHARED@ @LIBNETAPI_SHARED@ @LIBLUA_SHARED@ @echo Linking $@ - @$(CC) $(FLAGS) -o $@ $(NET_OBJ) $(DYNEXP) $(LDFLAGS) $(LIBS) \ + @$(CC) -o $@ $(NET_OBJ) $(DYNEXP) $(LDFLAGS) $(LIBS) \ $(POPT_LIBS) $(KRB5LIBS) $(UUID_LIBS) $(LDAP_LIBS) \ $(PASSDB_LIBS) $(TERMLDFLAGS) $(TERMLIBS) $(NSCD_LIBS) \ @INIPARSERLIBS@ $(LIBTALLOC_LIBS) $(LIBTDB_LIBS) $(WINBIND_LIBS) $(LIBNETAPI_LIBS) $(LIBLUA_LIBS) -lm \ @@ -1383,213 +1395,213 @@ bin/net@EXEEXT@: $(BINARY_PREREQS) $(NET_OBJ) @BUILD_POPT@ @LIBTALLOC_SHARED@ @L bin/profiles@EXEEXT@: $(BINARY_PREREQS) $(PROFILES_OBJ) @BUILD_POPT@ @LIBTALLOC_SHARED@ @LIBTDB_SHARED@ @echo Linking $@ - @$(CC) $(FLAGS) -o $@ $(PROFILES_OBJ) $(DYNEXP) $(LDFLAGS) $(LIBS) \ + @$(CC) -o $@ $(PROFILES_OBJ) $(DYNEXP) $(LDFLAGS) $(LIBS) \ $(LDAP_LIBS) $(POPT_LIBS) $(LIBTALLOC_LIBS) $(LIBTDB_LIBS) bin/smbspool@EXEEXT@: $(BINARY_PREREQS) $(CUPS_OBJ) @BUILD_POPT@ @LIBTALLOC_SHARED@ @LIBTDB_SHARED@ @echo Linking $@ - @$(CC) $(FLAGS) -o $@ $(CUPS_OBJ) $(DYNEXP) $(LDFLAGS) $(LIBS) \ + @$(CC) -o $@ $(CUPS_OBJ) $(DYNEXP) $(LDFLAGS) $(LIBS) \ $(KRB5LIBS) $(LDAP_LIBS) $(POPT_LIBS) $(LIBTALLOC_LIBS) $(LIBTDB_LIBS) $(ZLIB_LIBS) bin/mount.cifs@EXEEXT@: $(BINARY_PREREQS) $(CIFS_MOUNT_OBJ) @BUILD_POPT@ @echo Linking $@ - @$(CC) $(FLAGS) -o $@ $(CIFS_MOUNT_OBJ) $(DYNEXP) $(LDFLAGS) $(POPT_LIBS) + @$(CC) -o $@ $(CIFS_MOUNT_OBJ) $(DYNEXP) $(LDFLAGS) $(POPT_LIBS) bin/umount.cifs@EXEEXT@: $(BINARY_PREREQS) $(CIFS_UMOUNT_OBJ) @BUILD_POPT@ @echo Linking $@ - @$(CC) $(FLAGS) -o $@ $(CIFS_UMOUNT_OBJ) $(DYNEXP) $(LDFLAGS) $(POPT_LIBS) + @$(CC) -o $@ $(CIFS_UMOUNT_OBJ) $(DYNEXP) $(LDFLAGS) $(POPT_LIBS) bin/cifs.upcall@EXEEXT@: $(BINARY_PREREQS) $(CIFS_UPCALL_OBJ) $(LIBSMBCLIENT_OBJ1) @BUILD_POPT@ @LIBTALLOC_SHARED@ @LIBTDB_SHARED@ @LIBWBCLIENT_SHARED@ @echo Linking $@ - @$(CC) $(FLAGS) -o $@ $(CIFS_UPCALL_OBJ) $(DYNEXP) $(LDFLAGS) \ + @$(CC) -o $@ $(CIFS_UPCALL_OBJ) $(DYNEXP) $(LDFLAGS) \ -lkeyutils $(LIBS) $(LIBSMBCLIENT_OBJ1) $(KRB5LIBS) \ $(LDAP_LIBS) $(POPT_LIBS) $(LIBTALLOC_LIBS) $(WINBIND_LIBS) \ $(LIBTDB_LIBS) $(NSCD_LIBS) bin/testparm@EXEEXT@: $(BINARY_PREREQS) $(TESTPARM_OBJ) @BUILD_POPT@ @LIBTALLOC_SHARED@ @LIBTDB_SHARED@ @echo Linking $@ - @$(CC) $(FLAGS) -o $@ $(TESTPARM_OBJ) $(LDFLAGS) $(DYNEXP) $(LIBS) \ + @$(CC) -o $@ $(TESTPARM_OBJ) $(LDFLAGS) $(DYNEXP) $(LIBS) \ $(LDAP_LIBS) $(POPT_LIBS) $(LIBTALLOC_LIBS) $(LIBTDB_LIBS) bin/smbstatus@EXEEXT@: $(BINARY_PREREQS) $(STATUS_OBJ) @BUILD_POPT@ @LIBTALLOC_SHARED@ @LIBTDB_SHARED@ @echo Linking $@ - @$(CC) $(FLAGS) -o $@ $(STATUS_OBJ) $(LDFLAGS) $(DYNEXP) $(LIBS) \ + @$(CC) -o $@ $(STATUS_OBJ) $(LDFLAGS) $(DYNEXP) $(LIBS) \ $(LDAP_LIBS) $(POPT_LIBS) $(LIBTALLOC_LIBS) $(LIBTDB_LIBS) bin/smbcontrol@EXEEXT@: $(BINARY_PREREQS) $(SMBCONTROL_OBJ) @BUILD_POPT@ @LIBTALLOC_SHARED@ @LIBTDB_SHARED@ @echo Linking $@ - @$(CC) -DUSING_SMBCONTROL $(FLAGS) -o $@ \ + @$(CC) -DUSING_SMBCONTROL -o $@ \ $(SMBCONTROL_OBJ) $(DYNEXP) $(LDFLAGS) \ $(LIBS) $(LDAP_LIBS) @LIBUNWIND_PTRACE@ $(POPT_LIBS) \ $(LIBTALLOC_LIBS) $(LIBTDB_LIBS) bin/smbtree@EXEEXT@: $(BINARY_PREREQS) $(SMBTREE_OBJ) @BUILD_POPT@ @LIBTALLOC_SHARED@ @LIBTDB_SHARED@ @LIBWBCLIENT_SHARED@ @echo Linking $@ - @$(CC) $(FLAGS) -o $@ $(SMBTREE_OBJ) $(LDFLAGS) $(DYNEXP) \ + @$(CC) -o $@ $(SMBTREE_OBJ) $(LDFLAGS) $(DYNEXP) \ $(LIBS) $(POPT_LIBS) $(KRB5LIBS) $(LDAP_LIBS) $(NSCD_LIBS) \ $(LIBTALLOC_LIBS) $(LIBTDB_LIBS) $(WINBIND_LIBS) $(ZLIB_LIBS) bin/smbpasswd@EXEEXT@: $(BINARY_PREREQS) $(SMBPASSWD_OBJ) @BUILD_POPT@ @LIBTALLOC_SHARED@ @LIBTDB_SHARED@ @LIBWBCLIENT_SHARED@ @echo Linking $@ - @$(CC) $(FLAGS) -o $@ $(SMBPASSWD_OBJ) $(LDFLAGS) $(PASSDB_LIBS) \ + @$(CC) -o $@ $(SMBPASSWD_OBJ) $(LDFLAGS) $(PASSDB_LIBS) \ $(DYNEXP) $(LIBS) $(POPT_LIBS) $(KRB5LIBS) $(LDAP_LIBS) \ $(LIBTALLOC_LIBS) $(LIBTDB_LIBS) $(WINBIND_LIBS) $(ZLIB_LIBS) bin/pdbedit@EXEEXT@: $(BINARY_PREREQS) $(PDBEDIT_OBJ) @BUILD_POPT@ @LIBTALLOC_SHARED@ @LIBTDB_SHARED@ @LIBWBCLIENT_SHARED@ @echo Linking $@ - @$(CC) $(FLAGS) -o $@ $(PDBEDIT_OBJ) $(LDFLAGS) $(DYNEXP) $(LIBS) \ + @$(CC) -o $@ $(PDBEDIT_OBJ) $(LDFLAGS) $(DYNEXP) $(LIBS) \ $(POPT_LIBS) $(PASSDB_LIBS) $(LDAP_LIBS) $(LIBTALLOC_LIBS) \ $(LIBTDB_LIBS) $(WINBIND_LIBS) bin/smbget@EXEEXT@: $(BINARY_PREREQS) $(SMBGET_OBJ) @BUILD_POPT@ @LIBTALLOC_SHARED@ @LIBTDB_SHARED@ @LIBWBCLIENT_SHARED@ @echo Linking $@ - @$(CC) $(FLAGS) -o $@ $(SMBGET_OBJ) $(LDFLAGS) $(DYNEXP) $(LIBS) \ + @$(CC) -o $@ $(SMBGET_OBJ) $(LDFLAGS) $(DYNEXP) $(LIBS) \ $(POPT_LIBS) $(KRB5LIBS) $(LDAP_LIBS) $(NSCD_LIBS) \ $(LIBTALLOC_LIBS) $(LIBTDB_LIBS) $(WINBIND_LIBS) $(ZLIB_LIBS) bin/nmblookup@EXEEXT@: $(BINARY_PREREQS) $(NMBLOOKUP_OBJ) @BUILD_POPT@ @LIBTALLOC_SHARED@ @LIBTDB_SHARED@ @echo Linking $@ - @$(CC) $(FLAGS) -o $@ $(NMBLOOKUP_OBJ) $(LDFLAGS) $(DYNEXP) $(LIBS) \ + @$(CC) -o $@ $(NMBLOOKUP_OBJ) $(LDFLAGS) $(DYNEXP) $(LIBS) \ $(POPT_LIBS) $(LDAP_LIBS) $(LIBTALLOC_LIBS) $(LIBTDB_LIBS) bin/smbtorture@EXEEXT@: $(BINARY_PREREQS) $(SMBTORTURE_OBJ) @BUILD_POPT@ @LIBTALLOC_SHARED@ @LIBTDB_SHARED@ @echo Linking $@ - @$(CC) $(FLAGS) -o $@ $(SMBTORTURE_OBJ) $(LDFLAGS) $(DYNEXP) \ + @$(CC) -o $@ $(SMBTORTURE_OBJ) $(LDFLAGS) $(DYNEXP) \ $(LIBS) $(KRB5LIBS) $(LDAP_LIBS) $(POPT_LIBS) $(LIBTALLOC_LIBS) \ $(LIBTDB_LIBS) $(ZLIB_LIBS) bin/talloctort@EXEEXT@: $(BINARY_PREREQS) $(TALLOCTORT_OBJ) @BUILD_POPT@ @LIBTALLOC_SHARED@ @LIBTDB_SHARED@ @echo Linking $@ - @$(CC) $(FLAGS) -o $@ $(TALLOCTORT_OBJ) $(LDFLAGS) \ + @$(CC) -o $@ $(TALLOCTORT_OBJ) $(LDFLAGS) \ $(DYNEXP) $(LIBS) $(LDAP_LIBS) $(POPT_LIBS) \ $(LIBTALLOC_LIBS) $(LIBTDB_LIBS) bin/replacetort@EXEEXT@: $(REPLACETORT_OBJ) @BUILD_POPT@ @LIBTALLOC_SHARED@ @echo Linking $@ - @$(CC) $(FLAGS) @PIE_LDFLAGS@ -o $@ $(REPLACETORT_OBJ) $(LDFLAGS) \ + @$(CC) @PIE_LDFLAGS@ -o $@ $(REPLACETORT_OBJ) $(LDFLAGS) \ $(DYNEXP) $(LIBS) $(POPT_LIBS) $(LIBTALLOC_LIBS) bin/smbconftort@EXEEXT@: $(SMBCONFTORT_OBJ) @BUILD_POPT@ @LIBTALLOC_SHARED@ @LIBTDB_SHARED@ @echo Linking $@ - @$(CC) $(FLAGS) @PIE_LDFLAGS@ -o $@ $(SMBCONFTORT_OBJ) $(LDFLAGS) \ + @$(CC) @PIE_LDFLAGS@ -o $@ $(SMBCONFTORT_OBJ) $(LDFLAGS) \ $(DYNEXP) $(LIBS) $(LDAP_LIBS) $(POPT_LIBS) \ $(LIBTALLOC_LIBS) $(LIBTDB_LIBS) bin/masktest@EXEEXT@: $(BINARY_PREREQS) $(MASKTEST_OBJ) @BUILD_POPT@ @LIBTALLOC_SHARED@ @LIBTDB_SHARED@ @echo Linking $@ - @$(CC) $(FLAGS) -o $@ $(MASKTEST_OBJ) $(LDFLAGS) $(DYNEXP) \ + @$(CC) -o $@ $(MASKTEST_OBJ) $(LDFLAGS) $(DYNEXP) \ $(LIBS) $(KRB5LIBS) $(LDAP_LIBS) $(POPT_LIBS) \ $(LIBTALLOC_LIBS) $(LIBTDB_LIBS) $(ZLIB_LIBS) bin/msgtest@EXEEXT@: $(BINARY_PREREQS) $(MSGTEST_OBJ) @BUILD_POPT@ @LIBTALLOC_SHARED@ @LIBTDB_SHARED@ @echo Linking $@ - @$(CC) $(FLAGS) -o $@ $(MSGTEST_OBJ) $(LDFLAGS) $(DYNEXP) \ + @$(CC) -o $@ $(MSGTEST_OBJ) $(LDFLAGS) $(DYNEXP) \ $(LIBS) $(KRB5LIBS) $(LDAP_LIBS) $(POPT_LIBS) \ $(LIBTALLOC_LIBS) $(LIBTDB_LIBS) $(ZLIB_LIBS) bin/smbcacls@EXEEXT@: $(BINARY_PREREQS) $(SMBCACLS_OBJ) @BUILD_POPT@ @LIBTALLOC_SHARED@ @LIBTDB_SHARED@ @LIBWBCLIENT_SHARED@ @echo Linking $@ - @$(CC) $(FLAGS) -o $@ $(SMBCACLS_OBJ) $(DYNEXP) $(LDFLAGS) \ + @$(CC) -o $@ $(SMBCACLS_OBJ) $(DYNEXP) $(LDFLAGS) \ $(LIBS) $(POPT_LIBS) $(KRB5LIBS) $(LDAP_LIBS) $(NSCD_LIBS) \ $(LIBTALLOC_LIBS) $(LIBTDB_LIBS) $(WINBIND_LIBS) $(ZLIB_LIBS) bin/smbcquotas@EXEEXT@: $(BINARY_PREREQS) $(SMBCQUOTAS_OBJ) @BUILD_POPT@ @LIBTALLOC_SHARED@ @LIBTDB_SHARED@ @LIBWBCLIENT_SHARED@ @echo Linking $@ - @$(CC) $(FLAGS) -o $@ $(SMBCQUOTAS_OBJ) $(DYNEXP) $(LDFLAGS) \ + @$(CC) -o $@ $(SMBCQUOTAS_OBJ) $(DYNEXP) $(LDFLAGS) \ $(LIBS) $(POPT_LIBS) $(KRB5LIBS) $(LDAP_LIBS) $(NSCD_LIBS) \ $(LIBTALLOC_LIBS) $(LIBTDB_LIBS) $(WINBIND_LIBS) $(ZLIB_LIBS) bin/eventlogadm@EXEEXT@: $(BINARY_PREREQS) $(EVTLOGADM_OBJ) @BUILD_POPT@ @LIBTALLOC_SHARED@ @LIBTDB_SHARED@ @echo Linking $@ - @$(CC) $(FLAGS) -o $@ $(EVTLOGADM_OBJ) $(DYNEXP) $(LDFLAGS) \ + @$(CC) -o $@ $(EVTLOGADM_OBJ) $(DYNEXP) $(LDFLAGS) \ $(LIBS) $(LDAP_LIBS) $(POPT_LIBS) $(LIBTALLOC_LIBS) $(LIBTDB_LIBS) bin/sharesec@EXEEXT@: $(BINARY_PREREQS) $(SHARESEC_OBJ) @BUILD_POPT@ @LIBTALLOC_SHARED@ @LIBTDB_SHARED@ @echo Linking $@ - @$(CC) $(FLAGS) -o $@ $(SHARESEC_OBJ) $(DYNEXP) $(LDFLAGS) \ + @$(CC) -o $@ $(SHARESEC_OBJ) $(DYNEXP) $(LDFLAGS) \ $(LIBS) $(LDAP_LIBS) $(POPT_LIBS) $(LIBTALLOC_LIBS) $(LIBTDB_LIBS) bin/locktest@EXEEXT@: $(BINARY_PREREQS) $(LOCKTEST_OBJ) @BUILD_POPT@ @LIBTALLOC_SHARED@ @LIBTDB_SHARED@ @echo Linking $@ - @$(CC) $(FLAGS) -o $@ $(LOCKTEST_OBJ) $(LDFLAGS) $(DYNEXP) \ + @$(CC) -o $@ $(LOCKTEST_OBJ) $(LDFLAGS) $(DYNEXP) \ $(LIBS) $(KRB5LIBS) $(LDAP_LIBS) $(POPT_LIBS) \ $(LIBTALLOC_LIBS) $(LIBTDB_LIBS) $(ZLIB_LIBS) bin/nsstest@EXEEXT@: $(BINARY_PREREQS) $(NSSTEST_OBJ) @BUILD_POPT@ @LIBTALLOC_SHARED@ @LIBTDB_SHARED@ @echo Linking $@ - @$(CC) $(FLAGS) -o $@ $(NSSTEST_OBJ) $(LDFLAGS) $(DYNEXP) \ + @$(CC) -o $@ $(NSSTEST_OBJ) $(LDFLAGS) $(DYNEXP) \ $(LIBS) $(KRB5LIBS) $(LDAP_LIBS) $(POPT_LIBS) \ $(LIBTALLOC_LIBS) $(LIBTDB_LIBS) $(ZLIB_LIBS) bin/pdbtest@EXEEXT@: $(BINARY_PREREQS) $(PDBTEST_OBJ) @BUILD_POPT@ @LIBTALLOC_SHARED@ @LIBTDB_SHARED@ @LIBWBCLIENT_SHARED@ @echo Linking $@ - @$(CC) $(FLAGS) -o $@ $(PDBTEST_OBJ) $(LDFLAGS) $(DYNEXP) \ + @$(CC) -o $@ $(PDBTEST_OBJ) $(LDFLAGS) $(DYNEXP) \ $(LIBS) $(KRB5LIBS) $(LDAP_LIBS) $(PASSDB_LIBS) \ $(POPT_LIBS) $(LIBTALLOC_LIBS) $(LIBTDB_LIBS) $(WINBIND_LIBS) $(ZLIB_LIBS) bin/vfstest@EXEEXT@: $(BINARY_PREREQS) $(VFSTEST_OBJ) @BUILD_POPT@ @LIBTALLOC_SHARED@ @LIBTDB_SHARED@ @LIBWBCLIENT_SHARED@ @echo Linking $@ - @$(CC) $(FLAGS) -o $@ $(VFSTEST_OBJ) $(LDFLAGS) $(TERMLDFLAGS) \ - $(TERMLIBS) $(DYNEXP) $(PRINT_LIBS) $(AUTH_LIBS) \ + @$(CC) -o $@ $(VFSTEST_OBJ) $(LDFLAGS) $(TERMLDFLAGS) \ + $(TERMLIBS) $(DYNEXP) $(PRINT_LIBS) $(AUTH_LIBS) $(DNSSD_LIBS) \ $(ACL_LIBS) $(LIBS) $(POPT_LIBS) $(KRB5LIBS) $(LDAP_LIBS) \ @SMBD_LIBS@ $(NSCD_LIBS) $(LIBTALLOC_LIBS) $(LIBTDB_LIBS) \ $(WINBIND_LIBS) $(ZLIB_LIBS) bin/smbiconv@EXEEXT@: $(BINARY_PREREQS) $(SMBICONV_OBJ) @BUILD_POPT@ @LIBTALLOC_SHARED@ @LIBTDB_SHARED@ @echo Linking $@ - @$(CC) $(FLAGS) -o $@ $(SMBICONV_OBJ) $(LDFLAGS) $(TERMLDFLAGS) \ + @$(CC) -o $@ $(SMBICONV_OBJ) $(LDFLAGS) $(TERMLDFLAGS) \ $(TERMLIBS) $(DYNEXP) $(LIBS) $(LDAP_LIBS) $(POPT_LIBS) \ $(LIBTALLOC_LIBS) $(LIBTDB_LIBS) bin/log2pcap@EXEEXT@: $(BINARY_PREREQS) $(LOG2PCAP_OBJ) @BUILD_POPT@ @LIBTALLOC_SHARED@ @echo Linking $@ - @$(CC) $(FLAGS) -o $@ $(LOG2PCAP_OBJ) $(LDFLAGS) $(DYNEXP) \ + @$(CC) -o $@ $(LOG2PCAP_OBJ) $(LDFLAGS) $(DYNEXP) \ $(POPT_LIBS) $(LIBS) $(LIBTALLOC_LIBS) bin/locktest2@EXEEXT@: $(BINARY_PREREQS) $(LOCKTEST2_OBJ) @BUILD_POPT@ @LIBTALLOC_SHARED@ @LIBTDB_SHARED@ @echo Linking $@ - @$(CC) $(FLAGS) -o $@ $(LOCKTEST2_OBJ) $(LDFLAGS) $(DYNEXP) \ + @$(CC) -o $@ $(LOCKTEST2_OBJ) $(LDFLAGS) $(DYNEXP) \ $(LIBS) $(KRB5LIBS) $(LDAP_LIBS) $(POPT_LIBS) \ $(LIBTALLOC_LIBS) $(LIBTDB_LIBS) $(ZLIB_LIBS) bin/debug2html@EXEEXT@: $(BINARY_PREREQS) $(DEBUG2HTML_OBJ) @BUILD_POPT@ @LIBTALLOC_SHARED@ @echo Linking $@ - @$(CC) $(FLAGS) -o $@ $(DEBUG2HTML_OBJ) $(LDFLAGS) $(DYNEXP) \ + @$(CC) -o $@ $(DEBUG2HTML_OBJ) $(LDFLAGS) $(DYNEXP) \ $(LIBS) $(LIBTALLOC_LIBS) bin/smbfilter@EXEEXT@: $(BINARY_PREREQS) $(SMBFILTER_OBJ) @BUILD_POPT@ @LIBTALLOC_SHARED@ @LIBTDB_SHARED@ @echo Linking $@ - @$(CC) $(FLAGS) -o $@ $(SMBFILTER_OBJ) $(LDFLAGS) $(LIBS) \ + @$(CC) -o $@ $(SMBFILTER_OBJ) $(LDFLAGS) $(LIBS) \ $(KRB5LIBS) $(LDAP_LIBS) $(POPT_LIBS) \ $(LIBTALLOC_LIBS) $(LIBTDB_LIBS) $(ZLIB_LIBS) bin/ldbedit: $(BINARY_PREREQS) $(LDBEDIT_OBJ) @BUILD_POPT@ @LIBTALLOC_SHARED@ @LIBTDB_SHARED@ @LIBWBCLIENT_SHARED@ @echo Linking $@ - @$(CC) $(FLAGS) -o $@ $(LDBEDIT_OBJ) $(DYNEXP) $(LDFLAGS) \ + @$(CC) -o $@ $(LDBEDIT_OBJ) $(DYNEXP) $(LDFLAGS) \ $(LIBS) $(POPT_LIBS) $(LDAP_LIBS) \ $(LIBTALLOC_LIBS) $(LIBTDB_LIBS) $(WINBIND_LIBS) bin/ldbsearch: $(BINARY_PREREQS) $(LDBSEARCH_OBJ) @BUILD_POPT@ @LIBTALLOC_SHARED@ @LIBTDB_SHARED@ @LIBWBCLIENT_SHARED@ @echo Linking $@ - @$(CC) $(FLAGS) -o $@ $(LDBSEARCH_OBJ) $(DYNEXP) $(LDFLAGS) \ + @$(CC) -o $@ $(LDBSEARCH_OBJ) $(DYNEXP) $(LDFLAGS) \ $(LIBS) $(POPT_LIBS) $(LDAP_LIBS) \ $(LIBTALLOC_LIBS) $(LIBTDB_LIBS) $(WINBIND_LIBS) bin/ldbadd: $(BINARY_PREREQS) $(LDBADD_OBJ) @BUILD_POPT@ @LIBTALLOC_SHARED@ @LIBTDB_SHARED@ @LIBWBCLIENT_SHARED@ @echo Linking $@ - @$(CC) $(FLAGS) -o $@ $(LDBADD_OBJ) $(DYNEXP) $(LDFLAGS) \ + @$(CC) -o $@ $(LDBADD_OBJ) $(DYNEXP) $(LDFLAGS) \ $(LIBS) $(POPT_LIBS) $(LDAP_LIBS) \ $(LIBTALLOC_LIBS) $(LIBTDB_LIBS) $(WINBIND_LIBS) bin/ldbmodify: $(BINARY_PREREQS) $(LDBMODIFY_OBJ) @BUILD_POPT@ @LIBTALLOC_SHARED@ @LIBTDB_SHARED@ @LIBWBCLIENT_SHARED@ @echo Linking $@ - @$(CC) $(FLAGS) -o $@ $(LDBMODIFY_OBJ) $(DYNEXP) $(LDFLAGS) \ + @$(CC) -o $@ $(LDBMODIFY_OBJ) $(DYNEXP) $(LDFLAGS) \ $(LIBS) $(POPT_LIBS) $(LDAP_LIBS) \ $(LIBTALLOC_LIBS) $(LIBTDB_LIBS) $(WINBIND_LIBS) bin/ldbdel: $(BINARY_PREREQS) $(LDBDEL_OBJ) @BUILD_POPT@ @LIBTALLOC_SHARED@ @LIBTDB_SHARED@ @LIBWBCLIENT_SHARED@ @echo Linking $@ - @$(CC) $(FLAGS) -o $@ $(LDBDEL_OBJ) $(DYNEXP) $(LDFLAGS) \ + @$(CC) -o $@ $(LDBDEL_OBJ) $(DYNEXP) $(LDFLAGS) \ $(LIBS) $(POPT_LIBS) $(LDAP_LIBS) \ $(LIBTALLOC_LIBS) $(LIBTDB_LIBS) $(WINBIND_LIBS) @@ -2259,14 +2271,14 @@ bin/librpc_echo.@SHLIBEXT@: $(BINARY_PREREQS) $(RPC_ECHO_OBJ) bin/winbindd@EXEEXT@: $(BINARY_PREREQS) $(WINBINDD_OBJ) @BUILD_POPT@ @LIBTALLOC_SHARED@ @LIBTDB_SHARED@ @LIBWBCLIENT_SHARED@ @echo "Linking $@" - @$(CC) $(FLAGS) -o $@ $(WINBINDD_OBJ) $(LDFLAGS) $(DYNEXP) $(LIBS) \ + @$(CC) -o $@ $(WINBINDD_OBJ) $(LDFLAGS) $(DYNEXP) $(LIBS) \ $(POPT_LIBS) $(KRB5LIBS) $(LDAP_LIBS) \ $(PASSDB_LIBS) $(LIBTALLOC_LIBS) $(LIBTDB_LIBS) $(WINBIND_LIBS) \ $(ZLIB_LIBS) bin/vlp@EXEEXT@: $(BINARY_PREREQS) $(VLP_OBJ) @LIBTALLOC_SHARED@ @LIBTDB_SHARED@ @LIBWBCLIENT_SHARED@ @echo "Linking $@" - @$(CC) $(FLAGS) -o $@ $(VLP_OBJ) $(LDFLAGS) $(DYNEXP) \ + @$(CC) -o $@ $(VLP_OBJ) $(LDFLAGS) $(DYNEXP) \ $(TERMLDFLAGS) $(TERMLIBS) $(LIBS) $(POPT_LIBS) \ $(KRB5LIBS) $(LDAP_LIBS) $(NSCD_LIBS) \ $(LIBTALLOC_LIBS) $(LIBTDB_LIBS) $(WINBIND_LIBS) \ @@ -2557,14 +2569,14 @@ bin/security.@SHLIBEXT@: $(BINARY_PREREQS) libgpo/gpext/security.o bin/wbinfo@EXEEXT@: $(BINARY_PREREQS) $(WBINFO_OBJ) @BUILD_POPT@ @LIBTALLOC_SHARED@ @LIBTDB_SHARED@ @LIBWBCLIENT_SHARED@ @echo Linking $@ - @$(CC) $(FLAGS) -o $@ $(LDFLAGS) $(WBINFO_OBJ) $(DYNEXP) $(LIBS) \ + @$(CC) -o $@ $(LDFLAGS) $(WBINFO_OBJ) $(DYNEXP) $(LIBS) \ $(LDAP_LIBS) $(POPT_LIBS) $(LIBTALLOC_LIBS) $(LIBTDB_LIBS) \ $(WINBIND_LIBS) bin/ntlm_auth@EXEEXT@: $(BINARY_PREREQS) $(NTLM_AUTH_OBJ) $(PARAM_OBJ) \ $(LIB_NONSMBD_OBJ) @BUILD_POPT@ @LIBTALLOC_SHARED@ @LIBTDB_SHARED@ @LIBWBCLIENT_SHARED@ @echo Linking $@ - @$(CC) $(FLAGS) -o $@ $(LDFLAGS) $(DYNEXP) $(NTLM_AUTH_OBJ) \ + @$(CC) -o $@ $(LDFLAGS) $(DYNEXP) $(NTLM_AUTH_OBJ) \ $(PARAM_OBJ) $(LIB_NONSMBD_OBJ) $(LIBS) \ $(POPT_LIBS) $(KRB5LIBS) $(LDAP_LIBS) $(NSCD_LIBS) \ $(LIBTALLOC_LIBS) $(LIBTDB_LIBS) $(WINBIND_LIBS) @@ -2577,53 +2589,53 @@ bin/pam_smbpass.@SHLIBEXT@: $(BINARY_PREREQS) $(PAM_SMBPASS_OBJ) @LIBTALLOC_SHAR bin/tdbbackup@EXEEXT@: $(BINARY_PREREQS) $(TDBBACKUP_OBJ) @LIBTALLOC_SHARED@ @LIBTDB_SHARED@ @echo Linking $@ - @$(CC) $(FLAGS) -o $@ $(LDFLAGS) $(TDBBACKUP_OBJ) $(DYNEXP) \ + @$(CC) -o $@ $(LDFLAGS) $(TDBBACKUP_OBJ) $(DYNEXP) \ $(LIBS) $(LIBTALLOC_LIBS) $(LIBTDB_LIBS) bin/tdbtool@EXEEXT@: $(BINARY_PREREQS) $(TDBTOOL_OBJ) @LIBTALLOC_SHARED@ @LIBTDB_SHARED@ @echo Linking $@ - @$(CC) $(FLAGS) -o $@ $(LDFLAGS) $(TDBTOOL_OBJ) $(DYNEXP) \ + @$(CC) -o $@ $(LDFLAGS) $(TDBTOOL_OBJ) $(DYNEXP) \ $(LIBS) $(LIBTALLOC_LIBS) $(LIBTDB_LIBS) bin/tdbdump@EXEEXT@: $(BINARY_PREREQS) $(TDBDUMP_OBJ) @LIBTALLOC_SHARED@ @LIBTDB_SHARED@ @echo Linking $@ - @$(CC) $(FLAGS) -o $@ $(LDFLAGS) $(TDBDUMP_OBJ) $(DYNEXP) \ + @$(CC) -o $@ $(LDFLAGS) $(TDBDUMP_OBJ) $(DYNEXP) \ $(LIBS) $(LIBTALLOC_LIBS) $(LIBTDB_LIBS) bin/tdbtorture@EXEEXT@: $(BINARY_PREREQS) $(TDBTORTURE_OBJ) @LIBTALLOC_SHARED@ @LIBTDB_SHARED@ @echo Linking $@ - @$(CC) $(FLAGS) -o $@ $(LDFLAGS) $(TDBTORTURE_OBJ) $(DYNEXP) \ + @$(CC) -o $@ $(LDFLAGS) $(TDBTORTURE_OBJ) $(DYNEXP) \ $(LIBS) $(LIBTALLOC_LIBS) $(LIBTDB_LIBS) bin/t_strcmp@EXEEXT@: $(BINARY_PREREQS) @LIBTALLOC_SHARED@ bin/libbigballofmud.@SHLIBEXT@ torture/t_strcmp.o - $(CC) $(FLAGS) -o $@ $(DYNEXP) $(LIBS) $(LIBTALLOC_LIBS) \ + $(CC) -o $@ $(DYNEXP) $(LIBS) $(LIBTALLOC_LIBS) \ torture/t_strcmp.o -L ./bin -lbigballofmud bin/t_strstr@EXEEXT@: $(BINARY_PREREQS) @LIBTALLOC_SHARED@ bin/libbigballofmud.@SHLIBEXT@ torture/t_strstr.o - $(CC) $(FLAGS) -o $@ $(DYNEXP) $(LIBS) $(LIBTALLOC_LIBS) \ + $(CC) -o $@ $(DYNEXP) $(LIBS) $(LIBTALLOC_LIBS) \ torture/t_strstr.o -L ./bin -lbigballofmud bin/t_strappend@EXEEXT@: $(BINARY_PREREQS) @LIBTALLOC_SHARED@ bin/libbigballofmud.@SHLIBEXT@ torture/t_strappend.o - $(CC) $(FLAGS) -o $@ $(DYNEXP) $(LIBS) $(LIBTALLOC_LIBS) \ + $(CC) -o $@ $(DYNEXP) $(LIBS) $(LIBTALLOC_LIBS) \ torture/t_strappend.o -L ./bin -lbigballofmud bin/t_stringoverflow@EXEEXT@: $(BINARY_PREREQS) bin/libbigballofmud.@SHLIBEXT@ torture/t_stringoverflow.o - $(CC) $(FLAGS) -o $@ $(DYNEXP) torture/t_stringoverflow.o \ + $(CC) -o $@ $(DYNEXP) torture/t_stringoverflow.o \ -L./bin -lbigballofmud bin/timelimit@EXEEXT@: script/tests/timelimit.o @echo Linking $@ - @$(CC) $(FLAGS) -o $@ $(DYNEXP) script/tests/timelimit.o + @$(CC) -o $@ $(DYNEXP) script/tests/timelimit.o bin/rpc_open_tcp@EXEEXT@: $(BINARY_PREREQS) $(RPC_OPEN_TCP_OBJ) @LIBTALLOC_SHARED@ @LIBTDB_SHARED@ @LIBWBCLIENT_SHARED@ @echo "Linking $@" - @$(CC) $(FLAGS) -o $@ $(RPC_OPEN_TCP_OBJ) $(LDFLAGS) $(DYNEXP) \ + @$(CC) -o $@ $(RPC_OPEN_TCP_OBJ) $(LDFLAGS) $(DYNEXP) \ $(LIBS) $(LIBTALLOC_LIBS) @LIBTDB_SHARED@ $(WINBIND_LIBS) \ $(LDAP_LIBS) $(KRB5LIBS) $(NSCD_LIBS) bin/test_lp_load@EXEEXT@: $(BINARY_PREREQS) $(TEST_LP_LOAD_OBJ) @BUILD_POPT@ @LIBTALLOC_SHARED@ @LIBTDB_SHARED@ @echo "Linking $@" - @$(CC) $(FLAGS) -o $@ $(TEST_LP_LOAD_OBJ) \ + @$(CC) -o $@ $(TEST_LP_LOAD_OBJ) \ $(LDFLAGS) $(DYNEEXP) $(LIBS) \ $(LDAP_LIBS) \ $(POPT_LIBS) $(LIBTALLOC_LIBS) $(LIBTDB_LIBS) @@ -2928,9 +2940,12 @@ test_pam_modules:: pam_modules ## ## Targets for 'make test' ## + +TEST_EXTRA_ARGS = ${smbtorture4_option} ${selftest_shrdir} ${selftest_custom_conf} + test:: all torture timelimit @echo Running Test suite - @LIB_PATH_VAR=$(LIB_PATH_VAR) PERL="$(PERL)" $(srcdir)/script/tests/selftest.sh ${selftest_prefix} all "${smbtorture4_path}" ${selftest_shrdir} + @LIB_PATH_VAR=$(LIB_PATH_VAR) PERL="$(PERL)" $(srcdir)/script/tests/selftest.sh ${selftest_prefix} all ${TEST_EXTRA_ARGS} valgrindtest:: all torture timelimit @echo Running Test suite with valgrind @@ -2939,17 +2954,23 @@ valgrindtest:: all torture timelimit WINBINDD_VALGRIND="xterm -n winbindd -e valgrind -q --db-attach=yes --num-callers=30" \ SMBD_VALGRIND="xterm -n smbd -e valgrind -q --db-attach=yes --num-callers=30" \ VALGRIND="valgrind -q --num-callers=30 --log-file=${selftest_prefix}/valgrind.log" \ - PERL="$(PERL)" $(srcdir)/script/tests/selftest.sh ${selftest_prefix} all "${smbtorture4_path}" + PERL="$(PERL)" $(srcdir)/script/tests/selftest.sh ${selftest_prefix} all ${TEST_EXTRA_ARGS} SELFTEST_FORMAT = plain selftestdir = ../selftest +S3_LD_LIBPATH_OVERRIDE = $(LIB_PATH_VAR)="$(builddir)/bin" + selftest:: all torture timelimit - @$(selftestdir)/selftest.pl --prefix=st --target=samba3 \ + @LIB_PATH_VAR=$(LIB_PATH_VAR) $(S3_LD_LIBPATH_OVERRIDE) \ + SAMBA4SHAREDDIR="$(builddir)/bin/shared" SMBTORTURE4=$(smbtorture4_path) \ + PERL="$(PERL)" PYTHON="$(PYTHON)" \ + $(PERL) $(selftestdir)/selftest.pl \ + --prefix=${selftest_prefix} --target=samba3 \ --testlist="$(srcdir)/selftest/tests.sh|" \ --expected-failures=$(srcdir)/selftest/knownfail \ --exclude=$(srcdir)/selftest/skip \ - --socket-wrapper $(TESTS) --format=$(SELFTEST_FORMAT) + --socket-wrapper $(TESTS) --format=$(SELFTEST_FORMAT) --immediate selftest-%: $(MAKE) selftest TESTS=$* diff --git a/source3/auth/auth_netlogond.c b/source3/auth/auth_netlogond.c index a57f3b74a3..c39dd8c752 100644 --- a/source3/auth/auth_netlogond.c +++ b/source3/auth/auth_netlogond.c @@ -134,8 +134,6 @@ static char *mymachinepw(TALLOC_CTX *mem_ctx) return NULL; } - pwd[sizeof(pwd)-1] = '\0'; - nread = read(fd, pwd, sizeof(pwd)-1); close(fd); @@ -144,7 +142,7 @@ static char *mymachinepw(TALLOC_CTX *mem_ctx) return NULL; } - DEBUG(0, ("pwd: %d [%s]\n", (int)nread, pwd)); + pwd[nread] = '\0'; if (pwd[nread-1] == '\n') { pwd[nread-1] = '\0'; @@ -238,8 +236,6 @@ static NTSTATUS check_netlogond_security(const struct auth_context *auth_context goto done; } - TALLOC_FREE(auth); - plaintext_machinepw = mymachinepw(talloc_tos()); if (plaintext_machinepw == NULL) { status = NT_STATUS_NO_MEMORY; diff --git a/source3/client/smbspool.c b/source3/client/smbspool.c index 1910ccd4fe..7943cf5828 100644 --- a/source3/client/smbspool.c +++ b/source3/client/smbspool.c @@ -432,10 +432,13 @@ smb_complete_connection(const char *myname, return NULL; } - if (!cli_send_tconX(cli, share, "?????", password, strlen(password) + 1)) { - fprintf(stderr, "ERROR: Tree connect failed (%s)\n", cli_errstr(cli)); + nt_status = cli_tcon_andx(cli, share, "?????", password, + strlen(password) + 1); + if (!NT_STATUS_IS_OK(nt_status)) { + fprintf(stderr, "ERROR: Tree connect failed (%s)\n", + nt_errstr(nt_status)); - if (get_exit_code(cli, cli_nt_error(cli)) == 2) { + if (get_exit_code(cli, nt_status) == 2) { *need_auth = true; } diff --git a/source3/configure.in b/source3/configure.in index 321924889a..306566f26e 100644 --- a/source3/configure.in +++ b/source3/configure.in @@ -63,7 +63,7 @@ SAMBA_CPPFLAGS="${SAMBA_CPPFLAGS} ${TEVENT_CFLAGS}" SAMBA_CPPFLAGS="${SAMBA_CPPFLAGS} ${TDB_CFLAGS}" SAMBA_CPPFLAGS="${SAMBA_CPPFLAGS} -I${srcdir-.}/libaddns" SAMBA_CPPFLAGS="${SAMBA_CPPFLAGS} -I${srcdir-.}/librpc" -SAMBA_CPPFLAGS="${SAMBA_CPPFLAGS} -I${srcdir-.}/../lib/async_req" +SAMBA_CPPFLAGS="${SAMBA_CPPFLAGS} -I${srcdir-.}/.." SAMBA_CONFIGURE_CPPFLAGS="${SAMBA_CPPFLAGS} -I${srcdir-.}/../lib/popt" @@ -414,7 +414,7 @@ AC_SUBST(DYNEXP) dnl Add modules that have to be built by default here dnl These have to be built static: -default_static_modules="pdb_smbpasswd pdb_tdbsam rpc_lsarpc rpc_samr rpc_winreg rpc_initshutdown rpc_dssetup rpc_wkssvc rpc_svcctl rpc_ntsvcs rpc_netlogon rpc_netdfs rpc_srvsvc rpc_spoolss rpc_eventlog2 auth_sam auth_unix auth_winbind auth_server auth_domain auth_builtin auth_netlogond vfs_default nss_info_template" +default_static_modules="pdb_smbpasswd pdb_tdbsam rpc_lsarpc rpc_samr rpc_winreg rpc_initshutdown rpc_dssetup rpc_wkssvc rpc_svcctl rpc_ntsvcs rpc_netlogon rpc_netdfs rpc_srvsvc rpc_spoolss rpc_eventlog auth_sam auth_unix auth_winbind auth_server auth_domain auth_builtin auth_netlogond vfs_default nss_info_template" dnl These are preferably build shared, and static if dlopen() is not available default_shared_modules="vfs_recycle vfs_audit vfs_extd_audit vfs_full_audit vfs_netatalk vfs_fake_perms vfs_default_quota vfs_readonly vfs_cap vfs_expand_msdfs vfs_shadow_copy vfs_shadow_copy2 charset_CP850 charset_CP437 auth_script vfs_readahead vfs_xattr_tdb vfs_streams_xattr vfs_streams_depot vfs_acl_xattr vfs_acl_tdb vfs_smb_traffic_analyzer" @@ -1027,7 +1027,7 @@ fi AC_CHECK_FUNCS(getcwd fchown chmod fchmod mknod mknod64) AC_CHECK_FUNCS(strtol) -AC_CHECK_FUNCS(fstat strchr chflags) +AC_CHECK_FUNCS(strchr chflags) AC_CHECK_FUNCS(getrlimit fsync fdatasync setpgid) AC_CHECK_FUNCS(setsid glob strpbrk crypt16 getauthuid) AC_CHECK_FUNCS(sigprocmask sigblock sigaction sigset innetgr setnetgrent getnetgrent endnetgrent) @@ -1395,7 +1395,7 @@ if test x"$samba_cv_stat_hires" = x"yes" ; then [whether struct stat has sub-second timestamps]) fi -AC_CACHE_CHECK([whether struct stat has sub-second timestamps without struct timespec], samba_cv_stat_hires_notimespec, +AC_CACHE_CHECK([whether struct stat has sub-second timestamps without struct timespec suffixed nsec], samba_cv_stat_hires_notimespec, [ AC_TRY_COMPILE( [ @@ -1423,7 +1423,7 @@ AC_CACHE_CHECK([whether struct stat has sub-second timestamps without struct tim t.tv_sec = s.st_atime; t.tv_nsec = s.st_atimensec; ], - samba_cv_stat_hires=yes, samba_cv_stat_hires=no) + samba_cv_stat_hires_notimespec=yes, samba_cv_stat_hires_notimespec=no) ]) if test x"$samba_cv_stat_hires_notimespec" = x"yes" ; then @@ -1431,7 +1431,87 @@ if test x"$samba_cv_stat_hires_notimespec" = x"yes" ; then AC_DEFINE(HAVE_STAT_ST_ATIMENSEC, 1, [whether struct stat contains st_atimensec]) AC_DEFINE(HAVE_STAT_ST_CTIMENSEC, 1, [whether struct stat contains st_ctimensec]) AC_DEFINE(HAVE_STAT_HIRES_TIMESTAMPS, 1, - [whether struct stat has sub-second timestamps without struct timespec]) + [whether struct stat has sub-second timestamps without struct timespec suffixed nsec]) +fi + +dnl AIX stype sub-second timestamps: +AC_CACHE_CHECK([whether struct stat has sub-second timestamps without struct timespec suffixed _n], samba_cv_stat_hires_notimespec_n, + [ + AC_TRY_COMPILE( + [ +#if TIME_WITH_SYS_TIME +# include <sys/time.h> +# include <time.h> +#else +# if HAVE_SYS_TIME_H +# include <sys/time.h> +# else +# include <time.h> +# endif +#endif +#ifdef HAVE_SYS_STAT_H +#include <sys/stat.h> +#endif + ], + [ + struct timespec t; + struct stat s = {0}; + t.tv_sec = s.st_mtime; + t.tv_nsec = s.st_mtime_n; + t.tv_sec = s.st_ctime; + t.tv_nsec = s.st_ctime_n; + t.tv_sec = s.st_atime; + t.tv_nsec = s.st_atime_n; + ], + samba_cv_stat_hires_notimespec_n=yes, samba_cv_stat_hires_notimespec_n=no) + ]) + +if test x"$samba_cv_stat_hires_notimespec_n" = x"yes" ; then + AC_DEFINE(HAVE_STAT_ST_MTIME_N, 1, [whether struct stat contains st_mtime_n]) + AC_DEFINE(HAVE_STAT_ST_ATIME_N, 1, [whether struct stat contains st_atime_n]) + AC_DEFINE(HAVE_STAT_ST_CTIME_N, 1, [whether struct stat contains st_ctime_n]) + AC_DEFINE(HAVE_STAT_HIRES_TIMESTAMPS, 1, + [whether struct stat has sub-second timestamps without struct timespec suffixed _n]) +fi + +dnl Tru64 has _micro_second_ resolution: +AC_CACHE_CHECK([whether struct stat has sub-second timestamps in st_uXtime], samba_cv_stat_hires_uxtime, + [ + AC_TRY_COMPILE( + [ +#if TIME_WITH_SYS_TIME +# include <sys/time.h> +# include <time.h> +#else +# if HAVE_SYS_TIME_H +# include <sys/time.h> +# else +# include <time.h> +# endif +#endif +#ifdef HAVE_SYS_STAT_H +#include <sys/stat.h> +#endif + ], + [ + struct timespec t; + struct stat s = {0}; + t.tv_sec = s.st_mtime; + t.tv_nsec = s.st_umtime * 1000; + t.tv_sec = s.st_ctime; + t.tv_nsec = s.st_uctime * 1000; + t.tv_sec = s.st_atime; + t.tv_nsec = s.st_uatime * 1000; + ], + samba_cv_stat_hires_uxtime=yes, samba_cv_stat_hires_uxtime=no) + ]) + +if test x"$samba_cv_stat_hires_uxtime" = x"yes" ; then + AC_DEFINE(HAVE_STAT_ST_UMTIME, 1, [whether struct stat contains st_umtime]) + AC_DEFINE(HAVE_STAT_ST_UATIME, 1, [whether struct stat contains st_uatime]) + AC_DEFINE(HAVE_STAT_ST_UCTIME, 1, [whether struct stat contains st_uctime]) + AC_DEFINE(HAVE_STAT_HIRES_TIMESTAMPS, 1, + [whether struct stat has sub-second timestamps in st_uXtime]) fi AC_CACHE_CHECK([whether struct stat has st_birthtimespec], samba_cv_stat_st_birthtimespec, @@ -1457,7 +1537,7 @@ AC_CACHE_CHECK([whether struct stat has st_birthtimespec], samba_cv_stat_st_birt struct stat s = {0}; t = s.st_birthtimespec; ], - samba_cv_stat_st_birthtimespec=yes, samba_cv_stat_birthtimespec=no) + samba_cv_stat_st_birthtimespec=yes, samba_cv_stat_st_birthtimespec=no) ]) if test x"$samba_cv_stat_st_birthtimespec" = x"yes" ; then @@ -1487,7 +1567,7 @@ AC_CACHE_CHECK([whether struct stat has st_birthtimensec], samba_cv_stat_st_birt struct stat s = {0}; t.tv_nsec = s.st_birthtimensec; ], - samba_cv_stat_st_birthtimensec=yes, samba_cv_stat_birthtimensec=no) + samba_cv_stat_st_birthtimensec=yes, samba_cv_stat_st_birthtimensec=no) ]) if test x"$samba_cv_stat_st_birthtimensec" = x"yes" ; then @@ -1517,7 +1597,7 @@ AC_CACHE_CHECK([whether struct stat has st_birthtime], samba_cv_stat_st_birthtim struct stat s = {0}; t = s.st_birthtime; ], - samba_cv_stat_st_birthtime=yes, samba_cv_stat_birthtime=no) + samba_cv_stat_st_birthtime=yes, samba_cv_stat_st_birthtime=no) ]) if test x"$samba_cv_stat_st_birthtime" = x"yes" ; then @@ -5152,17 +5232,128 @@ AC_MSG_RESULT([$samba_cv_HAVE_EXPLICIT_LARGEFILE_SUPPORT]) ################################################# # check for cluster extensions -AC_MSG_CHECKING(whether to include cluster support) +CTDB_CFLAGS="" +AC_SUBST(CTDB_CFLAGS) +AC_ARG_WITH(ctdb, +[AS_HELP_STRING([--with-ctdb=DIR], [Where to find ctdb sources])], +[ case "$withval" in + yes|no) + AC_MSG_WARN([--with-ctdb called without argument]) + ;; + *) + CTDB_CPPFLAGS="-I$withval/include" + ;; + esac]) + +SAVED_CPPFLAGS="$CPPFLAGS" +CPPFLAGS="$CPPFLAGS $CTDB_CPPFLAGS" +ctdb_broken="missing or broken headers" + +AC_CHECK_HEADERS(ctdb.h ctdb_private.h,,,[ +#include "confdefs.h" +#define NO_CONFIG_H +#include "replace.h" +#include "system/wait.h" +#include "system/network.h" +#define private #error __USED_RESERVED_WORD_private__ +#include <talloc.h> +#include <tdb.h> +#include <ctdb.h> +]) + +AC_HAVE_DECL(CTDB_CONTROL_TRANS2_COMMIT_RETRY,[ +#include "confdefs.h" +#define NO_CONFIG_H +#include "replace.h" +#include "system/wait.h" +#include "system/network.h" +#include <talloc.h> +#include <tdb.h> +#include <ctdb.h> +#include <ctdb_private.h> +]) +if test x"$ac_cv_have_CTDB_CONTROL_TRANS2_COMMIT_RETRY_decl" = x"yes"; then + ctdb_broken=no +else + ctdb_broken="missing transaction support" +fi + +# in ctdb 1.0.57 ctdb_control_tcp was temparary renamed to ctdb_tcp_client +AC_CHECK_TYPE(struct ctdb_tcp_client,[ + AC_DEFINE([ctdb_control_tcp],[ctdb_tcp_client],[ctdb ipv4 support]) +],,[ +#include "confdefs.h" +#define NO_CONFIG_H +#include "replace.h" +#include "system/wait.h" +#include "system/network.h" +#include <talloc.h> +#include <tdb.h> +#include <ctdb.h> +#include <ctdb_private.h> +]) + +AC_CHECK_TYPE(struct ctdb_control_tcp,[ + AC_DEFINE([HAVE_STRUCT_CTDB_CONTROL_TCP],[1],[ctdb ipv4 support]) +],[ + ctdb_broken="missing struct ctdb_control_tcp" +],[ +#include "confdefs.h" +#define NO_CONFIG_H +#include "replace.h" +#include "system/wait.h" +#include "system/network.h" +#include <talloc.h> +#include <tdb.h> +#include <ctdb.h> +#include <ctdb_private.h> +]) + +AC_CHECK_TYPE(struct ctdb_control_tcp_addr,[ + AC_DEFINE([HAVE_STRUCT_CTDB_CONTROL_TCP_ADDR],[1],[ctdb ipv6 support]) +],,[ +#include "confdefs.h" +#define NO_CONFIG_H +#include "replace.h" +#include "system/wait.h" +#include "system/network.h" +#include <talloc.h> +#include <tdb.h> +#include <ctdb.h> +#include <ctdb_private.h> +]) +CPPFLAGS="$SAVED_CPPFLAGS" + +AC_MSG_CHECKING(cluster support) AC_ARG_WITH(cluster-support, -[AS_HELP_STRING([--with-cluster-support], [Enable cluster extensions (default=no)])]) -if test "x$with_cluster_support" = "xyes"; then +[AS_HELP_STRING([--with-cluster-support], [Enable cluster extensions (default=auto)])]) + +if test x"$with_cluster_support" = x ; then + with_cluster_support="auto" +fi + +if test x"$ac_cv_header_ctdb_private_h" != x"yes"; then + if test "x$with_cluster_support" = "xyes"; then + AC_MSG_ERROR("ctdb_private.h is required for cluster support") + fi + with_cluster_support=no +fi + +if test x"$ctdb_broken" != x"no"; then + if test "x$with_cluster_support" = "xyes"; then + AC_MSG_ERROR(["cluster support: $ctdb_broken"]) + fi + with_cluster_support=no +fi + +if test "x$with_cluster_support" != "xno"; then AC_DEFINE(CLUSTER_SUPPORT,1,[Whether to enable cluster extensions]) + SAMBA_CPPFLAGS="${SAMBA_CPPFLAGS} ${CTDB_CPPFLAGS}" AC_MSG_RESULT(yes) else AC_MSG_RESULT(no) fi - ################################################# # check for ACL support @@ -5724,6 +5915,8 @@ fi ############################################ # See if we have the Linux splice syscall. +case "$host_os" in +*linux*) AC_CACHE_CHECK([for Linux splice], samba_cv_HAVE_LINUX_SPLICE,[ AC_TRY_LINK([ @@ -5734,6 +5927,11 @@ AC_CACHE_CHECK([for Linux splice], [long ret = splice(0,0,1,0,400,0);], samba_cv_HAVE_LINUX_SPLICE=yes, samba_cv_HAVE_LINUX_SPLICE=no)]) +;; +*) +samba_cv_HAVE_LINUX_SPLICE=no +;; +esac if test x"$samba_cv_HAVE_LINUX_SPLICE" = x"yes"; then AC_DEFINE(HAVE_LINUX_SPLICE,1, @@ -5999,7 +6197,7 @@ if test x"$enable_dnssd" != x"no"; then AC_CHECK_FUNCS(DNSServiceRegister) AC_CHECK_LIB_EXT(dns_sd, DNSSD_LIBS, DNSServiceRegister) if test x"$ac_cv_func_DNSServiceRegister" != x"yes" -a \ - x"$ac_cv_lib_ext_DNSServiceRegister" != x"yes"; then + x"$ac_cv_lib_ext_dns_sd_DNSServiceRegister" != x"yes"; then have_dnssd_support=no fi @@ -6142,7 +6340,7 @@ SMB_MODULE(rpc_netlogon, \$(RPC_NETLOG_OBJ), "bin/librpc_NETLOGON.$SHLIBEXT", RP SMB_MODULE(rpc_netdfs, \$(RPC_DFS_OBJ), "bin/librpc_netdfs.$SHLIBEXT", RPC) SMB_MODULE(rpc_srvsvc, \$(RPC_SVC_OBJ), "bin/librpc_svcsvc.$SHLIBEXT", RPC) SMB_MODULE(rpc_spoolss, \$(RPC_SPOOLSS_OBJ), "bin/librpc_spoolss.$SHLIBEXT", RPC) -SMB_MODULE(rpc_eventlog2, \$(RPC_EVENTLOG_OBJ), "bin/librpc_eventlog2.$SHLIBEXT", RPC) +SMB_MODULE(rpc_eventlog, \$(RPC_EVENTLOG_OBJ), "bin/librpc_eventlog.$SHLIBEXT", RPC) SMB_MODULE(rpc_samr, \$(RPC_SAMR_OBJ), "bin/librpc_samr.$SHLIBEXT", RPC) SMB_MODULE(rpc_rpcecho, \$(RPC_ECHO_OBJ), "bin/librpc_rpcecho.$SHLIBEXT", RPC) SMB_SUBSYSTEM(RPC,smbd/server.o) @@ -6339,7 +6537,10 @@ fi if test x$enable_merged_build = xyes; then MERGED_BUILD=1 + saved_USESHARED="$USESHARED" + USESHARED="false" m4_include(samba4.m4) + USESHARED="$saved_USESHARED" fi AC_SUBST(ZLIB_LIBS) diff --git a/source3/include/async_sock.h b/source3/include/async_sock.h deleted file mode 100644 index c6f95d64d5..0000000000 --- a/source3/include/async_sock.h +++ /dev/null @@ -1,51 +0,0 @@ -/* - Unix SMB/CIFS implementation. - async socket operations - Copyright (C) Volker Lendecke 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 __ASYNC_SOCK_H__ -#define __ASYNC_SOCK_H__ - -#include "includes.h" - -ssize_t async_syscall_result_ssize_t(struct async_req *req, int *perrno); -size_t async_syscall_result_size_t(struct async_req *req, int *perrno); -int async_syscall_result_int(struct async_req *req, int *perrno); - -struct async_req *async_send(TALLOC_CTX *mem_ctx, struct event_context *ev, - int fd, const void *buffer, size_t length, - int flags); -struct async_req *async_recv(TALLOC_CTX *mem_ctx, struct event_context *ev, - int fd, void *buffer, size_t length, - int flags); -struct async_req *async_connect_send(TALLOC_CTX *mem_ctx, - struct event_context *ev, - int fd, const struct sockaddr *address, - socklen_t address_len); -NTSTATUS async_connect_recv(struct async_req *req, int *perrno); - -struct async_req *sendall_send(TALLOC_CTX *mem_ctx, struct event_context *ev, - int fd, const void *buffer, size_t length, - int flags); -NTSTATUS sendall_recv(struct async_req *req); - -struct async_req *recvall_send(TALLOC_CTX *mem_ctx, struct event_context *ev, - int fd, void *buffer, size_t length, - int flags); -NTSTATUS recvall_recv(struct async_req *req); - -#endif diff --git a/source3/include/idmap.h b/source3/include/idmap.h index 4322192155..672e373108 100644 --- a/source3/include/idmap.h +++ b/source3/include/idmap.h @@ -22,11 +22,6 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. */ -/* idmap version determines auto-conversion - this is the database - structure version specifier. */ - -#define IDMAP_VERSION 2 - /* The interface version specifier. Updated to 3 for enum types by JRA. */ diff --git a/source3/include/includes.h b/source3/include/includes.h index 9c7f15b9cb..4aa3c07343 100644 --- a/source3/include/includes.h +++ b/source3/include/includes.h @@ -619,11 +619,9 @@ struct smb_iconv_convenience *lp_iconv_convenience(void *lp_ctx); #include "ntlmssp.h" #include "auth.h" #include "ntdomain.h" -#include "rpc_lsa.h" #include "reg_objects.h" #include "reg_db.h" #include "rpc_spoolss.h" -#include "rpc_eventlog.h" #include "rpc_perfcount.h" #include "rpc_perfcount_defs.h" #include "librpc/gen_ndr/notify.h" @@ -647,9 +645,9 @@ struct smb_iconv_convenience *lp_iconv_convenience(void *lp_ctx); #include "ctdbd_conn.h" #include "../lib/util/talloc_stack.h" #include "memcache.h" -#include "async_req.h" +#include "../lib/async_req/async_req_ntstatus.h" #include "async_smb.h" -#include "async_sock.h" +#include "../lib/async_req/async_sock.h" #include "services.h" #include "eventlog.h" @@ -678,20 +676,6 @@ struct printjob; #include "smb_ldap.h" -struct dns_reg_state; - -void dns_register_smbd(struct dns_reg_state ** dns_state_ptr, - unsigned port, - int *maxfd, - fd_set *listen_set, - struct timeval *timeout); - -void dns_register_close(struct dns_reg_state ** dns_state_ptr); - - -bool dns_register_smbd_reply(struct dns_reg_state *dns_state, - fd_set *lfds, struct timeval *timeout); - /* * Reasons for cache flush. */ @@ -893,8 +877,25 @@ char *talloc_asprintf_strupper_m(TALLOC_CTX *t, const char *fmt, ...) PRINTF_ATT #define XATTR_REPLACE 0x2 /* set value, fail if attr does not exist */ #endif -#if defined(HAVE_KRB5) +/* + * This should be under the HAVE_KRB5 flag but since they're used + * in lp_kerberos_method(), they ned to be always available + */ +#define KERBEROS_VERIFY_SECRETS 0 +#define KERBEROS_VERIFY_SYSTEM_KEYTAB 1 +#define KERBEROS_VERIFY_DEDICATED_KEYTAB 2 +#define KERBEROS_VERIFY_SECRETS_AND_KEYTAB 3 + +/* + * If you add any entries to the above, please modify the below expressions + * so they remain accurate. + */ +#define USE_KERBEROS_KEYTAB (KERBEROS_VERIFY_SECRETS != lp_kerberos_method()) +#define USE_SYSTEM_KEYTAB \ + ((KERBEROS_VERIFY_SECRETS_AND_KEYTAB == lp_kerberos_method()) || \ + (KERBEROS_VERIFY_SYSTEM_KEYTAB == lp_kerberos_method())) +#if defined(HAVE_KRB5) krb5_error_code smb_krb5_parse_name(krb5_context context, const char *name, /* in unix charset */ krb5_principal *principal); diff --git a/source3/include/ntdomain.h b/source3/include/ntdomain.h index 3f501550da..2d6a358391 100644 --- a/source3/include/ntdomain.h +++ b/source3/include/ntdomain.h @@ -214,8 +214,7 @@ typedef struct pipes_struct { struct auth_serversupplied_info *server_info; - fstring name; - fstring pipe_srv_name; + struct ndr_syntax_id syntax; /* linked list of rpc dispatch tables associated with the open rpc contexts */ diff --git a/source3/include/proto.h b/source3/include/proto.h index 8838419705..267ee74482 100644 --- a/source3/include/proto.h +++ b/source3/include/proto.h @@ -1128,6 +1128,7 @@ bool add_gid_to_array_unique(TALLOC_CTX *mem_ctx, gid_t gid, bool file_exist_stat(const char *fname,SMB_STRUCT_STAT *sbuf); bool socket_exist(const char *fname); bool directory_exist_stat(char *dname,SMB_STRUCT_STAT *st); +uint64_t get_file_size_stat(const SMB_STRUCT_STAT *sbuf); SMB_OFF_T get_file_size(char *file_name); char *attrib_string(uint16 mode); void show_msg(char *buf); @@ -1674,8 +1675,6 @@ bool winbind_lookup_rids(TALLOC_CTX *mem_ctx, int num_rids, uint32 *rids, const char **domain_name, const char ***names, enum lsa_SidType **types); -bool winbind_allocate_uid(uid_t *uid); -bool winbind_allocate_gid(gid_t *gid); /* The following definitions come from lib/wins_srv.c */ @@ -2324,9 +2323,19 @@ NTSTATUS cli_session_setup(struct cli_state *cli, const char *pass, int passlen, const char *ntpass, int ntpasslen, const char *workgroup); +struct async_req *cli_session_setup_guest_send(TALLOC_CTX *mem_ctx, + struct event_context *ev, + struct cli_state *cli); +NTSTATUS cli_session_setup_guest_recv(struct async_req *req); bool cli_ulogoff(struct cli_state *cli); -bool cli_send_tconX(struct cli_state *cli, - const char *share, const char *dev, const char *pass, int passlen); +struct async_req *cli_tcon_andx_send(TALLOC_CTX *mem_ctx, + struct event_context *ev, + struct cli_state *cli, + const char *share, const char *dev, + const char *pass, int passlen); +NTSTATUS cli_tcon_andx_recv(struct async_req *req); +NTSTATUS cli_tcon_andx(struct cli_state *cli, const char *share, + const char *dev, const char *pass, int passlen); bool cli_tdis(struct cli_state *cli); void cli_negprot_sendsync(struct cli_state *cli); NTSTATUS cli_negprot(struct cli_state *cli); @@ -2462,6 +2471,8 @@ struct async_req *cli_echo_send(TALLOC_CTX *mem_ctx, struct event_context *ev, DATA_BLOB data); NTSTATUS cli_echo_recv(struct async_req *req); NTSTATUS cli_echo(struct cli_state *cli, uint16_t num_echos, DATA_BLOB data); +bool cli_ucs2(struct cli_state *cli); +bool is_andx_req(uint8_t cmd); /* The following definitions come from libsmb/clierror.c */ @@ -2499,8 +2510,31 @@ int cli_nt_create_full(struct cli_state *cli, const char *fname, uint32 FileAttributes, uint32 ShareAccess, uint32 CreateDisposition, uint32 CreateOptions, uint8 SecuityFlags); +struct async_req *cli_ntcreate_send(TALLOC_CTX *mem_ctx, + struct event_context *ev, + struct cli_state *cli, + const char *fname, + uint32_t CreatFlags, + uint32_t DesiredAccess, + uint32_t FileAttributes, + uint32_t ShareAccess, + uint32_t CreateDisposition, + uint32_t CreateOptions, + uint8_t SecurityFlags); +NTSTATUS cli_ntcreate_recv(struct async_req *req, uint16_t *pfnum); +NTSTATUS cli_ntcreate(struct cli_state *cli, + const char *fname, + uint32_t CreatFlags, + uint32_t DesiredAccess, + uint32_t FileAttributes, + uint32_t ShareAccess, + uint32_t CreateDisposition, + uint32_t CreateOptions, + uint8_t SecurityFlags, + uint16_t *pfid); int cli_nt_create(struct cli_state *cli, const char *fname, uint32 DesiredAccess); -uint8_t *smb_bytes_push_str(uint8_t *buf, bool ucs2, const char *str); +uint8_t *smb_bytes_push_str(uint8_t *buf, bool ucs2, const char *str, + size_t str_len, size_t *pconverted_size); struct async_req *cli_open_send(TALLOC_CTX *mem_ctx, struct event_context *ev, struct cli_state *cli, const char *fname, int flags, int share_mode); @@ -2944,7 +2978,6 @@ NTSTATUS map_nt_error_from_gss(uint32 gss_maj, uint32 minor); /* The following definitions come from libsmb/namecache.c */ bool namecache_enable(void); -bool namecache_shutdown(void); bool namecache_store(const char *name, int name_type, int num_names, @@ -3952,6 +3985,7 @@ bool lp_passdb_expand_explicit(void); char *lp_ldap_suffix(void); char *lp_ldap_admin_dn(void); int lp_ldap_ssl(void); +bool lp_ldap_ssl_ads(void); int lp_ldap_passwd_sync(void); bool lp_ldap_delete_dn(void); int lp_ldap_replication_sleep(void); @@ -4027,7 +4061,8 @@ bool lp_client_use_spnego(void); bool lp_hostname_lookups(void); bool lp_change_notify(const struct share_params *p ); bool lp_kernel_change_notify(const struct share_params *p ); -bool lp_use_kerberos_keytab(void); +char * lp_dedicated_keytab_file(void); +int lp_kerberos_method(void); bool lp_defer_sharing_violations(void); bool lp_enable_privileges(void); bool lp_enable_asu_support(void); @@ -5294,14 +5329,55 @@ NTSTATUS cli_rpc_pipe_open_krb5(struct cli_state *cli, NTSTATUS cli_get_session_key(TALLOC_CTX *mem_ctx, struct rpc_pipe_client *cli, DATA_BLOB *session_key); +NTSTATUS rpc_pipe_open_local(TALLOC_CTX *mem_ctx, + struct rpc_cli_smbd_conn *conn, + const struct ndr_syntax_id *syntax, + struct rpc_pipe_client **presult); /* The following definitions come from rpc_client/rpc_transport_np.c */ +struct async_req *rpc_transport_np_init_send(TALLOC_CTX *mem_ctx, + struct event_context *ev, + struct cli_state *cli, + const struct ndr_syntax_id *abstract_syntax); +NTSTATUS rpc_transport_np_init_recv(struct async_req *req, + TALLOC_CTX *mem_ctx, + struct rpc_cli_transport **presult); NTSTATUS rpc_transport_np_init(TALLOC_CTX *mem_ctx, struct cli_state *cli, const struct ndr_syntax_id *abstract_syntax, struct rpc_cli_transport **presult); struct cli_state *rpc_pipe_np_smb_conn(struct rpc_pipe_client *p); +/* The following definitions come from rpc_client/rpc_transport_smbd.c */ + +struct async_req *rpc_cli_smbd_conn_init_send(TALLOC_CTX *mem_ctx, + struct event_context *ev, + void (*stdout_callback)(char *buf, + size_t len, + void *priv), + void *priv); +NTSTATUS rpc_cli_smbd_conn_init_recv(struct async_req *req, + TALLOC_CTX *mem_ctx, + struct rpc_cli_smbd_conn **pconn); +NTSTATUS rpc_cli_smbd_conn_init(TALLOC_CTX *mem_ctx, + struct rpc_cli_smbd_conn **pconn, + void (*stdout_callback)(char *buf, + size_t len, + void *priv), + void *priv); + +struct async_req *rpc_transport_smbd_init_send(TALLOC_CTX *mem_ctx, + struct event_context *ev, + struct rpc_cli_smbd_conn *conn, + const struct ndr_syntax_id *abstract_syntax); +NTSTATUS rpc_transport_smbd_init_recv(struct async_req *req, + TALLOC_CTX *mem_ctx, + struct rpc_cli_transport **presult); +NTSTATUS rpc_transport_smbd_init(TALLOC_CTX *mem_ctx, + struct rpc_cli_smbd_conn *conn, + const struct ndr_syntax_id *abstract_syntax, + struct rpc_cli_transport **presult); + /* The following definitions come from rpc_client/rpc_transport_sock.c */ NTSTATUS rpc_transport_sock_init(TALLOC_CTX *mem_ctx, int fd, @@ -5600,100 +5676,29 @@ bool smb_io_relarraystr(const char *desc, RPC_BUFFER *buffer, int depth, uint16 bool smb_io_relsecdesc(const char *desc, RPC_BUFFER *buffer, int depth, SEC_DESC **secdesc); uint32 size_of_relative_string(UNISTR *string); -/* The following definitions come from rpc_parse/parse_eventlog.c */ - -bool eventlog_io_q_read_eventlog(const char *desc, EVENTLOG_Q_READ_EVENTLOG *q_u, - prs_struct *ps, int depth); -bool eventlog_io_r_read_eventlog(const char *desc, - EVENTLOG_Q_READ_EVENTLOG *q_u, - EVENTLOG_R_READ_EVENTLOG *r_u, - prs_struct *ps, - int depth); - /* The following definitions come from rpc_parse/parse_misc.c */ bool smb_io_time(const char *desc, NTTIME *nttime, prs_struct *ps, int depth); bool smb_io_nttime(const char *desc, prs_struct *ps, int depth, NTTIME *nttime); -uint32 get_enum_hnd(ENUM_HND *enh); -void init_enum_hnd(ENUM_HND *enh, uint32 hnd); -bool smb_io_enum_hnd(const char *desc, ENUM_HND *hnd, prs_struct *ps, int depth); bool smb_io_dom_sid(const char *desc, DOM_SID *sid, prs_struct *ps, int depth); -void init_dom_sid2(DOM_SID2 *sid2, const DOM_SID *sid); -bool smb_io_dom_sid2_p(const char *desc, prs_struct *ps, int depth, DOM_SID2 **sid2); -bool smb_io_dom_sid2(const char *desc, DOM_SID2 *sid, prs_struct *ps, int depth); bool smb_io_uuid(const char *desc, struct GUID *uuid, prs_struct *ps, int depth); -void init_str_hdr(STRHDR *hdr, int max_len, int len, uint32 buffer); -bool smb_io_strhdr(const char *desc, STRHDR *hdr, prs_struct *ps, int depth); -void init_uni_hdr(UNIHDR *hdr, UNISTR2 *str2); -bool smb_io_unihdr(const char *desc, UNIHDR *hdr, prs_struct *ps, int depth); -void init_buf_hdr(BUFHDR *hdr, int max_len, int len); -bool smb_io_hdrbuf_pre(const char *desc, BUFHDR *hdr, prs_struct *ps, int depth, uint32 *offset); -bool smb_io_hdrbuf_post(const char *desc, BUFHDR *hdr, prs_struct *ps, int depth, - uint32 ptr_hdrbuf, uint32 max_len, uint32 len); -bool smb_io_hdrbuf(const char *desc, BUFHDR *hdr, prs_struct *ps, int depth); void init_unistr(UNISTR *str, const char *buf); bool smb_io_unistr(const char *desc, UNISTR *uni, prs_struct *ps, int depth); -void init_rpc_blob_uint32(RPC_DATA_BLOB *str, uint32 val); -void init_rpc_blob_str(RPC_DATA_BLOB *str, const char *buf, int len); -void init_rpc_blob_hex(RPC_DATA_BLOB *str, const char *buf); -void init_rpc_blob_bytes(RPC_DATA_BLOB *str, uint8 *buf, size_t len); bool smb_io_buffer5(const char *desc, BUFFER5 *buf5, prs_struct *ps, int depth); void init_buf_unistr2(UNISTR2 *str, uint32 *ptr, const char *buf); void copy_unistr2(UNISTR2 *str, const UNISTR2 *from); -void init_string2(STRING2 *str, const char *buf, size_t max_len, size_t str_len); -bool smb_io_string2(const char *desc, STRING2 *str2, uint32 buffer, prs_struct *ps, int depth); void init_unistr2(UNISTR2 *str, const char *buf, enum unistr2_term_codes flags); -void init_unistr4(UNISTR4 *uni4, const char *buf, enum unistr2_term_codes flags); -void init_unistr4_w( TALLOC_CTX *ctx, UNISTR4 *uni4, const smb_ucs2_t *buf ); void init_unistr2_w(TALLOC_CTX *ctx, UNISTR2 *str, const smb_ucs2_t *buf); void init_unistr2_from_unistr(TALLOC_CTX *ctx, UNISTR2 *to, const UNISTR *from); void init_unistr2_from_datablob(UNISTR2 *str, DATA_BLOB *blob) ; bool prs_io_unistr2_p(const char *desc, prs_struct *ps, int depth, UNISTR2 **uni2); bool prs_io_unistr2(const char *desc, prs_struct *ps, int depth, UNISTR2 *uni2 ); bool smb_io_unistr2(const char *desc, UNISTR2 *uni2, uint32 buffer, prs_struct *ps, int depth); -bool prs_unistr4(const char *desc, prs_struct *ps, int depth, UNISTR4 *uni4); -bool prs_unistr4_hdr(const char *desc, prs_struct *ps, int depth, UNISTR4 *uni4); -bool prs_unistr4_str(const char *desc, prs_struct *ps, int depth, UNISTR4 *uni4); -bool prs_unistr4_array(const char *desc, prs_struct *ps, int depth, UNISTR4_ARRAY *array ); -bool init_unistr4_array( UNISTR4_ARRAY *array, uint32 count, const char **strings ); -void init_dom_rid(DOM_RID *prid, uint32 rid, uint16 type, uint32 idx); -bool smb_io_dom_rid(const char *desc, DOM_RID *rid, prs_struct *ps, int depth); -bool smb_io_dom_rid2(const char *desc, DOM_RID2 *rid, prs_struct *ps, int depth); -void init_dom_rid3(DOM_RID3 *rid3, uint32 rid, uint8 type); -bool smb_io_dom_rid3(const char *desc, DOM_RID3 *rid3, prs_struct *ps, int depth); -void init_dom_rid4(DOM_RID4 *rid4, uint16 unknown, uint16 attr, uint32 rid); -void init_clnt_srv(DOM_CLNT_SRV *logcln, const char *logon_srv, - const char *comp_name); -bool smb_io_clnt_srv(const char *desc, DOM_CLNT_SRV *logcln, prs_struct *ps, int depth); -void init_log_info(DOM_LOG_INFO *loginfo, const char *logon_srv, const char *acct_name, - uint16 sec_chan, const char *comp_name); -bool smb_io_log_info(const char *desc, DOM_LOG_INFO *loginfo, prs_struct *ps, int depth); -bool smb_io_chal(const char *desc, DOM_CHAL *chal, prs_struct *ps, int depth); -bool smb_io_cred(const char *desc, DOM_CRED *cred, prs_struct *ps, int depth); -void init_clnt_info2(DOM_CLNT_INFO2 *clnt, - const char *logon_srv, const char *comp_name, - const DOM_CRED *clnt_cred); -bool smb_io_clnt_info2(const char *desc, DOM_CLNT_INFO2 *clnt, prs_struct *ps, int depth); -void init_clnt_info(DOM_CLNT_INFO *clnt, - const char *logon_srv, const char *acct_name, - uint16 sec_chan, const char *comp_name, - const DOM_CRED *cred); -bool smb_io_clnt_info(const char *desc, DOM_CLNT_INFO *clnt, prs_struct *ps, int depth); -void init_logon_id(DOM_LOGON_ID *logonid, uint32 log_id_low, uint32 log_id_high); -bool smb_io_logon_id(const char *desc, DOM_LOGON_ID *logonid, prs_struct *ps, int depth); -void init_owf_info(OWF_INFO *hash, const uint8 data[16]); -bool smb_io_owf_info(const char *desc, OWF_INFO *hash, prs_struct *ps, int depth); -bool smb_io_gid(const char *desc, DOM_GID *gid, prs_struct *ps, int depth); bool smb_io_pol_hnd(const char *desc, POLICY_HND *pol, prs_struct *ps, int depth); void init_unistr3(UNISTR3 *str, const char *buf); bool smb_io_unistr3(const char *desc, UNISTR3 *name, prs_struct *ps, int depth); bool prs_uint64(const char *name, prs_struct *ps, int depth, uint64 *data64); -bool smb_io_bufhdr2(const char *desc, BUFHDR2 *hdr, prs_struct *ps, int depth); -bool smb_io_bufhdr4(const char *desc, BUFHDR4 *hdr, prs_struct *ps, int depth); -bool smb_io_rpc_blob(const char *desc, RPC_DATA_BLOB *blob, prs_struct *ps, int depth); -bool make_uni_hdr(UNIHDR *hdr, int len); -bool make_bufhdr2(BUFHDR2 *hdr, uint32 info_level, uint32 length, uint32 buffer); uint32 str_len_uni(UNISTR *source); bool policy_handle_is_valid(const POLICY_HND *hnd); @@ -5751,7 +5756,6 @@ bool prs_uint16s(bool charmode, const char *name, prs_struct *ps, int depth, uin bool prs_uint16uni(bool charmode, const char *name, prs_struct *ps, int depth, uint16 *data16s, int len); bool prs_uint32s(bool charmode, const char *name, prs_struct *ps, int depth, uint32 *data32s, int len); bool prs_buffer5(bool charmode, const char *name, prs_struct *ps, int depth, BUFFER5 *str); -bool prs_string2(bool charmode, const char *name, prs_struct *ps, int depth, STRING2 *str); bool prs_unistr2(bool charmode, const char *name, prs_struct *ps, int depth, UNISTR2 *str); bool prs_unistr3(bool charmode, const char *name, UNISTR3 *str, prs_struct *ps, int depth); bool prs_unistr(const char *name, prs_struct *ps, int depth, UNISTR *str); @@ -5778,8 +5782,7 @@ bool prs_data_blob(prs_struct *prs, DATA_BLOB *blob, TALLOC_CTX *mem_ctx); /* The following definitions come from rpc_parse/parse_rpc.c */ -const char *cli_get_pipe_name_from_iface(TALLOC_CTX *mem_ctx, - const struct ndr_syntax_id *interface); +const char *get_pipe_name_from_iface(const struct ndr_syntax_id *interface); void init_rpc_hdr(RPC_HDR *hdr, enum RPC_PKT_TYPE pkt_type, uint8 flags, uint32 call_id, int data_len, int auth_len); bool smb_io_rpc_hdr(const char *desc, RPC_HDR *rpc, prs_struct *ps, int depth); @@ -6172,33 +6175,43 @@ bool spoolss_io_r_xcvdataport(const char *desc, SPOOL_R_XCVDATAPORT *r_u, prs_st bool make_monitorui_buf( RPC_BUFFER *buf, const char *dllname ); bool convert_port_data_1( NT_PORT_DATA_1 *port1, RPC_BUFFER *buf ) ; -/* The following definitions come from rpc_server/srv_eventlog.c */ - -NTSTATUS rpc_eventlog2_init(void); -void eventlog2_get_pipe_fns(struct api_struct **fns, int *n_fns); - /* The following definitions come from rpc_server/srv_eventlog_lib.c */ TDB_CONTEXT *elog_init_tdb( char *tdbfilename ); char *elog_tdbname(TALLOC_CTX *ctx, const char *name ); int elog_tdb_size( TDB_CONTEXT * tdb, int *MaxSize, int *Retention ); bool prune_eventlog( TDB_CONTEXT * tdb ); -bool can_write_to_eventlog( TDB_CONTEXT * tdb, int32 needed ); -ELOG_TDB *elog_open_tdb( char *logname, bool force_clear ); +ELOG_TDB *elog_open_tdb( const char *logname, bool force_clear, bool read_only ); int elog_close_tdb( ELOG_TDB *etdb, bool force_close ); -int write_eventlog_tdb( TDB_CONTEXT * the_tdb, Eventlog_entry * ee ); -void fixup_eventlog_entry( Eventlog_entry * ee ); -bool parse_logentry( char *line, Eventlog_entry * entry, bool * eor ); +bool parse_logentry( TALLOC_CTX *mem_ctx, char *line, struct eventlog_Record_tdb *entry, bool * eor ); +size_t fixup_eventlog_record_tdb(struct eventlog_Record_tdb *r); +struct eventlog_Record_tdb *evlog_pull_record_tdb(TALLOC_CTX *mem_ctx, + TDB_CONTEXT *tdb, + uint32_t record_number); +NTSTATUS evlog_push_record_tdb(TALLOC_CTX *mem_ctx, + TDB_CONTEXT *tdb, + struct eventlog_Record_tdb *r, + uint32_t *record_number); +NTSTATUS evlog_push_record(TALLOC_CTX *mem_ctx, + TDB_CONTEXT *tdb, + struct EVENTLOGRECORD *r, + uint32_t *record_number); +struct EVENTLOGRECORD *evlog_pull_record(TALLOC_CTX *mem_ctx, + TDB_CONTEXT *tdb, + uint32_t record_number); +NTSTATUS evlog_evt_entry_to_tdb_entry(TALLOC_CTX *mem_ctx, + const struct EVENTLOGRECORD *e, + struct eventlog_Record_tdb *t); +NTSTATUS evlog_tdb_entry_to_evt_entry(TALLOC_CTX *mem_ctx, + const struct eventlog_Record_tdb *t, + struct EVENTLOGRECORD *e); /* The following definitions come from rpc_server/srv_eventlog_nt.c */ -NTSTATUS _eventlog_read_eventlog( pipes_struct * p, - EVENTLOG_Q_READ_EVENTLOG * q_u, - EVENTLOG_R_READ_EVENTLOG * r_u ); - /* The following definitions come from rpc_server/srv_lsa_hnd.c */ -bool init_pipe_handle_list(pipes_struct *p, const char *pipe_name); +bool init_pipe_handle_list(pipes_struct *p, + const struct ndr_syntax_id *syntax); bool create_policy_hnd(pipes_struct *p, POLICY_HND *hnd, void *data_ptr); bool find_policy_by_hnd(pipes_struct *p, POLICY_HND *hnd, void **data_p); bool close_policy_hnd(pipes_struct *p, POLICY_HND *hnd); @@ -6221,7 +6234,7 @@ NTSTATUS rpc_srv_register(int version, const char *clnt, const char *srv, const struct ndr_interface_table *iface, const struct api_struct *cmds, int size); -bool is_known_pipename(const char *cli_filename); +bool is_known_pipename(const char *cli_filename, struct ndr_syntax_id *syntax); bool api_pipe_bind_req(pipes_struct *p, prs_struct *rpc_in_p); bool api_pipe_alter_context(pipes_struct *p, prs_struct *rpc_in_p); bool api_pipe_ntlmssp_auth_process(pipes_struct *p, prs_struct *rpc_in, @@ -6240,10 +6253,15 @@ NTSTATUS np_open(TALLOC_CTX *mem_ctx, const char *name, const char *client_address, struct auth_serversupplied_info *server_info, struct fake_file_handle **phandle); -NTSTATUS np_write(struct fake_file_handle *handle, const uint8_t *data, - size_t len, ssize_t *nwritten); -NTSTATUS np_read(struct fake_file_handle *handle, uint8_t *data, size_t len, - ssize_t *nread, bool *is_data_outstanding); +struct async_req *np_write_send(TALLOC_CTX *mem_ctx, struct event_context *ev, + struct fake_file_handle *handle, + const uint8_t *data, size_t len); +NTSTATUS np_write_recv(struct async_req *req, ssize_t *nwritten); +struct async_req *np_read_send(TALLOC_CTX *mem_ctx, struct event_context *ev, + struct fake_file_handle *handle, + uint8_t *data, size_t len); +NTSTATUS np_read_recv(struct async_req *req, ssize_t *nread, + bool *is_data_outstanding); /* The following definitions come from rpc_server/srv_samr_util.c */ @@ -6476,8 +6494,6 @@ REGVAL_CTR *svcctl_fetch_regvalues( const char *name, NT_USER_TOKEN *token ); /* The following definitions come from smbd/aio.c */ -void aio_request_done(uint16_t mid); -bool aio_finished(void); void initialize_async_io_handler(void); bool schedule_aio_read_and_X(connection_struct *conn, struct smb_request *req, @@ -6488,23 +6504,9 @@ bool schedule_aio_write_and_X(connection_struct *conn, files_struct *fsp, char *data, SMB_OFF_T startpos, size_t numtowrite); -int process_aio_queue(void); int wait_for_aio_completion(files_struct *fsp); void cancel_aio_by_fsp(files_struct *fsp); -bool aio_finished(void); -void initialize_async_io_handler(void); -int process_aio_queue(void); -bool schedule_aio_read_and_X(connection_struct *conn, - struct smb_request *req, - files_struct *fsp, SMB_OFF_T startpos, - size_t smb_maxcnt); -bool schedule_aio_write_and_X(connection_struct *conn, - struct smb_request *req, - files_struct *fsp, char *data, - SMB_OFF_T startpos, - size_t numtowrite); -void cancel_aio_by_fsp(files_struct *fsp); -int wait_for_aio_completion(files_struct *fsp); +void smbd_aio_complete_mid(unsigned int mid); /* The following definitions come from smbd/blocking.c */ @@ -6668,14 +6670,9 @@ uint32 dmapi_file_flags(const char * const path); /* The following definitions come from smbd/dnsregister.c */ -void dns_register_close(struct dns_reg_state **dns_state_ptr); -void dns_register_smbd(struct dns_reg_state ** dns_state_ptr, - unsigned port, - int *maxfd, - fd_set *listen_set, - struct timeval *timeout); -bool dns_register_smbd_reply(struct dns_reg_state *dns_state, - fd_set *lfds, struct timeval *timeout); +bool smbd_setup_mdns_registration(struct tevent_context *ev, + TALLOC_CTX *mem_ctx, + uint16_t port); /* The following definitions come from smbd/dosmode.c */ @@ -7035,13 +7032,11 @@ NTSTATUS get_relative_fid_filename(connection_struct *conn, /* The following definitions come from smbd/oplock.c */ int32 get_number_of_exclusive_open_oplocks(void); -bool oplock_message_waiting(void); -void process_kernel_oplocks(struct messaging_context *msg_ctx); +void break_kernel_oplock(struct messaging_context *msg_ctx, files_struct *fsp); bool set_file_oplock(files_struct *fsp, int oplock_type); void release_file_oplock(files_struct *fsp); bool remove_oplock(files_struct *fsp); bool downgrade_oplock(files_struct *fsp); -int oplock_notify_fd(void); void reply_to_oplock_break_requests(files_struct *fsp); void release_level_2_oplocks_on_change(files_struct *fsp); void share_mode_entry_to_message(char *msg, const struct share_mode_entry *e); @@ -7116,6 +7111,8 @@ SEC_DESC *get_nt_acl_no_snum( TALLOC_CTX *ctx, const char *fname); /* The following definitions come from smbd/process.c */ +void smbd_setup_sig_term_handler(void); +void smbd_setup_sig_hup_handler(void); bool srv_send_smb(int fd, char *buffer, bool do_encrypt); int srv_set_message(char *buf, int num_words, @@ -7141,7 +7138,6 @@ struct idle_event *event_add_idle(struct event_context *event_ctx, void *private_data), void *private_data); NTSTATUS allow_new_trans(struct trans_state *list, int mid); -void respond_to_all_remaining_local_messages(void); void reply_outbuf(struct smb_request *req, uint8 num_words, uint32 num_bytes); const char *smb_fn_name(int type); void add_to_common_flags2(uint32 v); @@ -7149,6 +7145,7 @@ void remove_from_common_flags2(uint32 v); void construct_reply_common_req(struct smb_request *req, char *outbuf); size_t req_wct_ofs(struct smb_request *req); void chain_reply(struct smb_request *req); +bool req_is_in_chain(struct smb_request *req); void check_reload(time_t t); void smbd_process(void); @@ -7222,11 +7219,6 @@ void reply_ctemp(struct smb_request *req); NTSTATUS unlink_internals(connection_struct *conn, struct smb_request *req, uint32 dirtype, const char *name_in, bool has_wild); void reply_unlink(struct smb_request *req); -void send_file_readbraw(connection_struct *conn, - files_struct *fsp, - SMB_OFF_T startpos, - size_t nread, - ssize_t mincount); void reply_readbraw(struct smb_request *req); void reply_lockread(struct smb_request *req); void reply_read(struct smb_request *req); @@ -7400,7 +7392,6 @@ int sys_statvfs(const char *path, vfs_statvfs_struct *statbuf); /* The following definitions come from smbd/trans2.c */ uint64_t smb_roundup(connection_struct *conn, uint64_t val); -uint64_t get_allocation_size(connection_struct *conn, files_struct *fsp, const SMB_STRUCT_STAT *sbuf); NTSTATUS get_ea_value(TALLOC_CTX *mem_ctx, connection_struct *conn, files_struct *fsp, const char *fname, const char *ea_name, struct ea_struct *pea); @@ -7618,7 +7609,7 @@ NTSTATUS nss_info_template_init( void ); /* Misc protos */ -struct async_req *wb_trans_send(TALLOC_CTX *mem_ctx, struct event_context *ev, +struct async_req *wb_trans_send(TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct wb_context *wb_ctx, bool need_priv, const struct winbindd_request *wb_req); NTSTATUS wb_trans_recv(struct async_req *req, TALLOC_CTX *mem_ctx, diff --git a/source3/include/rpc_eventlog.h b/source3/include/rpc_eventlog.h deleted file mode 100644 index f17e448d9e..0000000000 --- a/source3/include/rpc_eventlog.h +++ /dev/null @@ -1,100 +0,0 @@ -/* - * Unix SMB/CIFS implementation. - * RPC Pipe client / server routines - * Copyright (C) Marcin Krzysztof Porwit 2005. - * - * 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 _RPC_EVENTLOG_H /* _RPC_EVENTLOG_H */ -#define _RPC_EVENTLOG_H - -/* opcodes */ - -#define EVENTLOG_CLEAREVENTLOG 0x00 -#define EVENTLOG_CLOSEEVENTLOG 0x02 -#define EVENTLOG_GETNUMRECORDS 0x04 -#define EVENTLOG_GETOLDESTENTRY 0x05 -#define EVENTLOG_OPENEVENTLOG 0x07 -#define EVENTLOG_READEVENTLOG 0x0a - -/* Eventlog read flags */ -/* defined in librpc/gen_ndr/eventlog.h */ - -/* Event types */ -/* defined in librpc/gen_ndr/eventlog.h */ - -/***********************************/ - -typedef struct -{ - POLICY_HND handle; - uint32 flags; - uint32 offset; - uint32 max_read_size; -} EVENTLOG_Q_READ_EVENTLOG; - -typedef struct { - uint32 length; - uint32 reserved1; - uint32 record_number; - uint32 time_generated; - uint32 time_written; - uint32 event_id; - uint16 event_type; - uint16 num_strings; - uint16 event_category; - uint16 reserved2; - uint32 closing_record_number; - uint32 string_offset; - uint32 user_sid_length; - uint32 user_sid_offset; - uint32 data_length; - uint32 data_offset; -} Eventlog_record; - -typedef struct { - uint32 source_name_len; - smb_ucs2_t *source_name; - uint32 computer_name_len; - smb_ucs2_t *computer_name; - uint32 sid_padding; - smb_ucs2_t *sid; - uint32 strings_len; - smb_ucs2_t *strings; - uint32 user_data_len; - char *user_data; - uint32 data_padding; -} Eventlog_data_record; - -typedef struct eventlog_entry { - Eventlog_record record; - Eventlog_data_record data_record; - uint8 *data; - uint8 *end_of_data_padding; - struct eventlog_entry *next; -} Eventlog_entry; - -typedef struct { - uint32 num_bytes_in_resp; - uint32 bytes_in_next_record; - uint32 num_records; - Eventlog_entry *entry; - uint8 *end_of_entries_padding; - uint32 sent_size; - uint32 real_size; - NTSTATUS status; -} EVENTLOG_R_READ_EVENTLOG; - -#endif /* _RPC_EVENTLOG_H */ diff --git a/source3/include/rpc_lsa.h b/source3/include/rpc_lsa.h deleted file mode 100644 index 1dc5ba4a7b..0000000000 --- a/source3/include/rpc_lsa.h +++ /dev/null @@ -1,60 +0,0 @@ -/* - Unix SMB/CIFS implementation. - SMB parameters and setup - Copyright (C) Andrew Tridgell 1992-1997 - Copyright (C) Luke Kenneth Casson Leighton 1996-1997 - Copyright (C) Paul Ashton 1997 - Copyright (C) Gerald (Jerry) Carter 2005 - - 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 _RPC_LSA_H /* _RPC_LSA_H */ -#define _RPC_LSA_H - -#define LSA_POLICY_ALL_ACCESS ( STANDARD_RIGHTS_REQUIRED_ACCESS |\ - LSA_POLICY_VIEW_LOCAL_INFORMATION |\ - LSA_POLICY_VIEW_AUDIT_INFORMATION |\ - LSA_POLICY_GET_PRIVATE_INFORMATION |\ - LSA_POLICY_TRUST_ADMIN |\ - LSA_POLICY_CREATE_ACCOUNT |\ - LSA_POLICY_CREATE_SECRET |\ - LSA_POLICY_CREATE_PRIVILEGE |\ - LSA_POLICY_SET_DEFAULT_QUOTA_LIMITS |\ - LSA_POLICY_SET_AUDIT_REQUIREMENTS |\ - LSA_POLICY_AUDIT_LOG_ADMIN |\ - LSA_POLICY_SERVER_ADMIN |\ - LSA_POLICY_LOOKUP_NAMES ) - - -#define LSA_POLICY_READ ( STANDARD_RIGHTS_READ_ACCESS |\ - LSA_POLICY_VIEW_LOCAL_INFORMATION |\ - LSA_POLICY_VIEW_AUDIT_INFORMATION |\ - LSA_POLICY_GET_PRIVATE_INFORMATION) - -#define LSA_POLICY_WRITE ( STD_RIGHT_READ_CONTROL_ACCESS |\ - LSA_POLICY_TRUST_ADMIN |\ - LSA_POLICY_CREATE_ACCOUNT |\ - LSA_POLICY_CREATE_SECRET |\ - LSA_POLICY_CREATE_PRIVILEGE |\ - LSA_POLICY_SET_DEFAULT_QUOTA_LIMITS |\ - LSA_POLICY_SET_AUDIT_REQUIREMENTS |\ - LSA_POLICY_AUDIT_LOG_ADMIN |\ - LSA_POLICY_SERVER_ADMIN) - -#define LSA_POLICY_EXECUTE ( STANDARD_RIGHTS_EXECUTE_ACCESS |\ - LSA_POLICY_VIEW_LOCAL_INFORMATION |\ - LSA_POLICY_LOOKUP_NAMES ) - -#endif /* _RPC_LSA_H */ diff --git a/source3/include/rpc_misc.h b/source3/include/rpc_misc.h index 3a3c61ecec..1e9d43bfa0 100644 --- a/source3/include/rpc_misc.h +++ b/source3/include/rpc_misc.h @@ -92,10 +92,6 @@ enum unistr2_term_codes { UNI_FLAGS_NONE = 0, UNI_STR_TERMINATE = 1, UNI_MAXLEN_ **********************************************************************/ typedef struct policy_handle POLICY_HND; -typedef struct { - uint32 ptr_hnd; /* pointer to enumeration handle */ - uint32 handle; /* enumeration handle */ -} ENUM_HND; #define OUR_HANDLE(hnd) (((hnd)==NULL) ? "NULL" :\ ( IVAL((hnd)->uuid.node,2) == (uint32)sys_getpid() ? "OURS" : \ @@ -104,53 +100,6 @@ typedef struct { /********************************************************************** - * Buffer Headers -- use by SEC_DESC_BUF in winreg and netlogon code - **********************************************************************/ - -/* TODO: replace this with an encompassing buffer structure */ -typedef struct { - uint32 buf_max_len; - uint32 buf_len; -} BUFHDR; - -/* this is a BUFHDR + a pointer to a buffer */ -typedef struct { - uint32 info_level; - uint32 length; /* uint8 chars */ - uint32 buffer; -} BUFHDR2; - -/* generic buffer ? wrapped around void*? */ -typedef struct { - uint32 size; - uint32 buffer; -} BUFHDR4; - - -/********************************************************************** - * Buffers - **********************************************************************/ - -/* buffer used by \winreg\ calls to fill in arbitrary REG_XXX values. - It *may* look like a UNISTR2 but it is *not*. This is not a goof - by the winreg developers. It is a generic buffer. buffer length - is stored in bytes (not # of uint16's) */ - -typedef struct { - uint32 buf_max_len; - uint32 offset; - uint32 buf_len; - uint16 *buffer; -} REGVAL_BUFFER; - -/* generic rpc version of the DATA_BLOB. Just a length and uint8 array */ - -typedef struct { - uint32 buf_len; - uint8 *buffer; -} RPC_DATA_BLOB; - -/********************************************************************** * Buffers use by spoolss (i might be able to replace it with * an RPC_DATA_BLOB) **********************************************************************/ @@ -162,22 +111,6 @@ typedef struct { /********************************************************************** - * Unicode and basic string headers - **********************************************************************/ - -typedef struct { - uint16 str_str_len; - uint16 str_max_len; - uint32 buffer; /* non-zero */ -} STRHDR; - -typedef struct { - uint16 uni_str_len; - uint16 uni_max_len; - uint32 buffer; -} UNIHDR; - -/********************************************************************** * UNICODE string variations **********************************************************************/ @@ -205,138 +138,4 @@ typedef struct { /* UNISTR3 - XXXX not sure about this structure */ UNISTR str; } UNISTR3; -typedef struct { /* Buffer wrapped around a UNISTR2 */ - uint16 length; /* number of bytes not counting NULL terminatation */ - uint16 size; /* number of bytes including NULL terminatation */ - UNISTR2 *string; -} UNISTR4; - -typedef struct { - uint32 count; - UNISTR4 *strings; -} UNISTR4_ARRAY; - - -/********************************************************************** - * String variations - **********************************************************************/ - -typedef struct { /* STRING2 - string size (in uint8 chars) and buffer */ - uint32 str_max_len; - uint32 offset; - uint32 str_str_len; - uint8 *buffer; /* uint8 characters. **NOT** necessarily null-terminated */ -} STRING2; - - - - -/********************************************************************** - * Domain SID structures - **********************************************************************/ - -typedef struct { - uint32 num_auths; /* length, bytes, including length of len :-) */ - DOM_SID sid; -} DOM_SID2; - - -/********************************************************************** - * Domain SID structures - **********************************************************************/ - -/* DOM_RID - domain RID structure for ntlsa pipe */ -typedef struct { - uint16 type; /* value is SID_NAME_USE enum */ - uint32 rid; - uint32 rid_idx; /* referenced domain index */ -} DOM_RID; - -/* DOM_RID2 - second domain RID structure for ntlsa pipe */ -typedef struct { - uint16 type; /* value is SID_NAME_USE enum */ - uint32 rid; - uint32 rid_idx; /* referenced domain index */ - uint32 unknown; -} DOM_RID2; - -typedef struct { /* DOM_RID3 - domain RID structure for samr pipe */ - uint32 rid; /* domain-relative (to a SID) id */ - uint32 type1; /* value is 0x1 */ - uint32 ptr_type; /* undocumented pointer */ - uint32 type2; /* value is 0x1 */ - uint32 unk; /* value is 0x2 */ -} DOM_RID3; - -/* DOM_RID4 - rid + user attributes */ -typedef struct domrid4_info -{ - uint32 unknown; - uint16 attr; - uint32 rid; /* user RID */ -} DOM_RID4; - -/* DOM_GID - group id + user attributes */ -typedef struct { - uint32 g_rid; /* a group RID */ - uint32 attr; -} DOM_GID; - -/********************************************************************** - * ???? - **********************************************************************/ - -/* DOM_CLNT_SRV - client / server names */ -typedef struct clnt_srv_info { - uint32 undoc_buffer; /* undocumented 32 bit buffer pointer */ - UNISTR2 uni_logon_srv; /* logon server name */ - uint32 undoc_buffer2; /* undocumented 32 bit buffer pointer */ - UNISTR2 uni_comp_name; /* client machine name */ -} DOM_CLNT_SRV; - -/* DOM_LOG_INFO - login info */ -typedef struct log_info { - uint32 undoc_buffer; /* undocumented 32 bit buffer pointer */ - UNISTR2 uni_logon_srv; /* logon server name */ - UNISTR2 uni_acct_name; /* account name */ - uint16 sec_chan; /* secure channel type */ - UNISTR2 uni_comp_name; /* client machine name */ -} DOM_LOG_INFO; - -/* DOM_CHAL - challenge info */ -typedef struct chal_info { - unsigned char data[8]; /* credentials */ -} DOM_CHAL; - -/* DOM_CREDs - timestamped client or server credentials */ -typedef struct cred_info { - DOM_CHAL challenge; /* credentials */ - UTIME timestamp; /* credential time-stamp */ -} DOM_CRED; - -/* DOM_CLNT_INFO - client info */ -typedef struct clnt_info { - DOM_LOG_INFO login; - DOM_CRED cred; -} DOM_CLNT_INFO; - -/* DOM_CLNT_INFO2 - client info */ -typedef struct clnt_info2 { - DOM_CLNT_SRV login; - uint32 ptr_cred; - DOM_CRED cred; -} DOM_CLNT_INFO2; - -/* DOM_LOGON_ID - logon id */ -typedef struct logon_info { - uint32 low; - uint32 high; -} DOM_LOGON_ID; - -/* OWF INFO */ -typedef struct owf_info { - uint8 data[16]; -} OWF_INFO; - - #endif /* _RPC_MISC_H */ diff --git a/source3/include/smb.h b/source3/include/smb.h index aa2db693a3..b441b3476a 100644 --- a/source3/include/smb.h +++ b/source3/include/smb.h @@ -367,6 +367,7 @@ struct uuid; struct named_mutex; struct pcap_cache; struct wb_context; +struct rpc_cli_smbd_conn; struct vfs_fsp_data { struct vfs_fsp_data *next; @@ -623,7 +624,18 @@ struct smb_request { uint16_t buflen; const uint8_t *buf; const uint8 *inbuf; + + /* + * Async handling in the main smb processing loop is directed by + * outbuf: reply_xxx routines indicate sync behaviour by putting their + * reply into "outbuf". If they leave it as NULL, they take of it + * themselves, possibly later. + * + * If async handling is wanted, the reply_xxx routine must make sure + * that it talloc_move()s the smb_req somewhere else. + */ uint8 *outbuf; + size_t unread_bytes; bool encrypted; connection_struct *conn; @@ -637,6 +649,11 @@ struct smb_request { * Here we collect the outbufs from the chain handlers */ uint8_t *chain_outbuf; + + /* + * state information for async smb handling + */ + void *async_priv; }; /* Defines for the sent_oplock_break field above. */ @@ -1242,7 +1259,7 @@ struct bitmap { /* Mapping of access rights to UNIX perms. for a UNIX directory. */ #define UNIX_DIRECTORY_ACCESS_RWX FILE_GENERIC_ALL #define UNIX_DIRECTORY_ACCESS_R FILE_GENERIC_READ -#define UNIX_DIRECTORY_ACCESS_W FILE_GENERIC_WRITE +#define UNIX_DIRECTORY_ACCESS_W (FILE_GENERIC_WRITE|FILE_DELETE_CHILD) #define UNIX_DIRECTORY_ACCESS_X FILE_GENERIC_EXECUTE #if 0 @@ -1549,11 +1566,6 @@ enum acl_compatibility {ACL_COMPAT_AUTO, ACL_COMPAT_WINNT, ACL_COMPAT_WIN2K}; #define COPYBUF_SIZE (8*1024) /* - * Used in chaining code. - */ -extern int chain_size; - -/* * Map the Core and Extended Oplock requesst bits down * to common bits (EXCLUSIVE_OPLOCK & BATCH_OPLOCK). */ @@ -1680,12 +1692,10 @@ struct kernel_oplocks { /* if a kernel does support oplocks then a structure of the following typee is used to describe how to interact with the kernel */ struct kernel_oplocks_ops { - files_struct * (*receive_message)(struct kernel_oplocks *ctx); bool (*set_oplock)(struct kernel_oplocks *ctx, files_struct *fsp, int oplock_type); void (*release_oplock)(struct kernel_oplocks *ctx, files_struct *fsp); - bool (*msg_waiting)(struct kernel_oplocks *ctx); }; #include "smb_macros.h" diff --git a/source3/include/smb_macros.h b/source3/include/smb_macros.h index 92c60a7530..fd1bba16a7 100644 --- a/source3/include/smb_macros.h +++ b/source3/include/smb_macros.h @@ -135,7 +135,7 @@ /* Note that chain_size must be available as an extern int to this macro. */ -#define smb_offset(p,buf) (PTR_DIFF(p,buf+4) + chain_size) +#define smb_offset(p,buf) (PTR_DIFF(p,buf+4)) #define smb_len(buf) (PVAL(buf,3)|(PVAL(buf,2)<<8)|((PVAL(buf,1)&1)<<16)) #define _smb_setlen(buf,len) do { buf[0] = 0; buf[1] = ((len)&0x10000)>>16; \ diff --git a/source3/include/smbprofile.h b/source3/include/smbprofile.h index 8945708ca3..131416b685 100644 --- a/source3/include/smbprofile.h +++ b/source3/include/smbprofile.h @@ -127,6 +127,10 @@ enum profile_stats_values #define syscall_lstat_count __profile_stats_value(PR_VALUE_SYSCALL_LSTAT, count) #define syscall_lstat_time __profile_stats_value(PR_VALUE_SYSCALL_LSTAT, time) + PR_VALUE_SYSCALL_GET_ALLOC_SIZE, +#define syscall_get_alloc_size_count __profile_stats_value(PR_VALUE_SYSCALL_GET_ALLOC_SIZE, count) +#define syscall_get_alloc_size_time __profile_stats_value(PR_VALUE_SYSCALL_GET_ALLOC_SIZE, time) + PR_VALUE_SYSCALL_UNLINK, #define syscall_unlink_count __profile_stats_value(PR_VALUE_SYSCALL_UNLINK, count) #define syscall_unlink_time __profile_stats_value(PR_VALUE_SYSCALL_UNLINK, time) diff --git a/source3/include/util_tdb.h b/source3/include/util_tdb.h index 127176b887..c79436434f 100644 --- a/source3/include/util_tdb.h +++ b/source3/include/util_tdb.h @@ -24,6 +24,7 @@ #include "talloc.h" /* for tdb_wrap_open() */ #include "../libcli/util/ntstatus.h" /* for map_nt_error_from_tdb() */ +#include "../../lib/util/util_tdb.h" struct tdb_wrap { struct tdb_context *tdb; @@ -31,47 +32,15 @@ struct tdb_wrap { struct tdb_wrap *next, *prev; }; -struct tdb_validation_status { - bool tdb_error; - bool bad_freelist; - bool bad_entry; - bool unknown_key; - bool success; -}; - -typedef int (*tdb_validate_data_func)(TDB_CONTEXT *the_tdb, TDB_DATA kbuf, TDB_DATA dbuf, void *state); - -TDB_DATA make_tdb_data(const uint8_t *dptr, size_t dsize); -TDB_DATA string_tdb_data(const char *string); -TDB_DATA string_term_tdb_data(const char *string); - int tdb_chainlock_with_timeout( struct tdb_context *tdb, TDB_DATA key, unsigned int timeout); -int tdb_lock_bystring(struct tdb_context *tdb, const char *keyval); int tdb_lock_bystring_with_timeout(struct tdb_context *tdb, const char *keyval, int timeout); -void tdb_unlock_bystring(struct tdb_context *tdb, const char *keyval); int tdb_read_lock_bystring_with_timeout(TDB_CONTEXT *tdb, const char *keyval, unsigned int timeout); -void tdb_read_unlock_bystring(struct tdb_context *tdb, const char *keyval); - -int32_t tdb_fetch_int32_byblob(struct tdb_context *tdb, TDB_DATA key); -int32_t tdb_fetch_int32(struct tdb_context *tdb, const char *keystr); -bool tdb_store_uint32_byblob(struct tdb_context *tdb, TDB_DATA key, uint32_t value); -bool tdb_store_uint32(struct tdb_context *tdb, const char *keystr, uint32_t value); -int tdb_store_int32_byblob(struct tdb_context *tdb, TDB_DATA key, int32_t v); -int tdb_store_int32(struct tdb_context *tdb, const char *keystr, int32_t v); -bool tdb_fetch_uint32_byblob(struct tdb_context *tdb, TDB_DATA key, uint32_t *value); -bool tdb_fetch_uint32(struct tdb_context *tdb, const char *keystr, uint32_t *value); -int32_t tdb_change_int32_atomic(struct tdb_context *tdb, const char *keystr, int32_t *oldval, int32_t change_val); -bool tdb_change_uint32_atomic(struct tdb_context *tdb, const char *keystr, - uint32_t *oldval, uint32_t change_val); -int tdb_store_bystring(struct tdb_context *tdb, const char *keystr, TDB_DATA data, int flags); int tdb_trans_store_bystring(TDB_CONTEXT *tdb, const char *keystr, TDB_DATA data, int flags); -TDB_DATA tdb_fetch_bystring(struct tdb_context *tdb, const char *keystr); -int tdb_delete_bystring(struct tdb_context *tdb, const char *keystr); int tdb_trans_store(struct tdb_context *tdb, TDB_DATA key, TDB_DATA dbuf, int flag); int tdb_trans_delete(struct tdb_context *tdb, TDB_DATA key); @@ -90,9 +59,4 @@ struct tdb_wrap *tdb_wrap_open(TALLOC_CTX *mem_ctx, NTSTATUS map_nt_error_from_tdb(enum TDB_ERROR err); -int tdb_validate(struct tdb_context *tdb, tdb_validate_data_func validate_fn); -int tdb_validate_open(const char *tdb_path, tdb_validate_data_func validate_fn); -int tdb_validate_and_backup(const char *tdb_path, - tdb_validate_data_func validate_fn); - #endif /* __TDBUTIL_H__ */ diff --git a/source3/include/vfs.h b/source3/include/vfs.h index 5df71da905..e9115ab807 100644 --- a/source3/include/vfs.h +++ b/source3/include/vfs.h @@ -112,6 +112,7 @@ /* Changed to version 25 - Jelmer's change from SMB_BIG_UINT to uint64_t. */ /* Leave at 25 - not yet released. Add create_file call. -- tprouty. */ /* Leave at 25 - not yet released. Add create time to ntimes. -- tstecher. */ +/* Leave at 25 - not yet released. Add get_alloc_size call. -- tprouty. */ #define SMB_VFS_INTERFACE_VERSION 25 @@ -189,6 +190,7 @@ typedef enum _vfs_op_type { SMB_VFS_OP_STAT, SMB_VFS_OP_FSTAT, SMB_VFS_OP_LSTAT, + SMB_VFS_OP_GET_ALLOC_SIZE, SMB_VFS_OP_UNLINK, SMB_VFS_OP_CHMOD, SMB_VFS_OP_FCHMOD, @@ -342,6 +344,7 @@ struct vfs_ops { int (*stat)(struct vfs_handle_struct *handle, const char *fname, SMB_STRUCT_STAT *sbuf); int (*fstat)(struct vfs_handle_struct *handle, struct files_struct *fsp, SMB_STRUCT_STAT *sbuf); int (*lstat)(struct vfs_handle_struct *handle, const char *path, SMB_STRUCT_STAT *sbuf); + uint64_t (*get_alloc_size)(struct vfs_handle_struct *handle, struct files_struct *fsp, const SMB_STRUCT_STAT *sbuf); int (*unlink)(struct vfs_handle_struct *handle, const char *path); int (*chmod)(struct vfs_handle_struct *handle, const char *path, mode_t mode); int (*fchmod)(struct vfs_handle_struct *handle, struct files_struct *fsp, mode_t mode); @@ -496,6 +499,7 @@ struct vfs_ops { struct vfs_handle_struct *stat; struct vfs_handle_struct *fstat; struct vfs_handle_struct *lstat; + struct vfs_handle_struct *get_alloc_size; struct vfs_handle_struct *unlink; struct vfs_handle_struct *chmod; struct vfs_handle_struct *fchmod; diff --git a/source3/include/vfs_macros.h b/source3/include/vfs_macros.h index c6ccd4912a..e7a9cfdc76 100644 --- a/source3/include/vfs_macros.h +++ b/source3/include/vfs_macros.h @@ -62,6 +62,7 @@ #define SMB_VFS_STAT(conn, fname, sbuf) ((conn)->vfs.ops.stat((conn)->vfs.handles.stat, (fname), (sbuf))) #define SMB_VFS_FSTAT(fsp, sbuf) ((fsp)->conn->vfs.ops.fstat((fsp)->conn->vfs.handles.fstat, (fsp), (sbuf))) #define SMB_VFS_LSTAT(conn, path, sbuf) ((conn)->vfs.ops.lstat((conn)->vfs.handles.lstat, (path), (sbuf))) +#define SMB_VFS_GET_ALLOC_SIZE(conn, fsp, sbuf) ((conn)->vfs.ops.get_alloc_size((conn)->vfs.handles.get_alloc_size, (fsp), (sbuf))) #define SMB_VFS_UNLINK(conn, path) ((conn)->vfs.ops.unlink((conn)->vfs.handles.unlink, (path))) #define SMB_VFS_CHMOD(conn, path, mode) ((conn)->vfs.ops.chmod((conn)->vfs.handles.chmod, (path), (mode))) #define SMB_VFS_FCHMOD(fsp, mode) ((fsp)->conn->vfs.ops.fchmod((fsp)->conn->vfs.handles.fchmod, (fsp), (mode))) @@ -189,6 +190,7 @@ #define SMB_VFS_OPAQUE_STAT(conn, fname, sbuf) ((conn)->vfs_opaque.ops.stat((conn)->vfs_opaque.handles.stat, (fname), (sbuf))) #define SMB_VFS_OPAQUE_FSTAT(fsp, sbuf) ((fsp)->conn->vfs_opaque.ops.fstat((fsp)->conn->vfs_opaque.handles.fstat, (fsp), (sbuf))) #define SMB_VFS_OPAQUE_LSTAT(conn, path, sbuf) ((conn)->vfs_opaque.ops.lstat((conn)->vfs_opaque.handles.lstat, (path), (sbuf))) +#define SMB_VFS_OPAQUE_GET_ALLOC_SIZE(conn, fsp, sbuf) ((conn)->vfs_opaque.ops.get_alloc_size((conn)->vfs_opaque.handles.get_alloc_size, (fsp), (sbuf))) #define SMB_VFS_OPAQUE_UNLINK(conn, path) ((conn)->vfs_opaque.ops.unlink((conn)->vfs_opaque.handles.unlink, (path))) #define SMB_VFS_OPAQUE_CHMOD(conn, path, mode) ((conn)->vfs_opaque.ops.chmod((conn)->vfs_opaque.handles.chmod, (path), (mode))) #define SMB_VFS_OPAQUE_FCHMOD(fsp, mode) ((fsp)->conn->vfs_opaque.ops.fchmod((fsp)->conn->vfs_opaque.handles.fchmod, (fsp), (mode))) @@ -317,6 +319,7 @@ #define SMB_VFS_NEXT_STAT(handle, fname, sbuf) ((handle)->vfs_next.ops.stat((handle)->vfs_next.handles.stat, (fname), (sbuf))) #define SMB_VFS_NEXT_FSTAT(handle, fsp, sbuf) ((handle)->vfs_next.ops.fstat((handle)->vfs_next.handles.fstat, (fsp), (sbuf))) #define SMB_VFS_NEXT_LSTAT(handle, path, sbuf) ((handle)->vfs_next.ops.lstat((handle)->vfs_next.handles.lstat, (path), (sbuf))) +#define SMB_VFS_NEXT_GET_ALLOC_SIZE(conn, fsp, sbuf) ((conn)->vfs_next.ops.get_alloc_size((conn)->vfs_next.handles.get_alloc_size, (fsp), (sbuf))) #define SMB_VFS_NEXT_UNLINK(handle, path) ((handle)->vfs_next.ops.unlink((handle)->vfs_next.handles.unlink, (path))) #define SMB_VFS_NEXT_CHMOD(handle, path, mode) ((handle)->vfs_next.ops.chmod((handle)->vfs_next.handles.chmod, (path), (mode))) #define SMB_VFS_NEXT_FCHMOD(handle, fsp, mode) ((handle)->vfs_next.ops.fchmod((handle)->vfs_next.handles.fchmod, (fsp), (mode))) diff --git a/source3/lib/async_sock.c b/source3/lib/async_sock.c deleted file mode 100644 index 73ff6f2870..0000000000 --- a/source3/lib/async_sock.c +++ /dev/null @@ -1,693 +0,0 @@ -/* - Unix SMB/CIFS implementation. - async socket syscalls - Copyright (C) Volker Lendecke 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/>. -*/ - -#include "includes.h" - -/** - * Discriminator for async_syscall_state - */ -enum async_syscall_type { - ASYNC_SYSCALL_SEND, - ASYNC_SYSCALL_SENDALL, - ASYNC_SYSCALL_RECV, - ASYNC_SYSCALL_RECVALL, - ASYNC_SYSCALL_CONNECT -}; - -/** - * Holder for syscall arguments and the result - */ - -struct async_syscall_state { - enum async_syscall_type syscall_type; - struct fd_event *fde; - - union { - struct param_send { - int fd; - const void *buffer; - size_t length; - int flags; - } param_send; - struct param_sendall { - int fd; - const void *buffer; - size_t length; - int flags; - size_t sent; - } param_sendall; - struct param_recv { - int fd; - void *buffer; - size_t length; - int flags; - } param_recv; - struct param_recvall { - int fd; - void *buffer; - size_t length; - int flags; - size_t received; - } param_recvall; - struct param_connect { - /** - * connect needs to be done on a nonblocking - * socket. Keep the old flags around - */ - long old_sockflags; - int fd; - const struct sockaddr *address; - socklen_t address_len; - } param_connect; - } param; - - union { - ssize_t result_ssize_t; - size_t result_size_t; - int result_int; - } result; - int sys_errno; -}; - -/** - * @brief Create a new async syscall req - * @param[in] mem_ctx The memory context to hang the result off - * @param[in] ev The event context to work from - * @param[in] type Which syscall will this be - * @param[in] pstate Where to put the newly created private_data state - * @retval The new request - * - * This is a helper function to prepare a new struct async_req with an - * associated struct async_syscall_state. The async_syscall_state will be put - * into the async_req as private_data. - */ - -static struct async_req *async_syscall_new(TALLOC_CTX *mem_ctx, - struct event_context *ev, - enum async_syscall_type type, - struct async_syscall_state **pstate) -{ - struct async_req *result; - struct async_syscall_state *state; - - if (!async_req_setup(mem_ctx, &result, &state, - struct async_syscall_state)) { - return NULL; - } - state->syscall_type = type; - - result->private_data = state; - - *pstate = state; - - return result; -} - -/** - * @brief Create a new async syscall req based on a fd - * @param[in] mem_ctx The memory context to hang the result off - * @param[in] ev The event context to work from - * @param[in] type Which syscall will this be - * @param[in] fd The file descriptor we work on - * @param[in] fde_flags EVENT_FD_READ/WRITE -- what are we interested in? - * @param[in] fde_cb The callback function for the file descriptor event - * @param[in] pstate Where to put the newly created private_data state - * @retval The new request - * - * This is a helper function to prepare a new struct async_req with an - * associated struct async_syscall_state and an associated file descriptor - * event. - */ - -static struct async_req *async_fde_syscall_new( - TALLOC_CTX *mem_ctx, - struct event_context *ev, - enum async_syscall_type type, - int fd, - uint16_t fde_flags, - void (*fde_cb)(struct event_context *ev, - struct fd_event *fde, uint16_t flags, - void *priv), - struct async_syscall_state **pstate) -{ - struct async_req *result; - struct async_syscall_state *state; - - result = async_syscall_new(mem_ctx, ev, type, &state); - if (result == NULL) { - return NULL; - } - - state->fde = event_add_fd(ev, state, fd, fde_flags, fde_cb, result); - if (state->fde == NULL) { - TALLOC_FREE(result); - return NULL; - } - *pstate = state; - return result; -} - -/** - * Retrieve a ssize_t typed result from an async syscall - * @param[in] req The syscall that has just finished - * @param[out] perrno Where to put the syscall's errno - * @retval The return value from the asynchronously called syscall - */ - -ssize_t async_syscall_result_ssize_t(struct async_req *req, int *perrno) -{ - struct async_syscall_state *state = talloc_get_type_abort( - req->private_data, struct async_syscall_state); - - *perrno = state->sys_errno; - return state->result.result_ssize_t; -} - -/** - * Retrieve a size_t typed result from an async syscall - * @param[in] req The syscall that has just finished - * @param[out] perrno Where to put the syscall's errno - * @retval The return value from the asynchronously called syscall - */ - -size_t async_syscall_result_size_t(struct async_req *req, int *perrno) -{ - struct async_syscall_state *state = talloc_get_type_abort( - req->private_data, struct async_syscall_state); - - *perrno = state->sys_errno; - return state->result.result_size_t; -} - -/** - * Retrieve a int typed result from an async syscall - * @param[in] req The syscall that has just finished - * @param[out] perrno Where to put the syscall's errno - * @retval The return value from the asynchronously called syscall - */ - -int async_syscall_result_int(struct async_req *req, int *perrno) -{ - struct async_syscall_state *state = talloc_get_type_abort( - req->private_data, struct async_syscall_state); - - *perrno = state->sys_errno; - return state->result.result_int; -} - -/** - * fde event handler for the "send" syscall - * @param[in] ev The event context that sent us here - * @param[in] fde The file descriptor event associated with the send - * @param[in] flags Can only be EVENT_FD_WRITE here - * @param[in] priv private data, "struct async_req *" in this case - */ - -static void async_send_callback(struct event_context *ev, - struct fd_event *fde, uint16_t flags, - void *priv) -{ - struct async_req *req = talloc_get_type_abort( - priv, struct async_req); - struct async_syscall_state *state = talloc_get_type_abort( - req->private_data, struct async_syscall_state); - struct param_send *p = &state->param.param_send; - - if (state->syscall_type != ASYNC_SYSCALL_SEND) { - async_req_error(req, NT_STATUS_INTERNAL_ERROR); - return; - } - - state->result.result_ssize_t = send(p->fd, p->buffer, p->length, - p->flags); - state->sys_errno = errno; - - TALLOC_FREE(state->fde); - - async_req_done(req); -} - -/** - * Async version of send(2) - * @param[in] mem_ctx The memory context to hang the result off - * @param[in] ev The event context to work from - * @param[in] fd The socket to send to - * @param[in] buffer The buffer to send - * @param[in] length How many bytes to send - * @param[in] flags flags passed to send(2) - * - * This function is a direct counterpart of send(2) - */ - -struct async_req *async_send(TALLOC_CTX *mem_ctx, struct event_context *ev, - int fd, const void *buffer, size_t length, - int flags) -{ - struct async_req *result; - struct async_syscall_state *state; - - result = async_fde_syscall_new( - mem_ctx, ev, ASYNC_SYSCALL_SEND, - fd, EVENT_FD_WRITE, async_send_callback, - &state); - if (result == NULL) { - return NULL; - } - - state->param.param_send.fd = fd; - state->param.param_send.buffer = buffer; - state->param.param_send.length = length; - state->param.param_send.flags = flags; - - return result; -} - -/** - * fde event handler for the "sendall" syscall group - * @param[in] ev The event context that sent us here - * @param[in] fde The file descriptor event associated with the send - * @param[in] flags Can only be EVENT_FD_WRITE here - * @param[in] priv private data, "struct async_req *" in this case - */ - -static void async_sendall_callback(struct event_context *ev, - struct fd_event *fde, uint16_t flags, - void *priv) -{ - struct async_req *req = talloc_get_type_abort( - priv, struct async_req); - struct async_syscall_state *state = talloc_get_type_abort( - req->private_data, struct async_syscall_state); - struct param_sendall *p = &state->param.param_sendall; - - if (state->syscall_type != ASYNC_SYSCALL_SENDALL) { - async_req_error(req, NT_STATUS_INTERNAL_ERROR); - return; - } - - state->result.result_ssize_t = send(p->fd, (char *)p->buffer + p->sent, - p->length - p->sent, p->flags); - state->sys_errno = errno; - - if (state->result.result_ssize_t == -1) { - async_req_error(req, map_nt_error_from_unix(state->sys_errno)); - return; - } - - if (state->result.result_ssize_t == 0) { - async_req_error(req, NT_STATUS_END_OF_FILE); - return; - } - - p->sent += state->result.result_ssize_t; - if (p->sent > p->length) { - async_req_error(req, NT_STATUS_INTERNAL_ERROR); - return; - } - - if (p->sent == p->length) { - TALLOC_FREE(state->fde); - async_req_done(req); - } -} - -/** - * @brief Send all bytes to a socket - * @param[in] mem_ctx The memory context to hang the result off - * @param[in] ev The event context to work from - * @param[in] fd The socket to send to - * @param[in] buffer The buffer to send - * @param[in] length How many bytes to send - * @param[in] flags flags passed to send(2) - * - * async_sendall calls send(2) as long as it is necessary to send all of the - * "length" bytes - */ - -struct async_req *sendall_send(TALLOC_CTX *mem_ctx, struct event_context *ev, - int fd, const void *buffer, size_t length, - int flags) -{ - struct async_req *result; - struct async_syscall_state *state; - - result = async_fde_syscall_new( - mem_ctx, ev, ASYNC_SYSCALL_SENDALL, - fd, EVENT_FD_WRITE, async_sendall_callback, - &state); - if (result == NULL) { - return NULL; - } - - state->param.param_sendall.fd = fd; - state->param.param_sendall.buffer = buffer; - state->param.param_sendall.length = length; - state->param.param_sendall.flags = flags; - state->param.param_sendall.sent = 0; - - return result; -} - -NTSTATUS sendall_recv(struct async_req *req) -{ - return async_req_simple_recv(req); -} - -/** - * fde event handler for the "recv" syscall - * @param[in] ev The event context that sent us here - * @param[in] fde The file descriptor event associated with the recv - * @param[in] flags Can only be EVENT_FD_READ here - * @param[in] priv private data, "struct async_req *" in this case - */ - -static void async_recv_callback(struct event_context *ev, - struct fd_event *fde, uint16_t flags, - void *priv) -{ - struct async_req *req = talloc_get_type_abort( - priv, struct async_req); - struct async_syscall_state *state = talloc_get_type_abort( - req->private_data, struct async_syscall_state); - struct param_recv *p = &state->param.param_recv; - - if (state->syscall_type != ASYNC_SYSCALL_RECV) { - async_req_error(req, NT_STATUS_INTERNAL_ERROR); - return; - } - - state->result.result_ssize_t = recv(p->fd, p->buffer, p->length, - p->flags); - state->sys_errno = errno; - - TALLOC_FREE(state->fde); - - async_req_done(req); -} - -/** - * Async version of recv(2) - * @param[in] mem_ctx The memory context to hang the result off - * @param[in] ev The event context to work from - * @param[in] fd The socket to recv from - * @param[in] buffer The buffer to recv into - * @param[in] length How many bytes to recv - * @param[in] flags flags passed to recv(2) - * - * This function is a direct counterpart of recv(2) - */ - -struct async_req *async_recv(TALLOC_CTX *mem_ctx, struct event_context *ev, - int fd, void *buffer, size_t length, - int flags) -{ - struct async_req *result; - struct async_syscall_state *state; - - result = async_fde_syscall_new( - mem_ctx, ev, ASYNC_SYSCALL_RECV, - fd, EVENT_FD_READ, async_recv_callback, - &state); - - if (result == NULL) { - return NULL; - } - - state->param.param_recv.fd = fd; - state->param.param_recv.buffer = buffer; - state->param.param_recv.length = length; - state->param.param_recv.flags = flags; - - return result; -} - -/** - * fde event handler for the "recvall" syscall group - * @param[in] ev The event context that sent us here - * @param[in] fde The file descriptor event associated with the recv - * @param[in] flags Can only be EVENT_FD_READ here - * @param[in] priv private data, "struct async_req *" in this case - */ - -static void async_recvall_callback(struct event_context *ev, - struct fd_event *fde, uint16_t flags, - void *priv) -{ - struct async_req *req = talloc_get_type_abort( - priv, struct async_req); - struct async_syscall_state *state = talloc_get_type_abort( - req->private_data, struct async_syscall_state); - struct param_recvall *p = &state->param.param_recvall; - - if (state->syscall_type != ASYNC_SYSCALL_RECVALL) { - async_req_error(req, NT_STATUS_INTERNAL_ERROR); - return; - } - - state->result.result_ssize_t = recv(p->fd, - (char *)p->buffer + p->received, - p->length - p->received, p->flags); - state->sys_errno = errno; - - if (state->result.result_ssize_t == -1) { - async_req_error(req, map_nt_error_from_unix(state->sys_errno)); - return; - } - - if (state->result.result_ssize_t == 0) { - async_req_error(req, NT_STATUS_END_OF_FILE); - return; - } - - p->received += state->result.result_ssize_t; - if (p->received > p->length) { - async_req_error(req, NT_STATUS_INTERNAL_ERROR); - return; - } - - if (p->received == p->length) { - TALLOC_FREE(state->fde); - async_req_done(req); - } -} - -/** - * Receive a specified number of bytes from a socket - * @param[in] mem_ctx The memory context to hang the result off - * @param[in] ev The event context to work from - * @param[in] fd The socket to recv from - * @param[in] buffer The buffer to recv into - * @param[in] length How many bytes to recv - * @param[in] flags flags passed to recv(2) - * - * async_recvall will call recv(2) until "length" bytes are received - */ - -struct async_req *recvall_send(TALLOC_CTX *mem_ctx, struct event_context *ev, - int fd, void *buffer, size_t length, - int flags) -{ - struct async_req *result; - struct async_syscall_state *state; - - result = async_fde_syscall_new( - mem_ctx, ev, ASYNC_SYSCALL_RECVALL, - fd, EVENT_FD_READ, async_recvall_callback, - &state); - if (result == NULL) { - return NULL; - } - - state->param.param_recvall.fd = fd; - state->param.param_recvall.buffer = buffer; - state->param.param_recvall.length = length; - state->param.param_recvall.flags = flags; - state->param.param_recvall.received = 0; - - return result; -} - -NTSTATUS recvall_recv(struct async_req *req) -{ - return async_req_simple_recv(req); -} - -struct async_connect_state { - int fd; - int result; - int sys_errno; - long old_sockflags; -}; - -static void async_connect_connected(struct event_context *ev, - struct fd_event *fde, uint16_t flags, - void *priv); - -/** - * @brief async version of connect(2) - * @param[in] mem_ctx The memory context to hang the result off - * @param[in] ev The event context to work from - * @param[in] fd The socket to recv from - * @param[in] address Where to connect? - * @param[in] address_len Length of *address - * @retval The async request - * - * This function sets the socket into non-blocking state to be able to call - * connect in an async state. This will be reset when the request is finished. - */ - -struct async_req *async_connect_send(TALLOC_CTX *mem_ctx, - struct event_context *ev, - int fd, const struct sockaddr *address, - socklen_t address_len) -{ - struct async_req *result; - struct async_connect_state *state; - struct fd_event *fde; - NTSTATUS status; - - if (!async_req_setup(mem_ctx, &result, &state, - struct async_connect_state)) { - return NULL; - } - - /** - * We have to set the socket to nonblocking for async connect(2). Keep - * the old sockflags around. - */ - - state->fd = fd; - state->sys_errno = 0; - - state->old_sockflags = sys_fcntl_long(fd, F_GETFL, 0); - if (state->old_sockflags == -1) { - goto post_errno; - } - - set_blocking(fd, false); - - state->result = connect(fd, address, address_len); - if (state->result == 0) { - state->sys_errno = 0; - status = NT_STATUS_OK; - goto post_status; - } - - /** - * A number of error messages show that something good is progressing - * and that we have to wait for readability. - * - * If none of them are present, bail out. - */ - - if (!(errno == EINPROGRESS || errno == EALREADY || -#ifdef EISCONN - errno == EISCONN || -#endif - errno == EAGAIN || errno == EINTR)) { - goto post_errno; - } - - fde = event_add_fd(ev, state, fd, EVENT_FD_READ | EVENT_FD_WRITE, - async_connect_connected, result); - if (fde == NULL) { - status = NT_STATUS_NO_MEMORY; - goto post_status; - } - return result; - - post_errno: - state->sys_errno = errno; - status = map_nt_error_from_unix(state->sys_errno); - post_status: - sys_fcntl_long(fd, F_SETFL, state->old_sockflags); - if (!async_post_status(result, ev, status)) { - goto fail; - } - return result; - fail: - TALLOC_FREE(result); - return NULL; -} - -/** - * fde event handler for connect(2) - * @param[in] ev The event context that sent us here - * @param[in] fde The file descriptor event associated with the connect - * @param[in] flags Indicate read/writeability of the socket - * @param[in] priv private data, "struct async_req *" in this case - */ - -static void async_connect_connected(struct event_context *ev, - struct fd_event *fde, uint16_t flags, - void *priv) -{ - struct async_req *req = talloc_get_type_abort( - priv, struct async_req); - struct async_connect_state *state = talloc_get_type_abort( - req->private_data, struct async_connect_state); - - TALLOC_FREE(fde); - - /* - * Stevens, Network Programming says that if there's a - * successful connect, the socket is only writable. Upon an - * error, it's both readable and writable. - */ - if ((flags & (EVENT_FD_READ|EVENT_FD_WRITE)) - == (EVENT_FD_READ|EVENT_FD_WRITE)) { - int sockerr; - socklen_t err_len = sizeof(sockerr); - - if (getsockopt(state->fd, SOL_SOCKET, SO_ERROR, - (void *)&sockerr, &err_len) == 0) { - errno = sockerr; - } - - state->sys_errno = errno; - - DEBUG(10, ("connect returned %s\n", strerror(errno))); - - sys_fcntl_long(state->fd, F_SETFL, state->old_sockflags); - async_req_error(req, map_nt_error_from_unix(state->sys_errno)); - return; - } - - state->sys_errno = 0; - async_req_done(req); -} - -NTSTATUS async_connect_recv(struct async_req *req, int *perrno) -{ - struct async_connect_state *state = talloc_get_type_abort( - req->private_data, struct async_connect_state); - NTSTATUS status; - - sys_fcntl_long(state->fd, F_SETFL, state->old_sockflags); - - *perrno = state->sys_errno; - - if (async_req_is_error(req, &status)) { - return status; - } - if (state->sys_errno == 0) { - return NT_STATUS_OK; - } - return map_nt_error_from_unix(state->sys_errno); -} diff --git a/source3/lib/ctdbd_conn.c b/source3/lib/ctdbd_conn.c index f8dae8fbd6..88d82caab8 100644 --- a/source3/lib/ctdbd_conn.c +++ b/source3/lib/ctdbd_conn.c @@ -1177,45 +1177,75 @@ NTSTATUS ctdbd_traverse(uint32 db_id, } /* + This is used to canonicalize a ctdb_sock_addr structure. +*/ +static void smbd_ctdb_canonicalize_ip(const struct sockaddr_storage *in, + struct sockaddr_storage *out) +{ + memcpy(out, in, sizeof (*out)); + +#ifdef HAVE_IPV6 + if (in->ss_family == AF_INET6) { + const char prefix[12] = { 0,0,0,0,0,0,0,0,0,0,0xff,0xff }; + const struct sockaddr_in6 *in6 = (struct sockaddr_in6 *)in; + struct sockaddr_in *out4 = (struct sockaddr_in *)out; + if (memcmp(&in6->sin6_addr, prefix, 12) == 0) { + memset(out, 0, sizeof(*out)); +#ifdef HAVE_SOCK_SIN_LEN + out4->sin_len = sizeof(*out); +#endif + out4->sin_family = AF_INET; + out4->sin_port = in6->sin6_port; + memcpy(&out4->sin_addr, &in6->sin6_addr.s6_addr32[3], 4); + } + } +#endif +} + +/* * Register us as a server for a particular tcp connection */ NTSTATUS ctdbd_register_ips(struct ctdbd_connection *conn, - const struct sockaddr_storage *server, - const struct sockaddr_storage *client, + const struct sockaddr_storage *_server, + const struct sockaddr_storage *_client, void (*release_ip_handler)(const char *ip_addr, void *private_data), void *private_data) { - struct sockaddr *sock = (struct sockaddr *)client; /* * we still use ctdb_control_tcp for ipv4 * because we want to work against older ctdb * versions at runtime */ struct ctdb_control_tcp p4; -#ifdef HAVE_IPV6 +#ifdef HAVE_STRUCT_CTDB_CONTROL_TCP_ADDR struct ctdb_control_tcp_addr p; #endif TDB_DATA data; NTSTATUS status; + struct sockaddr_storage client; + struct sockaddr_storage server; /* * Only one connection so far */ SMB_ASSERT(conn->release_ip_handler == NULL); - switch (sock->sa_family) { + smbd_ctdb_canonicalize_ip(_client, &client); + smbd_ctdb_canonicalize_ip(_server, &server); + + switch (client.ss_family) { case AF_INET: - p4.dest = *(struct sockaddr_in *)server; - p4.src = *(struct sockaddr_in *)client; + p4.dest = *(struct sockaddr_in *)&server; + p4.src = *(struct sockaddr_in *)&client; data.dptr = (uint8_t *)&p4; data.dsize = sizeof(p4); break; -#ifdef HAVE_IPV6 +#ifdef HAVE_STRUCT_CTDB_CONTROL_TCP_ADDR case AF_INET6: - p.dest.ip6 = *(struct sockaddr_in6 *)server; - p.src.ip6 = *(struct sockaddr_in6 *)client; + p.dest.ip6 = *(struct sockaddr_in6 *)&server; + p.src.ip6 = *(struct sockaddr_in6 *)&client; data.dptr = (uint8_t *)&p; data.dsize = sizeof(p); break; diff --git a/source3/lib/events.c b/source3/lib/events.c index 4484d5323b..44b4562757 100644 --- a/source3/lib/events.c +++ b/source3/lib/events.c @@ -83,45 +83,24 @@ bool event_add_to_select_args(struct tevent_context *ev, bool run_events(struct tevent_context *ev, int selrtn, fd_set *read_fds, fd_set *write_fds) { - bool fired = false; - struct tevent_fd *fde, *next; + struct tevent_fd *fde; + struct timeval now; if (ev->signal_events && tevent_common_check_signal(ev)) { return true; } - /* Run all events that are pending, not just one (as we - did previously. */ - - while (ev->timer_events) { - struct timeval now; - GetTimeOfDay(&now); - - if (timeval_compare( - &now, &ev->timer_events->next_event) < 0) { - /* Nothing to do yet */ - DEBUG(11, ("run_events: Nothing to do\n")); - break; - } - - DEBUG(10, ("Running event \"%s\" %p\n", - ev->timer_events->handler_name, - ev->timer_events)); + GetTimeOfDay(&now); - ev->timer_events->handler( - ev, - ev->timer_events, now, - ev->timer_events->private_data); + if ((ev->timer_events != NULL) + && (timeval_compare(&now, &ev->timer_events->next_event) >= 0)) { - fired = true; - } + DEBUG(10, ("Running timed event \"%s\" %p\n", + ev->timer_events->handler_name, ev->timer_events)); - if (fired) { - /* - * We might have changed the socket status during the timed - * events, return to run select again. - */ + ev->timer_events->handler(ev, ev->timer_events, now, + ev->timer_events->private_data); return true; } @@ -129,23 +108,22 @@ bool run_events(struct tevent_context *ev, /* * No fd ready */ - return fired; + return false; } - for (fde = ev->fd_events; fde; fde = next) { + for (fde = ev->fd_events; fde; fde = fde->next) { uint16 flags = 0; - next = fde->next; if (FD_ISSET(fde->fd, read_fds)) flags |= EVENT_FD_READ; if (FD_ISSET(fde->fd, write_fds)) flags |= EVENT_FD_WRITE; if (flags & fde->flags) { fde->handler(ev, fde, flags, fde->private_data); - fired = true; + return true; } } - return fired; + return false; } diff --git a/source3/lib/interface.c b/source3/lib/interface.c index 48fa4d32a9..b32ccb9c56 100644 --- a/source3/lib/interface.c +++ b/source3/lib/interface.c @@ -151,7 +151,8 @@ int iface_count_v4_nl(void) } /**************************************************************************** - Return a pointer to the in_addr of the first IPv4 interface. + Return a pointer to the in_addr of the first IPv4 interface that's + not 0.0.0.0. **************************************************************************/ const struct in_addr *first_ipv4_iface(void) @@ -159,7 +160,9 @@ const struct in_addr *first_ipv4_iface(void) struct interface *i; for (i=local_interfaces;i ;i=i->next) { - if (i->ip.ss_family == AF_INET) { + if ((i->ip.ss_family == AF_INET) && + (!is_zero_ip_v4(((struct sockaddr_in *)&i->ip)->sin_addr))) + { break; } } diff --git a/source3/lib/netapi/cm.c b/source3/lib/netapi/cm.c index d5ef09d831..233255fed4 100644 --- a/source3/lib/netapi/cm.c +++ b/source3/lib/netapi/cm.c @@ -184,7 +184,7 @@ WERROR libnetapi_open_pipe(struct libnetapi_ctx *ctx, status = pipe_cm_open(ctx, cli, interface, &result); if (!NT_STATUS_IS_OK(status)) { libnetapi_set_error_string(ctx, "failed to open PIPE %s: %s", - cli_get_pipe_name_from_iface(debug_ctx(), interface), + get_pipe_name_from_iface(interface), get_friendly_nt_error_msg(status)); return WERR_DEST_NOT_FOUND; } diff --git a/source3/lib/smbconf/testsuite.c b/source3/lib/smbconf/testsuite.c index 3d3c2d0ff0..b31dec0438 100644 --- a/source3/lib/smbconf/testsuite.c +++ b/source3/lib/smbconf/testsuite.c @@ -41,11 +41,11 @@ static bool test_get_includes(struct smbconf_ctx *ctx) char **includes = NULL; TALLOC_CTX *mem_ctx = talloc_stackframe(); - printf("test: get_includes\n"); + printf("TEST: get_includes\n"); werr = smbconf_get_global_includes(ctx, mem_ctx, &num_includes, &includes); if (!W_ERROR_IS_OK(werr)) { - printf("failure: get_includes - %s\n", win_errstr(werr)); + printf("FAIL: get_includes - %s\n", win_errstr(werr)); goto done; } @@ -53,7 +53,7 @@ static bool test_get_includes(struct smbconf_ctx *ctx) (num_includes > 0) ? ":" : "."); print_strings("", num_includes, (const char **)includes); - printf("success: get_includes\n"); + printf("OK: get_includes\n"); ret = true; done: @@ -75,11 +75,11 @@ static bool test_set_get_includes(struct smbconf_ctx *ctx) uint32_t get_num_includes = 0; TALLOC_CTX *mem_ctx = talloc_stackframe(); - printf("test: set_get_includes\n"); + printf("TEST: set_get_includes\n"); werr = smbconf_set_global_includes(ctx, set_num_includes, set_includes); if (!W_ERROR_IS_OK(werr)) { - printf("failure: get_set_includes (setting includes) - %s\n", + printf("FAIL: get_set_includes (setting includes) - %s\n", win_errstr(werr)); goto done; } @@ -87,13 +87,13 @@ static bool test_set_get_includes(struct smbconf_ctx *ctx) werr = smbconf_get_global_includes(ctx, mem_ctx, &get_num_includes, &get_includes); if (!W_ERROR_IS_OK(werr)) { - printf("failure: get_set_includes (getting includes) - %s\n", + printf("FAIL: get_set_includes (getting includes) - %s\n", win_errstr(werr)); goto done; } if (get_num_includes != set_num_includes) { - printf("failure: get_set_includes - set %d includes, got %d\n", + printf("FAIL: get_set_includes - set %d includes, got %d\n", set_num_includes, get_num_includes); goto done; } @@ -105,12 +105,12 @@ static bool test_set_get_includes(struct smbconf_ctx *ctx) printf("got: \n"); print_strings("* ", get_num_includes, (const char **)get_includes); - printf("failure: get_set_includes - data mismatch:\n"); + printf("FAIL: get_set_includes - data mismatch:\n"); goto done; } } - printf("success: set_includes\n"); + printf("OK: set_includes\n"); ret = true; done: @@ -130,18 +130,18 @@ static bool test_delete_includes(struct smbconf_ctx *ctx) uint32_t get_num_includes = 0; TALLOC_CTX *mem_ctx = talloc_stackframe(); - printf("test: delete_includes\n"); + printf("TEST: delete_includes\n"); werr = smbconf_set_global_includes(ctx, set_num_includes, set_includes); if (!W_ERROR_IS_OK(werr)) { - printf("failure: delete_includes (setting includes) - %s\n", + printf("FAIL: delete_includes (setting includes) - %s\n", win_errstr(werr)); goto done; } werr = smbconf_delete_global_includes(ctx); if (!W_ERROR_IS_OK(werr)) { - printf("failure: delete_includes (deleting includes) - %s\n", + printf("FAIL: delete_includes (deleting includes) - %s\n", win_errstr(werr)); goto done; } @@ -149,24 +149,24 @@ static bool test_delete_includes(struct smbconf_ctx *ctx) werr = smbconf_get_global_includes(ctx, mem_ctx, &get_num_includes, &get_includes); if (!W_ERROR_IS_OK(werr)) { - printf("failure: delete_includes (getting includes) - %s\n", + printf("FAIL: delete_includes (getting includes) - %s\n", win_errstr(werr)); goto done; } if (get_num_includes != 0) { - printf("failure: delete_includes (not empty after delete)\n"); + printf("FAIL: delete_includes (not empty after delete)\n"); goto done; } werr = smbconf_delete_global_includes(ctx); if (!W_ERROR_IS_OK(werr)) { - printf("failuer: delete_includes (delete empty includes) - " + printf("FAIL: delete_includes (delete empty includes) - " "%s\n", win_errstr(werr)); goto done; } - printf("success: delete_includes\n"); + printf("OK: delete_includes\n"); ret = true; done: @@ -177,7 +177,7 @@ static bool create_conf_file(const char *filename) { FILE *f; - printf("creating file\n"); + printf("TEST: creating file\n"); f = sys_fopen(filename, "w"); if (!f) { printf("failure: failed to open %s for writing: %s\n", @@ -192,7 +192,7 @@ static bool create_conf_file(const char *filename) fclose(f); - printf("success: create file\n"); + printf("OK: create file\n"); return true; } @@ -211,30 +211,29 @@ static bool torture_smbconf_txt(void) goto done; } - printf("test: init\n"); + printf("TEST: init\n"); werr = smbconf_init_txt(mem_ctx, &conf_ctx, filename); if (!W_ERROR_IS_OK(werr)) { - printf("failure: init failed: %s\n", win_errstr(werr)); + printf("FAIL: text backend\[ failed: %s\n", win_errstr(werr)); ret = false; goto done; } - printf("success: init\n"); + printf("OK: init\n"); ret &= test_get_includes(conf_ctx); smbconf_shutdown(conf_ctx); - printf("unlinking file\n"); + printf("TEST: unlink file\n"); if (unlink(filename) != 0) { - printf("failure: unlink failed: %s\n", strerror(errno)); + printf("OK: unlink failed: %s\n", strerror(errno)); ret = false; goto done; } - printf("success: unlink file\n"); - - printf("%s: text backend\n", ret ? "success" : "failure"); + printf("OK: unlink file\n"); done: + printf("%s: text backend\n", ret ? "success" : "failure"); talloc_free(mem_ctx); return ret; } @@ -248,14 +247,14 @@ static bool torture_smbconf_reg(void) printf("test: registry backend\n"); - printf("test: init\n"); + printf("TEST: init\n"); werr = smbconf_init_reg(mem_ctx, &conf_ctx, NULL); if (!W_ERROR_IS_OK(werr)) { - printf("failure: init failed: %s\n", win_errstr(werr)); + printf("FAIL: init failed: %s\n", win_errstr(werr)); ret = false; goto done; } - printf("success: init\n"); + printf("OK: init\n"); ret &= test_get_includes(conf_ctx); ret &= test_set_get_includes(conf_ctx); @@ -263,9 +262,8 @@ static bool torture_smbconf_reg(void) smbconf_shutdown(conf_ctx); - printf("%s: registry backend\n", ret ? "success" : "failure"); - done: + printf("%s: registry backend\n", ret ? "success" : "failure"); talloc_free(mem_ctx); return ret; } diff --git a/source3/lib/tdb_validate.c b/source3/lib/tdb_validate.c new file mode 100644 index 0000000000..1f5dfe4d25 --- /dev/null +++ b/source3/lib/tdb_validate.c @@ -0,0 +1,502 @@ +/* + * Unix SMB/CIFS implementation. + * + * A general tdb content validation mechanism + * + * Copyright (C) Michael Adam 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 "tdb_validate.h" +#include "includes.h" + +/* + * internal validation function, executed by the child. + */ +static int tdb_validate_child(struct tdb_context *tdb, + tdb_validate_data_func validate_fn) +{ + int ret = 1; + int num_entries = 0; + struct tdb_validation_status v_status; + + v_status.tdb_error = False; + v_status.bad_freelist = False; + v_status.bad_entry = False; + v_status.unknown_key = False; + v_status.success = True; + + if (!tdb) { + v_status.tdb_error = True; + v_status.success = False; + goto out; + } + + /* Check if the tdb's freelist is good. */ + if (tdb_validate_freelist(tdb, &num_entries) == -1) { + v_status.bad_freelist = True; + v_status.success = False; + goto out; + } + + DEBUG(10,("tdb_validate_child: tdb %s freelist has %d entries\n", + tdb_name(tdb), num_entries)); + + /* Now traverse the tdb to validate it. */ + num_entries = tdb_traverse(tdb, validate_fn, (void *)&v_status); + if (!v_status.success) { + goto out; + } else if (num_entries == -1) { + v_status.tdb_error = True; + v_status.success = False; + goto out; + } + + DEBUG(10,("tdb_validate_child: tdb %s is good with %d entries\n", + tdb_name(tdb), num_entries)); + ret = 0; /* Cache is good. */ + +out: + DEBUG(10, ("tdb_validate_child: summary of validation status:\n")); + DEBUGADD(10,(" * tdb error: %s\n", v_status.tdb_error ? "yes" : "no")); + DEBUGADD(10,(" * bad freelist: %s\n",v_status.bad_freelist?"yes":"no")); + DEBUGADD(10,(" * bad entry: %s\n", v_status.bad_entry ? "yes" : "no")); + DEBUGADD(10,(" * unknown key: %s\n", v_status.unknown_key?"yes":"no")); + DEBUGADD(10,(" => overall success: %s\n", v_status.success?"yes":"no")); + + return ret; +} + +/* + * tdb validation function. + * returns 0 if tdb is ok, != 0 if it isn't. + * this function expects an opened tdb. + */ +int tdb_validate(struct tdb_context *tdb, tdb_validate_data_func validate_fn) +{ + pid_t child_pid = -1; + int child_status = 0; + int wait_pid = 0; + int ret = 1; + + if (tdb == NULL) { + DEBUG(1, ("Error: tdb_validate called with tdb == NULL\n")); + return ret; + } + + DEBUG(5, ("tdb_validate called for tdb '%s'\n", tdb_name(tdb))); + + /* fork and let the child do the validation. + * benefit: no need to twist signal handlers and panic functions. + * just let the child panic. we catch the signal. */ + + DEBUG(10, ("tdb_validate: forking to let child do validation.\n")); + child_pid = sys_fork(); + if (child_pid == 0) { + /* child code */ + DEBUG(10, ("tdb_validate (validation child): created\n")); + DEBUG(10, ("tdb_validate (validation child): " + "calling tdb_validate_child\n")); + exit(tdb_validate_child(tdb, validate_fn)); + } + else if (child_pid < 0) { + DEBUG(1, ("tdb_validate: fork for validation failed.\n")); + goto done; + } + + /* parent */ + + DEBUG(10, ("tdb_validate: fork succeeded, child PID = %d\n",child_pid)); + + DEBUG(10, ("tdb_validate: waiting for child to finish...\n")); + while ((wait_pid = sys_waitpid(child_pid, &child_status, 0)) < 0) { + if (errno == EINTR) { + DEBUG(10, ("tdb_validate: got signal during waitpid, " + "retrying\n")); + errno = 0; + continue; + } + DEBUG(1, ("tdb_validate: waitpid failed with error '%s'.\n", + strerror(errno))); + goto done; + } + if (wait_pid != child_pid) { + DEBUG(1, ("tdb_validate: waitpid returned pid %d, " + "but %d was expected\n", wait_pid, child_pid)); + goto done; + } + + DEBUG(10, ("tdb_validate: validating child returned.\n")); + if (WIFEXITED(child_status)) { + DEBUG(10, ("tdb_validate: child exited, code %d.\n", + WEXITSTATUS(child_status))); + ret = WEXITSTATUS(child_status); + } + if (WIFSIGNALED(child_status)) { + DEBUG(10, ("tdb_validate: child terminated by signal %d\n", + WTERMSIG(child_status))); +#ifdef WCOREDUMP + if (WCOREDUMP(child_status)) { + DEBUGADD(10, ("core dumped\n")); + } +#endif + ret = WTERMSIG(child_status); + } + if (WIFSTOPPED(child_status)) { + DEBUG(10, ("tdb_validate: child was stopped by signal %d\n", + WSTOPSIG(child_status))); + ret = WSTOPSIG(child_status); + } + +done: + DEBUG(5, ("tdb_validate returning code '%d' for tdb '%s'\n", ret, + tdb_name(tdb))); + + return ret; +} + +/* + * tdb validation function. + * returns 0 if tdb is ok, != 0 if it isn't. + * this is a wrapper around the actual validation function that opens and closes + * the tdb. + */ +int tdb_validate_open(const char *tdb_path, tdb_validate_data_func validate_fn) +{ + TDB_CONTEXT *tdb = NULL; + int ret = 1; + + DEBUG(5, ("tdb_validate_open called for tdb '%s'\n", tdb_path)); + + tdb = tdb_open_log(tdb_path, 0, TDB_DEFAULT, O_RDONLY, 0); + if (!tdb) { + DEBUG(1, ("Error opening tdb %s\n", tdb_path)); + return ret; + } + + ret = tdb_validate(tdb, validate_fn); + tdb_close(tdb); + return ret; +} + +/* + * tdb backup function and helpers for tdb_validate wrapper with backup + * handling. + */ + +/* this structure eliminates the need for a global overall status for + * the traverse-copy */ +struct tdb_copy_data { + struct tdb_context *dst; + bool success; +}; + +static int traverse_copy_fn(struct tdb_context *tdb, TDB_DATA key, + TDB_DATA dbuf, void *private_data) +{ + struct tdb_copy_data *data = (struct tdb_copy_data *)private_data; + + if (tdb_store(data->dst, key, dbuf, TDB_INSERT) != 0) { + DEBUG(4, ("Failed to insert into %s: %s\n", tdb_name(data->dst), + strerror(errno))); + data->success = False; + return 1; + } + return 0; +} + +static int tdb_copy(struct tdb_context *src, struct tdb_context *dst) +{ + struct tdb_copy_data data; + int count; + + data.dst = dst; + data.success = True; + + count = tdb_traverse(src, traverse_copy_fn, (void *)(&data)); + if ((count < 0) || (data.success == False)) { + return -1; + } + return count; +} + +static int tdb_verify_basic(struct tdb_context *tdb) +{ + return tdb_traverse(tdb, NULL, NULL); +} + +/* this backup function is essentially taken from lib/tdb/tools/tdbbackup.tdb + */ +static int tdb_backup(TALLOC_CTX *ctx, const char *src_path, + const char *dst_path, int hash_size) +{ + struct tdb_context *src_tdb = NULL; + struct tdb_context *dst_tdb = NULL; + char *tmp_path = NULL; + struct stat st; + int count1, count2; + int saved_errno = 0; + int ret = -1; + + if (stat(src_path, &st) != 0) { + DEBUG(3, ("Could not stat '%s': %s\n", src_path, + strerror(errno))); + goto done; + } + + /* open old tdb RDWR - so we can lock it */ + src_tdb = tdb_open_log(src_path, 0, TDB_DEFAULT, O_RDWR, 0); + if (src_tdb == NULL) { + DEBUG(3, ("Failed to open tdb '%s'\n", src_path)); + goto done; + } + + if (tdb_lockall(src_tdb) != 0) { + DEBUG(3, ("Failed to lock tdb '%s'\n", src_path)); + goto done; + } + + tmp_path = talloc_asprintf(ctx, "%s%s", dst_path, ".tmp"); + unlink(tmp_path); + dst_tdb = tdb_open_log(tmp_path, + hash_size ? hash_size : tdb_hash_size(src_tdb), + TDB_DEFAULT, O_RDWR | O_CREAT | O_EXCL, + st.st_mode & 0777); + if (dst_tdb == NULL) { + DEBUG(3, ("Error creating tdb '%s': %s\n", tmp_path, + strerror(errno))); + saved_errno = errno; + unlink(tmp_path); + goto done; + } + + count1 = tdb_copy(src_tdb, dst_tdb); + if (count1 < 0) { + DEBUG(3, ("Failed to copy tdb '%s': %s\n", src_path, + strerror(errno))); + tdb_close(dst_tdb); + goto done; + } + + /* reopen ro and do basic verification */ + tdb_close(dst_tdb); + dst_tdb = tdb_open_log(tmp_path, 0, TDB_DEFAULT, O_RDONLY, 0); + if (!dst_tdb) { + DEBUG(3, ("Failed to reopen tdb '%s': %s\n", tmp_path, + strerror(errno))); + goto done; + } + count2 = tdb_verify_basic(dst_tdb); + if (count2 != count1) { + DEBUG(3, ("Failed to verify result of copying tdb '%s'.\n", + src_path)); + tdb_close(dst_tdb); + goto done; + } + + DEBUG(10, ("tdb_backup: successfully copied %d entries\n", count1)); + + /* make sure the new tdb has reached stable storage + * then rename it to its destination */ + fsync(tdb_fd(dst_tdb)); + tdb_close(dst_tdb); + unlink(dst_path); + if (rename(tmp_path, dst_path) != 0) { + DEBUG(3, ("Failed to rename '%s' to '%s': %s\n", + tmp_path, dst_path, strerror(errno))); + goto done; + } + + /* success */ + ret = 0; + +done: + if (src_tdb != NULL) { + tdb_close(src_tdb); + } + if (tmp_path != NULL) { + unlink(tmp_path); + TALLOC_FREE(tmp_path); + } + if (saved_errno != 0) { + errno = saved_errno; + } + return ret; +} + +static int rename_file_with_suffix(TALLOC_CTX *ctx, const char *path, + const char *suffix) +{ + int ret = -1; + char *dst_path; + + dst_path = talloc_asprintf(ctx, "%s%s", path, suffix); + + ret = (rename(path, dst_path) != 0); + + if (ret == 0) { + DEBUG(5, ("moved '%s' to '%s'\n", path, dst_path)); + } else if (errno == ENOENT) { + DEBUG(3, ("file '%s' does not exist - so not moved\n", path)); + ret = 0; + } else { + DEBUG(3, ("error renaming %s to %s: %s\n", path, dst_path, + strerror(errno))); + } + + TALLOC_FREE(dst_path); + return ret; +} + +/* + * do a backup of a tdb, moving the destination out of the way first + */ +static int tdb_backup_with_rotate(TALLOC_CTX *ctx, const char *src_path, + const char *dst_path, int hash_size, + const char *rotate_suffix, + bool retry_norotate_if_nospc, + bool rename_as_last_resort_if_nospc) +{ + int ret; + + rename_file_with_suffix(ctx, dst_path, rotate_suffix); + + ret = tdb_backup(ctx, src_path, dst_path, hash_size); + + if (ret != 0) { + DEBUG(10, ("backup of %s failed: %s\n", src_path, strerror(errno))); + } + if ((ret != 0) && (errno == ENOSPC) && retry_norotate_if_nospc) + { + char *rotate_path = talloc_asprintf(ctx, "%s%s", dst_path, + rotate_suffix); + DEBUG(10, ("backup of %s failed due to lack of space\n", + src_path)); + DEBUGADD(10, ("trying to free some space by removing rotated " + "dst %s\n", rotate_path)); + if (unlink(rotate_path) == -1) { + DEBUG(10, ("unlink of %s failed: %s\n", rotate_path, + strerror(errno))); + } else { + ret = tdb_backup(ctx, src_path, dst_path, hash_size); + } + TALLOC_FREE(rotate_path); + } + + if ((ret != 0) && (errno == ENOSPC) && rename_as_last_resort_if_nospc) + { + DEBUG(10, ("backup of %s failed due to lack of space\n", + src_path)); + DEBUGADD(10, ("using 'rename' as a last resort\n")); + ret = rename(src_path, dst_path); + } + + return ret; +} + +/* + * validation function with backup handling: + * + * - calls tdb_validate + * - if the tdb is ok, create a backup "name.bak", possibly moving + * existing backup to name.bak.old, + * return 0 (success) even if the backup fails + * - if the tdb is corrupt: + * - move the tdb to "name.corrupt" + * - check if there is valid backup. + * if so, restore the backup. + * if restore is successful, return 0 (success), + * - otherwise return -1 (failure) + */ +int tdb_validate_and_backup(const char *tdb_path, + tdb_validate_data_func validate_fn) +{ + int ret = -1; + const char *backup_suffix = ".bak"; + const char *corrupt_suffix = ".corrupt"; + const char *rotate_suffix = ".old"; + char *tdb_path_backup; + struct stat st; + TALLOC_CTX *ctx = NULL; + + ctx = talloc_new(NULL); + if (ctx == NULL) { + DEBUG(0, ("tdb_validate_and_backup: out of memory\n")); + goto done; + } + + tdb_path_backup = talloc_asprintf(ctx, "%s%s", tdb_path, backup_suffix); + + ret = tdb_validate_open(tdb_path, validate_fn); + + if (ret == 0) { + DEBUG(1, ("tdb '%s' is valid\n", tdb_path)); + ret = tdb_backup_with_rotate(ctx, tdb_path, tdb_path_backup, 0, + rotate_suffix, True, False); + if (ret != 0) { + DEBUG(1, ("Error creating backup of tdb '%s'\n", + tdb_path)); + /* the actual validation was successful: */ + ret = 0; + } else { + DEBUG(1, ("Created backup '%s' of tdb '%s'\n", + tdb_path_backup, tdb_path)); + } + } else { + DEBUG(1, ("tdb '%s' is invalid\n", tdb_path)); + + ret =stat(tdb_path_backup, &st); + if (ret != 0) { + DEBUG(5, ("Could not stat '%s': %s\n", tdb_path_backup, + strerror(errno))); + DEBUG(1, ("No backup found.\n")); + } else { + DEBUG(1, ("backup '%s' found.\n", tdb_path_backup)); + ret = tdb_validate_open(tdb_path_backup, validate_fn); + if (ret != 0) { + DEBUG(1, ("Backup '%s' is invalid.\n", + tdb_path_backup)); + } + } + + if (ret != 0) { + int renamed = rename_file_with_suffix(ctx, tdb_path, + corrupt_suffix); + if (renamed != 0) { + DEBUG(1, ("Error moving tdb to '%s%s'\n", + tdb_path, corrupt_suffix)); + } else { + DEBUG(1, ("Corrupt tdb stored as '%s%s'\n", + tdb_path, corrupt_suffix)); + } + goto done; + } + + DEBUG(1, ("valid backup '%s' found\n", tdb_path_backup)); + ret = tdb_backup_with_rotate(ctx, tdb_path_backup, tdb_path, 0, + corrupt_suffix, True, True); + if (ret != 0) { + DEBUG(1, ("Error restoring backup from '%s'\n", + tdb_path_backup)); + } else { + DEBUG(1, ("Restored tdb backup from '%s'\n", + tdb_path_backup)); + } + } + +done: + TALLOC_FREE(ctx); + return ret; +} diff --git a/source3/lib/tdb_validate.h b/source3/lib/tdb_validate.h new file mode 100644 index 0000000000..9eda79d7db --- /dev/null +++ b/source3/lib/tdb_validate.h @@ -0,0 +1,79 @@ +/* + * Unix SMB/CIFS implementation. + * + * A general tdb content validation mechanism + * + * Copyright (C) Michael Adam 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/>. + */ + +#ifndef __TDB_VALIDATE_H__ +#define __TDB_VALIDATE_H__ + +#include "lib/replace/replace.h" +#include "tdb.h" + +/** + * Flag field for keeping track of the status of a validation. + */ +struct tdb_validation_status { + bool tdb_error; + bool bad_freelist; + bool bad_entry; + bool unknown_key; + bool success; +}; + +/** + * Callback function type for the validation mechanism. + */ +typedef int (*tdb_validate_data_func)(TDB_CONTEXT *the_tdb, TDB_DATA kbuf, + TDB_DATA dbuf, void *state); + +/** + * tdb validation function. + * returns 0 if tdb is ok, != 0 if it isn't. + * this function expects an opened tdb. + */ +int tdb_validate(struct tdb_context *tdb, + tdb_validate_data_func validate_fn); + +/** + * tdb validation function. + * returns 0 if tdb is ok, != 0 if it isn't. + * This is a wrapper around the actual validation function that + * opens and closes the tdb. + */ +int tdb_validate_open(const char *tdb_path, + tdb_validate_data_func validate_fn); + +/** + * validation function with backup handling: + * + * - calls tdb_validate + * - if the tdb is ok, create a backup "name.bak", possibly moving + * existing backup to name.bak.old, + * return 0 (success) even if the backup fails + * - if the tdb is corrupt: + * - move the tdb to "name.corrupt" + * - check if there is valid backup. + * if so, restore the backup. + * if restore is successful, return 0 (success), + * - otherwise return -1 (failure) + */ +int tdb_validate_and_backup(const char *tdb_path, + tdb_validate_data_func validate_fn); + +#endif /* __TDB_VALIDATE_H__ */ diff --git a/source3/lib/time.c b/source3/lib/time.c index 7dd0da8fa8..e2cfe687b2 100644 --- a/source3/lib/time.c +++ b/source3/lib/time.c @@ -404,6 +404,16 @@ struct timespec get_atimespec(const SMB_STRUCT_STAT *pst) ret.tv_sec = pst->st_atime; ret.tv_nsec = pst->st_atimensec; return ret; +#elif defined(HAVE_STAT_ST_ATIME_N) + struct timespec ret; + ret.tv_sec = pst->st_atime; + ret.tv_nsec = pst->st_atime_n; + return ret; +#elif defined(HAVE_STAT_ST_UATIME) + struct timespec ret; + ret.tv_sec = pst->st_atime; + ret.tv_nsec = pst->st_uatime * 1000; + return ret; #elif defined(HAVE_STAT_ST_ATIMESPEC) return pst->st_atimespec; #else @@ -422,7 +432,13 @@ void set_atimespec(SMB_STRUCT_STAT *pst, struct timespec ts) pst->st_atim = ts; #elif defined(HAVE_STAT_ST_ATIMENSEC) pst->st_atime = ts.tv_sec; - pst->st_atimensec = ts.tv_nsec + pst->st_atimensec = ts.tv_nsec; +#elif defined(HAVE_STAT_ST_ATIME_N) + pst->st_atime = ts.tv_sec; + pst->st_atime_n = ts.tv_nsec; +#elif defined(HAVE_STAT_ST_UATIME) + pst->st_atime = ts.tv_sec; + pst->st_uatime = ts.tv_nsec / 1000; #elif defined(HAVE_STAT_ST_ATIMESPEC) pst->st_atimespec = ts; #else @@ -448,6 +464,16 @@ struct timespec get_mtimespec(const SMB_STRUCT_STAT *pst) ret.tv_sec = pst->st_mtime; ret.tv_nsec = pst->st_mtimensec; return ret; +#elif defined(HAVE_STAT_ST_MTIME_N) + struct timespec ret; + ret.tv_sec = pst->st_mtime; + ret.tv_nsec = pst->st_mtime_n; + return ret; +#elif defined(HAVE_STAT_ST_UMTIME) + struct timespec ret; + ret.tv_sec = pst->st_mtime; + ret.tv_nsec = pst->st_umtime * 1000; + return ret; #elif defined(HAVE_STAT_ST_MTIMESPEC) return pst->st_mtimespec; #else @@ -466,9 +492,15 @@ void set_mtimespec(SMB_STRUCT_STAT *pst, struct timespec ts) pst->st_mtim = ts; #elif defined(HAVE_STAT_ST_MTIMENSEC) pst->st_mtime = ts.tv_sec; - pst->st_mtimensec = ts.tv_nsec -#elif defined(HAVE_STAT_ST_ATIMESPEC) - pst->st_atimespec = ts; + pst->st_mtimensec = ts.tv_nsec; +#elif defined(HAVE_STAT_ST_MTIME_N) + pst->st_mtime = ts.tv_sec; + pst->st_mtime_n = ts.tv_nsec; +#elif defined(HAVE_STAT_ST_UMTIME) + pst->st_mtime = ts.tv_sec; + pst->st_umtime = ts.tv_nsec / 1000; +#elif defined(HAVE_STAT_ST_MTIMESPEC) + pst->st_mtimespec = ts; #else #error CONFIGURE_ERROR_IN_DETECTING_TIMESPEC_IN_STAT #endif @@ -492,6 +524,16 @@ struct timespec get_ctimespec(const SMB_STRUCT_STAT *pst) ret.tv_sec = pst->st_ctime; ret.tv_nsec = pst->st_ctimensec; return ret; +#elif defined(HAVE_STAT_ST_CTIME_N) + struct timespec ret; + ret.tv_sec = pst->st_ctime; + ret.tv_nsec = pst->st_ctime_n; + return ret; +#elif defined(HAVE_STAT_ST_UCTIME) + struct timespec ret; + ret.tv_sec = pst->st_ctime; + ret.tv_nsec = pst->st_uctime * 1000; + return ret; #elif defined(HAVE_STAT_ST_CTIMESPEC) return pst->st_ctimespec; #else @@ -510,7 +552,13 @@ void set_ctimespec(SMB_STRUCT_STAT *pst, struct timespec ts) pst->st_ctim = ts; #elif defined(HAVE_STAT_ST_CTIMENSEC) pst->st_ctime = ts.tv_sec; - pst->st_ctimensec = ts.tv_nsec + pst->st_ctimensec = ts.tv_nsec; +#elif defined(HAVE_STAT_ST_CTIME_N) + pst->st_ctime = ts.tv_sec; + pst->st_ctime_n = ts.tv_nsec; +#elif defined(HAVE_STAT_ST_UCTIME) + pst->st_ctime = ts.tv_sec; + pst->st_uctime = ts.tv_nsec / 1000; #elif defined(HAVE_STAT_ST_CTIMESPEC) pst->st_ctimespec = ts; #else diff --git a/source3/lib/util.c b/source3/lib/util.c index 2485d1def5..df01c0306f 100644 --- a/source3/lib/util.c +++ b/source3/lib/util.c @@ -57,9 +57,6 @@ extern unsigned int global_clobber_region_line; enum protocol_types Protocol = PROTOCOL_COREPLUS; -/* this is used by the chaining code */ -int chain_size = 0; - static enum remote_arch_types ra_type = RA_UNKNOWN; /*********************************************************************** @@ -542,6 +539,15 @@ bool directory_exist_stat(char *dname,SMB_STRUCT_STAT *st) } /******************************************************************* + Returns the size in bytes of the named given the stat struct. +********************************************************************/ + +uint64_t get_file_size_stat(const SMB_STRUCT_STAT *sbuf) +{ + return sbuf->st_size; +} + +/******************************************************************* Returns the size in bytes of the named file. ********************************************************************/ @@ -551,7 +557,7 @@ SMB_OFF_T get_file_size(char *file_name) buf.st_size = 0; if(sys_stat(file_name,&buf) != 0) return (SMB_OFF_T)-1; - return(buf.st_size); + return get_file_size_stat(&buf); } /******************************************************************* diff --git a/source3/lib/util_seaccess.c b/source3/lib/util_seaccess.c index fdc10f20ab..0da7442d19 100644 --- a/source3/lib/util_seaccess.c +++ b/source3/lib/util_seaccess.c @@ -149,7 +149,9 @@ static uint32_t access_check_max_allowed(const struct security_descriptor *sd, } /* - the main entry point for access checking. + The main entry point for access checking. If returning ACCESS_DENIED + this function returns the denied bits in the uint32_t pointed + to by the access_granted pointer. */ NTSTATUS se_access_check(const struct security_descriptor *sd, const NT_USER_TOKEN *token, @@ -238,6 +240,7 @@ NTSTATUS se_access_check(const struct security_descriptor *sd, done: if (bits_remaining != 0) { + *access_granted = bits_remaining; return NT_STATUS_ACCESS_DENIED; } diff --git a/source3/lib/util_sock.c b/source3/lib/util_sock.c index 3ddc4342a7..78431d93c8 100644 --- a/source3/lib/util_sock.c +++ b/source3/lib/util_sock.c @@ -1036,7 +1036,7 @@ struct async_req *open_socket_out_send(TALLOC_CTX *mem_ctx, return result; post_status: - if (!async_post_status(result, ev, status)) { + if (!async_post_ntstatus(result, ev, status)) { goto fail; } return result; @@ -1082,7 +1082,7 @@ static void open_socket_out_connected(struct async_req *subreq) } if (!async_req_set_timeout(subreq, state->ev, timeval_set(0, state->wait_nsec))) { - async_req_error(req, NT_STATUS_NO_MEMORY); + async_req_nterror(req, NT_STATUS_NO_MEMORY); return; } subreq->async.fn = open_socket_out_connected; @@ -1098,7 +1098,7 @@ static void open_socket_out_connected(struct async_req *subreq) #endif /* real error */ - async_req_error(req, map_nt_error_from_unix(sys_errno)); + async_req_nterror(req, map_nt_error_from_unix(sys_errno)); } NTSTATUS open_socket_out_recv(struct async_req *req, int *pfd) @@ -1107,7 +1107,7 @@ NTSTATUS open_socket_out_recv(struct async_req *req, int *pfd) req->private_data, struct open_socket_out_state); NTSTATUS status; - if (async_req_is_error(req, &status)) { + if (async_req_is_nterror(req, &status)) { return status; } *pfd = state->fd; @@ -1183,7 +1183,7 @@ struct async_req *open_socket_out_defer_send(TALLOC_CTX *mem_ctx, return result; post_status: - if (!async_post_status(result, ev, status)) { + if (!async_post_ntstatus(result, ev, status)) { goto fail; } return result; @@ -1198,12 +1198,12 @@ static void open_socket_out_defer_waited(struct async_req *subreq) subreq->async.priv, struct async_req); struct open_socket_out_defer_state *state = talloc_get_type_abort( req->private_data, struct open_socket_out_defer_state); - NTSTATUS status; + bool ret; - status = async_wait_recv(subreq); + ret = async_wait_recv(subreq); TALLOC_FREE(subreq); - if (!NT_STATUS_IS_OK(status)) { - async_req_error(req, status); + if (!ret) { + async_req_nterror(req, NT_STATUS_INTERNAL_ERROR); return; } @@ -1227,7 +1227,7 @@ static void open_socket_out_defer_connected(struct async_req *subreq) status = open_socket_out_recv(subreq, &state->fd); TALLOC_FREE(subreq); if (!NT_STATUS_IS_OK(status)) { - async_req_error(req, status); + async_req_nterror(req, status); return; } async_req_done(req); @@ -1239,7 +1239,7 @@ NTSTATUS open_socket_out_defer_recv(struct async_req *req, int *pfd) req->private_data, struct open_socket_out_defer_state); NTSTATUS status; - if (async_req_is_error(req, &status)) { + if (async_req_is_nterror(req, &status)) { return status; } *pfd = state->fd; diff --git a/source3/lib/util_tdb.c b/source3/lib/util_tdb.c index 2dbdd57947..78fa7cd0a1 100644 --- a/source3/lib/util_tdb.c +++ b/source3/lib/util_tdb.c @@ -630,487 +630,3 @@ NTSTATUS map_nt_error_from_tdb(enum TDB_ERROR err) return NT_STATUS_INTERNAL_ERROR; } - - -/********************************************************************* - * the following is a generic validation mechanism for tdbs. - *********************************************************************/ - -/* - * internal validation function, executed by the child. - */ -static int tdb_validate_child(struct tdb_context *tdb, - tdb_validate_data_func validate_fn) -{ - int ret = 1; - int num_entries = 0; - struct tdb_validation_status v_status; - - v_status.tdb_error = False; - v_status.bad_freelist = False; - v_status.bad_entry = False; - v_status.unknown_key = False; - v_status.success = True; - - if (!tdb) { - v_status.tdb_error = True; - v_status.success = False; - goto out; - } - - /* Check if the tdb's freelist is good. */ - if (tdb_validate_freelist(tdb, &num_entries) == -1) { - v_status.bad_freelist = True; - v_status.success = False; - goto out; - } - - DEBUG(10,("tdb_validate_child: tdb %s freelist has %d entries\n", - tdb_name(tdb), num_entries)); - - /* Now traverse the tdb to validate it. */ - num_entries = tdb_traverse(tdb, validate_fn, (void *)&v_status); - if (!v_status.success) { - goto out; - } else if (num_entries == -1) { - v_status.tdb_error = True; - v_status.success = False; - goto out; - } - - DEBUG(10,("tdb_validate_child: tdb %s is good with %d entries\n", - tdb_name(tdb), num_entries)); - ret = 0; /* Cache is good. */ - -out: - DEBUG(10, ("tdb_validate_child: summary of validation status:\n")); - DEBUGADD(10,(" * tdb error: %s\n", v_status.tdb_error ? "yes" : "no")); - DEBUGADD(10,(" * bad freelist: %s\n",v_status.bad_freelist?"yes":"no")); - DEBUGADD(10,(" * bad entry: %s\n", v_status.bad_entry ? "yes" : "no")); - DEBUGADD(10,(" * unknown key: %s\n", v_status.unknown_key?"yes":"no")); - DEBUGADD(10,(" => overall success: %s\n", v_status.success?"yes":"no")); - - return ret; -} - -/* - * tdb validation function. - * returns 0 if tdb is ok, != 0 if it isn't. - * this function expects an opened tdb. - */ -int tdb_validate(struct tdb_context *tdb, tdb_validate_data_func validate_fn) -{ - pid_t child_pid = -1; - int child_status = 0; - int wait_pid = 0; - int ret = 1; - - if (tdb == NULL) { - DEBUG(1, ("Error: tdb_validate called with tdb == NULL\n")); - return ret; - } - - DEBUG(5, ("tdb_validate called for tdb '%s'\n", tdb_name(tdb))); - - /* fork and let the child do the validation. - * benefit: no need to twist signal handlers and panic functions. - * just let the child panic. we catch the signal. */ - - DEBUG(10, ("tdb_validate: forking to let child do validation.\n")); - child_pid = sys_fork(); - if (child_pid == 0) { - /* child code */ - DEBUG(10, ("tdb_validate (validation child): created\n")); - DEBUG(10, ("tdb_validate (validation child): " - "calling tdb_validate_child\n")); - exit(tdb_validate_child(tdb, validate_fn)); - } - else if (child_pid < 0) { - DEBUG(1, ("tdb_validate: fork for validation failed.\n")); - goto done; - } - - /* parent */ - - DEBUG(10, ("tdb_validate: fork succeeded, child PID = %d\n",child_pid)); - - DEBUG(10, ("tdb_validate: waiting for child to finish...\n")); - while ((wait_pid = sys_waitpid(child_pid, &child_status, 0)) < 0) { - if (errno == EINTR) { - DEBUG(10, ("tdb_validate: got signal during waitpid, " - "retrying\n")); - errno = 0; - continue; - } - DEBUG(1, ("tdb_validate: waitpid failed with error '%s'.\n", - strerror(errno))); - goto done; - } - if (wait_pid != child_pid) { - DEBUG(1, ("tdb_validate: waitpid returned pid %d, " - "but %d was expected\n", wait_pid, child_pid)); - goto done; - } - - DEBUG(10, ("tdb_validate: validating child returned.\n")); - if (WIFEXITED(child_status)) { - DEBUG(10, ("tdb_validate: child exited, code %d.\n", - WEXITSTATUS(child_status))); - ret = WEXITSTATUS(child_status); - } - if (WIFSIGNALED(child_status)) { - DEBUG(10, ("tdb_validate: child terminated by signal %d\n", - WTERMSIG(child_status))); -#ifdef WCOREDUMP - if (WCOREDUMP(child_status)) { - DEBUGADD(10, ("core dumped\n")); - } -#endif - ret = WTERMSIG(child_status); - } - if (WIFSTOPPED(child_status)) { - DEBUG(10, ("tdb_validate: child was stopped by signal %d\n", - WSTOPSIG(child_status))); - ret = WSTOPSIG(child_status); - } - -done: - DEBUG(5, ("tdb_validate returning code '%d' for tdb '%s'\n", ret, - tdb_name(tdb))); - - return ret; -} - -/* - * tdb validation function. - * returns 0 if tdb is ok, != 0 if it isn't. - * this is a wrapper around the actual validation function that opens and closes - * the tdb. - */ -int tdb_validate_open(const char *tdb_path, tdb_validate_data_func validate_fn) -{ - TDB_CONTEXT *tdb = NULL; - int ret = 1; - - DEBUG(5, ("tdb_validate_open called for tdb '%s'\n", tdb_path)); - - tdb = tdb_open_log(tdb_path, 0, TDB_DEFAULT, O_RDONLY, 0); - if (!tdb) { - DEBUG(1, ("Error opening tdb %s\n", tdb_path)); - return ret; - } - - ret = tdb_validate(tdb, validate_fn); - tdb_close(tdb); - return ret; -} - -/* - * tdb backup function and helpers for tdb_validate wrapper with backup - * handling. - */ - -/* this structure eliminates the need for a global overall status for - * the traverse-copy */ -struct tdb_copy_data { - struct tdb_context *dst; - bool success; -}; - -static int traverse_copy_fn(struct tdb_context *tdb, TDB_DATA key, - TDB_DATA dbuf, void *private_data) -{ - struct tdb_copy_data *data = (struct tdb_copy_data *)private_data; - - if (tdb_store(data->dst, key, dbuf, TDB_INSERT) != 0) { - DEBUG(4, ("Failed to insert into %s: %s\n", tdb_name(data->dst), - strerror(errno))); - data->success = False; - return 1; - } - return 0; -} - -static int tdb_copy(struct tdb_context *src, struct tdb_context *dst) -{ - struct tdb_copy_data data; - int count; - - data.dst = dst; - data.success = True; - - count = tdb_traverse(src, traverse_copy_fn, (void *)(&data)); - if ((count < 0) || (data.success == False)) { - return -1; - } - return count; -} - -static int tdb_verify_basic(struct tdb_context *tdb) -{ - return tdb_traverse(tdb, NULL, NULL); -} - -/* this backup function is essentially taken from lib/tdb/tools/tdbbackup.tdb - */ -static int tdb_backup(TALLOC_CTX *ctx, const char *src_path, - const char *dst_path, int hash_size) -{ - struct tdb_context *src_tdb = NULL; - struct tdb_context *dst_tdb = NULL; - char *tmp_path = NULL; - struct stat st; - int count1, count2; - int saved_errno = 0; - int ret = -1; - - if (stat(src_path, &st) != 0) { - DEBUG(3, ("Could not stat '%s': %s\n", src_path, - strerror(errno))); - goto done; - } - - /* open old tdb RDWR - so we can lock it */ - src_tdb = tdb_open_log(src_path, 0, TDB_DEFAULT, O_RDWR, 0); - if (src_tdb == NULL) { - DEBUG(3, ("Failed to open tdb '%s'\n", src_path)); - goto done; - } - - if (tdb_lockall(src_tdb) != 0) { - DEBUG(3, ("Failed to lock tdb '%s'\n", src_path)); - goto done; - } - - tmp_path = talloc_asprintf(ctx, "%s%s", dst_path, ".tmp"); - unlink(tmp_path); - dst_tdb = tdb_open_log(tmp_path, - hash_size ? hash_size : tdb_hash_size(src_tdb), - TDB_DEFAULT, O_RDWR | O_CREAT | O_EXCL, - st.st_mode & 0777); - if (dst_tdb == NULL) { - DEBUG(3, ("Error creating tdb '%s': %s\n", tmp_path, - strerror(errno))); - saved_errno = errno; - unlink(tmp_path); - goto done; - } - - count1 = tdb_copy(src_tdb, dst_tdb); - if (count1 < 0) { - DEBUG(3, ("Failed to copy tdb '%s': %s\n", src_path, - strerror(errno))); - tdb_close(dst_tdb); - goto done; - } - - /* reopen ro and do basic verification */ - tdb_close(dst_tdb); - dst_tdb = tdb_open_log(tmp_path, 0, TDB_DEFAULT, O_RDONLY, 0); - if (!dst_tdb) { - DEBUG(3, ("Failed to reopen tdb '%s': %s\n", tmp_path, - strerror(errno))); - goto done; - } - count2 = tdb_verify_basic(dst_tdb); - if (count2 != count1) { - DEBUG(3, ("Failed to verify result of copying tdb '%s'.\n", - src_path)); - tdb_close(dst_tdb); - goto done; - } - - DEBUG(10, ("tdb_backup: successfully copied %d entries\n", count1)); - - /* make sure the new tdb has reached stable storage - * then rename it to its destination */ - fsync(tdb_fd(dst_tdb)); - tdb_close(dst_tdb); - unlink(dst_path); - if (rename(tmp_path, dst_path) != 0) { - DEBUG(3, ("Failed to rename '%s' to '%s': %s\n", - tmp_path, dst_path, strerror(errno))); - goto done; - } - - /* success */ - ret = 0; - -done: - if (src_tdb != NULL) { - tdb_close(src_tdb); - } - if (tmp_path != NULL) { - unlink(tmp_path); - TALLOC_FREE(tmp_path); - } - if (saved_errno != 0) { - errno = saved_errno; - } - return ret; -} - -static int rename_file_with_suffix(TALLOC_CTX *ctx, const char *path, - const char *suffix) -{ - int ret = -1; - char *dst_path; - - dst_path = talloc_asprintf(ctx, "%s%s", path, suffix); - - ret = (rename(path, dst_path) != 0); - - if (ret == 0) { - DEBUG(5, ("moved '%s' to '%s'\n", path, dst_path)); - } else if (errno == ENOENT) { - DEBUG(3, ("file '%s' does not exist - so not moved\n", path)); - ret = 0; - } else { - DEBUG(3, ("error renaming %s to %s: %s\n", path, dst_path, - strerror(errno))); - } - - TALLOC_FREE(dst_path); - return ret; -} - -/* - * do a backup of a tdb, moving the destination out of the way first - */ -static int tdb_backup_with_rotate(TALLOC_CTX *ctx, const char *src_path, - const char *dst_path, int hash_size, - const char *rotate_suffix, - bool retry_norotate_if_nospc, - bool rename_as_last_resort_if_nospc) -{ - int ret; - - rename_file_with_suffix(ctx, dst_path, rotate_suffix); - - ret = tdb_backup(ctx, src_path, dst_path, hash_size); - - if (ret != 0) { - DEBUG(10, ("backup of %s failed: %s\n", src_path, strerror(errno))); - } - if ((ret != 0) && (errno == ENOSPC) && retry_norotate_if_nospc) - { - char *rotate_path = talloc_asprintf(ctx, "%s%s", dst_path, - rotate_suffix); - DEBUG(10, ("backup of %s failed due to lack of space\n", - src_path)); - DEBUGADD(10, ("trying to free some space by removing rotated " - "dst %s\n", rotate_path)); - if (unlink(rotate_path) == -1) { - DEBUG(10, ("unlink of %s failed: %s\n", rotate_path, - strerror(errno))); - } else { - ret = tdb_backup(ctx, src_path, dst_path, hash_size); - } - TALLOC_FREE(rotate_path); - } - - if ((ret != 0) && (errno == ENOSPC) && rename_as_last_resort_if_nospc) - { - DEBUG(10, ("backup of %s failed due to lack of space\n", - src_path)); - DEBUGADD(10, ("using 'rename' as a last resort\n")); - ret = rename(src_path, dst_path); - } - - return ret; -} - -/* - * validation function with backup handling: - * - * - calls tdb_validate - * - if the tdb is ok, create a backup "name.bak", possibly moving - * existing backup to name.bak.old, - * return 0 (success) even if the backup fails - * - if the tdb is corrupt: - * - move the tdb to "name.corrupt" - * - check if there is valid backup. - * if so, restore the backup. - * if restore is successful, return 0 (success), - * - otherwise return -1 (failure) - */ -int tdb_validate_and_backup(const char *tdb_path, - tdb_validate_data_func validate_fn) -{ - int ret = -1; - const char *backup_suffix = ".bak"; - const char *corrupt_suffix = ".corrupt"; - const char *rotate_suffix = ".old"; - char *tdb_path_backup; - struct stat st; - TALLOC_CTX *ctx = NULL; - - ctx = talloc_new(NULL); - if (ctx == NULL) { - DEBUG(0, ("tdb_validate_and_backup: out of memory\n")); - goto done; - } - - tdb_path_backup = talloc_asprintf(ctx, "%s%s", tdb_path, backup_suffix); - - ret = tdb_validate_open(tdb_path, validate_fn); - - if (ret == 0) { - DEBUG(1, ("tdb '%s' is valid\n", tdb_path)); - ret = tdb_backup_with_rotate(ctx, tdb_path, tdb_path_backup, 0, - rotate_suffix, True, False); - if (ret != 0) { - DEBUG(1, ("Error creating backup of tdb '%s'\n", - tdb_path)); - /* the actual validation was successful: */ - ret = 0; - } else { - DEBUG(1, ("Created backup '%s' of tdb '%s'\n", - tdb_path_backup, tdb_path)); - } - } else { - DEBUG(1, ("tdb '%s' is invalid\n", tdb_path)); - - ret =stat(tdb_path_backup, &st); - if (ret != 0) { - DEBUG(5, ("Could not stat '%s': %s\n", tdb_path_backup, - strerror(errno))); - DEBUG(1, ("No backup found.\n")); - } else { - DEBUG(1, ("backup '%s' found.\n", tdb_path_backup)); - ret = tdb_validate_open(tdb_path_backup, validate_fn); - if (ret != 0) { - DEBUG(1, ("Backup '%s' is invalid.\n", - tdb_path_backup)); - } - } - - if (ret != 0) { - int renamed = rename_file_with_suffix(ctx, tdb_path, - corrupt_suffix); - if (renamed != 0) { - DEBUG(1, ("Error moving tdb to '%s%s'\n", - tdb_path, corrupt_suffix)); - } else { - DEBUG(1, ("Corrupt tdb stored as '%s%s'\n", - tdb_path, corrupt_suffix)); - } - goto done; - } - - DEBUG(1, ("valid backup '%s' found\n", tdb_path_backup)); - ret = tdb_backup_with_rotate(ctx, tdb_path_backup, tdb_path, 0, - corrupt_suffix, True, True); - if (ret != 0) { - DEBUG(1, ("Error restoring backup from '%s'\n", - tdb_path_backup)); - } else { - DEBUG(1, ("Restored tdb backup from '%s'\n", - tdb_path_backup)); - } - } - -done: - TALLOC_FREE(ctx); - return ret; -} diff --git a/source3/lib/wb_reqtrans.c b/source3/lib/wb_reqtrans.c index 0e6e5d15c4..b56c0fd4d3 100644 --- a/source3/lib/wb_reqtrans.c +++ b/source3/lib/wb_reqtrans.c @@ -27,7 +27,7 @@ struct req_read_state { struct winbindd_request *wb_req; - struct event_context *ev; + struct tevent_context *ev; size_t max_extra_data; int fd; }; @@ -37,7 +37,7 @@ static void wb_req_read_main(struct async_req *subreq); static void wb_req_read_extra(struct async_req *subreq); struct async_req *wb_req_read_send(TALLOC_CTX *mem_ctx, - struct event_context *ev, + struct tevent_context *ev, int fd, size_t max_extra_data) { struct async_req *result, *subreq; @@ -81,7 +81,7 @@ static void wb_req_read_len(struct async_req *subreq) status = recvall_recv(subreq); TALLOC_FREE(subreq); if (!NT_STATUS_IS_OK(status)) { - async_req_error(req, status); + async_req_nterror(req, status); return; } @@ -89,7 +89,7 @@ static void wb_req_read_len(struct async_req *subreq) DEBUG(0, ("wb_req_read_len: Invalid request size received: " "%d (expected %d)\n", (int)state->wb_req->length, (int)sizeof(struct winbindd_request))); - async_req_error(req, NT_STATUS_INVALID_BUFFER_SIZE); + async_req_nterror(req, NT_STATUS_INVALID_BUFFER_SIZE); return; } @@ -115,7 +115,7 @@ static void wb_req_read_main(struct async_req *subreq) status = recvall_recv(subreq); TALLOC_FREE(subreq); if (!NT_STATUS_IS_OK(status)) { - async_req_error(req, status); + async_req_nterror(req, status); return; } @@ -124,7 +124,7 @@ static void wb_req_read_main(struct async_req *subreq) DEBUG(3, ("Got request with %d bytes extra data on " "unprivileged socket\n", (int)state->wb_req->extra_len)); - async_req_error(req, NT_STATUS_INVALID_BUFFER_SIZE); + async_req_nterror(req, NT_STATUS_INVALID_BUFFER_SIZE); return; } @@ -161,7 +161,7 @@ static void wb_req_read_extra(struct async_req *subreq) status = recvall_recv(subreq); TALLOC_FREE(subreq); if (!NT_STATUS_IS_OK(status)) { - async_req_error(req, status); + async_req_nterror(req, status); return; } async_req_done(req); @@ -175,7 +175,7 @@ NTSTATUS wb_req_read_recv(struct async_req *req, TALLOC_CTX *mem_ctx, req->private_data, struct req_read_state); NTSTATUS status; - if (async_req_is_error(req, &status)) { + if (async_req_is_nterror(req, &status)) { return status; } *preq = talloc_move(mem_ctx, &state->wb_req); @@ -184,7 +184,7 @@ NTSTATUS wb_req_read_recv(struct async_req *req, TALLOC_CTX *mem_ctx, struct req_write_state { struct winbindd_request *wb_req; - struct event_context *ev; + struct tevent_context *ev; int fd; }; @@ -192,7 +192,7 @@ static void wb_req_write_main(struct async_req *subreq); static void wb_req_write_extra(struct async_req *subreq); struct async_req *wb_req_write_send(TALLOC_CTX *mem_ctx, - struct event_context *ev, int fd, + struct tevent_context *ev, int fd, struct winbindd_request *wb_req) { struct async_req *result, *subreq; @@ -232,7 +232,7 @@ static void wb_req_write_main(struct async_req *subreq) status = sendall_recv(subreq); TALLOC_FREE(subreq); if (!NT_STATUS_IS_OK(status)) { - async_req_error(req, status); + async_req_nterror(req, status); return; } @@ -261,7 +261,7 @@ static void wb_req_write_extra(struct async_req *subreq) status = sendall_recv(subreq); TALLOC_FREE(subreq); if (!NT_STATUS_IS_OK(status)) { - async_req_error(req, status); + async_req_nterror(req, status); return; } @@ -270,12 +270,12 @@ static void wb_req_write_extra(struct async_req *subreq) NTSTATUS wb_req_write_recv(struct async_req *req) { - return async_req_simple_recv(req); + return async_req_simple_recv_ntstatus(req); } struct resp_read_state { struct winbindd_response *wb_resp; - struct event_context *ev; + struct tevent_context *ev; size_t max_extra_data; int fd; }; @@ -285,7 +285,7 @@ static void wb_resp_read_main(struct async_req *subreq); static void wb_resp_read_extra(struct async_req *subreq); struct async_req *wb_resp_read_send(TALLOC_CTX *mem_ctx, - struct event_context *ev, int fd) + struct tevent_context *ev, int fd) { struct async_req *result, *subreq; struct resp_read_state *state; @@ -327,7 +327,7 @@ static void wb_resp_read_len(struct async_req *subreq) status = recvall_recv(subreq); TALLOC_FREE(subreq); if (!NT_STATUS_IS_OK(status)) { - async_req_error(req, status); + async_req_nterror(req, status); return; } @@ -336,7 +336,7 @@ static void wb_resp_read_len(struct async_req *subreq) "%d (expected at least%d)\n", (int)state->wb_resp->length, (int)sizeof(struct winbindd_response))); - async_req_error(req, NT_STATUS_INVALID_BUFFER_SIZE); + async_req_nterror(req, NT_STATUS_INVALID_BUFFER_SIZE); return; } @@ -363,7 +363,7 @@ static void wb_resp_read_main(struct async_req *subreq) status = recvall_recv(subreq); TALLOC_FREE(subreq); if (!NT_STATUS_IS_OK(status)) { - async_req_error(req, status); + async_req_nterror(req, status); return; } @@ -400,7 +400,7 @@ static void wb_resp_read_extra(struct async_req *subreq) status = recvall_recv(subreq); TALLOC_FREE(subreq); if (!NT_STATUS_IS_OK(status)) { - async_req_error(req, status); + async_req_nterror(req, status); return; } async_req_done(req); @@ -414,7 +414,7 @@ NTSTATUS wb_resp_read_recv(struct async_req *req, TALLOC_CTX *mem_ctx, req->private_data, struct resp_read_state); NTSTATUS status; - if (async_req_is_error(req, &status)) { + if (async_req_is_nterror(req, &status)) { return status; } *presp = talloc_move(mem_ctx, &state->wb_resp); @@ -423,7 +423,7 @@ NTSTATUS wb_resp_read_recv(struct async_req *req, TALLOC_CTX *mem_ctx, struct resp_write_state { struct winbindd_response *wb_resp; - struct event_context *ev; + struct tevent_context *ev; int fd; }; @@ -431,7 +431,7 @@ static void wb_resp_write_main(struct async_req *subreq); static void wb_resp_write_extra(struct async_req *subreq); struct async_req *wb_resp_write_send(TALLOC_CTX *mem_ctx, - struct event_context *ev, int fd, + struct tevent_context *ev, int fd, struct winbindd_response *wb_resp) { struct async_req *result, *subreq; @@ -471,7 +471,7 @@ static void wb_resp_write_main(struct async_req *subreq) status = sendall_recv(subreq); TALLOC_FREE(subreq); if (!NT_STATUS_IS_OK(status)) { - async_req_error(req, status); + async_req_nterror(req, status); return; } @@ -501,7 +501,7 @@ static void wb_resp_write_extra(struct async_req *subreq) status = sendall_recv(subreq); TALLOC_FREE(subreq); if (!NT_STATUS_IS_OK(status)) { - async_req_error(req, status); + async_req_nterror(req, status); return; } @@ -510,5 +510,5 @@ static void wb_resp_write_extra(struct async_req *subreq) NTSTATUS wb_resp_write_recv(struct async_req *req) { - return async_req_simple_recv(req); + return async_req_simple_recv_ntstatus(req); } diff --git a/source3/lib/wbclient.c b/source3/lib/wbclient.c index ea0bcb512e..ae9a034cc8 100644 --- a/source3/lib/wbclient.c +++ b/source3/lib/wbclient.c @@ -155,7 +155,7 @@ struct wb_context *wb_context_init(TALLOC_CTX *mem_ctx) } static struct async_req *wb_connect_send(TALLOC_CTX *mem_ctx, - struct event_context *ev, + struct tevent_context *ev, struct wb_context *wb_ctx, const char *dir) { @@ -232,7 +232,7 @@ static struct async_req *wb_connect_send(TALLOC_CTX *mem_ctx, if (req == NULL) { return NULL; } - if (async_post_status(req, ev, status)) { + if (async_post_ntstatus(req, ev, status)) { return req; } TALLOC_FREE(req); @@ -272,7 +272,7 @@ static struct winbindd_request *winbindd_request_copy( } struct wb_int_trans_state { - struct event_context *ev; + struct tevent_context *ev; int fd; struct winbindd_request *wb_req; struct winbindd_response *wb_resp; @@ -282,7 +282,7 @@ static void wb_int_trans_write_done(struct async_req *subreq); static void wb_int_trans_read_done(struct async_req *subreq); static struct async_req *wb_int_trans_send(TALLOC_CTX *mem_ctx, - struct event_context *ev, int fd, + struct tevent_context *ev, int fd, struct winbindd_request *wb_req) { struct async_req *result; @@ -295,8 +295,8 @@ static struct async_req *wb_int_trans_send(TALLOC_CTX *mem_ctx, } if (winbind_closed_fd(fd)) { - if (!async_post_status(result, ev, - NT_STATUS_PIPE_DISCONNECTED)) { + if (!async_post_ntstatus(result, ev, + NT_STATUS_PIPE_DISCONNECTED)) { goto fail; } return result; @@ -334,13 +334,13 @@ static void wb_int_trans_write_done(struct async_req *subreq) status = wb_req_write_recv(subreq); TALLOC_FREE(subreq); if (!NT_STATUS_IS_OK(status)) { - async_req_error(req, status); + async_req_nterror(req, status); return; } subreq = wb_resp_read_send(state, state->ev, state->fd); if (subreq == NULL) { - async_req_error(req, NT_STATUS_NO_MEMORY); + async_req_nterror(req, NT_STATUS_NO_MEMORY); } subreq->async.fn = wb_int_trans_read_done; subreq->async.priv = req; @@ -357,7 +357,7 @@ static void wb_int_trans_read_done(struct async_req *subreq) status = wb_resp_read_recv(subreq, state, &state->wb_resp); TALLOC_FREE(subreq); if (!NT_STATUS_IS_OK(status)) { - async_req_error(req, status); + async_req_nterror(req, status); return; } @@ -372,7 +372,7 @@ static NTSTATUS wb_int_trans_recv(struct async_req *req, req->private_data, struct wb_int_trans_state); NTSTATUS status; - if (async_req_is_error(req, &status)) { + if (async_req_is_nterror(req, &status)) { return status; } @@ -396,7 +396,7 @@ static const char *winbindd_socket_dir(void) struct wb_open_pipe_state { struct wb_context *wb_ctx; - struct event_context *ev; + struct tevent_context *ev; bool need_priv; struct winbindd_request wb_req; }; @@ -407,7 +407,7 @@ static void wb_open_pipe_getpriv_done(struct async_req *subreq); static void wb_open_pipe_connect_priv_done(struct async_req *subreq); static struct async_req *wb_open_pipe_send(TALLOC_CTX *mem_ctx, - struct event_context *ev, + struct tevent_context *ev, struct wb_context *wb_ctx, bool need_priv) { @@ -454,7 +454,7 @@ static void wb_open_pipe_connect_nonpriv_done(struct async_req *subreq) TALLOC_FREE(subreq); if (!NT_STATUS_IS_OK(status)) { state->wb_ctx->is_priv = true; - async_req_error(req, status); + async_req_nterror(req, status); return; } @@ -483,7 +483,7 @@ static void wb_open_pipe_ping_done(struct async_req *subreq) status = wb_int_trans_recv(subreq, state, &wb_resp); TALLOC_FREE(subreq); if (!NT_STATUS_IS_OK(status)) { - async_req_error(req, status); + async_req_nterror(req, status); return; } @@ -516,7 +516,7 @@ static void wb_open_pipe_getpriv_done(struct async_req *subreq) status = wb_int_trans_recv(subreq, state, &wb_resp); TALLOC_FREE(subreq); if (!NT_STATUS_IS_OK(status)) { - async_req_error(req, status); + async_req_nterror(req, status); return; } @@ -545,7 +545,7 @@ static void wb_open_pipe_connect_priv_done(struct async_req *subreq) status = wb_connect_recv(subreq); TALLOC_FREE(subreq); if (!NT_STATUS_IS_OK(status)) { - async_req_error(req, status); + async_req_nterror(req, status); return; } state->wb_ctx->is_priv = true; @@ -554,13 +554,13 @@ static void wb_open_pipe_connect_priv_done(struct async_req *subreq) static NTSTATUS wb_open_pipe_recv(struct async_req *req) { - return async_req_simple_recv(req); + return async_req_simple_recv_ntstatus(req); } struct wb_trans_state { struct wb_trans_state *prev, *next; struct wb_context *wb_ctx; - struct event_context *ev; + struct tevent_context *ev; struct winbindd_request *wb_req; struct winbindd_response *wb_resp; int num_retries; @@ -599,7 +599,7 @@ static void wb_trigger_trans(struct async_req *req) subreq->async.priv = req; } -struct async_req *wb_trans_send(TALLOC_CTX *mem_ctx, struct event_context *ev, +struct async_req *wb_trans_send(TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct wb_context *wb_ctx, bool need_priv, const struct winbindd_request *wb_req) { @@ -645,13 +645,13 @@ static bool wb_trans_retry(struct async_req *req, * Winbind not around or we can't connect to the pipe. Fail * immediately. */ - async_req_error(req, status); + async_req_nterror(req, status); return true; } state->num_retries -= 1; if (state->num_retries == 0) { - async_req_error(req, status); + async_req_nterror(req, status); return true; } @@ -680,12 +680,12 @@ static void wb_trans_retry_wait_done(struct async_req *subreq) subreq->async.priv, struct async_req); struct wb_trans_state *state = talloc_get_type_abort( req->private_data, struct wb_trans_state); - NTSTATUS status; + bool ret; - status = async_wait_recv(subreq); + ret = async_wait_recv(subreq); TALLOC_FREE(subreq); - if (!NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT)) { - async_req_error(req, status); + if (ret) { + async_req_nterror(req, NT_STATUS_INTERNAL_ERROR); return; } @@ -748,7 +748,7 @@ NTSTATUS wb_trans_recv(struct async_req *req, TALLOC_CTX *mem_ctx, req->private_data, struct wb_trans_state); NTSTATUS status; - if (async_req_is_error(req, &status)) { + if (async_req_is_nterror(req, &status)) { return status; } diff --git a/source3/libads/kerberos_verify.c b/source3/libads/kerberos_verify.c index de3fdeb9de..b903b2a6eb 100644 --- a/source3/libads/kerberos_verify.c +++ b/source3/libads/kerberos_verify.c @@ -31,6 +31,87 @@ const krb5_data *krb5_princ_component(krb5_context, krb5_principal, int ); #endif +static bool ads_dedicated_keytab_verify_ticket(krb5_context context, + krb5_auth_context auth_context, + const DATA_BLOB *ticket, + krb5_ticket **pp_tkt, + krb5_keyblock **keyblock, + krb5_error_code *perr) +{ + krb5_error_code ret = 0; + bool auth_ok = false; + krb5_keytab keytab = NULL; + krb5_keytab_entry kt_entry; + krb5_ticket *dec_ticket = NULL; + + krb5_data packet; + krb5_kvno kvno = 0; + krb5_enctype enctype; + + *pp_tkt = NULL; + *keyblock = NULL; + *perr = 0; + + ZERO_STRUCT(kt_entry); + + ret = smb_krb5_open_keytab(context, lp_dedicated_keytab_file(), true, + &keytab); + if (ret) { + DEBUG(1, ("smb_krb5_open_keytab failed (%s)\n", + error_message(ret))); + goto out; + } + + packet.length = ticket->length; + packet.data = (char *)ticket->data; + + ret = krb5_rd_req(context, &auth_context, &packet, NULL, keytab, + NULL, &dec_ticket); + if (ret) { + DEBUG(0, ("krb5_rd_req failed (%s)\n", error_message(ret))); + goto out; + } + +#ifdef HAVE_ETYPE_IN_ENCRYPTEDDATA /* Heimdal */ + enctype = dec_ticket->ticket.key.keytype; +#else /* MIT */ + enctype = dec_ticket->enc_part.enctype; + kvno = dec_ticket->enc_part.kvno; +#endif + + /* Get the key for checking the pac signature */ + ret = krb5_kt_get_entry(context, keytab, dec_ticket->server, + kvno, enctype, &kt_entry); + if (ret) { + DEBUG(0, ("krb5_kt_get_entry failed (%s)\n", + error_message(ret))); + goto out; + } + + ret = krb5_copy_keyblock(context, KRB5_KT_KEY(&kt_entry), keyblock); + smb_krb5_kt_free_entry(context, &kt_entry); + + if (ret) { + DEBUG(0, ("failed to copy key: %s\n", + error_message(ret))); + goto out; + } + + auth_ok = true; + *pp_tkt = dec_ticket; + dec_ticket = NULL; + + out: + if (dec_ticket) + krb5_free_ticket(context, dec_ticket); + + if (keytab) + krb5_kt_close(context, keytab); + + *perr = ret; + return auth_ok; +} + /********************************************************************************** Try to verify a ticket using the system keytab... the system keytab has kvno -1 entries, so it's more like what microsoft does... see comment in utils/net_ads.c in the @@ -437,22 +518,38 @@ NTSTATUS ads_verify_ticket(TALLOC_CTX *mem_ctx, } } - /* Try secrets.tdb first and fallback to the krb5.keytab if - necessary */ - - auth_ok = ads_secrets_verify_ticket(context, auth_context, host_princ, - ticket, &tkt, &keyblock, &ret); - - if (!auth_ok && - (ret == KRB5KRB_AP_ERR_TKT_NYV || - ret == KRB5KRB_AP_ERR_TKT_EXPIRED || - ret == KRB5KRB_AP_ERR_SKEW)) { - goto auth_failed; - } - - if (!auth_ok && lp_use_kerberos_keytab()) { - auth_ok = ads_keytab_verify_ticket(context, auth_context, - ticket, &tkt, &keyblock, &ret); + switch (lp_kerberos_method()) { + default: + case KERBEROS_VERIFY_SECRETS: + auth_ok = ads_secrets_verify_ticket(context, auth_context, + host_princ, ticket, &tkt, &keyblock, &ret); + break; + case KERBEROS_VERIFY_SYSTEM_KEYTAB: + auth_ok = ads_keytab_verify_ticket(context, auth_context, + ticket, &tkt, &keyblock, &ret); + break; + case KERBEROS_VERIFY_DEDICATED_KEYTAB: + auth_ok = ads_dedicated_keytab_verify_ticket(context, + auth_context, ticket, &tkt, &keyblock, &ret); + break; + case KERBEROS_VERIFY_SECRETS_AND_KEYTAB: + /* First try secrets.tdb and fallback to the krb5.keytab if + necessary. This is the pre 3.4 behavior when + "use kerberos keytab" was true.*/ + auth_ok = ads_secrets_verify_ticket(context, auth_context, + host_princ, ticket, &tkt, &keyblock, &ret); + + if (!auth_ok) { + /* Only fallback if we failed to decrypt the ticket */ + if (ret != KRB5KRB_AP_ERR_TKT_NYV && + ret != KRB5KRB_AP_ERR_TKT_EXPIRED && + ret != KRB5KRB_AP_ERR_SKEW) { + auth_ok = ads_keytab_verify_ticket(context, + auth_context, ticket, &tkt, &keyblock, + &ret); + } + } + break; } if ( use_replay_cache ) { @@ -465,7 +562,6 @@ NTSTATUS ads_verify_ticket(TALLOC_CTX *mem_ctx, #endif } - auth_failed: if (!auth_ok) { DEBUG(3,("ads_verify_ticket: krb5_rd_req with auth failed (%s)\n", error_message(ret))); diff --git a/source3/libads/ldap.c b/source3/libads/ldap.c index f6da54f35b..edbd69392c 100644 --- a/source3/libads/ldap.c +++ b/source3/libads/ldap.c @@ -672,9 +672,11 @@ got_connection: ldap_set_option(ads->ldap.ld, LDAP_OPT_PROTOCOL_VERSION, &version); - status = ADS_ERROR(smb_ldap_start_tls(ads->ldap.ld, version)); - if (!ADS_ERR_OK(status)) { - goto out; + if ( lp_ldap_ssl_ads() ) { + status = ADS_ERROR(smb_ldap_start_tls(ads->ldap.ld, version)); + if (!ADS_ERR_OK(status)) { + goto out; + } } /* fill in the current time and offsets */ diff --git a/source3/libnet/libnet_join.c b/source3/libnet/libnet_join.c index be6943bad9..20f7b97745 100644 --- a/source3/libnet/libnet_join.c +++ b/source3/libnet/libnet_join.c @@ -504,7 +504,7 @@ static ADS_STATUS libnet_join_set_os_attributes(TALLOC_CTX *mem_ctx, static bool libnet_join_create_keytab(TALLOC_CTX *mem_ctx, struct libnet_JoinCtx *r) { - if (!lp_use_kerberos_keytab()) { + if (!USE_SYSTEM_KEYTAB) { return true; } @@ -790,7 +790,8 @@ static NTSTATUS libnet_join_joindomain_rpc(TALLOC_CTX *mem_ctx, status = rpccli_samr_Connect2(pipe_hnd, mem_ctx, pipe_hnd->desthost, - SEC_RIGHTS_MAXIMUM_ALLOWED, + SAMR_ACCESS_ENUM_DOMAINS + | SAMR_ACCESS_OPEN_DOMAIN, &sam_pol); if (!NT_STATUS_IS_OK(status)) { goto done; @@ -798,7 +799,9 @@ static NTSTATUS libnet_join_joindomain_rpc(TALLOC_CTX *mem_ctx, status = rpccli_samr_OpenDomain(pipe_hnd, mem_ctx, &sam_pol, - SEC_RIGHTS_MAXIMUM_ALLOWED, + SAMR_DOMAIN_ACCESS_LOOKUP_INFO_1 + | SAMR_DOMAIN_ACCESS_CREATE_USER + | SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT, r->out.domain_sid, &domain_pol); if (!NT_STATUS_IS_OK(status)) { diff --git a/source3/libnet/libnet_samsync_ldif.c b/source3/libnet/libnet_samsync_ldif.c index 3068f8d3eb..dc3bc75541 100644 --- a/source3/libnet/libnet_samsync_ldif.c +++ b/source3/libnet/libnet_samsync_ldif.c @@ -345,100 +345,129 @@ static NTSTATUS map_populate_groups(TALLOC_CTX *mem_ctx, groupmap[0].sambaSID = talloc_asprintf(mem_ctx, "%s-512", sid); groupmap[0].group_dn = talloc_asprintf(mem_ctx, "cn=Domain Admins,ou=%s,%s", group_attr, suffix); - NT_STATUS_HAVE_NO_MEMORY(groupmap[0].sambaSID); - NT_STATUS_HAVE_NO_MEMORY(groupmap[0].group_dn); + if (groupmap[0].sambaSID == NULL || groupmap[0].group_dn == NULL) { + goto err; + } accountmap[0].rid = 512; accountmap[0].cn = talloc_strdup(mem_ctx, "Domain Admins"); - NT_STATUS_HAVE_NO_MEMORY(accountmap[0].cn); + if (accountmap[0].cn == NULL) { + goto err; + } groupmap[1].rid = 513; groupmap[1].gidNumber = 513; groupmap[1].sambaSID = talloc_asprintf(mem_ctx, "%s-513", sid); groupmap[1].group_dn = talloc_asprintf(mem_ctx, "cn=Domain Users,ou=%s,%s", group_attr, suffix); - NT_STATUS_HAVE_NO_MEMORY(groupmap[1].sambaSID); - NT_STATUS_HAVE_NO_MEMORY(groupmap[1].group_dn); + if (groupmap[1].sambaSID == NULL || groupmap[1].group_dn == NULL) { + goto err; + } accountmap[1].rid = 513; accountmap[1].cn = talloc_strdup(mem_ctx, "Domain Users"); - NT_STATUS_HAVE_NO_MEMORY(accountmap[1].cn); + if (accountmap[1].cn == NULL) { + goto err; + } groupmap[2].rid = 514; groupmap[2].gidNumber = 514; groupmap[2].sambaSID = talloc_asprintf(mem_ctx, "%s-514", sid); groupmap[2].group_dn = talloc_asprintf(mem_ctx, "cn=Domain Guests,ou=%s,%s", group_attr, suffix); - NT_STATUS_HAVE_NO_MEMORY(groupmap[2].sambaSID); - NT_STATUS_HAVE_NO_MEMORY(groupmap[2].group_dn); + if (groupmap[2].sambaSID == NULL || groupmap[2].group_dn == NULL) { + goto err; + } accountmap[2].rid = 514; accountmap[2].cn = talloc_strdup(mem_ctx, "Domain Guests"); - NT_STATUS_HAVE_NO_MEMORY(accountmap[2].cn); + if (accountmap[2].cn == NULL) { + goto err; + } groupmap[3].rid = 515; groupmap[3].gidNumber = 515; groupmap[3].sambaSID = talloc_asprintf(mem_ctx, "%s-515", sid); groupmap[3].group_dn = talloc_asprintf(mem_ctx, "cn=Domain Computers,ou=%s,%s", group_attr, suffix); - NT_STATUS_HAVE_NO_MEMORY(groupmap[3].sambaSID); - NT_STATUS_HAVE_NO_MEMORY(groupmap[3].group_dn); + if (groupmap[3].sambaSID == NULL || groupmap[3].group_dn == NULL) { + goto err; + } accountmap[3].rid = 515; accountmap[3].cn = talloc_strdup(mem_ctx, "Domain Computers"); - NT_STATUS_HAVE_NO_MEMORY(accountmap[3].cn); + if (accountmap[3].cn == NULL) { + goto err; + } groupmap[4].rid = 544; groupmap[4].gidNumber = 544; groupmap[4].sambaSID = talloc_asprintf(mem_ctx, "%s-544", builtin_sid); groupmap[4].group_dn = talloc_asprintf(mem_ctx, "cn=Administrators,ou=%s,%s", group_attr, suffix); - NT_STATUS_HAVE_NO_MEMORY(groupmap[4].sambaSID); - NT_STATUS_HAVE_NO_MEMORY(groupmap[4].group_dn); + if (groupmap[4].sambaSID == NULL || groupmap[4].group_dn == NULL) { + goto err; + } accountmap[4].rid = 515; accountmap[4].cn = talloc_strdup(mem_ctx, "Administrators"); - NT_STATUS_HAVE_NO_MEMORY(accountmap[4].cn); + if (accountmap[4].cn == NULL) { + goto err; + } groupmap[5].rid = 550; groupmap[5].gidNumber = 550; groupmap[5].sambaSID = talloc_asprintf(mem_ctx, "%s-550", builtin_sid); groupmap[5].group_dn = talloc_asprintf(mem_ctx, "cn=Print Operators,ou=%s,%s", group_attr, suffix); - NT_STATUS_HAVE_NO_MEMORY(groupmap[5].sambaSID); - NT_STATUS_HAVE_NO_MEMORY(groupmap[5].group_dn); + if (groupmap[5].sambaSID == NULL || groupmap[5].group_dn == NULL) { + goto err; + } accountmap[5].rid = 550; accountmap[5].cn = talloc_strdup(mem_ctx, "Print Operators"); - NT_STATUS_HAVE_NO_MEMORY(accountmap[5].cn); + if (accountmap[5].cn == NULL) { + goto err; + } groupmap[6].rid = 551; groupmap[6].gidNumber = 551; groupmap[6].sambaSID = talloc_asprintf(mem_ctx, "%s-551", builtin_sid); groupmap[6].group_dn = talloc_asprintf(mem_ctx, "cn=Backup Operators,ou=%s,%s", group_attr, suffix); - NT_STATUS_HAVE_NO_MEMORY(groupmap[6].sambaSID); - NT_STATUS_HAVE_NO_MEMORY(groupmap[6].group_dn); + if (groupmap[6].sambaSID == NULL || groupmap[6].group_dn == NULL) { + goto err; + } accountmap[6].rid = 551; accountmap[6].cn = talloc_strdup(mem_ctx, "Backup Operators"); - NT_STATUS_HAVE_NO_MEMORY(accountmap[6].cn); + if (accountmap[6].cn == NULL) { + goto err; + } groupmap[7].rid = 552; groupmap[7].gidNumber = 552; groupmap[7].sambaSID = talloc_asprintf(mem_ctx, "%s-552", builtin_sid); groupmap[7].group_dn = talloc_asprintf(mem_ctx, "cn=Replicators,ou=%s,%s", group_attr, suffix); - NT_STATUS_HAVE_NO_MEMORY(groupmap[7].sambaSID); - NT_STATUS_HAVE_NO_MEMORY(groupmap[7].group_dn); + if (groupmap[7].sambaSID == NULL || groupmap[7].group_dn == NULL) { + goto err; + } accountmap[7].rid = 551; accountmap[7].cn = talloc_strdup(mem_ctx, "Replicators"); - NT_STATUS_HAVE_NO_MEMORY(accountmap[7].cn); + if (accountmap[7].cn == NULL) { + goto err; + } SAFE_FREE(group_attr); return NT_STATUS_OK; + + err: + + SAFE_FREE(group_attr); + return NT_STATUS_NO_MEMORY; } /* @@ -542,8 +571,10 @@ static NTSTATUS fetch_group_info_to_ldif(TALLOC_CTX *mem_ctx, groupmap->sambaSID = talloc_asprintf(mem_ctx, "%s-%d", sid, g_rid); groupmap->group_dn = talloc_asprintf(mem_ctx, "cn=%s,ou=%s,%s", groupname, group_attr, suffix); - NT_STATUS_HAVE_NO_MEMORY(groupmap->sambaSID); - NT_STATUS_HAVE_NO_MEMORY(groupmap->group_dn); + if (groupmap->sambaSID == NULL || groupmap->group_dn == NULL) { + SAFE_FREE(group_attr); + return NT_STATUS_NO_MEMORY; + } /* Write the data to the temporary add ldif file */ fprintf(add_fd, "# %s, %s, %s\n", groupname, group_attr, @@ -776,7 +807,10 @@ static NTSTATUS fetch_alias_info_to_ldif(TALLOC_CTX *mem_ctx, g_rid = r->rid; groupmap->gidNumber = ldif_gid; groupmap->sambaSID = talloc_asprintf(mem_ctx, "%s-%d", sid, g_rid); - NT_STATUS_HAVE_NO_MEMORY(groupmap->sambaSID); + if (groupmap->sambaSID == NULL) { + SAFE_FREE(group_attr); + return NT_STATUS_NO_MEMORY; + } /* Write the data to the temporary add ldif file */ fprintf(add_fd, "# %s, %s, %s\n", aliasname, group_attr, diff --git a/source3/librpc/ndr/ndr_string.c b/source3/librpc/ndr/ndr_string.c index 86d7b26586..985d0f4daa 100644 --- a/source3/librpc/ndr/ndr_string.c +++ b/source3/librpc/ndr/ndr_string.c @@ -595,6 +595,29 @@ _PUBLIC_ void ndr_print_string_array(struct ndr_print *ndr, const char *name, co ndr->depth--; } +_PUBLIC_ size_t ndr_size_string_array(const char **a, uint32_t count, int flags) +{ + uint32_t i; + size_t size = 0; + + switch (flags & LIBNDR_STRING_FLAGS) { + case LIBNDR_FLAG_STR_NULLTERM: + for (i = 0; i < count; i++) { + size += strlen_m_term(a[i]); + } + break; + case LIBNDR_FLAG_STR_NOTERM: + for (i = 0; i < count; i++) { + size += strlen_m(a[i]); + } + break; + default: + return 0; + } + + return size; +} + /** * Return number of elements in a string including the last (zeroed) element */ diff --git a/source3/libsmb/async_smb.c b/source3/libsmb/async_smb.c index a1fcf8eb07..e579d1c9f0 100644 --- a/source3/libsmb/async_smb.c +++ b/source3/libsmb/async_smb.c @@ -152,32 +152,6 @@ bool cli_in_chain(struct cli_state *cli) } /** - * Is the SMB command able to hold an AND_X successor - * @param[in] cmd The SMB command in question - * @retval Can we add a chained request after "cmd"? - */ - -static bool is_andx_req(uint8_t cmd) -{ - switch (cmd) { - case SMBtconX: - case SMBlockingX: - case SMBopenX: - case SMBreadX: - case SMBwriteX: - case SMBsesssetupX: - case SMBulogoffX: - case SMBntcreateX: - return true; - break; - default: - break; - } - - return false; -} - -/** * @brief Find the smb_cmd offset of the last command pushed * @param[in] buf The buffer we're building up * @retval Where can we put our next andx cmd? @@ -1005,7 +979,7 @@ static void handle_incoming_pdu(struct cli_state *cli) nt_errstr(status))); for (req = cli->outstanding_requests; req; req = req->next) { - async_req_error(req->async[0], status); + async_req_nterror(req->async[0], status); } return; } @@ -1022,7 +996,7 @@ static void cli_state_handler(struct event_context *event_ctx, struct fd_event *event, uint16 flags, void *p) { struct cli_state *cli = (struct cli_state *)p; - struct cli_request *req; + struct cli_request *req, *next; NTSTATUS status; DEBUG(11, ("cli_state_handler called with flags %d\n", flags)); @@ -1128,10 +1102,15 @@ static void cli_state_handler(struct event_context *event_ctx, return; sock_error: - for (req = cli->outstanding_requests; req; req = req->next) { - int i; - for (i=0; i<req->num_async; i++) { - async_req_error(req->async[i], status); + + for (req = cli->outstanding_requests; req; req = next) { + int i, num_async; + + next = req->next; + num_async = req->num_async; + + for (i=0; i<num_async; i++) { + async_req_nterror(req->async[i], status); } } TALLOC_FREE(cli->fd_event); diff --git a/source3/libsmb/cliconnect.c b/source3/libsmb/cliconnect.c index bc690f2e02..a39e035d2a 100644 --- a/source3/libsmb/cliconnect.c +++ b/source3/libsmb/cliconnect.c @@ -161,50 +161,79 @@ static uint32 cli_session_setup_capabilities(struct cli_state *cli) Do a NT1 guest session setup. ****************************************************************************/ -static NTSTATUS cli_session_setup_guest(struct cli_state *cli) +struct async_req *cli_session_setup_guest_send(TALLOC_CTX *mem_ctx, + struct event_context *ev, + struct cli_state *cli) { - char *p; - uint32 capabilities = cli_session_setup_capabilities(cli); + struct async_req *result; + uint16_t vwv[13]; + uint8_t *bytes; - memset(cli->outbuf, '\0', smb_size); - cli_set_message(cli->outbuf,13,0,True); - SCVAL(cli->outbuf,smb_com,SMBsesssetupX); - cli_setup_packet(cli); - - SCVAL(cli->outbuf,smb_vwv0,0xFF); - SSVAL(cli->outbuf,smb_vwv2,CLI_BUFFER_SIZE); - SSVAL(cli->outbuf,smb_vwv3,2); - SSVAL(cli->outbuf,smb_vwv4,cli->pid); - SIVAL(cli->outbuf,smb_vwv5,cli->sesskey); - SSVAL(cli->outbuf,smb_vwv7,0); - SSVAL(cli->outbuf,smb_vwv8,0); - SIVAL(cli->outbuf,smb_vwv11,capabilities); - p = smb_buf(cli->outbuf); - p += clistr_push(cli, p, "", -1, STR_TERMINATE); /* username */ - p += clistr_push(cli, p, "", -1, STR_TERMINATE); /* workgroup */ - p += clistr_push(cli, p, "Unix", -1, STR_TERMINATE); - p += clistr_push(cli, p, "Samba", -1, STR_TERMINATE); - cli_setup_bcc(cli, p); + SCVAL(vwv+0, 0, 0xFF); + SCVAL(vwv+0, 1, 0); + SSVAL(vwv+1, 0, 0); + SSVAL(vwv+2, 0, CLI_BUFFER_SIZE); + SSVAL(vwv+3, 0, 2); + SSVAL(vwv+4, 0, cli->pid); + SIVAL(vwv+5, 0, cli->sesskey); + SSVAL(vwv+7, 0, 0); + SSVAL(vwv+8, 0, 0); + SSVAL(vwv+9, 0, 0); + SSVAL(vwv+10, 0, 0); + SIVAL(vwv+11, 0, cli_session_setup_capabilities(cli)); + + bytes = talloc_array(talloc_tos(), uint8_t, 0); + + bytes = smb_bytes_push_str(bytes, cli_ucs2(cli), "", 1, /* username */ + NULL); + bytes = smb_bytes_push_str(bytes, cli_ucs2(cli), "", 1, /* workgroup */ + NULL); + bytes = smb_bytes_push_str(bytes, cli_ucs2(cli), "Unix", + strlen("Unix")+1, NULL); + bytes = smb_bytes_push_str(bytes, cli_ucs2(cli), "Samba", + strlen("Samba")+1, NULL); + + if (bytes == NULL) { + return NULL; + } + + result = cli_request_send(mem_ctx, ev, cli, SMBsesssetupX, 0, + 13, vwv, 0, talloc_get_size(bytes), bytes); + TALLOC_FREE(bytes); + return result; +} - if (!cli_send_smb(cli) || !cli_receive_smb(cli)) { - return cli_nt_error(cli); +NTSTATUS cli_session_setup_guest_recv(struct async_req *req) +{ + struct cli_request *cli_req = talloc_get_type_abort( + req->private_data, struct cli_request); + struct cli_state *cli = cli_req->cli; + uint8_t wct; + uint16_t *vwv; + uint16_t num_bytes; + uint8_t *bytes; + uint8_t *p; + NTSTATUS status; + + if (async_req_is_nterror(req, &status)) { + return status; } - - show_msg(cli->inbuf); - - if (cli_is_error(cli)) { - return cli_nt_error(cli); + + status = cli_pull_reply(req, &wct, &vwv, &num_bytes, &bytes); + if (!NT_STATUS_IS_OK(status)) { + return status; } - cli->vuid = SVAL(cli->inbuf,smb_uid); + p = bytes; - p = smb_buf(cli->inbuf); - p += clistr_pull(cli->inbuf, cli->server_os, p, sizeof(fstring), - -1, STR_TERMINATE); - p += clistr_pull(cli->inbuf, cli->server_type, p, sizeof(fstring), - -1, STR_TERMINATE); - p += clistr_pull(cli->inbuf, cli->server_domain, p, sizeof(fstring), - -1, STR_TERMINATE); + cli->vuid = SVAL(cli_req->inbuf, smb_uid); + + p += clistr_pull(cli_req->inbuf, cli->server_os, (char *)p, + sizeof(fstring), bytes+num_bytes-p, STR_TERMINATE); + p += clistr_pull(cli_req->inbuf, cli->server_type, (char *)p, + sizeof(fstring), bytes+num_bytes-p, STR_TERMINATE); + p += clistr_pull(cli_req->inbuf, cli->server_domain, (char *)p, + sizeof(fstring), bytes+num_bytes-p, STR_TERMINATE); if (strstr(cli->server_type, "Samba")) { cli->is_samba = True; @@ -215,6 +244,43 @@ static NTSTATUS cli_session_setup_guest(struct cli_state *cli) return NT_STATUS_OK; } +static NTSTATUS cli_session_setup_guest(struct cli_state *cli) +{ + TALLOC_CTX *frame = talloc_stackframe(); + struct event_context *ev; + struct async_req *req; + NTSTATUS status; + + if (cli->fd_event != NULL) { + /* + * Can't use sync call while an async call is in flight + */ + status = NT_STATUS_INVALID_PARAMETER; + goto fail; + } + + ev = event_context_init(frame); + if (ev == NULL) { + status = NT_STATUS_NO_MEMORY; + goto fail; + } + + req = cli_session_setup_guest_send(frame, ev, cli); + if (req == NULL) { + status = NT_STATUS_NO_MEMORY; + goto fail; + } + + while (req->state < ASYNC_REQ_DONE) { + event_loop_once(ev); + } + + status = cli_session_setup_guest_recv(req); + fail: + TALLOC_FREE(frame); + return status; +} + /**************************************************************************** Do a NT1 plaintext session setup. ****************************************************************************/ @@ -1107,13 +1173,17 @@ bool cli_ulogoff(struct cli_state *cli) Send a tconX. ****************************************************************************/ -bool cli_send_tconX(struct cli_state *cli, - const char *share, const char *dev, const char *pass, int passlen) +struct async_req *cli_tcon_andx_send(TALLOC_CTX *mem_ctx, + struct event_context *ev, + struct cli_state *cli, + const char *share, const char *dev, + const char *pass, int passlen) { - fstring fullshare, pword; - char *p; - memset(cli->outbuf,'\0',smb_size); - memset(cli->inbuf,'\0',smb_size); + fstring pword; + char *tmp = NULL; + struct async_req *result; + uint16_t vwv[4]; + uint8_t *bytes; fstrcpy(cli->share, share); @@ -1121,9 +1191,10 @@ bool cli_send_tconX(struct cli_state *cli, if (cli->sec_mode & NEGOTIATE_SECURITY_USER_LEVEL) { passlen = 1; pass = ""; - } else if (!pass) { - DEBUG(1, ("Server not using user level security and no password supplied.\n")); - return False; + } else if (pass == NULL) { + DEBUG(1, ("Server not using user level security and no " + "password supplied.\n")); + goto access_denied; } if ((cli->sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) && @@ -1132,28 +1203,36 @@ bool cli_send_tconX(struct cli_state *cli, DEBUG(1, ("Server requested LANMAN password " "(share-level security) but " "'client lanman auth' is disabled\n")); - return False; + goto access_denied; } /* - * Non-encrypted passwords - convert to DOS codepage before encryption. + * Non-encrypted passwords - convert to DOS codepage before + * encryption. */ passlen = 24; - SMBencrypt(pass,cli->secblob.data,(uchar *)pword); + SMBencrypt(pass, cli->secblob.data, (uchar *)pword); } else { - if((cli->sec_mode & (NEGOTIATE_SECURITY_USER_LEVEL|NEGOTIATE_SECURITY_CHALLENGE_RESPONSE)) == 0) { + if((cli->sec_mode & (NEGOTIATE_SECURITY_USER_LEVEL + |NEGOTIATE_SECURITY_CHALLENGE_RESPONSE)) + == 0) { if (!lp_client_plaintext_auth() && (*pass)) { DEBUG(1, ("Server requested plaintext " "password but 'client plaintext " "auth' is disabled\n")); - return False; + goto access_denied; } /* - * Non-encrypted passwords - convert to DOS codepage before using. + * Non-encrypted passwords - convert to DOS codepage + * before using. */ - passlen = clistr_push(cli, pword, pass, sizeof(pword), STR_TERMINATE); - + passlen = clistr_push(cli, pword, pass, sizeof(pword), + STR_TERMINATE); + if (passlen == -1) { + DEBUG(1, ("clistr_push(pword) failed\n")); + goto access_denied; + } } else { if (passlen) { memcpy(pword, pass, passlen); @@ -1161,52 +1240,139 @@ bool cli_send_tconX(struct cli_state *cli, } } - slprintf(fullshare, sizeof(fullshare)-1, - "\\\\%s\\%s", cli->desthost, share); + SCVAL(vwv+0, 0, 0xFF); + SCVAL(vwv+0, 1, 0); + SSVAL(vwv+1, 0, 0); + SSVAL(vwv+2, 0, TCONX_FLAG_EXTENDED_RESPONSE); + SSVAL(vwv+3, 0, passlen); - cli_set_message(cli->outbuf,4, 0, True); - SCVAL(cli->outbuf,smb_com,SMBtconX); - cli_setup_packet(cli); + if (passlen) { + bytes = (uint8_t *)talloc_memdup(talloc_tos(), pword, passlen); + } else { + bytes = talloc_array(talloc_tos(), uint8_t, 0); + } - SSVAL(cli->outbuf,smb_vwv0,0xFF); - SSVAL(cli->outbuf,smb_vwv2,TCONX_FLAG_EXTENDED_RESPONSE); - SSVAL(cli->outbuf,smb_vwv3,passlen); + /* + * Add the sharename + */ + tmp = talloc_asprintf_strupper_m(talloc_tos(), "\\\\%s\\%s", + cli->desthost, share); + if (tmp == NULL) { + TALLOC_FREE(bytes); + return NULL; + } + bytes = smb_bytes_push_str(bytes, cli_ucs2(cli), tmp, strlen(tmp)+1, + NULL); + TALLOC_FREE(tmp); - p = smb_buf(cli->outbuf); - if (passlen) { - memcpy(p,pword,passlen); + /* + * Add the devicetype + */ + tmp = talloc_strdup_upper(talloc_tos(), dev); + if (tmp == NULL) { + TALLOC_FREE(bytes); + return NULL; } - p += passlen; - p += clistr_push(cli, p, fullshare, -1, STR_TERMINATE |STR_UPPER); - p += clistr_push(cli, p, dev, -1, STR_TERMINATE |STR_UPPER | STR_ASCII); + bytes = smb_bytes_push_str(bytes, false, tmp, strlen(tmp)+1, NULL); + TALLOC_FREE(tmp); - cli_setup_bcc(cli, p); + if (bytes == NULL) { + return NULL; + } - cli_send_smb(cli); - if (!cli_receive_smb(cli)) - return False; + result = cli_request_send(mem_ctx, ev, cli, SMBtconX, 0, + 4, vwv, 0, talloc_get_size(bytes), bytes); + TALLOC_FREE(bytes); + return result; - if (cli_is_error(cli)) - return False; + access_denied: + result = async_req_new(mem_ctx); + if (async_post_ntstatus(result, ev, NT_STATUS_ACCESS_DENIED)) { + return result; + } + TALLOC_FREE(result); + return NULL; +} + +NTSTATUS cli_tcon_andx_recv(struct async_req *req) +{ + struct cli_request *cli_req = talloc_get_type_abort( + req->private_data, struct cli_request); + struct cli_state *cli = cli_req->cli; + uint8_t wct; + uint16_t *vwv; + uint16_t num_bytes; + uint8_t *bytes; + NTSTATUS status; + + if (async_req_is_nterror(req, &status)) { + return status; + } - clistr_pull(cli->inbuf, cli->dev, smb_buf(cli->inbuf), sizeof(fstring), - -1, STR_TERMINATE|STR_ASCII); + status = cli_pull_reply(req, &wct, &vwv, &num_bytes, &bytes); + if (!NT_STATUS_IS_OK(status)) { + return status; + } + + clistr_pull(cli_req->inbuf, cli->dev, bytes, sizeof(fstring), + num_bytes, STR_TERMINATE|STR_ASCII); - if (cli->protocol >= PROTOCOL_NT1 && - smb_buflen(cli->inbuf) == 3) { + if ((cli->protocol >= PROTOCOL_NT1) && (num_bytes == 3)) { /* almost certainly win95 - enable bug fixes */ cli->win95 = True; } - /* Make sure that we have the optional support 16-bit field. WCT > 2 */ - /* Avoids issues when connecting to Win9x boxes sharing files */ + /* + * Make sure that we have the optional support 16-bit field. WCT > 2. + * Avoids issues when connecting to Win9x boxes sharing files + */ + + cli->dfsroot = false; - cli->dfsroot = False; - if ( (CVAL(cli->inbuf, smb_wct))>2 && cli->protocol >= PROTOCOL_LANMAN2 ) - cli->dfsroot = (SVAL( cli->inbuf, smb_vwv2 ) & SMB_SHARE_IN_DFS) ? True : False; + if ((wct > 2) && (cli->protocol >= PROTOCOL_LANMAN2)) { + cli->dfsroot = ((SVAL(vwv+2, 0) & SMB_SHARE_IN_DFS) != 0); + } - cli->cnum = SVAL(cli->inbuf,smb_tid); - return True; + cli->cnum = SVAL(cli_req->inbuf,smb_tid); + return NT_STATUS_OK; +} + +NTSTATUS cli_tcon_andx(struct cli_state *cli, const char *share, + const char *dev, const char *pass, int passlen) +{ + TALLOC_CTX *frame = talloc_stackframe(); + struct event_context *ev; + struct async_req *req; + NTSTATUS status; + + if (cli->fd_event != NULL) { + /* + * Can't use sync call while an async call is in flight + */ + status = NT_STATUS_INVALID_PARAMETER; + goto fail; + } + + ev = event_context_init(frame); + if (ev == NULL) { + status = NT_STATUS_NO_MEMORY; + goto fail; + } + + req = cli_tcon_andx_send(frame, ev, cli, share, dev, pass, passlen); + if (req == NULL) { + status = NT_STATUS_NO_MEMORY; + goto fail; + } + + while (req->state < ASYNC_REQ_DONE) { + event_loop_once(ev); + } + + status = cli_tcon_andx_recv(req); + fail: + TALLOC_FREE(frame); + return status; } /**************************************************************************** @@ -1294,7 +1460,10 @@ struct async_req *cli_negprot_send(TALLOC_CTX *mem_ctx, if (bytes == NULL) { return NULL; } - bytes = smb_bytes_push_str(bytes, false, prots[numprots].name); + bytes = smb_bytes_push_str(bytes, false, + prots[numprots].name, + strlen(prots[numprots].name)+1, + NULL); if (bytes == NULL) { return NULL; } @@ -1318,7 +1487,7 @@ NTSTATUS cli_negprot_recv(struct async_req *req) NTSTATUS status; uint16_t protnum; - if (async_req_is_error(req, &status)) { + if (async_req_is_nterror(req, &status)) { return status; } @@ -1887,8 +2056,9 @@ NTSTATUS cli_full_connection(struct cli_state **output_cli, } if (service) { - if (!cli_send_tconX(cli, service, service_type, password, pw_len)) { - nt_status = cli_nt_error(cli); + nt_status = cli_tcon_andx(cli, service, service_type, password, + pw_len); + if (!NT_STATUS_IS_OK(nt_status)) { DEBUG(1,("failed tcon_X with %s\n", nt_errstr(nt_status))); cli_shutdown(cli); if (NT_STATUS_IS_OK(nt_status)) { diff --git a/source3/libsmb/clidfs.c b/source3/libsmb/clidfs.c index f853e4e670..e642f169f9 100644 --- a/source3/libsmb/clidfs.c +++ b/source3/libsmb/clidfs.c @@ -275,9 +275,10 @@ static struct cli_state *do_connect(TALLOC_CTX *ctx, /* must be a normal share */ - if (!cli_send_tconX(c, sharename, "?????", - password, strlen(password)+1)) { - d_printf("tree connect failed: %s\n", cli_errstr(c)); + status = cli_tcon_andx(c, sharename, "?????", + password, strlen(password)+1); + if (!NT_STATUS_IS_OK(status)) { + d_printf("tree connect failed: %s\n", nt_errstr(status)); cli_shutdown(c); return NULL; } @@ -1077,7 +1078,7 @@ static bool cli_check_msdfs_proxy(TALLOC_CTX *ctx, /* check for the referral */ - if (!cli_send_tconX(cli, "IPC$", "IPC", NULL, 0)) { + if (!NT_STATUS_IS_OK(cli_tcon_andx(cli, "IPC$", "IPC", NULL, 0))) { return false; } diff --git a/source3/libsmb/clientgen.c b/source3/libsmb/clientgen.c index 0bec24202c..0382ef5fae 100644 --- a/source3/libsmb/clientgen.c +++ b/source3/libsmb/clientgen.c @@ -56,6 +56,16 @@ void cli_set_port(struct cli_state *cli, int port) } /**************************************************************************** + convenience routine to find if we negotiated ucs2 +****************************************************************************/ + +bool cli_ucs2(struct cli_state *cli) +{ + return ((cli->capabilities & CAP_UNICODE) != 0); +} + + +/**************************************************************************** Read an smb from a fd ignoring all keepalive packets. The timeout is in milliseconds @@ -640,7 +650,7 @@ static void cli_echo_recv_helper(struct async_req *req) status = cli_pull_reply(req, &wct, &vwv, &num_bytes, &bytes); if (!NT_STATUS_IS_OK(status)) { - async_req_error(req, status); + async_req_nterror(req, status); return; } @@ -649,7 +659,7 @@ static void cli_echo_recv_helper(struct async_req *req) if ((num_bytes != cli_req->data.echo.data.length) || (memcmp(cli_req->data.echo.data.data, bytes, num_bytes) != 0)) { - async_req_error(req, NT_STATUS_INVALID_NETWORK_RESPONSE); + async_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE); return; } @@ -717,7 +727,7 @@ struct async_req *cli_echo_send(TALLOC_CTX *mem_ctx, struct event_context *ev, NTSTATUS cli_echo_recv(struct async_req *req) { - return async_req_simple_recv(req); + return async_req_simple_recv_ntstatus(req); } /** @@ -765,3 +775,28 @@ NTSTATUS cli_echo(struct cli_state *cli, uint16_t num_echos, DATA_BLOB data) TALLOC_FREE(frame); return status; } + +/** + * Is the SMB command able to hold an AND_X successor + * @param[in] cmd The SMB command in question + * @retval Can we add a chained request after "cmd"? + */ +bool is_andx_req(uint8_t cmd) +{ + switch (cmd) { + case SMBtconX: + case SMBlockingX: + case SMBopenX: + case SMBreadX: + case SMBwriteX: + case SMBsesssetupX: + case SMBulogoffX: + case SMBntcreateX: + return true; + break; + default: + break; + } + + return false; +} diff --git a/source3/libsmb/clifile.c b/source3/libsmb/clifile.c index 02cd2108bf..0703f04c5f 100644 --- a/source3/libsmb/clifile.c +++ b/source3/libsmb/clifile.c @@ -771,6 +771,138 @@ int cli_nt_create_full(struct cli_state *cli, const char *fname, return SVAL(cli->inbuf,smb_vwv2 + 1); } +struct async_req *cli_ntcreate_send(TALLOC_CTX *mem_ctx, + struct event_context *ev, + struct cli_state *cli, + const char *fname, + uint32_t CreatFlags, + uint32_t DesiredAccess, + uint32_t FileAttributes, + uint32_t ShareAccess, + uint32_t CreateDisposition, + uint32_t CreateOptions, + uint8_t SecurityFlags) +{ + struct async_req *result; + uint8_t *bytes; + size_t converted_len; + uint16_t vwv[24]; + + SCVAL(vwv+0, 0, 0xFF); + SCVAL(vwv+0, 1, 0); + SSVAL(vwv+1, 0, 0); + SCVAL(vwv+2, 0, 0); + + if (cli->use_oplocks) { + CreatFlags |= (REQUEST_OPLOCK|REQUEST_BATCH_OPLOCK); + } + SIVAL(vwv+3, 1, CreatFlags); + SIVAL(vwv+5, 1, 0x0); /* RootDirectoryFid */ + SIVAL(vwv+7, 1, DesiredAccess); + SIVAL(vwv+9, 1, 0x0); /* AllocationSize */ + SIVAL(vwv+11, 1, 0x0); /* AllocationSize */ + SIVAL(vwv+13, 1, FileAttributes); + SIVAL(vwv+15, 1, ShareAccess); + SIVAL(vwv+17, 1, CreateDisposition); + SIVAL(vwv+19, 1, CreateOptions); + SIVAL(vwv+21, 1, 0x02); /* ImpersonationLevel */ + SCVAL(vwv+23, 1, SecurityFlags); + + bytes = talloc_array(talloc_tos(), uint8_t, 0); + bytes = smb_bytes_push_str(bytes, cli_ucs2(cli), + fname, strlen(fname)+1, + &converted_len); + + /* sigh. this copes with broken netapp filer behaviour */ + bytes = smb_bytes_push_str(bytes, cli_ucs2(cli), "", 1, NULL); + + if (bytes == NULL) { + return NULL; + } + + SIVAL(vwv+2, 1, converted_len); + + result = cli_request_send(mem_ctx, ev, cli, SMBntcreateX, 0, + 24, vwv, 0, talloc_get_size(bytes), bytes); + TALLOC_FREE(bytes); + return result; +} + +NTSTATUS cli_ntcreate_recv(struct async_req *req, uint16_t *pfnum) +{ + uint8_t wct; + uint16_t *vwv; + uint16_t num_bytes; + uint8_t *bytes; + NTSTATUS status; + + if (async_req_is_nterror(req, &status)) { + return status; + } + + status = cli_pull_reply(req, &wct, &vwv, &num_bytes, &bytes); + if (!NT_STATUS_IS_OK(status)) { + return status; + } + + if (wct < 3) { + return NT_STATUS_INVALID_NETWORK_RESPONSE; + } + + *pfnum = SVAL(vwv+2, 1); + + return NT_STATUS_OK; +} + +NTSTATUS cli_ntcreate(struct cli_state *cli, + const char *fname, + uint32_t CreatFlags, + uint32_t DesiredAccess, + uint32_t FileAttributes, + uint32_t ShareAccess, + uint32_t CreateDisposition, + uint32_t CreateOptions, + uint8_t SecurityFlags, + uint16_t *pfid) +{ + TALLOC_CTX *frame = talloc_stackframe(); + struct event_context *ev; + struct async_req *req; + NTSTATUS status; + + if (cli->fd_event != NULL) { + /* + * Can't use sync call while an async call is in flight + */ + status = NT_STATUS_INVALID_PARAMETER; + goto fail; + } + + ev = event_context_init(frame); + if (ev == NULL) { + status = NT_STATUS_NO_MEMORY; + goto fail; + } + + req = cli_ntcreate_send(frame, ev, cli, fname, CreatFlags, + DesiredAccess, FileAttributes, ShareAccess, + CreateDisposition, CreateOptions, + SecurityFlags); + if (req == NULL) { + status = NT_STATUS_NO_MEMORY; + goto fail; + } + + while (req->state < ASYNC_REQ_DONE) { + event_loop_once(ev); + } + + status = cli_ntcreate_recv(req, pfid); + fail: + TALLOC_FREE(frame); + return status; +} + /**************************************************************************** Open a file. ****************************************************************************/ @@ -781,7 +913,9 @@ int cli_nt_create(struct cli_state *cli, const char *fname, uint32 DesiredAccess FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_OPEN, 0x0, 0x0); } -uint8_t *smb_bytes_push_str(uint8_t *buf, bool ucs2, const char *str) +uint8_t *smb_bytes_push_str(uint8_t *buf, bool ucs2, + const char *str, size_t str_len, + size_t *pconverted_size) { size_t buflen; char *converted; @@ -806,7 +940,7 @@ uint8_t *smb_bytes_push_str(uint8_t *buf, bool ucs2, const char *str) if (!convert_string_allocate(talloc_tos(), CH_UNIX, ucs2 ? CH_UTF16LE : CH_DOS, - str, strlen(str)+1, &converted, + str, str_len, &converted, &converted_size, true)) { return NULL; } @@ -821,6 +955,11 @@ uint8_t *smb_bytes_push_str(uint8_t *buf, bool ucs2, const char *str) memcpy(buf + buflen, converted, converted_size); TALLOC_FREE(converted); + + if (pconverted_size) { + *pconverted_size = converted_size; + } + return buf; } @@ -890,12 +1029,8 @@ struct async_req *cli_open_send(TALLOC_CTX *mem_ctx, struct event_context *ev, } bytes = talloc_array(talloc_tos(), uint8_t, 0); - if (bytes == NULL) { - return NULL; - } - - bytes = smb_bytes_push_str( - bytes, (cli->capabilities & CAP_UNICODE) != 0, fname); + bytes = smb_bytes_push_str(bytes, cli_ucs2(cli), fname, + strlen(fname)+1, NULL); if (bytes == NULL) { return NULL; } @@ -914,7 +1049,7 @@ NTSTATUS cli_open_recv(struct async_req *req, int *fnum) uint8_t *bytes; NTSTATUS status; - if (async_req_is_error(req, &status)) { + if (async_req_is_nterror(req, &status)) { return status; } @@ -992,7 +1127,7 @@ NTSTATUS cli_close_recv(struct async_req *req) uint8_t *bytes; NTSTATUS status; - if (async_req_is_error(req, &status)) { + if (async_req_is_nterror(req, &status)) { return status; } diff --git a/source3/libsmb/clireadwrite.c b/source3/libsmb/clireadwrite.c index 1ba93d827d..9d17ff86a5 100644 --- a/source3/libsmb/clireadwrite.c +++ b/source3/libsmb/clireadwrite.c @@ -148,7 +148,7 @@ NTSTATUS cli_read_andx_recv(struct async_req *req, ssize_t *received, NTSTATUS status; size_t size; - if (async_req_is_error(req, &status)) { + if (async_req_is_nterror(req, &status)) { return status; } @@ -297,7 +297,7 @@ struct async_req *cli_pull_send(TALLOC_CTX *mem_ctx, state->top_req = 0; if (size == 0) { - if (!async_post_status(result, ev, NT_STATUS_OK)) { + if (!async_post_ntstatus(result, ev, NT_STATUS_OK)) { goto failed; } return result; @@ -367,7 +367,7 @@ static void cli_pull_read_done(struct async_req *read_req) status = cli_read_andx_recv(read_req, &read_state->data.read.received, &read_state->data.read.rcvbuf); if (!NT_STATUS_IS_OK(status)) { - async_req_error(state->req, status); + async_req_nterror(state->req, status); return; } @@ -404,7 +404,7 @@ static void cli_pull_read_done(struct async_req *read_req) top_read->data.read.received, state->priv); if (!NT_STATUS_IS_OK(status)) { - async_req_error(state->req, status); + async_req_nterror(state->req, status); return; } state->pushed += top_read->data.read.received; @@ -455,7 +455,7 @@ NTSTATUS cli_pull_recv(struct async_req *req, SMB_OFF_T *received) req->private_data, struct cli_pull_state); NTSTATUS status; - if (async_req_is_error(req, &status)) { + if (async_req_is_nterror(req, &status)) { return status; } *received = state->pushed; @@ -792,7 +792,7 @@ NTSTATUS cli_write_andx_recv(struct async_req *req, size_t *pwritten) NTSTATUS status; size_t written; - if (async_req_is_error(req, &status)) { + if (async_req_is_nterror(req, &status)) { return status; } @@ -879,14 +879,14 @@ static void cli_writeall_written(struct async_req *subreq) status = cli_write_andx_recv(subreq, &written); TALLOC_FREE(subreq); if (!NT_STATUS_IS_OK(status)) { - async_req_error(req, status); + async_req_nterror(req, status); return; } state->written += written; if (state->written > state->size) { - async_req_error(req, NT_STATUS_INVALID_NETWORK_RESPONSE); + async_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE); return; } @@ -902,7 +902,7 @@ static void cli_writeall_written(struct async_req *subreq) state->buf + state->written, state->offset + state->written, to_write); if (subreq == NULL) { - async_req_error(req, NT_STATUS_NO_MEMORY); + async_req_nterror(req, NT_STATUS_NO_MEMORY); return; } @@ -912,7 +912,7 @@ static void cli_writeall_written(struct async_req *subreq) static NTSTATUS cli_writeall_recv(struct async_req *req) { - return async_req_simple_recv(req); + return async_req_simple_recv_ntstatus(req); } struct cli_push_state { @@ -1018,7 +1018,7 @@ struct async_req *cli_push_send(TALLOC_CTX *mem_ctx, struct event_context *ev, } if (i == 0) { - if (!async_post_status(result, ev, NT_STATUS_OK)) { + if (!async_post_ntstatus(result, ev, NT_STATUS_OK)) { goto failed; } return result; @@ -1047,7 +1047,7 @@ static void cli_push_written(struct async_req *req) } if (i == state->num_reqs) { - async_req_error(state->req, NT_STATUS_INTERNAL_ERROR); + async_req_nterror(state->req, NT_STATUS_INTERNAL_ERROR); return; } @@ -1055,7 +1055,7 @@ static void cli_push_written(struct async_req *req) TALLOC_FREE(state->reqs[i]); req = NULL; if (!NT_STATUS_IS_OK(status)) { - async_req_error(state->req, status); + async_req_nterror(state->req, status); return; } @@ -1081,7 +1081,7 @@ static void cli_push_written(struct async_req *req) state->reqs, state->ev, state->cli, state->fnum, state->mode, buf, state->start_offset + state->sent, to_write); if (state->reqs[i] == NULL) { - async_req_error(state->req, NT_STATUS_NO_MEMORY); + async_req_nterror(state->req, NT_STATUS_NO_MEMORY); return; } @@ -1094,7 +1094,7 @@ static void cli_push_written(struct async_req *req) NTSTATUS cli_push_recv(struct async_req *req) { - return async_req_simple_recv(req); + return async_req_simple_recv_ntstatus(req); } NTSTATUS cli_push(struct cli_state *cli, uint16_t fnum, uint16_t mode, diff --git a/source3/libsmb/clitrans.c b/source3/libsmb/clitrans.c index baa73aeb14..69e2be3af7 100644 --- a/source3/libsmb/clitrans.c +++ b/source3/libsmb/clitrans.c @@ -765,9 +765,9 @@ static struct async_req *cli_ship_trans(TALLOC_CTX *mem_ctx, if (bytes == NULL) { goto fail; } - bytes = smb_bytes_push_str( - bytes, (state->cli->capabilities & CAP_UNICODE) != 0, - state->pipe_name); + bytes = smb_bytes_push_str(bytes, cli_ucs2(state->cli), + state->pipe_name, + strlen(state->pipe_name)+1, NULL); if (bytes == NULL) { goto fail; } @@ -962,7 +962,7 @@ static void cli_trans_ship_rest(struct async_req *req, { state->secondary_request_ctx = talloc_new(state); if (state->secondary_request_ctx == NULL) { - async_req_error(req, NT_STATUS_NO_MEMORY); + async_req_nterror(req, NT_STATUS_NO_MEMORY); return; } @@ -972,7 +972,7 @@ static void cli_trans_ship_rest(struct async_req *req, cli_req = cli_ship_trans(state->secondary_request_ctx, state); if (cli_req == NULL) { - async_req_error(req, NT_STATUS_NO_MEMORY); + async_req_nterror(req, NT_STATUS_NO_MEMORY); return; } } @@ -1133,7 +1133,7 @@ static void cli_trans_recv_helper(struct async_req *req) */ if (NT_STATUS_IS_ERR(status)) { - async_req_error(req, status); + async_req_nterror(req, status); return; } @@ -1154,7 +1154,7 @@ static void cli_trans_recv_helper(struct async_req *req) state->rsetup = (uint16_t *)TALLOC_MEMDUP( state, setup, sizeof(uint16_t) * num_setup); if (state->rsetup == NULL) { - async_req_error(req, NT_STATUS_NO_MEMORY); + async_req_nterror(req, NT_STATUS_NO_MEMORY); return; } } @@ -1165,7 +1165,7 @@ static void cli_trans_recv_helper(struct async_req *req) if (!NT_STATUS_IS_OK(status)) { DEBUG(10, ("Pulling params failed: %s\n", nt_errstr(status))); - async_req_error(req, status); + async_req_nterror(req, status); return; } @@ -1175,7 +1175,7 @@ static void cli_trans_recv_helper(struct async_req *req) if (!NT_STATUS_IS_OK(status)) { DEBUG(10, ("Pulling data failed: %s\n", nt_errstr(status))); - async_req_error(req, status); + async_req_nterror(req, status); return; } @@ -1318,7 +1318,7 @@ NTSTATUS cli_trans_recv(struct async_req *req, TALLOC_CTX *mem_ctx, cli_req->recv_helper.priv, struct cli_trans_state); NTSTATUS status; - if (async_req_is_error(req, &status)) { + if (async_req_is_nterror(req, &status)) { return status; } diff --git a/source3/libsmb/credentials.c b/source3/libsmb/credentials.c index 9d33e6d93d..9ba460f869 100644 --- a/source3/libsmb/credentials.c +++ b/source3/libsmb/credentials.c @@ -146,7 +146,7 @@ static void creds_init_64(struct dcinfo *dc, static void creds_step(struct dcinfo *dc) { - DOM_CHAL time_chal; + struct netr_Credential time_chal; DEBUG(5,("\tsequence = 0x%x\n", (unsigned int)dc->sequence )); diff --git a/source3/libsmb/libsmb_server.c b/source3/libsmb/libsmb_server.c index 0ece5bb649..6d7a86241a 100644 --- a/source3/libsmb/libsmb_server.c +++ b/source3/libsmb/libsmb_server.c @@ -300,11 +300,11 @@ SMBC_server(TALLOC_CTX *ctx, * tid. */ - if (!cli_send_tconX(srv->cli, share, "?????", - *pp_password, - strlen(*pp_password)+1)) { - - errno = SMBC_errno(context, srv->cli); + status = cli_tcon_andx(srv->cli, share, "?????", + *pp_password, + strlen(*pp_password)+1); + if (!NT_STATUS_IS_OK(status)) { + errno = map_errno_from_nt_status(status); cli_shutdown(srv->cli); srv->cli = NULL; smbc_getFunctionRemoveCachedServer(context)(context, @@ -501,9 +501,10 @@ again: DEBUG(4,(" session setup ok\n")); - if (!cli_send_tconX(c, share, "?????", - *pp_password, strlen(*pp_password)+1)) { - errno = SMBC_errno(context, c); + status = cli_tcon_andx(c, share, "?????", *pp_password, + strlen(*pp_password)+1); + if (!NT_STATUS_IS_OK(status)) { + errno = map_errno_from_nt_status(status); cli_shutdown(c); return NULL; } diff --git a/source3/libsmb/namecache.c b/source3/libsmb/namecache.c index ba706e5ee2..d3230cffef 100644 --- a/source3/libsmb/namecache.c +++ b/source3/libsmb/namecache.c @@ -62,27 +62,6 @@ bool namecache_enable(void) } /** - * Shutdown namecache. Routine calls gencache close function - * to safely close gencache file. - * - * @return true upon successful shutdown of the cache or - * false on failure - **/ - -bool namecache_shutdown(void) -{ - if (!gencache_shutdown()) { - DEBUG(2, ("namecache_shutdown: " - "Couldn't close namecache on top of gencache.\n")); - return False; - } - - DEBUG(5, ("namecache_shutdown: " - "netbios namecache closed successfully.\n")); - return True; -} - -/** * Generates a key for netbios name lookups on basis of * netbios name and type. * The caller must free returned key string when finished. diff --git a/source3/libsmb/namequery.c b/source3/libsmb/namequery.c index 05679570d4..ac38d40271 100644 --- a/source3/libsmb/namequery.c +++ b/source3/libsmb/namequery.c @@ -1502,7 +1502,7 @@ NTSTATUS internal_resolve_name(const char *name, *return_count = 0; DEBUG(10, ("internal_resolve_name: looking up %s#%x (sitename %s)\n", - name, name_type, sitename ? sitename : NULL)); + name, name_type, sitename ? sitename : "(null)")); if (is_ipaddress(name)) { if ((*return_iplist = SMB_MALLOC_P(struct ip_service)) == diff --git a/source3/libsmb/passchange.c b/source3/libsmb/passchange.c index 76b06088d6..f9ff4b3191 100644 --- a/source3/libsmb/passchange.c +++ b/source3/libsmb/passchange.c @@ -138,13 +138,13 @@ NTSTATUS remote_password_change(const char *remote_machine, const char *user_nam cli_init_creds(cli, user_name, "", old_passwd); } - if (!cli_send_tconX(cli, "IPC$", "IPC", "", 1)) { - if (asprintf(err_str, "machine %s rejected the tconX on the IPC$ " - "share. Error was : %s.\n", - remote_machine, cli_errstr(cli)) == -1) { + result = cli_tcon_andx(cli, "IPC$", "IPC", "", 1); + if (!NT_STATUS_IS_OK(result)) { + if (asprintf(err_str, "machine %s rejected the tconX on the " + "IPC$ share. Error was : %s.\n", + remote_machine, nt_errstr(result))) { *err_str = NULL; } - result = cli_nt_error(cli); cli_shutdown(cli); return result; } diff --git a/source3/m4/check_path.m4 b/source3/m4/check_path.m4 index 444ea1c401..0a61733870 100644 --- a/source3/m4/check_path.m4 +++ b/source3/m4/check_path.m4 @@ -215,19 +215,6 @@ AC_ARG_WITH(logfilebase, ################################################# -# set ctdb source directory location -AC_ARG_WITH(ctdb, -[AS_HELP_STRING([--with-ctdb=DIR], [Where to find ctdb sources])], -[ case "$withval" in - yes|no) - AC_MSG_WARN([--with-ctdb called without argument]) - ;; - * ) - ctdbdir="$withval" - ;; - esac]) - -################################################# # set shared modules (internal lib) directory location AC_ARG_WITH(modulesdir, [AS_HELP_STRING([--with-modulesdir=DIR], [Where to put shared modules ($libdir)])], @@ -297,7 +284,6 @@ AC_SUBST(lockdir) AC_SUBST(piddir) AC_SUBST(ncalrpcdir) AC_SUBST(logfilebase) -AC_SUBST(ctdbdir) AC_SUBST(privatedir) AC_SUBST(swatdir) AC_SUBST(bindir) @@ -337,7 +323,7 @@ AC_ARG_WITH(selftest-shrdir, AC_MSG_WARN([--with-selftest-shrdir called without argument - will use default]) ;; * ) - selftest_shrdir="$withval" + selftest_shrdir="-s $withval" ;; esac ]) @@ -346,6 +332,8 @@ AC_ARG_WITH(selftest-shrdir, # set path of samba4's smbtorture smbtorture4_path="" AC_SUBST(smbtorture4_path) +smbtorture4_option="" +AC_SUBST(smbtorture4_option) AC_ARG_WITH(smbtorture4_path, [AS_HELP_STRING([--with-smbtorture4-path=PATH], [The path to a samba4 smbtorture for make test (none)])], [ case "$withval" in @@ -357,6 +345,27 @@ AC_ARG_WITH(smbtorture4_path, if test -z "$smbtorture4_path" -a ! -f $smbtorture4_path; then AC_MSG_ERROR(['$smbtorture_path' does not exist!]) fi + smbtorture4_option="-t $withval" + ;; + esac +]) + +################################################# +# set custom conf for make test +selftest_custom_conf="" +AC_SUBST(selftest_custom_conf) +AC_ARG_WITH(selftest_custom_conf, +[AS_HELP_STRING([--with-selftest-custom-conf=PATH], [An optional custom smb.conf that is included in the server smb.conf during make test(none)])], +[ case "$withval" in + yes|no) + AC_MSG_ERROR([--with-selftest-custom-conf should take a path]) + ;; + * ) + selftest_custom_conf="$withval" + if test -z "$selftest_custom_conf" -a ! -f $selftest_custom_conf; then + AC_MSG_ERROR(['$selftest_custom_conf' does not exist!]) + fi + selftest_custom_conf="-c $withval" ;; esac ]) diff --git a/source3/modules/onefs_acl.c b/source3/modules/onefs_acl.c index b9ec2d68e0..14b27b80e0 100644 --- a/source3/modules/onefs_acl.c +++ b/source3/modules/onefs_acl.c @@ -667,7 +667,7 @@ onefs_fget_nt_acl(vfs_handle_struct *handle, files_struct *fsp, } error = ifs_get_security_descriptor(fsp->fh->fd, security_info, - &sd_size, sd); + sd_size, &sd_size, sd); if (error && (errno != EMSGSIZE)) { DEBUG(0, ("Failed getting size of security descriptor! " "errno=%d\n", errno)); diff --git a/source3/modules/onefs_streams.c b/source3/modules/onefs_streams.c index e9543e237f..78b0fd61bf 100644 --- a/source3/modules/onefs_streams.c +++ b/source3/modules/onefs_streams.c @@ -533,8 +533,8 @@ static NTSTATUS walk_onefs_streams(connection_struct *conn, files_struct *fsp, if (!add_one_stream(state->mem_ctx, &state->num_streams, &state->streams, dp->d_name, stream_sbuf.st_size, - get_allocation_size(conn, NULL, - &stream_sbuf))) { + SMB_VFS_GET_ALLOC_SIZE(conn, NULL, + &stream_sbuf))) { state->status = NT_STATUS_NO_MEMORY; break; } @@ -594,8 +594,8 @@ NTSTATUS onefs_streaminfo(vfs_handle_struct *handle, if (!add_one_stream(mem_ctx, &state.num_streams, &state.streams, "", sbuf.st_size, - get_allocation_size(handle->conn, fsp, - &sbuf))) { + SMB_VFS_GET_ALLOC_SIZE(handle->conn, fsp, + &sbuf))) { return NT_STATUS_NO_MEMORY; } } diff --git a/source3/modules/vfs_aio_fork.c b/source3/modules/vfs_aio_fork.c index 30b14f280f..e29ce5e7a8 100644 --- a/source3/modules/vfs_aio_fork.c +++ b/source3/modules/vfs_aio_fork.c @@ -406,8 +406,7 @@ static void handle_aio_completion(struct event_context *event_ctx, DEBUG(10, ("mid %d finished\n", (int)mid)); - aio_request_done(mid); - process_aio_queue(); + smbd_aio_complete_mid(mid); } static int aio_child_destructor(struct aio_child *child) diff --git a/source3/modules/vfs_default.c b/source3/modules/vfs_default.c index a9aabab768..679be57558 100644 --- a/source3/modules/vfs_default.c +++ b/source3/modules/vfs_default.c @@ -551,6 +551,39 @@ int vfswrap_lstat(vfs_handle_struct *handle, const char *path, SMB_STRUCT_STAT return result; } +/******************************************************************** + Given a stat buffer return the allocated size on disk, taking into + account sparse files. +********************************************************************/ +static uint64_t vfswrap_get_alloc_size(vfs_handle_struct *handle, + struct files_struct *fsp, + const SMB_STRUCT_STAT *sbuf) +{ + uint64_t result; + + START_PROFILE(syscall_get_alloc_size); + + if(S_ISDIR(sbuf->st_mode)) { + result = 0; + goto out; + } + +#if defined(HAVE_STAT_ST_BLOCKS) && defined(STAT_ST_BLOCKSIZE) + result = (uint64_t)STAT_ST_BLOCKSIZE * (uint64_t)sbuf->st_blocks; +#else + result = get_file_size_stat(sbuf); +#endif + + if (fsp && fsp->initial_allocation_size) + result = MAX(result,fsp->initial_allocation_size); + + result = smb_roundup(handle->conn, result); + + out: + END_PROFILE(syscall_get_alloc_size); + return result; +} + static int vfswrap_unlink(vfs_handle_struct *handle, const char *path) { int result; @@ -702,7 +735,7 @@ static int vfswrap_ntimes(vfs_handle_struct *handle, const char *path, struct utimbuf times; times.actime = convert_timespec_to_time_t(ft->atime); times.modtime = convert_timespec_to_time_t(ft->mtime); - result = utime(path, times); + result = utime(path, ×); } else { result = utime(path, NULL); } @@ -1043,7 +1076,7 @@ static NTSTATUS vfswrap_streaminfo(vfs_handle_struct *handle, } streams->size = sbuf.st_size; - streams->alloc_size = get_allocation_size(handle->conn, fsp, &sbuf); + streams->alloc_size = SMB_VFS_GET_ALLOC_SIZE(handle->conn, fsp, &sbuf); streams->name = talloc_strdup(streams, "::$DATA"); if (streams->name == NULL) { @@ -1443,6 +1476,8 @@ static vfs_op_tuple vfs_default_ops[] = { SMB_VFS_LAYER_OPAQUE}, {SMB_VFS_OP(vfswrap_lstat), SMB_VFS_OP_LSTAT, SMB_VFS_LAYER_OPAQUE}, + {SMB_VFS_OP(vfswrap_get_alloc_size), SMB_VFS_OP_GET_ALLOC_SIZE, + SMB_VFS_LAYER_OPAQUE}, {SMB_VFS_OP(vfswrap_unlink), SMB_VFS_OP_UNLINK, SMB_VFS_LAYER_OPAQUE}, {SMB_VFS_OP(vfswrap_chmod), SMB_VFS_OP_CHMOD, diff --git a/source3/modules/vfs_full_audit.c b/source3/modules/vfs_full_audit.c index 73758a2d9d..c6d62fdd87 100644 --- a/source3/modules/vfs_full_audit.c +++ b/source3/modules/vfs_full_audit.c @@ -155,6 +155,8 @@ static int smb_full_audit_fstat(vfs_handle_struct *handle, files_struct *fsp, SMB_STRUCT_STAT *sbuf); static int smb_full_audit_lstat(vfs_handle_struct *handle, const char *path, SMB_STRUCT_STAT *sbuf); +static int smb_full_audit_get_alloc_size(vfs_handle_struct *handle, + files_struct *fsp, const SMB_STRUCT_STAT *sbuf); static int smb_full_audit_unlink(vfs_handle_struct *handle, const char *path); static int smb_full_audit_chmod(vfs_handle_struct *handle, @@ -403,6 +405,8 @@ static vfs_op_tuple audit_op_tuples[] = { SMB_VFS_LAYER_LOGGER}, {SMB_VFS_OP(smb_full_audit_lstat), SMB_VFS_OP_LSTAT, SMB_VFS_LAYER_LOGGER}, + {SMB_VFS_OP(smb_full_audit_get_alloc_size), SMB_VFS_OP_GET_ALLOC_SIZE, + SMB_VFS_LAYER_LOGGER}, {SMB_VFS_OP(smb_full_audit_unlink), SMB_VFS_OP_UNLINK, SMB_VFS_LAYER_LOGGER}, {SMB_VFS_OP(smb_full_audit_chmod), SMB_VFS_OP_CHMOD, @@ -597,6 +601,7 @@ static struct { { SMB_VFS_OP_STAT, "stat" }, { SMB_VFS_OP_FSTAT, "fstat" }, { SMB_VFS_OP_LSTAT, "lstat" }, + { SMB_VFS_OP_GET_ALLOC_SIZE, "get_alloc_size" }, { SMB_VFS_OP_UNLINK, "unlink" }, { SMB_VFS_OP_CHMOD, "chmod" }, { SMB_VFS_OP_FCHMOD, "fchmod" }, @@ -1325,6 +1330,18 @@ static int smb_full_audit_lstat(vfs_handle_struct *handle, return result; } +static int smb_full_audit_get_alloc_size(vfs_handle_struct *handle, + files_struct *fsp, const SMB_STRUCT_STAT *sbuf) +{ + int result; + + result = SMB_VFS_NEXT_GET_ALLOC_SIZE(handle, fsp, sbuf); + + do_log(SMB_VFS_OP_GET_ALLOC_SIZE, (result >= 0), handle, "%d", result); + + return result; +} + static int smb_full_audit_unlink(vfs_handle_struct *handle, const char *path) { diff --git a/source3/modules/vfs_onefs.c b/source3/modules/vfs_onefs.c index e048e89589..e2f272aa11 100644 --- a/source3/modules/vfs_onefs.c +++ b/source3/modules/vfs_onefs.c @@ -40,6 +40,31 @@ static int onefs_open(vfs_handle_struct *handle, const char *fname, return SMB_VFS_NEXT_OPEN(handle, fname, fsp, flags, mode); } +static uint64_t onefs_get_alloc_size(struct vfs_handle_struct *handle, files_struct *fsp, + const SMB_STRUCT_STAT *sbuf) +{ + uint64_t result; + + START_PROFILE(syscall_get_alloc_size); + + if(S_ISDIR(sbuf->st_mode)) { + result = 0; + goto out; + } + + /* Just use the file size since st_blocks is unreliable on OneFS. */ + result = get_file_size_stat(sbuf); + + if (fsp && fsp->initial_allocation_size) + result = MAX(result,fsp->initial_allocation_size); + + result = smb_roundup(handle->conn, result); + + out: + END_PROFILE(syscall_get_alloc_size); + return result; +} + static int onefs_statvfs(vfs_handle_struct *handle, const char *path, vfs_statvfs_struct *statbuf) { @@ -123,6 +148,8 @@ static vfs_op_tuple onefs_ops[] = { SMB_VFS_LAYER_TRANSPARENT}, {SMB_VFS_OP(onefs_lstat), SMB_VFS_OP_LSTAT, SMB_VFS_LAYER_TRANSPARENT}, + {SMB_VFS_OP(onefs_get_alloc_size), SMB_VFS_OP_GET_ALLOC_SIZE, + SMB_VFS_LAYER_OPAQUE}, {SMB_VFS_OP(onefs_unlink), SMB_VFS_OP_UNLINK, SMB_VFS_LAYER_TRANSPARENT}, {SMB_VFS_OP(onefs_ntimes), SMB_VFS_OP_NTIMES, diff --git a/source3/modules/vfs_streams_depot.c b/source3/modules/vfs_streams_depot.c index 54c17db1ce..77efb277de 100644 --- a/source3/modules/vfs_streams_depot.c +++ b/source3/modules/vfs_streams_depot.c @@ -648,8 +648,8 @@ static bool collect_one_stream(const char *dirname, if (!add_one_stream(state->mem_ctx, &state->num_streams, &state->streams, dirent, sbuf.st_size, - get_allocation_size( - state->handle->conn, NULL, &sbuf))) { + SMB_VFS_GET_ALLOC_SIZE(state->handle->conn, NULL, + &sbuf))) { state->status = NT_STATUS_NO_MEMORY; return false; } @@ -693,8 +693,8 @@ static NTSTATUS streams_depot_streaminfo(vfs_handle_struct *handle, if (!add_one_stream(mem_ctx, &state.num_streams, &state.streams, "::$DATA", sbuf.st_size, - get_allocation_size(handle->conn, fsp, - &sbuf))) { + SMB_VFS_GET_ALLOC_SIZE(handle->conn, fsp, + &sbuf))) { return NT_STATUS_NO_MEMORY; } } diff --git a/source3/modules/vfs_streams_xattr.c b/source3/modules/vfs_streams_xattr.c index 1df4932167..37473439dd 100644 --- a/source3/modules/vfs_streams_xattr.c +++ b/source3/modules/vfs_streams_xattr.c @@ -732,8 +732,8 @@ static NTSTATUS streams_xattr_streaminfo(vfs_handle_struct *handle, if (!add_one_stream(mem_ctx, &state.num_streams, &state.streams, "::$DATA", sbuf.st_size, - get_allocation_size(handle->conn, fsp, - &sbuf))) { + SMB_VFS_GET_ALLOC_SIZE(handle->conn, fsp, + &sbuf))) { return NT_STATUS_NO_MEMORY; } } diff --git a/source3/nmbd/asyncdns.c b/source3/nmbd/asyncdns.c index baa88bc44b..0736a66fb8 100644 --- a/source3/nmbd/asyncdns.c +++ b/source3/nmbd/asyncdns.c @@ -210,9 +210,6 @@ void run_dns_queue(void) if (fd_in == -1) return; - /* Allow SIGTERM to kill us. */ - BlockSignals(False, SIGTERM); - if (!process_exists_by_pid(child_pid)) { close(fd_in); close(fd_out); @@ -224,12 +221,9 @@ void run_dns_queue(void) if (!NT_STATUS_IS_OK(status)) { DEBUG(0, ("read from child failed: %s\n", nt_errstr(status))); fd_in = -1; - BlockSignals(True, SIGTERM); return; } - BlockSignals(True, SIGTERM); - namerec = add_dns_result(&r.name, r.result); if (dns_current) { @@ -338,14 +332,8 @@ bool queue_dns_query(struct packet_struct *p,struct nmb_name *question) DEBUG(3,("DNS search for %s - ", nmb_namestr(question))); - /* Unblock TERM signal so we can be killed in DNS lookup. */ - BlockSignals(False, SIGTERM); - dns_ip.s_addr = interpret_addr(qname); - /* Re-block TERM signal. */ - BlockSignals(True, SIGTERM); - namerec = add_dns_result(question, dns_ip); if(namerec == NULL) { send_wins_name_query_response(NAM_ERR, p, NULL); diff --git a/source3/nmbd/nmbd.c b/source3/nmbd/nmbd.c index 0922e455a3..adefb7d94f 100644 --- a/source3/nmbd/nmbd.c +++ b/source3/nmbd/nmbd.c @@ -85,41 +85,80 @@ static void terminate(void) exit(0); } -/**************************************************************************** ** - Handle a SHUTDOWN message from smbcontrol. - **************************************************************************** */ - -static void nmbd_terminate(struct messaging_context *msg, - void *private_data, - uint32_t msg_type, - struct server_id server_id, - DATA_BLOB *data) +static void nmbd_sig_term_handler(struct tevent_context *ev, + struct tevent_signal *se, + int signum, + int count, + void *siginfo, + void *private_data) { terminate(); } -/**************************************************************************** ** - Catch a SIGTERM signal. - **************************************************************************** */ +static bool nmbd_setup_sig_term_handler(void) +{ + struct tevent_signal *se; + + se = tevent_add_signal(nmbd_event_context(), + nmbd_event_context(), + SIGTERM, 0, + nmbd_sig_term_handler, + NULL); + if (!se) { + DEBUG(0,("failed to setup SIGTERM handler")); + return false; + } -static SIG_ATOMIC_T got_sig_term; + return true; +} + +static void msg_reload_nmbd_services(struct messaging_context *msg, + void *private_data, + uint32_t msg_type, + struct server_id server_id, + DATA_BLOB *data); + +static void nmbd_sig_hup_handler(struct tevent_context *ev, + struct tevent_signal *se, + int signum, + int count, + void *siginfo, + void *private_data) +{ + DEBUG(0,("Got SIGHUP dumping debug info.\n")); + msg_reload_nmbd_services(nmbd_messaging_context(), + NULL, MSG_SMB_CONF_UPDATED, + procid_self(), NULL); +} -static void sig_term(int sig) +static bool nmbd_setup_sig_hup_handler(void) { - got_sig_term = 1; - sys_select_signal(SIGTERM); + struct tevent_signal *se; + + se = tevent_add_signal(nmbd_event_context(), + nmbd_event_context(), + SIGHUP, 0, + nmbd_sig_hup_handler, + NULL); + if (!se) { + DEBUG(0,("failed to setup SIGHUP handler")); + return false; + } + + return true; } /**************************************************************************** ** - Catch a SIGHUP signal. + Handle a SHUTDOWN message from smbcontrol. **************************************************************************** */ -static SIG_ATOMIC_T reload_after_sighup; - -static void sig_hup(int sig) +static void nmbd_terminate(struct messaging_context *msg, + void *private_data, + uint32_t msg_type, + struct server_id server_id, + DATA_BLOB *data) { - reload_after_sighup = 1; - sys_select_signal(SIGHUP); + terminate(); } /**************************************************************************** ** @@ -282,6 +321,7 @@ static void reload_interfaces(time_t t) /* We need to wait if there are no subnets... */ if (FIRST_SUBNET == NULL) { + void (*saved_handler)(int); if (print_waiting_msg) { DEBUG(0,("reload_interfaces: " @@ -293,29 +333,20 @@ static void reload_interfaces(time_t t) * Whilst we're waiting for an interface, allow SIGTERM to * cause us to exit. */ - - BlockSignals(false, SIGTERM); + saved_handler = CatchSignal( SIGTERM, SIGNAL_CAST SIG_DFL ); /* We only count IPv4, non-loopback interfaces here. */ - while (iface_count_v4_nl() == 0 && !got_sig_term) { + while (iface_count_v4_nl() == 0) { sleep(5); load_interfaces(); } - /* - * Handle termination inband. - */ - - if (got_sig_term) { - got_sig_term = 0; - terminate(); - } + CatchSignal( SIGTERM, SIGNAL_CAST saved_handler ); /* * We got an interface, go back to blocking term. */ - BlockSignals(true, SIGTERM); goto try_again; } } @@ -460,15 +491,6 @@ static void process(void) } /* - * Handle termination inband. - */ - - if (got_sig_term) { - got_sig_term = 0; - terminate(); - } - - /* * Process all incoming packets * read above. This calls the success and * failure functions registered when response @@ -637,19 +659,6 @@ static void process(void) clear_unexpected(t); - /* - * Reload the services file if we got a sighup. - */ - - if(reload_after_sighup) { - DEBUG( 0, ( "Got SIGHUP dumping debug info.\n" ) ); - msg_reload_nmbd_services(nmbd_messaging_context(), - NULL, MSG_SMB_CONF_UPDATED, - procid_self(), NULL); - - reload_after_sighup = 0; - } - /* check for new network interfaces */ reload_interfaces(t); @@ -815,10 +824,7 @@ static bool open_sockets(bool isdaemon, int port) BlockSignals(False, SIGHUP); BlockSignals(False, SIGUSR1); BlockSignals(False, SIGTERM); - - CatchSignal( SIGHUP, SIGNAL_CAST sig_hup ); - CatchSignal( SIGTERM, SIGNAL_CAST sig_term ); - + #if defined(SIGFPE) /* we are never interested in SIGFPE */ BlockSignals(True,SIGFPE); @@ -913,6 +919,11 @@ static bool open_sockets(bool isdaemon, int port) exit(1); } + if (!nmbd_setup_sig_term_handler()) + exit(1); + if (!nmbd_setup_sig_hup_handler()) + exit(1); + /* get broadcast messages */ claim_connection(NULL,"",FLAG_MSG_GENERAL|FLAG_MSG_DBWRAP); @@ -977,9 +988,6 @@ static bool open_sockets(bool isdaemon, int port) exit(1); } - /* We can only take signals in the select. */ - BlockSignals( True, SIGTERM ); - TALLOC_FREE(frame); process(); diff --git a/source3/nmbd/nmbd_become_dmb.c b/source3/nmbd/nmbd_become_dmb.c index a0b2ef15f8..827d56cb06 100644 --- a/source3/nmbd/nmbd_become_dmb.c +++ b/source3/nmbd/nmbd_become_dmb.c @@ -128,7 +128,8 @@ in workgroup %s on subnet %s\n", work->dmb_name = nmbname; - /* Pick the first interface IPv4 address as the domain master browser ip. */ + /* Pick the first interface IPv4 address as the domain master + * browser ip. */ nip = first_ipv4_iface(); if (!nip) { DEBUG(0,("become_domain_master_stage2: " diff --git a/source3/nmbd/nmbd_packets.c b/source3/nmbd/nmbd_packets.c index 489034899e..f69845b346 100644 --- a/source3/nmbd/nmbd_packets.c +++ b/source3/nmbd/nmbd_packets.c @@ -1794,16 +1794,8 @@ bool listen_for_packets(bool run_election) &r_fds, &w_fds, &timeout, &maxfd); } - /* Prepare for the select - allow certain signals. */ - - BlockSignals(False, SIGTERM); - selrtn = sys_select(maxfd+1,&r_fds,&w_fds,NULL,&timeout); - /* We can only take signals when we are in the select - block them again here. */ - - BlockSignals(True, SIGTERM); - if (run_events(nmbd_event_context(), selrtn, &r_fds, &w_fds)) { return False; } diff --git a/source3/nmbd/nmbd_subnetdb.c b/source3/nmbd/nmbd_subnetdb.c index 61af0bb4a4..13bc931863 100644 --- a/source3/nmbd/nmbd_subnetdb.c +++ b/source3/nmbd/nmbd_subnetdb.c @@ -287,7 +287,8 @@ bool create_subnets(void) } if (lp_we_are_a_wins_server()) { - /* Pick the first interface IPv4 address as the WINS server ip. */ + /* Pick the first interface IPv4 address as the WINS server + * ip. */ const struct in_addr *nip = first_ipv4_iface(); if (!nip) { diff --git a/source3/nmbd/nmbd_synclists.c b/source3/nmbd/nmbd_synclists.c index 3e672aef25..5da0da81e5 100644 --- a/source3/nmbd/nmbd_synclists.c +++ b/source3/nmbd/nmbd_synclists.c @@ -109,7 +109,7 @@ static void sync_child(char *name, int nm_type, return; } - if (!cli_send_tconX(cli, "IPC$", "IPC", "", 1)) { + if (!NT_STATUS_IS_OK(cli_tcon_andx(cli, "IPC$", "IPC", "", 1))) { cli_shutdown(cli); return; } diff --git a/source3/param/loadparm.c b/source3/param/loadparm.c index 6438888942..bc7d9974f4 100644 --- a/source3/param/loadparm.c +++ b/source3/param/loadparm.c @@ -250,6 +250,7 @@ struct global { char *szLdapIdmapSuffix; char *szLdapGroupSuffix; int ldap_ssl; + bool ldap_ssl_ads; char *szLdapSuffix; char *szLdapAdminDn; int ldap_debug_level; @@ -322,7 +323,8 @@ struct global { bool bHostnameLookups; bool bUnixExtensions; bool bDisableNetbios; - bool bUseKerberosKeytab; + char * szDedicatedKeytabFile; + int iKerberosMethod; bool bDeferSharingViolations; bool bEnablePrivileges; bool bASUSupport; @@ -861,6 +863,17 @@ static const struct enum_list enum_config_backend[] = { {-1, NULL} }; +/* ADS kerberos ticket verification options */ + +static const struct enum_list enum_kerberos_method[] = { + {KERBEROS_VERIFY_SECRETS, "default"}, + {KERBEROS_VERIFY_SECRETS, "secrets only"}, + {KERBEROS_VERIFY_SYSTEM_KEYTAB, "system keytab"}, + {KERBEROS_VERIFY_DEDICATED_KEYTAB, "dedicated keytab"}, + {KERBEROS_VERIFY_SECRETS_AND_KEYTAB, "secrets and keytab"}, + {-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 @@ -1745,14 +1758,24 @@ static struct parm_struct parm_table[] = { .flags = FLAG_ADVANCED | FLAG_GLOBAL, }, { - .label = "use kerberos keytab", - .type = P_BOOL, + .label = "dedicated keytab file", + .type = P_STRING, .p_class = P_GLOBAL, - .ptr = &Globals.bUseKerberosKeytab, + .ptr = &Globals.szDedicatedKeytabFile, .special = NULL, .enum_list = NULL, .flags = FLAG_ADVANCED, }, + { + .label = "kerberos method", + .type = P_ENUM, + .p_class = P_GLOBAL, + .ptr = &Globals.iKerberosMethod, + .special = NULL, + .enum_list = enum_kerberos_method, + .flags = FLAG_ADVANCED, + }, + {N_("Logging Options"), P_SEP, P_SEPARATOR}, @@ -3589,6 +3612,15 @@ static struct parm_struct parm_table[] = { .flags = FLAG_ADVANCED, }, { + .label = "ldap ssl ads", + .type = P_BOOL, + .p_class = P_GLOBAL, + .ptr = &Globals.ldap_ssl_ads, + .special = NULL, + .enum_list = NULL, + .flags = FLAG_ADVANCED, + }, + { .label = "ldap timeout", .type = P_INTEGER, .p_class = P_GLOBAL, @@ -4900,6 +4932,7 @@ static void init_globals(bool first_time_only) string_set(&Globals.szLdapAdminDn, ""); Globals.ldap_ssl = LDAP_SSL_START_TLS; + Globals.ldap_ssl_ads = False; Globals.ldap_passwd_sync = LDAP_PASSWD_SYNC_OFF; Globals.ldap_delete_dn = False; Globals.ldap_replication_sleep = 1000; /* wait 1 sec for replication */ @@ -5244,6 +5277,7 @@ FN_GLOBAL_BOOL(lp_passdb_expand_explicit, &Globals.bPassdbExpandExplicit) FN_GLOBAL_STRING(lp_ldap_suffix, &Globals.szLdapSuffix) FN_GLOBAL_STRING(lp_ldap_admin_dn, &Globals.szLdapAdminDn) FN_GLOBAL_INTEGER(lp_ldap_ssl, &Globals.ldap_ssl) +FN_GLOBAL_BOOL(lp_ldap_ssl_ads, &Globals.ldap_ssl_ads) FN_GLOBAL_INTEGER(lp_ldap_passwd_sync, &Globals.ldap_passwd_sync) FN_GLOBAL_BOOL(lp_ldap_delete_dn, &Globals.ldap_delete_dn) FN_GLOBAL_INTEGER(lp_ldap_replication_sleep, &Globals.ldap_replication_sleep) @@ -5322,7 +5356,8 @@ FN_GLOBAL_BOOL(lp_client_use_spnego, &Globals.bClientUseSpnego) FN_GLOBAL_BOOL(lp_hostname_lookups, &Globals.bHostnameLookups) FN_LOCAL_PARM_BOOL(lp_change_notify, bChangeNotify) FN_LOCAL_PARM_BOOL(lp_kernel_change_notify, bKernelChangeNotify) -FN_GLOBAL_BOOL(lp_use_kerberos_keytab, &Globals.bUseKerberosKeytab) +FN_GLOBAL_STRING(lp_dedicated_keytab_file, &Globals.szDedicatedKeytabFile) +FN_GLOBAL_INTEGER(lp_kerberos_method, &Globals.iKerberosMethod) FN_GLOBAL_BOOL(lp_defer_sharing_violations, &Globals.bDeferSharingViolations) FN_GLOBAL_BOOL(lp_enable_privileges, &Globals.bEnablePrivileges) FN_GLOBAL_BOOL(lp_enable_asu_support, &Globals.bASUSupport) diff --git a/source3/passdb/passdb.c b/source3/passdb/passdb.c index e677d429af..d26a667f44 100644 --- a/source3/passdb/passdb.c +++ b/source3/passdb/passdb.c @@ -7,17 +7,17 @@ Copyright (C) Andrew Bartlett 2001-2002 Copyright (C) Simo Sorce 2003 Copyright (C) Volker Lendecke 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 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/>. */ @@ -67,16 +67,16 @@ static int samu_destroy(struct samu *user) struct samu *samu_new( TALLOC_CTX *ctx ) { struct samu *user; - + if ( !(user = TALLOC_ZERO_P( ctx, struct samu )) ) { DEBUG(0,("samuser_new: Talloc failed!\n")); return NULL; } - + talloc_set_destructor( user, samu_destroy ); - + /* no initial methods */ - + user->methods = NULL; /* Don't change these timestamp settings without a good reason. @@ -98,7 +98,7 @@ struct samu *samu_new( TALLOC_CTX *ctx ) /* Some parts of samba strlen their pdb_get...() returns, so this keeps the interface unchanged for now. */ - + user->username = ""; user->domain = ""; user->nt_username = ""; @@ -118,8 +118,7 @@ struct samu *samu_new( TALLOC_CTX *ctx ) asks for a filtered list of users. */ user->acct_ctrl = ACB_NORMAL; - - + return user; } @@ -140,7 +139,7 @@ static NTSTATUS samu_set_unix_internal(struct samu *user, const struct passwd *p } /* Basic properties based upon the Unix account information */ - + pdb_set_username(user, pwd->pw_name, PDB_SET); pdb_set_fullname(user, pwd->pw_gecos, PDB_SET); pdb_set_domain (user, get_global_sam_name(), PDB_DEFAULT); @@ -149,29 +148,29 @@ static NTSTATUS samu_set_unix_internal(struct samu *user, const struct passwd *p will be rejected by other parts of the Samba code. Rely on pdb_get_group_sid() to "Do The Right Thing" (TM) --jerry */ - + gid_to_sid(&group_sid, pwd->pw_gid); pdb_set_group_sid(user, &group_sid, PDB_SET); #endif - + /* save the password structure for later use */ - + user->unix_pw = tcopy_passwd( user, pwd ); /* Special case for the guest account which must have a RID of 501 */ - + if ( strequal( pwd->pw_name, guest_account ) ) { if ( !pdb_set_user_sid_from_rid(user, DOMAIN_USER_RID_GUEST, PDB_DEFAULT)) { return NT_STATUS_NO_SUCH_USER; } return NT_STATUS_OK; } - + /* Non-guest accounts...Check for a workstation or user account */ if (pwd->pw_name[strlen(pwd->pw_name)-1] == '$') { /* workstation */ - + if (!pdb_set_acct_ctrl(user, ACB_WSTRUST, PDB_DEFAULT)) { DEBUG(1, ("Failed to set 'workstation account' flags for user %s.\n", pwd->pw_name)); @@ -180,15 +179,15 @@ static NTSTATUS samu_set_unix_internal(struct samu *user, const struct passwd *p } else { /* user */ - + if (!pdb_set_acct_ctrl(user, ACB_NORMAL, PDB_DEFAULT)) { DEBUG(1, ("Failed to set 'normal account' flags for user %s.\n", pwd->pw_name)); return NT_STATUS_INVALID_ACCOUNT_NAME; } - + /* set some basic attributes */ - + pdb_set_profile_path(user, talloc_sub_specified(user, lp_logon_path(), pwd->pw_name, domain, pwd->pw_uid, pwd->pw_gid), PDB_DEFAULT); @@ -202,7 +201,7 @@ static NTSTATUS samu_set_unix_internal(struct samu *user, const struct passwd *p lp_logon_script(), pwd->pw_name, domain, pwd->pw_uid, pwd->pw_gid), PDB_DEFAULT); } - + /* Now deal with the user SID. If we have a backend that can generate RIDs, then do so. But sometimes the caller just wanted a structure initialized and will fill in these fields later (such as from a @@ -211,7 +210,7 @@ static NTSTATUS samu_set_unix_internal(struct samu *user, const struct passwd *p if ( create && !pdb_rid_algorithm() ) { uint32 user_rid; DOM_SID user_sid; - + if ( !pdb_new_rid( &user_rid ) ) { DEBUG(3, ("Could not allocate a new RID\n")); return NT_STATUS_ACCESS_DENIED; @@ -224,18 +223,18 @@ static NTSTATUS samu_set_unix_internal(struct samu *user, const struct passwd *p DEBUG(3, ("pdb_set_user_sid failed\n")); return NT_STATUS_INTERNAL_ERROR; } - + return NT_STATUS_OK; } /* generate a SID for the user with the RID algorithm */ - + urid = algorithmic_pdb_uid_to_user_rid( user->unix_pw->pw_uid ); - + if ( !pdb_set_user_sid_from_rid( user, urid, PDB_SET) ) { return NT_STATUS_INTERNAL_ERROR; } - + return NT_STATUS_OK; } @@ -365,10 +364,10 @@ bool pdb_gethexpwd(const char *p, unsigned char *pwd) unsigned char lonybble, hinybble; const char *hexchars = "0123456789ABCDEF"; char *p1, *p2; - + if (!p) return false; - + for (i = 0; i < 32; i += 2) { hinybble = toupper_ascii(p[i]); lonybble = toupper_ascii(p[i + 1]); @@ -554,16 +553,16 @@ bool lookup_global_sam_name(const char *name, int flags, uint32_t *rid, { GROUP_MAP map; bool ret; - + /* Windows treats "MACHINE\None" as a special name for rid 513 on non-DCs. You cannot create a user or group name "None" on Windows. You will get an error that the group already exists. */ - + if ( strequal( name, "None" ) ) { *rid = DOMAIN_GROUP_RID_USERS; *type = SID_NAME_DOM_GRP; - + return True; } @@ -578,7 +577,7 @@ bool lookup_global_sam_name(const char *name, int flags, uint32_t *rid, if ( !(sam_account = samu_new( NULL )) ) { return False; } - + become_root(); ret = pdb_getsampwnam(sam_account, name); unbecome_root(); @@ -586,7 +585,7 @@ bool lookup_global_sam_name(const char *name, int flags, uint32_t *rid, if (ret) { sid_copy(&user_sid, pdb_get_user_sid(sam_account)); } - + TALLOC_FREE(sam_account); if (ret) { @@ -654,7 +653,7 @@ NTSTATUS local_password_change(const char *user_name, if(!pdb_getsampwnam(sam_pass, user_name)) { unbecome_root(); TALLOC_FREE(sam_pass); - + if ((local_flags & LOCAL_ADD_USER) || (local_flags & LOCAL_DELETE_USER)) { int tmp_debug = DEBUGLEVEL; struct passwd *pwd; @@ -754,7 +753,7 @@ NTSTATUS local_password_change(const char *user_name, return NT_STATUS_UNSUCCESSFUL; } } - + if (local_flags & LOCAL_SET_NO_PASSWORD) { if (!pdb_set_acct_ctrl (sam_pass, pdb_get_acct_ctrl(sam_pass)|ACB_PWNOTREQ, PDB_CHANGED)) { if (asprintf(pp_err_str, "Failed to set 'no password required' flag for user %s.\n", user_name) < 0) { @@ -789,7 +788,7 @@ NTSTATUS local_password_change(const char *user_name, TALLOC_FREE(sam_pass); return NT_STATUS_UNSUCCESSFUL; } - + if (!pdb_set_plaintext_passwd (sam_pass, new_passwd)) { if (asprintf(pp_err_str, "Failed to set password for user %s.\n", user_name) < 0) { *pp_err_str = NULL; @@ -893,7 +892,7 @@ static bool init_samu_from_buffer_v0(struct samu *sampass, uint8 *buf, uint32 bu dir_drive_len, unknown_str_len, munged_dial_len, fullname_len, homedir_len, logon_script_len, profile_path_len, acct_desc_len, workstations_len; - + uint32 user_rid, group_rid, remove_me, hours_len, unknown_6; uint16 acct_ctrl, logon_divs; uint16 bad_password_count, logon_count; @@ -902,7 +901,7 @@ static bool init_samu_from_buffer_v0(struct samu *sampass, uint8 *buf, uint32 bu uint32 len = 0; uint32 lm_pw_len, nt_pw_len, hourslen; bool ret = True; - + if(sampass == NULL || buf == NULL) { DEBUG(0, ("init_samu_from_buffer_v0: NULL parameters found!\n")); return False; @@ -942,7 +941,7 @@ static bool init_samu_from_buffer_v0(struct samu *sampass, uint8 *buf, uint32 bu &bad_password_count, /* w */ &logon_count, /* w */ &unknown_6); /* d */ - + if (len == (uint32) -1) { ret = False; goto done; @@ -987,7 +986,7 @@ static bool init_samu_from_buffer_v0(struct samu *sampass, uint8 *buf, uint32 bu lp_logon_script()), PDB_DEFAULT); } - + if (profile_path) { pdb_set_profile_path(sampass, profile_path, PDB_SET); } else { @@ -1079,7 +1078,7 @@ static bool init_samu_from_buffer_v1(struct samu *sampass, uint8 *buf, uint32 bu dir_drive_len, unknown_str_len, munged_dial_len, fullname_len, homedir_len, logon_script_len, profile_path_len, acct_desc_len, workstations_len; - + uint32 user_rid, group_rid, remove_me, hours_len, unknown_6; uint16 acct_ctrl, logon_divs; uint16 bad_password_count, logon_count; @@ -1088,7 +1087,7 @@ static bool init_samu_from_buffer_v1(struct samu *sampass, uint8 *buf, uint32 bu uint32 len = 0; uint32 lm_pw_len, nt_pw_len, hourslen; bool ret = True; - + if(sampass == NULL || buf == NULL) { DEBUG(0, ("init_samu_from_buffer_v1: NULL parameters found!\n")); return False; @@ -1130,7 +1129,7 @@ static bool init_samu_from_buffer_v1(struct samu *sampass, uint8 *buf, uint32 bu &bad_password_count, /* w */ &logon_count, /* w */ &unknown_6); /* d */ - + if (len == (uint32) -1) { ret = False; goto done; @@ -1178,7 +1177,7 @@ static bool init_samu_from_buffer_v1(struct samu *sampass, uint8 *buf, uint32 bu lp_logon_script()), PDB_DEFAULT); } - + if (profile_path) { pdb_set_profile_path(sampass, profile_path, PDB_SET); } else { @@ -1268,7 +1267,7 @@ static bool init_samu_from_buffer_v2(struct samu *sampass, uint8 *buf, uint32 bu dir_drive_len, unknown_str_len, munged_dial_len, fullname_len, homedir_len, logon_script_len, profile_path_len, acct_desc_len, workstations_len; - + uint32 user_rid, group_rid, hours_len, unknown_6; uint16 acct_ctrl, logon_divs; uint16 bad_password_count, logon_count; @@ -1280,12 +1279,12 @@ static bool init_samu_from_buffer_v2(struct samu *sampass, uint8 *buf, uint32 bu bool ret = True; fstring tmp_string; bool expand_explicit = lp_passdb_expand_explicit(); - + if(sampass == NULL || buf == NULL) { DEBUG(0, ("init_samu_from_buffer_v2: NULL parameters found!\n")); return False; } - + /* SAMU_BUFFER_FORMAT_V2 "dddddddBBBBBBBBBBBBddBBBwwdBwwd" */ /* unpack the buffer into variables */ @@ -1323,7 +1322,7 @@ static bool init_samu_from_buffer_v2(struct samu *sampass, uint8 *buf, uint32 bu &bad_password_count, /* w */ &logon_count, /* w */ &unknown_6); /* d */ - + if (len == (uint32) -1) { ret = False; goto done; @@ -1376,7 +1375,7 @@ static bool init_samu_from_buffer_v2(struct samu *sampass, uint8 *buf, uint32 bu lp_logon_script()), PDB_DEFAULT); } - + if (profile_path) { fstrcpy( tmp_string, profile_path ); if (expand_explicit) { @@ -1503,7 +1502,7 @@ static bool init_samu_from_buffer_v3(struct samu *sampass, uint8 *buf, uint32 bu dir_drive_len, unknown_str_len, munged_dial_len, fullname_len, homedir_len, logon_script_len, profile_path_len, acct_desc_len, workstations_len; - + uint32 user_rid, group_rid, hours_len, unknown_6, acct_ctrl; uint16 logon_divs; uint16 bad_password_count, logon_count; @@ -1515,12 +1514,12 @@ static bool init_samu_from_buffer_v3(struct samu *sampass, uint8 *buf, uint32 bu bool ret = True; fstring tmp_string; bool expand_explicit = lp_passdb_expand_explicit(); - + if(sampass == NULL || buf == NULL) { DEBUG(0, ("init_samu_from_buffer_v3: NULL parameters found!\n")); return False; } - + /* SAMU_BUFFER_FORMAT_V3 "dddddddBBBBBBBBBBBBddBBBdwdBwwd" */ /* unpack the buffer into variables */ @@ -1559,7 +1558,7 @@ static bool init_samu_from_buffer_v3(struct samu *sampass, uint8 *buf, uint32 bu &bad_password_count, /* w */ &logon_count, /* w */ &unknown_6); /* d */ - + if (len == (uint32) -1) { ret = False; goto done; @@ -1612,7 +1611,7 @@ static bool init_samu_from_buffer_v3(struct samu *sampass, uint8 *buf, uint32 bu lp_logon_script()), PDB_DEFAULT); } - + if (profile_path) { fstrcpy( tmp_string, profile_path ); if (expand_explicit) { @@ -1839,12 +1838,12 @@ static uint32 init_buffer_from_samu_v3 (uint8 **buf, struct samu *sampass, bool } else { profile_path_len = 0; } - + lm_pw = pdb_get_lanman_passwd(sampass); if (!lm_pw) { lm_pw_len = 0; } - + nt_pw = pdb_get_nt_passwd(sampass); if (!nt_pw) { nt_pw_len = 0; @@ -1927,7 +1926,7 @@ static uint32 init_buffer_from_samu_v3 (uint8 **buf, struct samu *sampass, bool DEBUG(0,("init_buffer_from_samu_v3: Unable to malloc() memory for buffer!\n")); return (-1); } - + /* now for the real call to tdb_pack() */ buflen = tdb_pack(*buf, len, SAMU_BUFFER_FORMAT_V3, logon_time, /* d */ @@ -1961,7 +1960,7 @@ static uint32 init_buffer_from_samu_v3 (uint8 **buf, struct samu *sampass, bool pdb_get_bad_password_count(sampass), /* w */ pdb_get_logon_count(sampass), /* w */ pdb_get_unknown_6(sampass)); /* d */ - + /* check to make sure we got it correct */ if (buflen != len) { DEBUG(0, ("init_buffer_from_samu_v3: somthing odd is going on here: bufflen (%lu) != len (%lu) in tdb_pack operations!\n", @@ -2038,7 +2037,7 @@ bool pdb_copy_sam_account(struct samu *dst, struct samu *src ) } dst->methods = src->methods; - + if ( src->unix_pw ) { dst->unix_pw = tcopy_passwd( dst, src->unix_pw ); if (!dst->unix_pw) { @@ -2127,7 +2126,7 @@ bool pdb_update_autolock_flag(struct samu *sampass, bool *updated) DEBUG(9, ("pdb_update_autolock_flag: No reset duration, can't reset autolock\n")); return True; } - + LastBadPassword = pdb_get_bad_password_time(sampass); DEBUG(7, ("pdb_update_autolock_flag: Account %s, LastBadPassword=%d, duration=%d, current time =%d.\n", pdb_get_username(sampass), (uint32)LastBadPassword, duration*60, (uint32)time(NULL))); @@ -2150,7 +2149,7 @@ bool pdb_update_autolock_flag(struct samu *sampass, bool *updated) *updated = True; } } - + return True; } diff --git a/source3/printing/printing.c b/source3/printing/printing.c index bb29380007..0721713c01 100644 --- a/source3/printing/printing.c +++ b/source3/printing/printing.c @@ -22,8 +22,6 @@ #include "includes.h" #include "printing.h" -extern SIG_ATOMIC_T got_sig_term; -extern SIG_ATOMIC_T reload_after_sighup; extern struct current_user current_user; extern userdom_struct current_user_info; @@ -1427,6 +1425,9 @@ void start_background_queue(void) smb_panic("reinit_after_fork() failed"); } + smbd_setup_sig_term_handler(); + smbd_setup_sig_hup_handler(); + claim_connection( NULL, "smbd lpq backend", FLAG_MSG_GENERAL|FLAG_MSG_SMBD|FLAG_MSG_PRINT_GENERAL); @@ -1483,19 +1484,6 @@ void start_background_queue(void) exit_server_cleanly(NULL); } - /* check for some essential signals first */ - - if (got_sig_term) { - exit_server_cleanly(NULL); - } - - if (reload_after_sighup) { - change_to_root_user(); - DEBUG(1,("Reloading services after SIGHUP\n")); - reload_services(False); - reload_after_sighup = 0; - } - if (run_events(smbd_event_context(), ret, &r_fds, &w_fds)) { continue; } diff --git a/source3/registry/reg_init_basic.c b/source3/registry/reg_init_basic.c index 60dcabdcf2..eab4ca7f9d 100644 --- a/source3/registry/reg_init_basic.c +++ b/source3/registry/reg_init_basic.c @@ -37,6 +37,14 @@ WERROR registry_init_common(void) if (!W_ERROR_IS_OK(werr)) { DEBUG(0, ("Failed to initialize the reghook cache: %s\n", win_errstr(werr))); + goto done; + } + + /* setup the necessary keys and values */ + + werr = init_registry_data(); + if (!W_ERROR_IS_OK(werr)) { + DEBUG(0, ("Failed to initialize data in registry!\n")); } done: diff --git a/source3/registry/reg_init_full.c b/source3/registry/reg_init_full.c index 91e55d76b2..b5a06f2582 100644 --- a/source3/registry/reg_init_full.c +++ b/source3/registry/reg_init_full.c @@ -72,14 +72,6 @@ WERROR registry_init_full(void) goto fail; } - /* setup the necessary keys and values */ - - werr = init_registry_data(); - if (!W_ERROR_IS_OK(werr)) { - DEBUG(0, ("Failed to initialize data in registry!\n")); - goto fail; - } - /* build the cache tree of registry hooks */ for ( i=0; reg_hooks[i].keyname; i++ ) { diff --git a/source3/rpc_client/cli_pipe.c b/source3/rpc_client/cli_pipe.c index 5a53c0d940..2841ff08f6 100644 --- a/source3/rpc_client/cli_pipe.c +++ b/source3/rpc_client/cli_pipe.c @@ -81,9 +81,10 @@ static const struct pipe_id_info { Return the pipe name from the interface. ****************************************************************************/ -const char *cli_get_pipe_name_from_iface(TALLOC_CTX *mem_ctx, - const struct ndr_syntax_id *interface) +const char *get_pipe_name_from_iface(const struct ndr_syntax_id *interface) { + char *guid_str; + const char *result; int i; for (i = 0; pipe_names[i].client_pipe; i++) { if (ndr_syntax_id_equal(pipe_names[i].abstr_syntax, @@ -97,7 +98,18 @@ const char *cli_get_pipe_name_from_iface(TALLOC_CTX *mem_ctx, * interested in the known pipes mentioned in pipe_names[] */ - return NULL; + guid_str = GUID_string(talloc_tos(), &interface->uuid); + if (guid_str == NULL) { + return NULL; + } + result = talloc_asprintf(talloc_tos(), "Interface %s.%d", guid_str, + (int)interface->if_version); + TALLOC_FREE(guid_str); + + if (result == NULL) { + return "PIPE"; + } + return result; } /******************************************************************** @@ -243,7 +255,7 @@ static void rpc_read_done(struct async_req *subreq) status = state->transport->read_recv(subreq, &received); TALLOC_FREE(subreq); if (!NT_STATUS_IS_OK(status)) { - async_req_error(req, status); + async_req_nterror(req, status); return; } @@ -266,7 +278,7 @@ static void rpc_read_done(struct async_req *subreq) static NTSTATUS rpc_read_recv(struct async_req *req) { - return async_req_simple_recv(req); + return async_req_simple_recv_ntstatus(req); } struct rpc_write_state { @@ -323,7 +335,7 @@ static void rpc_write_done(struct async_req *subreq) status = state->transport->write_recv(subreq, &written); TALLOC_FREE(subreq); if (!NT_STATUS_IS_OK(status)) { - async_req_error(req, status); + async_req_nterror(req, status); return; } @@ -347,7 +359,7 @@ static void rpc_write_done(struct async_req *subreq) static NTSTATUS rpc_write_recv(struct async_req *req) { - return async_req_simple_recv(req); + return async_req_simple_recv_ntstatus(req); } @@ -458,7 +470,7 @@ static struct async_req *get_complete_frag_send(TALLOC_CTX *mem_ctx, status = NT_STATUS_OK; post_status: - if (async_post_status(result, ev, status)) { + if (async_post_ntstatus(result, ev, status)) { return result; } TALLOC_FREE(result); @@ -476,18 +488,18 @@ static void get_complete_frag_got_header(struct async_req *subreq) status = rpc_read_recv(subreq); TALLOC_FREE(subreq); if (!NT_STATUS_IS_OK(status)) { - async_req_error(req, status); + async_req_nterror(req, status); return; } status = parse_rpc_header(state->cli, state->prhdr, state->pdu); if (!NT_STATUS_IS_OK(status)) { - async_req_error(req, status); + async_req_nterror(req, status); return; } if (!rpc_grow_buffer(state->pdu, state->prhdr->frag_len)) { - async_req_error(req, NT_STATUS_NO_MEMORY); + async_req_nterror(req, NT_STATUS_NO_MEMORY); return; } @@ -516,7 +528,7 @@ static void get_complete_frag_got_rest(struct async_req *subreq) status = rpc_read_recv(subreq); TALLOC_FREE(subreq); if (!NT_STATUS_IS_OK(status)) { - async_req_error(req, status); + async_req_nterror(req, status); return; } async_req_done(req); @@ -524,7 +536,7 @@ static void get_complete_frag_got_rest(struct async_req *subreq) static NTSTATUS get_complete_frag_recv(struct async_req *req) { - return async_req_simple_recv(req); + return async_req_simple_recv_ntstatus(req); } /**************************************************************************** @@ -1084,7 +1096,7 @@ static struct async_req *cli_api_pipe_send(TALLOC_CTX *mem_ctx, status = NT_STATUS_INVALID_PARAMETER; post_status: - if (async_post_status(result, ev, status)) { + if (async_post_ntstatus(result, ev, status)) { return result; } fail: @@ -1104,7 +1116,7 @@ static void cli_api_pipe_trans_done(struct async_req *subreq) &state->rdata_len); TALLOC_FREE(subreq); if (!NT_STATUS_IS_OK(status)) { - async_req_error(req, status); + async_req_nterror(req, status); return; } async_req_done(req); @@ -1121,7 +1133,7 @@ static void cli_api_pipe_write_done(struct async_req *subreq) status = rpc_write_recv(subreq); TALLOC_FREE(subreq); if (!NT_STATUS_IS_OK(status)) { - async_req_error(req, status); + async_req_nterror(req, status); return; } @@ -1157,7 +1169,7 @@ static void cli_api_pipe_read_done(struct async_req *subreq) status = state->transport->read_recv(subreq, &received); TALLOC_FREE(subreq); if (!NT_STATUS_IS_OK(status)) { - async_req_error(req, status); + async_req_nterror(req, status); return; } state->rdata_len = received; @@ -1171,7 +1183,7 @@ static NTSTATUS cli_api_pipe_recv(struct async_req *req, TALLOC_CTX *mem_ctx, req->private_data, struct cli_api_pipe_state); NTSTATUS status; - if (async_req_is_error(req, &status)) { + if (async_req_is_nterror(req, &status)) { return status; } @@ -1252,7 +1264,7 @@ static struct async_req *rpc_api_pipe_send(TALLOC_CTX *mem_ctx, prs_init_empty(&state->incoming_pdu, state, UNMARSHALL); /* Make incoming_pdu dynamic with no memory. */ - prs_give_memory(&state->incoming_pdu, 0, 0, true); + prs_give_memory(&state->incoming_pdu, NULL, 0, true); talloc_set_destructor(state, rpc_api_pipe_state_destructor); @@ -1284,7 +1296,7 @@ static struct async_req *rpc_api_pipe_send(TALLOC_CTX *mem_ctx, return result; post_status: - if (async_post_status(result, ev, status)) { + if (async_post_ntstatus(result, ev, status)) { return result; } TALLOC_FREE(result); @@ -1306,7 +1318,7 @@ static void rpc_api_pipe_trans_done(struct async_req *subreq) TALLOC_FREE(subreq); if (!NT_STATUS_IS_OK(status)) { DEBUG(5, ("cli_api_pipe failed: %s\n", nt_errstr(status))); - async_req_error(req, status); + async_req_nterror(req, status); return; } @@ -1354,7 +1366,7 @@ static void rpc_api_pipe_got_pdu(struct async_req *subreq) if (!NT_STATUS_IS_OK(status)) { DEBUG(5, ("get_complete_frag failed: %s\n", nt_errstr(status))); - async_req_error(req, status); + async_req_nterror(req, status); return; } @@ -1369,7 +1381,7 @@ static void rpc_api_pipe_got_pdu(struct async_req *subreq) nt_errstr(status))); if (!NT_STATUS_IS_OK(status)) { - async_req_error(req, status); + async_req_nterror(req, status); return; } @@ -1393,13 +1405,13 @@ static void rpc_api_pipe_got_pdu(struct async_req *subreq) "%s\n", state->incoming_pdu.bigendian_data?"big":"little", state->incoming_frag.bigendian_data?"big":"little")); - async_req_error(req, NT_STATUS_INVALID_PARAMETER); + async_req_nterror(req, NT_STATUS_INVALID_PARAMETER); return; } /* Now copy the data portion out of the pdu into rbuf. */ if (!prs_force_grow(&state->incoming_pdu, rdata_len)) { - async_req_error(req, NT_STATUS_NO_MEMORY); + async_req_nterror(req, NT_STATUS_NO_MEMORY); return; } @@ -1410,7 +1422,7 @@ static void rpc_api_pipe_got_pdu(struct async_req *subreq) status = cli_pipe_reset_current_pdu(state->cli, &state->rhdr, &state->incoming_frag); if (!NT_STATUS_IS_OK(status)) { - async_req_error(req, status); + async_req_nterror(req, status); return; } @@ -1438,7 +1450,7 @@ static NTSTATUS rpc_api_pipe_recv(struct async_req *req, TALLOC_CTX *mem_ctx, req->private_data, struct rpc_api_pipe_state); NTSTATUS status; - if (async_req_is_error(req, &status)) { + if (async_req_is_nterror(req, &status)) { return status; } @@ -2105,7 +2117,7 @@ struct async_req *rpc_api_pipe_req_send(TALLOC_CTX *mem_ctx, return result; post_status: - if (async_post_status(result, ev, status)) { + if (async_post_ntstatus(result, ev, status)) { return result; } TALLOC_FREE(result); @@ -2209,13 +2221,13 @@ static void rpc_api_pipe_req_write_done(struct async_req *subreq) status = rpc_write_recv(subreq); TALLOC_FREE(subreq); if (!NT_STATUS_IS_OK(status)) { - async_req_error(req, status); + async_req_nterror(req, status); return; } status = prepare_next_frag(state, &is_last_frag); if (!NT_STATUS_IS_OK(status)) { - async_req_error(req, status); + async_req_nterror(req, status); return; } @@ -2253,7 +2265,7 @@ static void rpc_api_pipe_req_done(struct async_req *subreq) status = rpc_api_pipe_recv(subreq, state, &state->reply_pdu); TALLOC_FREE(subreq); if (!NT_STATUS_IS_OK(status)) { - async_req_error(req, status); + async_req_nterror(req, status); return; } async_req_done(req); @@ -2266,7 +2278,7 @@ NTSTATUS rpc_api_pipe_req_recv(struct async_req *req, TALLOC_CTX *mem_ctx, req->private_data, struct rpc_api_pipe_req_state); NTSTATUS status; - if (async_req_is_error(req, &status)) { + if (async_req_is_nterror(req, &status)) { /* * We always have to initialize to reply pdu, even if there is * none. The rpccli_* caller routines expect this. @@ -2573,7 +2585,7 @@ struct async_req *rpc_pipe_bind_send(TALLOC_CTX *mem_ctx, return result; post_status: - if (async_post_status(result, ev, status)) { + if (async_post_ntstatus(result, ev, status)) { return result; } TALLOC_FREE(result); @@ -2597,27 +2609,30 @@ static void rpc_pipe_bind_step_one_done(struct async_req *subreq) DEBUG(3, ("rpc_pipe_bind: %s bind request returned %s\n", rpccli_pipe_txt(debug_ctx(), state->cli), nt_errstr(status))); - async_req_error(req, status); + async_req_nterror(req, status); return; } /* Unmarshall the RPC header */ if (!smb_io_rpc_hdr("hdr", &hdr, &reply_pdu, 0)) { DEBUG(0, ("rpc_pipe_bind: failed to unmarshall RPC_HDR.\n")); - async_req_error(req, NT_STATUS_BUFFER_TOO_SMALL); + prs_mem_free(&reply_pdu); + async_req_nterror(req, NT_STATUS_BUFFER_TOO_SMALL); return; } if (!smb_io_rpc_hdr_ba("", &hdr_ba, &reply_pdu, 0)) { DEBUG(0, ("rpc_pipe_bind: Failed to unmarshall " "RPC_HDR_BA.\n")); - async_req_error(req, NT_STATUS_BUFFER_TOO_SMALL); + prs_mem_free(&reply_pdu); + async_req_nterror(req, NT_STATUS_BUFFER_TOO_SMALL); return; } if (!check_bind_response(&hdr_ba, &state->cli->transfer_syntax)) { DEBUG(2, ("rpc_pipe_bind: check_bind_response failed.\n")); - async_req_error(req, NT_STATUS_BUFFER_TOO_SMALL); + prs_mem_free(&reply_pdu); + async_req_nterror(req, NT_STATUS_BUFFER_TOO_SMALL); return; } @@ -2633,6 +2648,7 @@ static void rpc_pipe_bind_step_one_done(struct async_req *subreq) case PIPE_AUTH_TYPE_NONE: case PIPE_AUTH_TYPE_SCHANNEL: /* Bind complete. */ + prs_mem_free(&reply_pdu); async_req_done(req); break; @@ -2640,8 +2656,9 @@ static void rpc_pipe_bind_step_one_done(struct async_req *subreq) /* Need to send AUTH3 packet - no reply. */ status = rpc_finish_auth3_bind_send(req, state, &hdr, &reply_pdu); + prs_mem_free(&reply_pdu); if (!NT_STATUS_IS_OK(status)) { - async_req_error(req, status); + async_req_nterror(req, status); } break; @@ -2649,8 +2666,9 @@ static void rpc_pipe_bind_step_one_done(struct async_req *subreq) /* Need to send alter context request and reply. */ status = rpc_finish_spnego_ntlmssp_bind_send(req, state, &hdr, &reply_pdu); + prs_mem_free(&reply_pdu); if (!NT_STATUS_IS_OK(status)) { - async_req_error(req, status); + async_req_nterror(req, status); } break; @@ -2660,7 +2678,8 @@ static void rpc_pipe_bind_step_one_done(struct async_req *subreq) default: DEBUG(0,("cli_finish_bind_auth: unknown auth type %u\n", (unsigned int)state->cli->auth->auth_type)); - async_req_error(req, NT_STATUS_INTERNAL_ERROR); + prs_mem_free(&reply_pdu); + async_req_nterror(req, NT_STATUS_INTERNAL_ERROR); } } @@ -2737,7 +2756,7 @@ static void rpc_bind_auth3_write_done(struct async_req *subreq) status = rpc_write_recv(subreq); TALLOC_FREE(subreq); if (!NT_STATUS_IS_OK(status)) { - async_req_error(req, status); + async_req_nterror(req, status); return; } async_req_done(req); @@ -2852,7 +2871,7 @@ static void rpc_bind_ntlmssp_api_done(struct async_req *subreq) status = rpc_api_pipe_recv(subreq, talloc_tos(), &reply_pdu); TALLOC_FREE(subreq); if (!NT_STATUS_IS_OK(status)) { - async_req_error(req, status); + async_req_nterror(req, status); return; } @@ -2860,19 +2879,19 @@ static void rpc_bind_ntlmssp_api_done(struct async_req *subreq) if (!smb_io_rpc_hdr("rpc_hdr ", &hdr, &reply_pdu, 0)) { DEBUG(0, ("rpc_finish_spnego_ntlmssp_bind: Failed to " "unmarshall RPC_HDR.\n")); - async_req_error(req, NT_STATUS_BUFFER_TOO_SMALL); + async_req_nterror(req, NT_STATUS_BUFFER_TOO_SMALL); return; } if (!prs_set_offset( &reply_pdu, hdr.frag_len - hdr.auth_len - RPC_HDR_AUTH_LEN)) { - async_req_error(req, NT_STATUS_INVALID_PARAMETER); + async_req_nterror(req, NT_STATUS_INVALID_PARAMETER); return; } if (!smb_io_rpc_hdr_auth("hdr_auth", &hdr_auth, &reply_pdu, 0)) { - async_req_error(req, NT_STATUS_INVALID_PARAMETER); + async_req_nterror(req, NT_STATUS_INVALID_PARAMETER); return; } @@ -2885,7 +2904,7 @@ static void rpc_bind_ntlmssp_api_done(struct async_req *subreq) OID_NTLMSSP, &tmp_blob)) { data_blob_free(&server_spnego_response); data_blob_free(&tmp_blob); - async_req_error(req, NT_STATUS_INVALID_PARAMETER); + async_req_nterror(req, NT_STATUS_INVALID_PARAMETER); return; } @@ -2899,7 +2918,7 @@ static void rpc_bind_ntlmssp_api_done(struct async_req *subreq) NTSTATUS rpc_pipe_bind_recv(struct async_req *req) { - return async_req_simple_recv(req); + return async_req_simple_recv_ntstatus(req); } NTSTATUS rpc_pipe_bind(struct rpc_pipe_client *cli, @@ -3511,6 +3530,61 @@ static NTSTATUS rpc_pipe_open_np(struct cli_state *cli, return NT_STATUS_OK; } +NTSTATUS rpc_pipe_open_local(TALLOC_CTX *mem_ctx, + struct rpc_cli_smbd_conn *conn, + const struct ndr_syntax_id *syntax, + struct rpc_pipe_client **presult) +{ + struct rpc_pipe_client *result; + struct cli_pipe_auth_data *auth; + NTSTATUS status; + + result = talloc(mem_ctx, struct rpc_pipe_client); + if (result == NULL) { + return NT_STATUS_NO_MEMORY; + } + result->abstract_syntax = *syntax; + result->transfer_syntax = ndr_transfer_syntax; + result->dispatch = cli_do_rpc_ndr; + result->max_xmit_frag = RPC_MAX_PDU_FRAG_LEN; + result->max_recv_frag = RPC_MAX_PDU_FRAG_LEN; + + result->desthost = talloc_strdup(result, global_myname()); + result->srv_name_slash = talloc_asprintf_strupper_m( + result, "\\\\%s", global_myname()); + if ((result->desthost == NULL) || (result->srv_name_slash == NULL)) { + TALLOC_FREE(result); + return NT_STATUS_NO_MEMORY; + } + + status = rpc_transport_smbd_init(result, conn, syntax, + &result->transport); + if (!NT_STATUS_IS_OK(status)) { + DEBUG(1, ("rpc_transport_smbd_init failed: %s\n", + nt_errstr(status))); + TALLOC_FREE(result); + return status; + } + + status = rpccli_anon_bind_data(result, &auth); + if (!NT_STATUS_IS_OK(status)) { + DEBUG(1, ("rpccli_anon_bind_data failed: %s\n", + nt_errstr(status))); + TALLOC_FREE(result); + return status; + } + + status = rpc_pipe_bind(result, auth); + if (!NT_STATUS_IS_OK(status)) { + DEBUG(1, ("rpc_pipe_bind failed: %s\n", nt_errstr(status))); + TALLOC_FREE(result); + return status; + } + + *presult = result; + return NT_STATUS_OK; +} + /**************************************************************************** Open a pipe to a remote server. ****************************************************************************/ @@ -3587,8 +3661,7 @@ NTSTATUS cli_rpc_pipe_open_noauth(struct cli_state *cli, } DEBUG(lvl, ("cli_rpc_pipe_open_noauth: rpc_pipe_bind for pipe " "%s failed with error %s\n", - cli_get_pipe_name_from_iface(debug_ctx(), - interface), + get_pipe_name_from_iface(interface), nt_errstr(status) )); TALLOC_FREE(result); return status; @@ -3596,8 +3669,7 @@ NTSTATUS cli_rpc_pipe_open_noauth(struct cli_state *cli, DEBUG(10,("cli_rpc_pipe_open_noauth: opened pipe %s to machine " "%s and bound anonymously.\n", - cli_get_pipe_name_from_iface(debug_ctx(), interface), - cli->desthost )); + get_pipe_name_from_iface(interface), cli->desthost)); *presult = result; return NT_STATUS_OK; @@ -3643,8 +3715,8 @@ static NTSTATUS cli_rpc_pipe_open_ntlmssp_internal(struct cli_state *cli, DEBUG(10,("cli_rpc_pipe_open_ntlmssp_internal: opened pipe %s to " "machine %s and bound NTLMSSP as user %s\\%s.\n", - cli_get_pipe_name_from_iface(debug_ctx(), interface), - cli->desthost, domain, username )); + get_pipe_name_from_iface(interface), cli->desthost, domain, + username )); *presult = result; return NT_STATUS_OK; @@ -3835,7 +3907,7 @@ NTSTATUS cli_rpc_pipe_open_schannel_with_key(struct cli_state *cli, DEBUG(10,("cli_rpc_pipe_open_schannel_with_key: opened pipe %s to machine %s " "for domain %s and bound using schannel.\n", - cli_get_pipe_name_from_iface(debug_ctx(), interface), + get_pipe_name_from_iface(interface), cli->desthost, domain )); *presult = result; @@ -4045,40 +4117,3 @@ NTSTATUS cli_get_session_key(TALLOC_CTX *mem_ctx, return NT_STATUS_OK; } - -/** - * Create a new RPC client context which uses a local dispatch function. - */ -NTSTATUS rpc_pipe_open_internal(TALLOC_CTX *mem_ctx, const struct ndr_syntax_id *abstract_syntax, - NTSTATUS (*dispatch) (struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, const struct ndr_interface_table *table, uint32_t opnum, void *r), - struct auth_serversupplied_info *serversupplied_info, - struct rpc_pipe_client **presult) -{ - struct rpc_pipe_client *result; - - result = TALLOC_ZERO_P(mem_ctx, struct rpc_pipe_client); - if (result == NULL) { - return NT_STATUS_NO_MEMORY; - } - - result->abstract_syntax = *abstract_syntax; - result->transfer_syntax = ndr_transfer_syntax; - result->dispatch = dispatch; - - result->pipes_struct = TALLOC_ZERO_P(mem_ctx, pipes_struct); - if (result->pipes_struct == NULL) { - TALLOC_FREE(result); - return NT_STATUS_NO_MEMORY; - } - result->pipes_struct->mem_ctx = mem_ctx; - result->pipes_struct->server_info = serversupplied_info; - result->pipes_struct->pipe_bound = true; - - result->max_xmit_frag = -1; - result->max_recv_frag = -1; - - *presult = result; - return NT_STATUS_OK; -} - - diff --git a/source3/rpc_client/init_netlogon.c b/source3/rpc_client/init_netlogon.c index 6f7a541f72..793b9c7de5 100644 --- a/source3/rpc_client/init_netlogon.c +++ b/source3/rpc_client/init_netlogon.c @@ -144,7 +144,8 @@ static NTSTATUS nt_token_to_group_list(TALLOC_CTX *mem_ctx, const DOM_SID *domain_sid, size_t num_sids, const DOM_SID *sids, - int *numgroups, DOM_GID **pgids) + int *numgroups, + struct samr_RidWithAttribute **pgids) { int i; @@ -152,13 +153,14 @@ static NTSTATUS nt_token_to_group_list(TALLOC_CTX *mem_ctx, *pgids = NULL; for (i=0; i<num_sids; i++) { - DOM_GID gid; - if (!sid_peek_check_rid(domain_sid, &sids[i], &gid.g_rid)) { + struct samr_RidWithAttribute gid; + if (!sid_peek_check_rid(domain_sid, &sids[i], &gid.rid)) { continue; } - gid.attr = (SE_GROUP_MANDATORY|SE_GROUP_ENABLED_BY_DEFAULT| + gid.attributes = (SE_GROUP_MANDATORY|SE_GROUP_ENABLED_BY_DEFAULT| SE_GROUP_ENABLED); - ADD_TO_ARRAY(mem_ctx, DOM_GID, gid, pgids, numgroups); + ADD_TO_ARRAY(mem_ctx, struct samr_RidWithAttribute, + gid, pgids, numgroups); if (*pgids == NULL) { return NT_STATUS_NO_MEMORY; } @@ -177,7 +179,7 @@ NTSTATUS serverinfo_to_SamInfo3(struct auth_serversupplied_info *server_info, struct netr_SamInfo3 *sam3) { struct samu *sampw; - DOM_GID *gids = NULL; + struct samr_RidWithAttribute *gids = NULL; const DOM_SID *user_sid = NULL; const DOM_SID *group_sid = NULL; DOM_SID domain_sid; @@ -277,8 +279,8 @@ NTSTATUS serverinfo_to_SamInfo3(struct auth_serversupplied_info *server_info, } for (i=0; i < groups.count; i++) { - groups.rids[i].rid = gids[i].g_rid; - groups.rids[i].attributes = gids[i].attr; + groups.rids[i].rid = gids[i].rid; + groups.rids[i].attributes = gids[i].attributes; } unix_to_nt_time(&last_logon, pdb_get_logon_time(sampw)); diff --git a/source3/rpc_client/rpc_transport_np.c b/source3/rpc_client/rpc_transport_np.c index e8a333e509..80ff384046 100644 --- a/source3/rpc_client/rpc_transport_np.c +++ b/source3/rpc_client/rpc_transport_np.c @@ -93,7 +93,7 @@ static void rpc_np_write_done(struct async_req *subreq) status = cli_write_andx_recv(subreq, &state->written); TALLOC_FREE(subreq); if (!NT_STATUS_IS_OK(status)) { - async_req_error(req, status); + async_req_nterror(req, status); return; } async_req_done(req); @@ -105,7 +105,7 @@ static NTSTATUS rpc_np_write_recv(struct async_req *req, ssize_t *pwritten) req->private_data, struct rpc_np_write_state); NTSTATUS status; - if (async_req_is_error(req, &status)) { + if (async_req_is_nterror(req, &status)) { return status; } *pwritten = state->written; @@ -169,13 +169,13 @@ static void rpc_np_read_done(struct async_req *subreq) } if (!NT_STATUS_IS_OK(status)) { TALLOC_FREE(subreq); - async_req_error(req, status); + async_req_nterror(req, status); return; } if (state->received > state->size) { TALLOC_FREE(subreq); - async_req_error(req, NT_STATUS_INVALID_NETWORK_RESPONSE); + async_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE); return; } @@ -189,7 +189,7 @@ static NTSTATUS rpc_np_read_recv(struct async_req *req, ssize_t *preceived) req->private_data, struct rpc_np_read_state); NTSTATUS status; - if (async_req_is_error(req, &status)) { + if (async_req_is_nterror(req, &status)) { return status; } *preceived = state->received; @@ -251,7 +251,7 @@ static void rpc_np_trans_done(struct async_req *subreq) &state->rdata, &state->rdata_len); TALLOC_FREE(subreq); if (!NT_STATUS_IS_OK(status)) { - async_req_error(req, status); + async_req_nterror(req, status); return; } async_req_done(req); @@ -264,7 +264,7 @@ static NTSTATUS rpc_np_trans_recv(struct async_req *req, TALLOC_CTX *mem_ctx, req->private_data, struct rpc_np_trans_state); NTSTATUS status; - if (async_req_is_error(req, &status)) { + if (async_req_is_nterror(req, &status)) { return status; } *prdata = talloc_move(mem_ctx, &state->rdata); @@ -272,49 +272,129 @@ static NTSTATUS rpc_np_trans_recv(struct async_req *req, TALLOC_CTX *mem_ctx, return NT_STATUS_OK; } +struct rpc_transport_np_init_state { + struct rpc_cli_transport *transport; + struct rpc_transport_np_state *transport_np; +}; + +static void rpc_transport_np_init_pipe_open(struct async_req *subreq); + +struct async_req *rpc_transport_np_init_send(TALLOC_CTX *mem_ctx, + struct event_context *ev, + struct cli_state *cli, + const struct ndr_syntax_id *abstract_syntax) +{ + struct async_req *result, *subreq; + struct rpc_transport_np_init_state *state; + + if (!async_req_setup(mem_ctx, &result, &state, + struct rpc_transport_np_init_state)) { + return NULL; + } + + state->transport = talloc(state, struct rpc_cli_transport); + if (state->transport == NULL) { + goto fail; + } + state->transport_np = talloc(state->transport, + struct rpc_transport_np_state); + if (state->transport_np == NULL) { + goto fail; + } + state->transport->priv = state->transport_np; + + state->transport_np->pipe_name = get_pipe_name_from_iface( + abstract_syntax); + state->transport_np->cli = cli; + + subreq = cli_ntcreate_send( + state, ev, cli, state->transport_np->pipe_name, 0, + DESIRED_ACCESS_PIPE, 0, FILE_SHARE_READ|FILE_SHARE_WRITE, + FILE_OPEN, 0, 0); + if (subreq == NULL) { + goto fail; + } + subreq->async.fn = rpc_transport_np_init_pipe_open; + subreq->async.priv = result; + return result; + + fail: + TALLOC_FREE(result); + return NULL; +} + +static void rpc_transport_np_init_pipe_open(struct async_req *subreq) +{ + struct async_req *req = talloc_get_type_abort( + subreq->async.priv, struct async_req); + struct rpc_transport_np_init_state *state = talloc_get_type_abort( + req->private_data, struct rpc_transport_np_init_state); + NTSTATUS status; + + status = cli_ntcreate_recv(subreq, &state->transport_np->fnum); + TALLOC_FREE(subreq); + if (!NT_STATUS_IS_OK(status)) { + async_req_nterror(req, status); + return; + } + + talloc_set_destructor(state->transport_np, + rpc_transport_np_state_destructor); + async_req_done(req); +} + +NTSTATUS rpc_transport_np_init_recv(struct async_req *req, + TALLOC_CTX *mem_ctx, + struct rpc_cli_transport **presult) +{ + struct rpc_transport_np_init_state *state = talloc_get_type_abort( + req->private_data, struct rpc_transport_np_init_state); + NTSTATUS status; + + if (async_req_is_nterror(req, &status)) { + return status; + } + + state->transport->write_send = rpc_np_write_send; + state->transport->write_recv = rpc_np_write_recv; + state->transport->read_send = rpc_np_read_send; + state->transport->read_recv = rpc_np_read_recv; + state->transport->trans_send = rpc_np_trans_send; + state->transport->trans_recv = rpc_np_trans_recv; + + *presult = talloc_move(mem_ctx, &state->transport); + return NT_STATUS_OK; +} + NTSTATUS rpc_transport_np_init(TALLOC_CTX *mem_ctx, struct cli_state *cli, const struct ndr_syntax_id *abstract_syntax, struct rpc_cli_transport **presult) { - struct rpc_cli_transport *result; - struct rpc_transport_np_state *state; - int fnum; + TALLOC_CTX *frame = talloc_stackframe(); + struct event_context *ev; + struct async_req *req; + NTSTATUS status; - result = talloc(mem_ctx, struct rpc_cli_transport); - if (result == NULL) { - return NT_STATUS_NO_MEMORY; - } - state = talloc(result, struct rpc_transport_np_state); - if (state == NULL) { - TALLOC_FREE(result); - return NT_STATUS_NO_MEMORY; + ev = event_context_init(frame); + if (ev == NULL) { + status = NT_STATUS_NO_MEMORY; + goto fail; } - result->priv = state; - - state->cli = cli; - state->pipe_name = cli_get_pipe_name_from_iface( - state, abstract_syntax); - - fnum = cli_nt_create(cli, state->pipe_name, DESIRED_ACCESS_PIPE); - if (fnum == -1) { - DEBUG(3,("rpc_pipe_open_np: cli_nt_create failed on pipe %s " - "to machine %s. Error was %s\n", state->pipe_name, - cli->desthost, cli_errstr(cli))); - TALLOC_FREE(result); - return cli_get_nt_error(cli); + + req = rpc_transport_np_init_send(frame, ev, cli, abstract_syntax); + if (req == NULL) { + status = NT_STATUS_NO_MEMORY; + goto fail; } - state->fnum = fnum; - talloc_set_destructor(state, rpc_transport_np_state_destructor); - result->write_send = rpc_np_write_send; - result->write_recv = rpc_np_write_recv; - result->read_send = rpc_np_read_send; - result->read_recv = rpc_np_read_recv; - result->trans_send = rpc_np_trans_send; - result->trans_recv = rpc_np_trans_recv; + while (req->state < ASYNC_REQ_DONE) { + event_loop_once(ev); + } - *presult = result; - return NT_STATUS_OK; + status = rpc_transport_np_init_recv(req, mem_ctx, presult); + fail: + TALLOC_FREE(frame); + return status; } struct cli_state *rpc_pipe_np_smb_conn(struct rpc_pipe_client *p) diff --git a/source3/rpc_client/rpc_transport_smbd.c b/source3/rpc_client/rpc_transport_smbd.c new file mode 100644 index 0000000000..bf4aa65dae --- /dev/null +++ b/source3/rpc_client/rpc_transport_smbd.c @@ -0,0 +1,694 @@ +/* + * Unix SMB/CIFS implementation. + * RPC client transport over named pipes to a child smbd + * Copyright (C) Volker Lendecke 2009 + * + * 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" + +#undef DBGC_CLASS +#define DBGC_CLASS DBGC_RPC_CLI + +/** + * struct rpc_cli_smbd_conn represents a forked smbd. This structure should + * exist only once per process which does the rpc calls. + * + * RPC pipe handles can be attached to this smbd connection with + * rpc_pipe_open_local(). + * + * For this to work right, we can not use rpc_transport_np directly, because + * the child smbd wants to write its DEBUG output somewhere. We redirect the + * child's output to rpc_cli_smbd_conn->stdout_fd. While the RPC calls are + * active, we have an event context available and attach a fd event to the + * stdout_df. + */ + +struct rpc_cli_smbd_conn { + /** + * The smb connection to handle the named pipe traffic over + */ + struct cli_state *cli; + + /** + * Attached to stdout in the forked smbd, this is where smbd will + * print its DEBUG. + */ + int stdout_fd; + + /** + * Custom callback provided by the owner of the + * rpc_cli_smbd_conn. Here we send the smbd DEBUG output. Can be NULL. + */ + struct { + void (*fn)(char *buf, size_t len, void *priv); + void *priv; + } stdout_callback ; +}; + +/** + * Event handler to be called whenever the forked smbd prints debugging + * output. + */ + +static void rpc_cli_smbd_stdout_reader(struct event_context *ev, + struct fd_event *fde, + uint16_t flags, void *priv) +{ + struct rpc_cli_smbd_conn *conn = talloc_get_type_abort( + priv, struct rpc_cli_smbd_conn); + char buf[1024]; + ssize_t nread; + + if ((flags & EVENT_FD_READ) == 0) { + return; + } + + nread = read(conn->stdout_fd, buf, sizeof(buf)-1); + if (nread < 0) { + DEBUG(0, ("Could not read from smbd stdout: %s\n", + strerror(errno))); + TALLOC_FREE(fde); + return; + } + if (nread == 0) { + DEBUG(0, ("EOF from smbd stdout\n")); + TALLOC_FREE(fde); + return; + } + + if (conn->stdout_callback.fn != NULL) { + conn->stdout_callback.fn(buf, nread, + conn->stdout_callback.priv); + } +} + +/** + * struct rpc_transport_smbd_state is the link from a struct rpc_pipe_client + * to the rpc_cli_smbd_conn. We use a named pipe transport as a subtransport. + */ + +struct rpc_transport_smbd_state { + struct rpc_cli_smbd_conn *conn; + struct rpc_cli_transport *sub_transp; +}; + +static int rpc_cli_smbd_conn_destructor(struct rpc_cli_smbd_conn *conn) +{ + if (conn->cli != NULL) { + cli_shutdown(conn->cli); + conn->cli = NULL; + } + if (conn->stdout_fd != -1) { + close(conn->stdout_fd); + conn->stdout_fd = -1; + } + return 0; +} + +/* + * Do the negprot/sesssetup/tcon to an anonymous ipc$ connection + */ + +struct get_anon_ipc_state { + struct event_context *ev; + struct cli_state *cli; +}; + +static void get_anon_ipc_negprot_done(struct async_req *subreq); +static void get_anon_ipc_sesssetup_done(struct async_req *subreq); +static void get_anon_ipc_tcon_done(struct async_req *subreq); + +static struct async_req *get_anon_ipc_send(TALLOC_CTX *mem_ctx, + struct event_context *ev, + struct cli_state *cli) +{ + struct async_req *result, *subreq; + struct get_anon_ipc_state *state; + + if (!async_req_setup(mem_ctx, &result, &state, + struct get_anon_ipc_state)) { + return NULL; + } + + state->ev = ev; + state->cli = cli; + + subreq = cli_negprot_send(state, ev, cli); + if (subreq == NULL) { + goto fail; + } + subreq->async.fn = get_anon_ipc_negprot_done; + subreq->async.priv = result; + return result; + fail: + TALLOC_FREE(result); + return NULL; +} + +static void get_anon_ipc_negprot_done(struct async_req *subreq) +{ + struct async_req *req = talloc_get_type_abort( + subreq->async.priv, struct async_req); + struct get_anon_ipc_state *state = talloc_get_type_abort( + req->private_data, struct get_anon_ipc_state); + NTSTATUS status; + + status = cli_negprot_recv(subreq); + TALLOC_FREE(subreq); + if (!NT_STATUS_IS_OK(status)) { + async_req_nterror(req, status); + return; + } + + subreq = cli_session_setup_guest_send(state, state->ev, state->cli); + if (async_req_nomem(subreq, req)) { + return; + } + subreq->async.fn = get_anon_ipc_sesssetup_done; + subreq->async.priv = req; +} + +static void get_anon_ipc_sesssetup_done(struct async_req *subreq) +{ + struct async_req *req = talloc_get_type_abort( + subreq->async.priv, struct async_req); + struct get_anon_ipc_state *state = talloc_get_type_abort( + req->private_data, struct get_anon_ipc_state); + NTSTATUS status; + + status = cli_session_setup_guest_recv(subreq); + TALLOC_FREE(subreq); + if (!NT_STATUS_IS_OK(status)) { + async_req_nterror(req, status); + return; + } + + subreq = cli_tcon_andx_send(state, state->ev, state->cli, + "IPC$", "IPC", NULL, 0); + if (async_req_nomem(subreq, req)) { + return; + } + subreq->async.fn = get_anon_ipc_tcon_done; + subreq->async.priv = req; +} + +static void get_anon_ipc_tcon_done(struct async_req *subreq) +{ + struct async_req *req = talloc_get_type_abort( + subreq->async.priv, struct async_req); + NTSTATUS status; + + status = cli_tcon_andx_recv(subreq); + TALLOC_FREE(subreq); + if (!NT_STATUS_IS_OK(status)) { + async_req_nterror(req, status); + return; + } + async_req_done(req); +} + +static NTSTATUS get_anon_ipc_recv(struct async_req *req) +{ + return async_req_simple_recv_ntstatus(req); +} + +struct rpc_cli_smbd_conn_init_state { + struct event_context *ev; + struct rpc_cli_smbd_conn *conn; +}; + +static void rpc_cli_smbd_conn_init_done(struct async_req *subreq); + +struct async_req *rpc_cli_smbd_conn_init_send(TALLOC_CTX *mem_ctx, + struct event_context *ev, + void (*stdout_callback)(char *buf, + size_t len, + void *priv), + void *priv) +{ + struct async_req *result, *subreq; + struct rpc_cli_smbd_conn_init_state *state; + int smb_sock[2]; + int stdout_pipe[2]; + NTSTATUS status; + pid_t pid; + int ret; + + smb_sock[0] = smb_sock[1] = stdout_pipe[0] = stdout_pipe[1] = -1; + + if (!async_req_setup(mem_ctx, &result, &state, + struct rpc_cli_smbd_conn_init_state)) { + return NULL; + } + state->ev = ev; + + state->conn = talloc(state, struct rpc_cli_smbd_conn); + if (state->conn == NULL) { + goto nomem; + } + + state->conn->cli = cli_initialise(); + if (state->conn->cli == NULL) { + goto nomem; + } + state->conn->stdout_fd = -1; + state->conn->stdout_callback.fn = stdout_callback; + state->conn->stdout_callback.priv = priv; + talloc_set_destructor(state->conn, rpc_cli_smbd_conn_destructor); + + ret = socketpair(AF_UNIX, SOCK_STREAM, 0, smb_sock); + if (ret == -1) { + status = map_nt_error_from_unix(errno); + goto post_status; + } + ret = pipe(stdout_pipe); + if (ret == -1) { + status = map_nt_error_from_unix(errno); + goto post_status; + } + + pid = sys_fork(); + if (pid == -1) { + status = map_nt_error_from_unix(errno); + goto post_status; + } + if (pid == 0) { + char *smbd_cmd; + + close(smb_sock[0]); + close(stdout_pipe[0]); + close(0); + if (dup(smb_sock[1]) == -1) { + exit(1); + } + close(smb_sock[1]); + close(1); + if (dup(stdout_pipe[1]) == -1) { + exit(1); + } + close(stdout_pipe[1]); + + smbd_cmd = getenv("SMB_PATH"); + + if ((smbd_cmd == NULL) + && (asprintf(&smbd_cmd, "%s/smbd", get_dyn_SBINDIR()) + == -1)) { + printf("no memory"); + exit(1); + } + if (asprintf(&smbd_cmd, "%s -F -S", smbd_cmd) == -1) { + printf("no memory"); + exit(1); + } + + exit(system(smbd_cmd)); + } + + state->conn->cli->fd = smb_sock[0]; + smb_sock[0] = -1; + close(smb_sock[1]); + smb_sock[1] = -1; + + state->conn->stdout_fd = stdout_pipe[0]; + stdout_pipe[0] = -1; + close(stdout_pipe[1]); + stdout_pipe[1] = -1; + + subreq = get_anon_ipc_send(state, ev, state->conn->cli); + if (subreq == NULL) { + goto nomem; + } + + if (event_add_fd(ev, subreq, state->conn->stdout_fd, EVENT_FD_READ, + rpc_cli_smbd_stdout_reader, state->conn) == NULL) { + goto nomem; + } + + subreq->async.fn = rpc_cli_smbd_conn_init_done; + subreq->async.priv = result; + return result; + + nomem: + status = NT_STATUS_NO_MEMORY; + post_status: + if (smb_sock[0] != -1) { + close(smb_sock[0]); + } + if (smb_sock[1] != -1) { + close(smb_sock[1]); + } + if (stdout_pipe[0] != -1) { + close(stdout_pipe[0]); + } + if (stdout_pipe[1] != -1) { + close(stdout_pipe[1]); + } + if (async_post_ntstatus(result, ev, status)) { + return result; + } + TALLOC_FREE(result); + return NULL; +} + +static void rpc_cli_smbd_conn_init_done(struct async_req *subreq) +{ + struct async_req *req = talloc_get_type_abort( + subreq->async.priv, struct async_req); + NTSTATUS status; + + status = get_anon_ipc_recv(subreq); + TALLOC_FREE(subreq); + if (!NT_STATUS_IS_OK(status)) { + async_req_nterror(req, status); + return; + } + async_req_done(req); +} + +NTSTATUS rpc_cli_smbd_conn_init_recv(struct async_req *req, + TALLOC_CTX *mem_ctx, + struct rpc_cli_smbd_conn **pconn) +{ + struct rpc_cli_smbd_conn_init_state *state = talloc_get_type_abort( + req->private_data, struct rpc_cli_smbd_conn_init_state); + NTSTATUS status; + + if (async_req_is_nterror(req, &status)) { + return status; + } + *pconn = talloc_move(mem_ctx, &state->conn); + return NT_STATUS_OK; +} + +NTSTATUS rpc_cli_smbd_conn_init(TALLOC_CTX *mem_ctx, + struct rpc_cli_smbd_conn **pconn, + void (*stdout_callback)(char *buf, + size_t len, + void *priv), + void *priv) +{ + TALLOC_CTX *frame = talloc_stackframe(); + struct event_context *ev; + struct async_req *req; + NTSTATUS status; + + ev = event_context_init(frame); + if (ev == NULL) { + status = NT_STATUS_NO_MEMORY; + goto fail; + } + + req = rpc_cli_smbd_conn_init_send(frame, ev, stdout_callback, priv); + if (req == NULL) { + status = NT_STATUS_NO_MEMORY; + goto fail; + } + + while (req->state < ASYNC_REQ_DONE) { + event_loop_once(ev); + } + + status = rpc_cli_smbd_conn_init_recv(req, mem_ctx, pconn); + fail: + TALLOC_FREE(frame); + return status; +} + +struct rpc_smbd_write_state { + struct rpc_cli_transport *sub_transp; + ssize_t written; +}; + +static void rpc_smbd_write_done(struct async_req *subreq); + +static struct async_req *rpc_smbd_write_send(TALLOC_CTX *mem_ctx, + struct event_context *ev, + const uint8_t *data, size_t size, + void *priv) +{ + struct rpc_transport_smbd_state *transp = talloc_get_type_abort( + priv, struct rpc_transport_smbd_state); + struct async_req *result, *subreq; + struct rpc_smbd_write_state *state; + + if (!async_req_setup(mem_ctx, &result, &state, + struct rpc_smbd_write_state)) { + return NULL; + } + state->sub_transp = transp->sub_transp; + + subreq = transp->sub_transp->write_send(state, ev, data, size, + transp->sub_transp->priv); + if (subreq == NULL) { + goto fail; + } + + if (event_add_fd(ev, subreq, transp->conn->stdout_fd, EVENT_FD_READ, + rpc_cli_smbd_stdout_reader, transp->conn) == NULL) { + goto fail; + } + + subreq->async.fn = rpc_smbd_write_done; + subreq->async.priv = result; + return result; + + fail: + TALLOC_FREE(result); + return NULL; +} + +static void rpc_smbd_write_done(struct async_req *subreq) +{ + struct async_req *req = talloc_get_type_abort( + subreq->async.priv, struct async_req); + struct rpc_smbd_write_state *state = talloc_get_type_abort( + req->private_data, struct rpc_smbd_write_state); + NTSTATUS status; + + status = state->sub_transp->write_recv(subreq, &state->written); + TALLOC_FREE(subreq); + if (!NT_STATUS_IS_OK(status)) { + async_req_nterror(req, status); + return; + } + async_req_done(req); +} + +static NTSTATUS rpc_smbd_write_recv(struct async_req *req, ssize_t *pwritten) +{ + struct rpc_smbd_write_state *state = talloc_get_type_abort( + req->private_data, struct rpc_smbd_write_state); + NTSTATUS status; + + if (async_req_is_nterror(req, &status)) { + return status; + } + *pwritten = state->written; + return NT_STATUS_OK; +} + +struct rpc_smbd_read_state { + struct rpc_cli_transport *sub_transp; + ssize_t received; +}; + +static void rpc_smbd_read_done(struct async_req *subreq); + +static struct async_req *rpc_smbd_read_send(TALLOC_CTX *mem_ctx, + struct event_context *ev, + uint8_t *data, size_t size, + void *priv) +{ + struct rpc_transport_smbd_state *transp = talloc_get_type_abort( + priv, struct rpc_transport_smbd_state); + struct async_req *result, *subreq; + struct rpc_smbd_read_state *state; + + if (!async_req_setup(mem_ctx, &result, &state, + struct rpc_smbd_read_state)) { + return NULL; + } + state->sub_transp = transp->sub_transp; + + subreq = transp->sub_transp->read_send(state, ev, data, size, + transp->sub_transp->priv); + if (subreq == NULL) { + goto fail; + } + + if (event_add_fd(ev, subreq, transp->conn->stdout_fd, EVENT_FD_READ, + rpc_cli_smbd_stdout_reader, transp->conn) == NULL) { + goto fail; + } + + subreq->async.fn = rpc_smbd_read_done; + subreq->async.priv = result; + return result; + + fail: + TALLOC_FREE(result); + return NULL; +} + +static void rpc_smbd_read_done(struct async_req *subreq) +{ + struct async_req *req = talloc_get_type_abort( + subreq->async.priv, struct async_req); + struct rpc_smbd_read_state *state = talloc_get_type_abort( + req->private_data, struct rpc_smbd_read_state); + NTSTATUS status; + + status = state->sub_transp->read_recv(subreq, &state->received); + TALLOC_FREE(subreq); + if (!NT_STATUS_IS_OK(status)) { + async_req_nterror(req, status); + return; + } + async_req_done(req); +} + +static NTSTATUS rpc_smbd_read_recv(struct async_req *req, ssize_t *preceived) +{ + struct rpc_smbd_read_state *state = talloc_get_type_abort( + req->private_data, struct rpc_smbd_read_state); + NTSTATUS status; + + if (async_req_is_nterror(req, &status)) { + return status; + } + *preceived = state->received; + return NT_STATUS_OK; +} + +struct rpc_transport_smbd_init_state { + struct rpc_cli_transport *transport; + struct rpc_transport_smbd_state *transport_smbd; +}; + +static void rpc_transport_smbd_init_done(struct async_req *subreq); + +struct async_req *rpc_transport_smbd_init_send(TALLOC_CTX *mem_ctx, + struct event_context *ev, + struct rpc_cli_smbd_conn *conn, + const struct ndr_syntax_id *abstract_syntax) +{ + struct async_req *result, *subreq; + struct rpc_transport_smbd_init_state *state; + + if (!async_req_setup(mem_ctx, &result, &state, + struct rpc_transport_smbd_init_state)) { + return NULL; + } + + state->transport = talloc(state, struct rpc_cli_transport); + if (state->transport == NULL) { + goto fail; + } + state->transport_smbd = talloc(state->transport, + struct rpc_transport_smbd_state); + if (state->transport_smbd == NULL) { + goto fail; + } + state->transport_smbd->conn = conn; + state->transport->priv = state->transport_smbd; + + subreq = rpc_transport_np_init_send(state, ev, conn->cli, + abstract_syntax); + if (subreq == NULL) { + goto fail; + } + subreq->async.fn = rpc_transport_smbd_init_done; + subreq->async.priv = result; + return result; + + fail: + TALLOC_FREE(result); + return NULL; +} + +static void rpc_transport_smbd_init_done(struct async_req *subreq) +{ + struct async_req *req = talloc_get_type_abort( + subreq->async.priv, struct async_req); + struct rpc_transport_smbd_init_state *state = talloc_get_type_abort( + req->private_data, struct rpc_transport_smbd_init_state); + NTSTATUS status; + + status = rpc_transport_np_init_recv( + subreq, state->transport_smbd, + &state->transport_smbd->sub_transp); + TALLOC_FREE(subreq); + if (!NT_STATUS_IS_OK(status)) { + async_req_nterror(req, status); + return; + } + async_req_done(req); +} + +NTSTATUS rpc_transport_smbd_init_recv(struct async_req *req, + TALLOC_CTX *mem_ctx, + struct rpc_cli_transport **presult) +{ + struct rpc_transport_smbd_init_state *state = talloc_get_type_abort( + req->private_data, struct rpc_transport_smbd_init_state); + NTSTATUS status; + + if (async_req_is_nterror(req, &status)) { + return status; + } + + state->transport->write_send = rpc_smbd_write_send; + state->transport->write_recv = rpc_smbd_write_recv; + state->transport->read_send = rpc_smbd_read_send; + state->transport->read_recv = rpc_smbd_read_recv; + state->transport->trans_send = NULL; + state->transport->trans_recv = NULL; + + *presult = talloc_move(mem_ctx, &state->transport); + return NT_STATUS_OK; +} + +NTSTATUS rpc_transport_smbd_init(TALLOC_CTX *mem_ctx, + struct rpc_cli_smbd_conn *conn, + const struct ndr_syntax_id *abstract_syntax, + struct rpc_cli_transport **presult) +{ + TALLOC_CTX *frame = talloc_stackframe(); + struct event_context *ev; + struct async_req *req; + NTSTATUS status; + + ev = event_context_init(frame); + if (ev == NULL) { + status = NT_STATUS_NO_MEMORY; + goto fail; + } + + req = rpc_transport_smbd_init_send(frame, ev, conn, abstract_syntax); + if (req == NULL) { + status = NT_STATUS_NO_MEMORY; + goto fail; + } + + while (req->state < ASYNC_REQ_DONE) { + event_loop_once(ev); + } + + status = rpc_transport_smbd_init_recv(req, mem_ctx, presult); + fail: + TALLOC_FREE(frame); + return status; +} diff --git a/source3/rpc_parse/parse_eventlog.c b/source3/rpc_parse/parse_eventlog.c deleted file mode 100644 index 40930a2500..0000000000 --- a/source3/rpc_parse/parse_eventlog.c +++ /dev/null @@ -1,210 +0,0 @@ -/* - * Unix SMB/CIFS implementation. - * RPC Pipe client / server routines - * Copyright (C) Marcin Krzysztof Porwit 2005. - * - * 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" - -#undef DBGC_CLASS -#define DBGC_CLASS DBGC_RPC_PARSE - -/******************************************************************** -********************************************************************/ - -bool eventlog_io_q_read_eventlog(const char *desc, EVENTLOG_Q_READ_EVENTLOG *q_u, - prs_struct *ps, int depth) -{ - if(q_u == NULL) - return False; - - prs_debug(ps, depth, desc, "eventlog_io_q_read_eventlog"); - depth++; - - if(!(prs_align(ps))) - return False; - - if(!(smb_io_pol_hnd("log handle", &(q_u->handle), ps, depth))) - return False; - - if(!(prs_uint32("read flags", ps, depth, &(q_u->flags)))) - return False; - - if(!(prs_uint32("read offset", ps, depth, &(q_u->offset)))) - return False; - - if(!(prs_uint32("read buf size", ps, depth, &(q_u->max_read_size)))) - return False; - - return True; -} - -static bool smb_io_eventlog_entry(const char *name, prs_struct *ps, int depth, Eventlog_entry *entry) -{ - if(entry == NULL) - return False; - - prs_debug(ps, depth, name, "smb_io_eventlog_entry"); - depth++; - - if(!prs_align(ps)) - return False; - - if(!(prs_uint32("length", ps, depth, &(entry->record.length)))) - return False; - if(!(prs_uint32("reserved", ps, depth, &(entry->record.reserved1)))) - return False; - if(!(prs_uint32("record number", ps, depth, &(entry->record.record_number)))) - return False; - if(!(prs_uint32("time generated", ps, depth, &(entry->record.time_generated)))) - return False; - if(!(prs_uint32("time written", ps, depth, &(entry->record.time_written)))) - return False; - if(!(prs_uint32("event id", ps, depth, &(entry->record.event_id)))) - return False; - if(!(prs_uint16("event type", ps, depth, &(entry->record.event_type)))) - return False; - if(!(prs_uint16("num strings", ps, depth, &(entry->record.num_strings)))) - return False; - if(!(prs_uint16("event category", ps, depth, &(entry->record.event_category)))) - return False; - if(!(prs_uint16("reserved2", ps, depth, &(entry->record.reserved2)))) - return False; - if(!(prs_uint32("closing record", ps, depth, &(entry->record.closing_record_number)))) - return False; - if(!(prs_uint32("string offset", ps, depth, &(entry->record.string_offset)))) - return False; - if(!(prs_uint32("user sid length", ps, depth, &(entry->record.user_sid_length)))) - return False; - if(!(prs_uint32("user sid offset", ps, depth, &(entry->record.user_sid_offset)))) - return False; - if(!(prs_uint32("data length", ps, depth, &(entry->record.data_length)))) - return False; - if(!(prs_uint32("data offset", ps, depth, &(entry->record.data_offset)))) - return False; - if(!(prs_align(ps))) - return False; - - /* Now encoding data */ - - if(!(prs_uint8s(False, "buffer", ps, depth, entry->data, - entry->record.length - sizeof(Eventlog_record) - sizeof(entry->record.length)))) - { - return False; - } - - if(!(prs_align(ps))) - return False; - - if(!(prs_uint32("length 2", ps, depth, &(entry->record.length)))) - return False; - - return True; -} - -/** Structure of response seems to be: - DWORD num_bytes_in_resp -- MUST be the same as q_u->max_read_size - for i=0..n - EVENTLOGRECORD record - DWORD sent_size -- sum of EVENTLOGRECORD lengths if records returned, 0 otherwise - DWORD real_size -- 0 if records returned, otherwise length of next record to be returned - WERROR status */ -bool eventlog_io_r_read_eventlog(const char *desc, - EVENTLOG_Q_READ_EVENTLOG *q_u, - EVENTLOG_R_READ_EVENTLOG *r_u, - prs_struct *ps, - int depth) -{ - Eventlog_entry *entry; - uint32 record_written = 0; - uint32 record_total = 0; - - if(r_u == NULL) - return False; - - prs_debug(ps, depth, desc, "eventlog_io_r_read_eventlog"); - depth++; - - /* First, see if we've read more logs than we can output */ - - if(r_u->num_bytes_in_resp > q_u->max_read_size) { - entry = r_u->entry; - - /* remove the size of the last entry from the list */ - - while(entry->next != NULL) - entry = entry->next; - - r_u->num_bytes_in_resp -= entry->record.length; - - /* do not output the last log entry */ - - r_u->num_records--; - } - - entry = r_u->entry; - record_total = r_u->num_records; - - if(r_u->num_bytes_in_resp != 0) - r_u->sent_size = r_u->num_bytes_in_resp; - else - r_u->real_size = r_u->bytes_in_next_record; - - if(!(prs_align(ps))) - return False; - if(!(prs_uint32("bytes in resp", ps, depth, &(q_u->max_read_size)))) - return False; - - while(entry != NULL && record_written < record_total) - { - DEBUG(11, ("eventlog_io_r_read_eventlog: writing record [%d] out of [%d].\n", record_written, record_total)); - - /* Encode the actual eventlog record record */ - - if (!(smb_io_eventlog_entry("entry", ps, depth, entry))) - return false; - - entry = entry->next; - record_written++; - - } /* end of encoding EVENTLOGRECORD */ - - /* Now pad with whitespace until the end of the response buffer */ - - if (q_u->max_read_size - r_u->num_bytes_in_resp) { - r_u->end_of_entries_padding = PRS_ALLOC_MEM(ps, uint8_t, q_u->max_read_size - r_u->num_bytes_in_resp); - if (!r_u->end_of_entries_padding) { - return False; - } - - if(!(prs_uint8s(False, "end of entries padding", ps, - depth, r_u->end_of_entries_padding, - (q_u->max_read_size - r_u->num_bytes_in_resp)))) { - return False; - } - } - - /* We had better be DWORD aligned here */ - - if(!(prs_uint32("sent size", ps, depth, &(r_u->sent_size)))) - return False; - if(!(prs_uint32("real size", ps, depth, &(r_u->real_size)))) - return False; - if(!(prs_ntstatus("status code", ps, depth, &r_u->status))) - return False; - - return True; -} diff --git a/source3/rpc_parse/parse_misc.c b/source3/rpc_parse/parse_misc.c index 7d1d00a373..38d5b95376 100644 --- a/source3/rpc_parse/parse_misc.c +++ b/source3/rpc_parse/parse_misc.c @@ -26,27 +26,6 @@ #define DBGC_CLASS DBGC_RPC_PARSE /******************************************************************* - Reads or writes a UTIME type. -********************************************************************/ - -static bool smb_io_utime(const char *desc, UTIME *t, prs_struct *ps, int depth) -{ - if (t == NULL) - return False; - - prs_debug(ps, depth, desc, "smb_io_utime"); - depth++; - - if(!prs_align(ps)) - return False; - - if(!prs_uint32 ("time", ps, depth, &t->time)) - return False; - - return True; -} - -/******************************************************************* Reads or writes an NTTIME structure. ********************************************************************/ @@ -89,53 +68,6 @@ bool smb_io_nttime(const char *desc, prs_struct *ps, int depth, NTTIME *nttime) } /******************************************************************* - Gets an enumeration handle from an ENUM_HND structure. -********************************************************************/ - -uint32 get_enum_hnd(ENUM_HND *enh) -{ - return (enh && enh->ptr_hnd != 0) ? enh->handle : 0; -} - -/******************************************************************* - Inits an ENUM_HND structure. -********************************************************************/ - -void init_enum_hnd(ENUM_HND *enh, uint32 hnd) -{ - DEBUG(5,("smb_io_enum_hnd\n")); - - enh->ptr_hnd = (hnd != 0) ? 1 : 0; - enh->handle = hnd; -} - -/******************************************************************* - Reads or writes an ENUM_HND structure. -********************************************************************/ - -bool smb_io_enum_hnd(const char *desc, ENUM_HND *hnd, prs_struct *ps, int depth) -{ - if (hnd == NULL) - return False; - - prs_debug(ps, depth, desc, "smb_io_enum_hnd"); - depth++; - - if(!prs_align(ps)) - return False; - - if(!prs_uint32("ptr_hnd", ps, depth, &hnd->ptr_hnd)) /* pointer */ - return False; - - if (hnd->ptr_hnd != 0) { - if(!prs_uint32("handle ", ps, depth, &hnd->handle )) /* enum handle */ - return False; - } - - return True; -} - -/******************************************************************* Reads or writes a DOM_SID structure. ********************************************************************/ @@ -174,67 +106,6 @@ bool smb_io_dom_sid(const char *desc, DOM_SID *sid, prs_struct *ps, int depth) } /******************************************************************* - Inits a DOM_SID2 structure. -********************************************************************/ - -void init_dom_sid2(DOM_SID2 *sid2, const DOM_SID *sid) -{ - sid2->sid = *sid; - sid2->num_auths = sid2->sid.num_auths; -} - -/******************************************************************* - Reads or writes a DOM_SID2 structure. -********************************************************************/ - -bool smb_io_dom_sid2_p(const char *desc, prs_struct *ps, int depth, DOM_SID2 **sid2) -{ - uint32 data_p; - - /* caputure the pointer value to stream */ - - data_p = *sid2 ? 0xf000baaa : 0; - - if ( !prs_uint32("dom_sid2_p", ps, depth, &data_p )) - return False; - - /* we're done if there is no data */ - - if ( !data_p ) - return True; - - if (UNMARSHALLING(ps)) { - if ( !(*sid2 = PRS_ALLOC_MEM(ps, DOM_SID2, 1)) ) - return False; - } - - return True; -} -/******************************************************************* - Reads or writes a DOM_SID2 structure. -********************************************************************/ - -bool smb_io_dom_sid2(const char *desc, DOM_SID2 *sid, prs_struct *ps, int depth) -{ - if (sid == NULL) - return False; - - prs_debug(ps, depth, desc, "smb_io_dom_sid2"); - depth++; - - if(!prs_align(ps)) - return False; - - if(!prs_uint32("num_auths", ps, depth, &sid->num_auths)) - return False; - - if(!smb_io_dom_sid("sid", &sid->sid, ps, depth)) - return False; - - return True; -} - -/******************************************************************* Reads or writes a struct GUID ********************************************************************/ @@ -263,163 +134,6 @@ bool smb_io_uuid(const char *desc, struct GUID *uuid, } /******************************************************************* -creates a STRHDR structure. -********************************************************************/ - -void init_str_hdr(STRHDR *hdr, int max_len, int len, uint32 buffer) -{ - hdr->str_max_len = max_len; - hdr->str_str_len = len; - hdr->buffer = buffer; -} - -/******************************************************************* - Reads or writes a STRHDR structure. -********************************************************************/ - -bool smb_io_strhdr(const char *desc, STRHDR *hdr, prs_struct *ps, int depth) -{ - if (hdr == NULL) - return False; - - prs_debug(ps, depth, desc, "smb_io_strhdr"); - depth++; - - if(!prs_align(ps)) - return False; - - if(!prs_uint16("str_str_len", ps, depth, &hdr->str_str_len)) - return False; - if(!prs_uint16("str_max_len", ps, depth, &hdr->str_max_len)) - return False; - if(!prs_uint32("buffer ", ps, depth, &hdr->buffer)) - return False; - - return True; -} - -/******************************************************************* - Inits a UNIHDR structure. -********************************************************************/ - -void init_uni_hdr(UNIHDR *hdr, UNISTR2 *str2) -{ - hdr->uni_str_len = 2 * (str2->uni_str_len); - hdr->uni_max_len = 2 * (str2->uni_max_len); - hdr->buffer = (str2->uni_str_len != 0) ? 1 : 0; -} - -/******************************************************************* - Reads or writes a UNIHDR structure. -********************************************************************/ - -bool smb_io_unihdr(const char *desc, UNIHDR *hdr, prs_struct *ps, int depth) -{ - if (hdr == NULL) - return False; - - prs_debug(ps, depth, desc, "smb_io_unihdr"); - depth++; - - if(!prs_align(ps)) - return False; - - if(!prs_uint16("uni_str_len", ps, depth, &hdr->uni_str_len)) - return False; - if(!prs_uint16("uni_max_len", ps, depth, &hdr->uni_max_len)) - return False; - if(!prs_uint32("buffer ", ps, depth, &hdr->buffer)) - return False; - - return True; -} - -/******************************************************************* - Inits a BUFHDR structure. -********************************************************************/ - -void init_buf_hdr(BUFHDR *hdr, int max_len, int len) -{ - hdr->buf_max_len = max_len; - hdr->buf_len = len; -} - -/******************************************************************* - prs_uint16 wrapper. Call this and it sets up a pointer to where the - uint16 should be stored, or gets the size if reading. - ********************************************************************/ - -bool smb_io_hdrbuf_pre(const char *desc, BUFHDR *hdr, prs_struct *ps, int depth, uint32 *offset) -{ - (*offset) = prs_offset(ps); - if (ps->io) { - - /* reading. */ - - if(!smb_io_hdrbuf(desc, hdr, ps, depth)) - return False; - - } else { - - /* writing. */ - - if(!prs_set_offset(ps, prs_offset(ps) + (sizeof(uint32) * 2))) - return False; - } - - return True; -} - -/******************************************************************* - smb_io_hdrbuf wrapper. Call this and it retrospectively stores the size. - Does nothing on reading, as that is already handled by ...._pre() - ********************************************************************/ - -bool smb_io_hdrbuf_post(const char *desc, BUFHDR *hdr, prs_struct *ps, int depth, - uint32 ptr_hdrbuf, uint32 max_len, uint32 len) -{ - if (!ps->io) { - /* writing: go back and do a retrospective job. i hate this */ - - uint32 old_offset = prs_offset(ps); - - init_buf_hdr(hdr, max_len, len); - if(!prs_set_offset(ps, ptr_hdrbuf)) - return False; - if(!smb_io_hdrbuf(desc, hdr, ps, depth)) - return False; - - if(!prs_set_offset(ps, old_offset)) - return False; - } - - return True; -} - -/******************************************************************* - Reads or writes a BUFHDR structure. -********************************************************************/ - -bool smb_io_hdrbuf(const char *desc, BUFHDR *hdr, prs_struct *ps, int depth) -{ - if (hdr == NULL) - return False; - - prs_debug(ps, depth, desc, "smb_io_hdrbuf"); - depth++; - - if(!prs_align(ps)) - return False; - - if(!prs_uint32("buf_max_len", ps, depth, &hdr->buf_max_len)) - return False; - if(!prs_uint32("buf_len ", ps, depth, &hdr->buf_len)) - return False; - - return True; -} - -/******************************************************************* Inits a UNISTR structure. ********************************************************************/ @@ -458,82 +172,6 @@ bool smb_io_unistr(const char *desc, UNISTR *uni, prs_struct *ps, int depth) } /******************************************************************* - Allocate the RPC_DATA_BLOB memory. -********************************************************************/ - -static void create_rpc_blob(RPC_DATA_BLOB *str, size_t len) -{ - if (len) { - str->buffer = (uint8 *)TALLOC_ZERO(talloc_tos(), len); - if (str->buffer == NULL) - smb_panic("create_rpc_blob: talloc fail"); - str->buf_len = len; - } else { - str->buffer = NULL; - str->buf_len = 0; - } -} - -/******************************************************************* - Inits a RPC_DATA_BLOB structure from a uint32 -********************************************************************/ - -void init_rpc_blob_uint32(RPC_DATA_BLOB *str, uint32 val) -{ - ZERO_STRUCTP(str); - - /* set up string lengths. */ - create_rpc_blob(str, sizeof(uint32)); - SIVAL(str->buffer, 0, val); -} - -/******************************************************************* - Inits a RPC_DATA_BLOB structure. -********************************************************************/ - -void init_rpc_blob_str(RPC_DATA_BLOB *str, const char *buf, int len) -{ - ZERO_STRUCTP(str); - - /* set up string lengths. */ - if (len) { - create_rpc_blob(str, len*2); - rpcstr_push(str->buffer, buf, (size_t)str->buf_len, STR_TERMINATE); - } -} - -/******************************************************************* - Inits a RPC_DATA_BLOB structure from a hex string. -********************************************************************/ - -void init_rpc_blob_hex(RPC_DATA_BLOB *str, const char *buf) -{ - ZERO_STRUCTP(str); - if (buf && *buf) { - size_t len = strlen(buf); - create_rpc_blob(str, len); - str->buf_len = strhex_to_str((char *)str->buffer, str->buf_len, - buf, len); - } -} - -/******************************************************************* - Inits a RPC_DATA_BLOB structure. -********************************************************************/ - -void init_rpc_blob_bytes(RPC_DATA_BLOB *str, uint8 *buf, size_t len) -{ - ZERO_STRUCTP(str); - - /* max buffer size (allocated size) */ - if (buf != NULL && len) { - create_rpc_blob(str, len); - memcpy(str->buffer, buf, len); - } - str->buf_len = len; -} - -/******************************************************************* reads or writes a BUFFER5 structure. the buf_len member tells you how large the buffer is. ********************************************************************/ @@ -609,77 +247,6 @@ void copy_unistr2(UNISTR2 *str, const UNISTR2 *from) } /******************************************************************* - Creates a STRING2 structure. -********************************************************************/ - -void init_string2(STRING2 *str, const char *buf, size_t max_len, size_t str_len) -{ - /* set up string lengths. */ - SMB_ASSERT(max_len >= str_len); - - /* Ensure buf is valid if str_len was set. Coverity check. */ - if (str_len && !buf) { - return; - } - - str->str_max_len = max_len; - str->offset = 0; - str->str_str_len = str_len; - - /* store the string */ - if(str_len != 0) { - str->buffer = (uint8 *)TALLOC_ZERO(talloc_tos(), - str->str_max_len); - if (str->buffer == NULL) - smb_panic("init_string2: malloc fail"); - memcpy(str->buffer, buf, str_len); - } -} - -/******************************************************************* - Reads or writes a STRING2 structure. - XXXX NOTE: STRING2 structures need NOT be null-terminated. - the str_str_len member tells you how long the string is; - the str_max_len member tells you how large the buffer is. -********************************************************************/ - -bool smb_io_string2(const char *desc, STRING2 *str2, uint32 buffer, prs_struct *ps, int depth) -{ - if (str2 == NULL) - return False; - - if (buffer) { - - prs_debug(ps, depth, desc, "smb_io_string2"); - depth++; - - if(!prs_align(ps)) - return False; - - if(!prs_uint32("str_max_len", ps, depth, &str2->str_max_len)) - return False; - if(!prs_uint32("offset ", ps, depth, &str2->offset)) - return False; - if(!prs_uint32("str_str_len", ps, depth, &str2->str_str_len)) - return False; - - /* buffer advanced by indicated length of string - NOT by searching for null-termination */ - if(!prs_string2(True, "buffer ", ps, depth, str2)) - return False; - - } else { - - prs_debug(ps, depth, desc, "smb_io_string2 - NULL"); - depth++; - memset((char *)str2, '\0', sizeof(*str2)); - - } - - return True; -} - -/******************************************************************* Inits a UNISTR2 structure. ********************************************************************/ @@ -735,36 +302,6 @@ void init_unistr2(UNISTR2 *str, const char *buf, enum unistr2_term_codes flags) str->uni_max_len++; } -/******************************************************************* - Inits a UNISTR4 structure. -********************************************************************/ - -void init_unistr4(UNISTR4 *uni4, const char *buf, enum unistr2_term_codes flags) -{ - uni4->string = TALLOC_P( talloc_tos(), UNISTR2 ); - if (!uni4->string) { - smb_panic("init_unistr4: talloc fail"); - return; - } - init_unistr2( uni4->string, buf, flags ); - - uni4->length = 2 * (uni4->string->uni_str_len); - uni4->size = 2 * (uni4->string->uni_max_len); -} - -void init_unistr4_w( TALLOC_CTX *ctx, UNISTR4 *uni4, const smb_ucs2_t *buf ) -{ - uni4->string = TALLOC_P( ctx, UNISTR2 ); - if (!uni4->string) { - smb_panic("init_unistr4_w: talloc fail"); - return; - } - init_unistr2_w( ctx, uni4->string, buf ); - - uni4->length = 2 * (uni4->string->uni_str_len); - uni4->size = 2 * (uni4->string->uni_max_len); -} - /** * Inits a UNISTR2 structure. * @param ctx talloc context to allocate string on @@ -970,583 +507,6 @@ bool smb_io_unistr2(const char *desc, UNISTR2 *uni2, uint32 buffer, prs_struct * } /******************************************************************* - now read/write UNISTR4 -********************************************************************/ - -bool prs_unistr4(const char *desc, prs_struct *ps, int depth, UNISTR4 *uni4) -{ - void *ptr; - prs_debug(ps, depth, desc, "prs_unistr4"); - depth++; - - if ( !prs_uint16("length", ps, depth, &uni4->length )) - return False; - if ( !prs_uint16("size", ps, depth, &uni4->size )) - return False; - - ptr = uni4->string; - - if ( !prs_pointer( desc, ps, depth, &ptr, sizeof(UNISTR2), (PRS_POINTER_CAST)prs_io_unistr2 ) ) - return False; - - uni4->string = (UNISTR2 *)ptr; - - return True; -} - -/******************************************************************* - now read/write UNISTR4 header -********************************************************************/ - -bool prs_unistr4_hdr(const char *desc, prs_struct *ps, int depth, UNISTR4 *uni4) -{ - prs_debug(ps, depth, desc, "prs_unistr4_hdr"); - depth++; - - if ( !prs_uint16("length", ps, depth, &uni4->length) ) - return False; - if ( !prs_uint16("size", ps, depth, &uni4->size) ) - return False; - if ( !prs_io_unistr2_p(desc, ps, depth, &uni4->string) ) - return False; - - return True; -} - -/******************************************************************* - now read/write UNISTR4 string -********************************************************************/ - -bool prs_unistr4_str(const char *desc, prs_struct *ps, int depth, UNISTR4 *uni4) -{ - prs_debug(ps, depth, desc, "prs_unistr4_str"); - depth++; - - if ( !prs_io_unistr2(desc, ps, depth, uni4->string) ) - return False; - - return True; -} - -/******************************************************************* - Reads or writes a UNISTR4_ARRAY structure. -********************************************************************/ - -bool prs_unistr4_array(const char *desc, prs_struct *ps, int depth, UNISTR4_ARRAY *array ) -{ - unsigned int i; - - prs_debug(ps, depth, desc, "prs_unistr4_array"); - depth++; - - if(!prs_uint32("count", ps, depth, &array->count)) - return False; - - if (UNMARSHALLING(ps)) { - if (array->count) { - if ( !(array->strings = TALLOC_ZERO_ARRAY( talloc_tos(), UNISTR4, array->count)) ) - return False; - } else { - array->strings = NULL; - } - } - - /* write the headers and then the actual string buffer */ - - for ( i=0; i<array->count; i++ ) { - if ( !prs_unistr4_hdr( "string", ps, depth, &array->strings[i]) ) - return False; - } - - for (i=0;i<array->count;i++) { - if ( !prs_unistr4_str("string", ps, depth, &array->strings[i]) ) - return False; - } - - return True; -} - -/******************************************************************** - initialise a UNISTR_ARRAY from a char** -********************************************************************/ - -bool init_unistr4_array( UNISTR4_ARRAY *array, uint32 count, const char **strings ) -{ - unsigned int i; - - array->count = count; - - /* allocate memory for the array of UNISTR4 objects */ - - if (array->count) { - if ( !(array->strings = TALLOC_ZERO_ARRAY(talloc_tos(), UNISTR4, count )) ) - return False; - } else { - array->strings = NULL; - } - - for ( i=0; i<count; i++ ) - init_unistr4( &array->strings[i], strings[i], UNI_STR_TERMINATE ); - - return True; -} - -/******************************************************************* - Inits a DOM_RID structure. -********************************************************************/ - -void init_dom_rid(DOM_RID *prid, uint32 rid, uint16 type, uint32 idx) -{ - prid->type = type; - prid->rid = rid; - prid->rid_idx = idx; -} - -/******************************************************************* - Reads or writes a DOM_RID structure. -********************************************************************/ - -bool smb_io_dom_rid(const char *desc, DOM_RID *rid, prs_struct *ps, int depth) -{ - if (rid == NULL) - return False; - - prs_debug(ps, depth, desc, "smb_io_dom_rid"); - depth++; - - if(!prs_align(ps)) - return False; - - if(!prs_uint16("type ", ps, depth, &rid->type)) - return False; - if(!prs_align(ps)) - return False; - if(!prs_uint32("rid ", ps, depth, &rid->rid)) - return False; - if(!prs_uint32("rid_idx", ps, depth, &rid->rid_idx)) - return False; - - return True; -} - -/******************************************************************* - Reads or writes a DOM_RID2 structure. -********************************************************************/ - -bool smb_io_dom_rid2(const char *desc, DOM_RID2 *rid, prs_struct *ps, int depth) -{ - if (rid == NULL) - return False; - - prs_debug(ps, depth, desc, "smb_io_dom_rid2"); - depth++; - - if(!prs_align(ps)) - return False; - - if(!prs_uint16("type ", ps, depth, &rid->type)) - return False; - if(!prs_align(ps)) - return False; - if(!prs_uint32("rid ", ps, depth, &rid->rid)) - return False; - if(!prs_uint32("rid_idx", ps, depth, &rid->rid_idx)) - return False; - if(!prs_uint32("unknown", ps, depth, &rid->unknown)) - return False; - - return True; -} - - -/******************************************************************* -creates a DOM_RID3 structure. -********************************************************************/ - -void init_dom_rid3(DOM_RID3 *rid3, uint32 rid, uint8 type) -{ - rid3->rid = rid; - rid3->type1 = type; - rid3->ptr_type = 0x1; /* non-zero, basically. */ - rid3->type2 = 0x1; - rid3->unk = type; -} - -/******************************************************************* -reads or writes a DOM_RID3 structure. -********************************************************************/ - -bool smb_io_dom_rid3(const char *desc, DOM_RID3 *rid3, prs_struct *ps, int depth) -{ - if (rid3 == NULL) - return False; - - prs_debug(ps, depth, desc, "smb_io_dom_rid3"); - depth++; - - if(!prs_align(ps)) - return False; - - if(!prs_uint32("rid ", ps, depth, &rid3->rid)) - return False; - if(!prs_uint32("type1 ", ps, depth, &rid3->type1)) - return False; - if(!prs_uint32("ptr_type", ps, depth, &rid3->ptr_type)) - return False; - if(!prs_uint32("type2 ", ps, depth, &rid3->type2)) - return False; - if(!prs_uint32("unk ", ps, depth, &rid3->unk)) - return False; - - return True; -} - -/******************************************************************* - Inits a DOM_RID4 structure. -********************************************************************/ - -void init_dom_rid4(DOM_RID4 *rid4, uint16 unknown, uint16 attr, uint32 rid) -{ - rid4->unknown = unknown; - rid4->attr = attr; - rid4->rid = rid; -} - -/******************************************************************* - Inits a DOM_CLNT_SRV structure. -********************************************************************/ - -void init_clnt_srv(DOM_CLNT_SRV *logcln, const char *logon_srv, - const char *comp_name) -{ - DEBUG(5,("init_clnt_srv: %d\n", __LINE__)); - - if (logon_srv != NULL) { - logcln->undoc_buffer = 1; - init_unistr2(&logcln->uni_logon_srv, logon_srv, UNI_STR_TERMINATE); - } else { - logcln->undoc_buffer = 0; - } - - if (comp_name != NULL) { - logcln->undoc_buffer2 = 1; - init_unistr2(&logcln->uni_comp_name, comp_name, UNI_STR_TERMINATE); - } else { - logcln->undoc_buffer2 = 0; - } -} - -/******************************************************************* - Inits or writes a DOM_CLNT_SRV structure. -********************************************************************/ - -bool smb_io_clnt_srv(const char *desc, DOM_CLNT_SRV *logcln, prs_struct *ps, int depth) -{ - if (logcln == NULL) - return False; - - prs_debug(ps, depth, desc, "smb_io_clnt_srv"); - depth++; - - if(!prs_align(ps)) - return False; - - if(!prs_uint32("undoc_buffer ", ps, depth, &logcln->undoc_buffer)) - return False; - - if (logcln->undoc_buffer != 0) { - if(!smb_io_unistr2("unistr2", &logcln->uni_logon_srv, logcln->undoc_buffer, ps, depth)) - return False; - } - - if(!prs_align(ps)) - return False; - - if(!prs_uint32("undoc_buffer2", ps, depth, &logcln->undoc_buffer2)) - return False; - - if (logcln->undoc_buffer2 != 0) { - if(!smb_io_unistr2("unistr2", &logcln->uni_comp_name, logcln->undoc_buffer2, ps, depth)) - return False; - } - - return True; -} - -/******************************************************************* - Inits a DOM_LOG_INFO structure. -********************************************************************/ - -void init_log_info(DOM_LOG_INFO *loginfo, const char *logon_srv, const char *acct_name, - uint16 sec_chan, const char *comp_name) -{ - DEBUG(5,("make_log_info %d\n", __LINE__)); - - loginfo->undoc_buffer = 1; - - init_unistr2(&loginfo->uni_logon_srv, logon_srv, UNI_STR_TERMINATE); - init_unistr2(&loginfo->uni_acct_name, acct_name, UNI_STR_TERMINATE); - - loginfo->sec_chan = sec_chan; - - init_unistr2(&loginfo->uni_comp_name, comp_name, UNI_STR_TERMINATE); -} - -/******************************************************************* - Reads or writes a DOM_LOG_INFO structure. -********************************************************************/ - -bool smb_io_log_info(const char *desc, DOM_LOG_INFO *loginfo, prs_struct *ps, int depth) -{ - if (loginfo == NULL) - return False; - - prs_debug(ps, depth, desc, "smb_io_log_info"); - depth++; - - if(!prs_align(ps)) - return False; - - if(!prs_uint32("undoc_buffer", ps, depth, &loginfo->undoc_buffer)) - return False; - - if(!smb_io_unistr2("unistr2", &loginfo->uni_logon_srv, True, ps, depth)) - return False; - if(!smb_io_unistr2("unistr2", &loginfo->uni_acct_name, True, ps, depth)) - return False; - - if(!prs_uint16("sec_chan", ps, depth, &loginfo->sec_chan)) - return False; - - if(!smb_io_unistr2("unistr2", &loginfo->uni_comp_name, True, ps, depth)) - return False; - - return True; -} - -/******************************************************************* - Reads or writes a DOM_CHAL structure. -********************************************************************/ - -bool smb_io_chal(const char *desc, DOM_CHAL *chal, prs_struct *ps, int depth) -{ - if (chal == NULL) - return False; - - prs_debug(ps, depth, desc, "smb_io_chal"); - depth++; - - if(!prs_uint8s (False, "data", ps, depth, chal->data, 8)) - return False; - - return True; -} - -/******************************************************************* - Reads or writes a DOM_CRED structure. -********************************************************************/ - -bool smb_io_cred(const char *desc, DOM_CRED *cred, prs_struct *ps, int depth) -{ - if (cred == NULL) - return False; - - prs_debug(ps, depth, desc, "smb_io_cred"); - depth++; - - if(!prs_align(ps)) - return False; - - if(!smb_io_chal ("", &cred->challenge, ps, depth)) - return False; - - if(!smb_io_utime("", &cred->timestamp, ps, depth)) - return False; - - return True; -} - -/******************************************************************* - Inits a DOM_CLNT_INFO2 structure. -********************************************************************/ - -void init_clnt_info2(DOM_CLNT_INFO2 *clnt, - const char *logon_srv, const char *comp_name, - const DOM_CRED *clnt_cred) -{ - DEBUG(5,("make_clnt_info: %d\n", __LINE__)); - - init_clnt_srv(&clnt->login, logon_srv, comp_name); - - if (clnt_cred != NULL) { - clnt->ptr_cred = 1; - memcpy(&clnt->cred, clnt_cred, sizeof(clnt->cred)); - } else { - clnt->ptr_cred = 0; - } -} - -/******************************************************************* - Reads or writes a DOM_CLNT_INFO2 structure. -********************************************************************/ - -bool smb_io_clnt_info2(const char *desc, DOM_CLNT_INFO2 *clnt, prs_struct *ps, int depth) -{ - if (clnt == NULL) - return False; - - prs_debug(ps, depth, desc, "smb_io_clnt_info2"); - depth++; - - if(!prs_align(ps)) - return False; - - if(!smb_io_clnt_srv("", &clnt->login, ps, depth)) - return False; - - if(!prs_align(ps)) - return False; - - if(!prs_uint32("ptr_cred", ps, depth, &clnt->ptr_cred)) - return False; - if(!smb_io_cred("", &clnt->cred, ps, depth)) - return False; - - return True; -} - -/******************************************************************* - Inits a DOM_CLNT_INFO structure. -********************************************************************/ - -void init_clnt_info(DOM_CLNT_INFO *clnt, - const char *logon_srv, const char *acct_name, - uint16 sec_chan, const char *comp_name, - const DOM_CRED *cred) -{ - DEBUG(5,("make_clnt_info\n")); - - init_log_info(&clnt->login, logon_srv, acct_name, sec_chan, comp_name); - memcpy(&clnt->cred, cred, sizeof(clnt->cred)); -} - -/******************************************************************* - Reads or writes a DOM_CLNT_INFO structure. -********************************************************************/ - -bool smb_io_clnt_info(const char *desc, DOM_CLNT_INFO *clnt, prs_struct *ps, int depth) -{ - if (clnt == NULL) - return False; - - prs_debug(ps, depth, desc, "smb_io_clnt_info"); - depth++; - - if(!prs_align(ps)) - return False; - - if(!smb_io_log_info("", &clnt->login, ps, depth)) - return False; - if(!smb_io_cred("", &clnt->cred, ps, depth)) - return False; - - return True; -} - -/******************************************************************* - Inits a DOM_LOGON_ID structure. -********************************************************************/ - -void init_logon_id(DOM_LOGON_ID *logonid, uint32 log_id_low, uint32 log_id_high) -{ - DEBUG(5,("make_logon_id: %d\n", __LINE__)); - - logonid->low = log_id_low; - logonid->high = log_id_high; -} - -/******************************************************************* - Reads or writes a DOM_LOGON_ID structure. -********************************************************************/ - -bool smb_io_logon_id(const char *desc, DOM_LOGON_ID *logonid, prs_struct *ps, int depth) -{ - if (logonid == NULL) - return False; - - prs_debug(ps, depth, desc, "smb_io_logon_id"); - depth++; - - if(!prs_align(ps)) - return False; - - if(!prs_uint32("low ", ps, depth, &logonid->low )) - return False; - if(!prs_uint32("high", ps, depth, &logonid->high)) - return False; - - return True; -} - -/******************************************************************* - Inits an OWF_INFO structure. -********************************************************************/ - -void init_owf_info(OWF_INFO *hash, const uint8 data[16]) -{ - DEBUG(5,("init_owf_info: %d\n", __LINE__)); - - if (data != NULL) - memcpy(hash->data, data, sizeof(hash->data)); - else - memset((char *)hash->data, '\0', sizeof(hash->data)); -} - -/******************************************************************* - Reads or writes an OWF_INFO structure. -********************************************************************/ - -bool smb_io_owf_info(const char *desc, OWF_INFO *hash, prs_struct *ps, int depth) -{ - if (hash == NULL) - return False; - - prs_debug(ps, depth, desc, "smb_io_owf_info"); - depth++; - - if(!prs_align(ps)) - return False; - - if(!prs_uint8s (False, "data", ps, depth, hash->data, 16)) - return False; - - return True; -} - -/******************************************************************* - Reads or writes a DOM_GID structure. -********************************************************************/ - -bool smb_io_gid(const char *desc, DOM_GID *gid, prs_struct *ps, int depth) -{ - if (gid == NULL) - return False; - - prs_debug(ps, depth, desc, "smb_io_gid"); - depth++; - - if(!prs_align(ps)) - return False; - - if(!prs_uint32("g_rid", ps, depth, &gid->g_rid)) - return False; - if(!prs_uint32("attr ", ps, depth, &gid->attr)) - return False; - - return True; -} - -/******************************************************************* Reads or writes an POLICY_HND structure. ********************************************************************/ @@ -1654,103 +614,6 @@ bool prs_uint64(const char *name, prs_struct *ps, int depth, uint64 *data64) } /******************************************************************* -reads or writes a BUFHDR2 structure. -********************************************************************/ -bool smb_io_bufhdr2(const char *desc, BUFHDR2 *hdr, prs_struct *ps, int depth) -{ - prs_debug(ps, depth, desc, "smb_io_bufhdr2"); - depth++; - - if (!prs_align(ps)) - return False; - if (!prs_uint32("info_level", ps, depth, &(hdr->info_level))) - return False; - if (!prs_uint32("length ", ps, depth, &(hdr->length ))) - return False; - if (!prs_uint32("buffer ", ps, depth, &(hdr->buffer ))) - return False; - - return True; -} - -/******************************************************************* -reads or writes a BUFHDR4 structure. -********************************************************************/ -bool smb_io_bufhdr4(const char *desc, BUFHDR4 *hdr, prs_struct *ps, int depth) -{ - prs_debug(ps, depth, desc, "smb_io_bufhdr4"); - depth++; - - if (!prs_align(ps)) - return False; - if (!prs_uint32("size", ps, depth, &hdr->size)) - return False; - if (!prs_uint32("buffer", ps, depth, &hdr->buffer)) - return False; - - return True; -} - -/******************************************************************* -reads or writes a RPC_DATA_BLOB structure. -********************************************************************/ - -bool smb_io_rpc_blob(const char *desc, RPC_DATA_BLOB *blob, prs_struct *ps, int depth) -{ - prs_debug(ps, depth, desc, "smb_io_rpc_blob"); - depth++; - - if (!prs_align(ps)) - return False; - if ( !prs_uint32("buf_len", ps, depth, &blob->buf_len) ) - return False; - - if ( blob->buf_len == 0 ) - return True; - - if (UNMARSHALLING(ps)) { - blob->buffer = PRS_ALLOC_MEM(ps, uint8, blob->buf_len); - if (!blob->buffer) { - return False; - } - } - - if ( !prs_uint8s(True, "buffer", ps, depth, blob->buffer, blob->buf_len) ) - return False; - - return True; -} - -/******************************************************************* -creates a UNIHDR structure. -********************************************************************/ - -bool make_uni_hdr(UNIHDR *hdr, int len) -{ - if (hdr == NULL) - { - return False; - } - hdr->uni_str_len = 2 * len; - hdr->uni_max_len = 2 * len; - hdr->buffer = len != 0 ? 1 : 0; - - return True; -} - -/******************************************************************* -creates a BUFHDR2 structure. -********************************************************************/ -bool make_bufhdr2(BUFHDR2 *hdr, uint32 info_level, uint32 length, uint32 buffer) -{ - hdr->info_level = info_level; - hdr->length = length; - hdr->buffer = buffer; - - return True; -} - -/******************************************************************* return the length of a UNISTR string. ********************************************************************/ diff --git a/source3/rpc_parse/parse_prs.c b/source3/rpc_parse/parse_prs.c index 1332a8311a..e8103ad866 100644 --- a/source3/rpc_parse/parse_prs.c +++ b/source3/rpc_parse/parse_prs.c @@ -1053,56 +1053,6 @@ bool prs_buffer5(bool charmode, const char *name, prs_struct *ps, int depth, BUF } /****************************************************************** - Stream a string, length/buffer specified separately, - in uint8 chars. - ********************************************************************/ - -bool prs_string2(bool charmode, const char *name, prs_struct *ps, int depth, STRING2 *str) -{ - unsigned int i; - char *q = prs_mem_get(ps, str->str_str_len); - if (q == NULL) - return False; - - if (UNMARSHALLING(ps)) { - if (str->str_str_len > str->str_max_len) { - return False; - } - if (str->str_max_len) { - str->buffer = PRS_ALLOC_MEM(ps,unsigned char, str->str_max_len); - if (str->buffer == NULL) - return False; - } else { - str->buffer = NULL; - /* Return early to ensure Coverity isn't confused. */ - DEBUGADD(5,("%s%04x %s: \n", tab_depth(5,depth), ps->data_offset, name)); - return True; - } - } - - if (UNMARSHALLING(ps)) { - for (i = 0; i < str->str_str_len; i++) - str->buffer[i] = CVAL(q,i); - } else { - for (i = 0; i < str->str_str_len; i++) - SCVAL(q, i, str->buffer[i]); - } - - DEBUGADD(5,("%s%04x %s: ", tab_depth(5,depth), ps->data_offset, name)); - if (charmode) - print_asc(5, (unsigned char*)str->buffer, str->str_str_len); - else { - for (i = 0; i < str->str_str_len; i++) - DEBUG(5,("%02x ", str->buffer[i])); - } - DEBUGADD(5,("\n")); - - ps->data_offset += str->str_str_len; - - return True; -} - -/****************************************************************** Stream a unicode string, length/buffer specified separately, in uint16 chars. The unicode string is already in little-endian format. ********************************************************************/ diff --git a/source3/rpc_server/srv_eventlog.c b/source3/rpc_server/srv_eventlog.c deleted file mode 100644 index 39e3115561..0000000000 --- a/source3/rpc_server/srv_eventlog.c +++ /dev/null @@ -1,119 +0,0 @@ -/* - * Unix SMB/CIFS implementation. - * RPC Pipe client / server routines - * Copyright (C) Marcin Krzysztof Porwit 2005. - * Copyright (C) Gerald Carter 2005 - 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/srv_eventlog.h" - -#undef DBGC_CLASS -#define DBGC_CLASS DBGC_RPC_SRV - -static bool proxy_eventlog_call(pipes_struct *p, uint8 opnum) -{ - struct api_struct *fns; - int n_fns; - - eventlog_get_pipe_fns(&fns, &n_fns); - - if (opnum >= n_fns) - return False; - - if (fns[opnum].opnum != opnum) { - smb_panic("EVENTLOG function table not sorted\n"); - } - - return fns[opnum].fn(p); -} - -static bool api_eventlog_open_eventlog(pipes_struct *p) -{ - return proxy_eventlog_call(p, NDR_EVENTLOG_OPENEVENTLOGW); -} - -static bool api_eventlog_close_eventlog(pipes_struct *p) -{ - return proxy_eventlog_call( p, NDR_EVENTLOG_CLOSEEVENTLOG ); -} - -static bool api_eventlog_get_num_records(pipes_struct *p) -{ - return proxy_eventlog_call(p, NDR_EVENTLOG_GETNUMRECORDS); -} - -static bool api_eventlog_get_oldest_entry(pipes_struct *p) -{ - return proxy_eventlog_call(p, NDR_EVENTLOG_GETOLDESTRECORD); -} - -static bool api_eventlog_read_eventlog(pipes_struct *p) -{ - EVENTLOG_Q_READ_EVENTLOG q_u; - EVENTLOG_R_READ_EVENTLOG r_u; - prs_struct *data = &p->in_data.data; - prs_struct *rdata = &p->out_data.rdata; - - ZERO_STRUCT(q_u); - ZERO_STRUCT(r_u); - - if (!(eventlog_io_q_read_eventlog("", &q_u, data, 0))) { - DEBUG(0, ("eventlog_io_q_read_eventlog: unable to unmarshall EVENTLOG_Q_READ_EVENTLOG.\n")); - return False; - } - - r_u.status = _eventlog_read_eventlog(p, &q_u, &r_u); - - if (!(eventlog_io_r_read_eventlog("", &q_u, &r_u, rdata, 0))) { - DEBUG(0, ("eventlog_io_r_read_eventlog: unable to marshall EVENTLOG_R_READ_EVENTLOG.\n")); - return False; - } - - return True; -} - -static bool api_eventlog_clear_eventlog(pipes_struct *p) -{ - return proxy_eventlog_call(p, NDR_EVENTLOG_CLEAREVENTLOGW); -} - -/* - \pipe\eventlog commands -*/ -struct api_struct api_eventlog_cmds[] = -{ - {"EVENTLOG_OPENEVENTLOG", EVENTLOG_OPENEVENTLOG, api_eventlog_open_eventlog }, - {"EVENTLOG_CLOSEEVENTLOG", EVENTLOG_CLOSEEVENTLOG, api_eventlog_close_eventlog }, - {"EVENTLOG_GETNUMRECORDS", EVENTLOG_GETNUMRECORDS, api_eventlog_get_num_records }, - {"EVENTLOG_GETOLDESTENTRY", EVENTLOG_GETOLDESTENTRY, api_eventlog_get_oldest_entry }, - {"EVENTLOG_READEVENTLOG", EVENTLOG_READEVENTLOG, api_eventlog_read_eventlog }, - {"EVENTLOG_CLEAREVENTLOG", EVENTLOG_CLEAREVENTLOG, api_eventlog_clear_eventlog } -}; - -NTSTATUS rpc_eventlog2_init(void) -{ - return rpc_srv_register(SMB_RPC_INTERFACE_VERSION, - "eventlog", "eventlog", &ndr_table_eventlog, - api_eventlog_cmds, - sizeof(api_eventlog_cmds)/sizeof(struct api_struct)); -} - -void eventlog2_get_pipe_fns(struct api_struct **fns, int *n_fns) -{ - *fns = api_eventlog_cmds; - *n_fns = sizeof(api_eventlog_cmds) / sizeof(struct api_struct); -} diff --git a/source3/rpc_server/srv_eventlog_lib.c b/source3/rpc_server/srv_eventlog_lib.c index 8cbb319e9b..57b3be43ad 100644 --- a/source3/rpc_server/srv_eventlog_lib.c +++ b/source3/rpc_server/srv_eventlog_lib.c @@ -4,6 +4,7 @@ * Copyright (C) Marcin Krzysztof Porwit 2005, * Copyright (C) Brian Moran 2005. * Copyright (C) Gerald (Jerry) Carter 2005. + * Copyright (C) Guenther Deschner 2009. * * 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 @@ -269,7 +270,7 @@ bool prune_eventlog( TDB_CONTEXT * tdb ) /******************************************************************** ********************************************************************/ -bool can_write_to_eventlog( TDB_CONTEXT * tdb, int32_t needed ) +static bool can_write_to_eventlog( TDB_CONTEXT * tdb, int32_t needed ) { int calcd_size; int MaxSize, Retention; @@ -312,7 +313,7 @@ bool can_write_to_eventlog( TDB_CONTEXT * tdb, int32_t needed ) /******************************************************************* *******************************************************************/ -ELOG_TDB *elog_open_tdb( char *logname, bool force_clear ) +ELOG_TDB *elog_open_tdb( const char *logname, bool force_clear, bool read_only ) { TDB_CONTEXT *tdb = NULL; uint32_t vers_id; @@ -322,6 +323,13 @@ ELOG_TDB *elog_open_tdb( char *logname, bool force_clear ) char *eventlogdir; TALLOC_CTX *ctx = talloc_tos(); + /* check for invalid options */ + + if (force_clear && read_only) { + DEBUG(1,("elog_open_tdb: Invalid flags\n")); + return NULL; + } + /* first see if we have an open context */ for ( ptr=open_elog_list; ptr; ptr=ptr->next ) { @@ -363,7 +371,7 @@ ELOG_TDB *elog_open_tdb( char *logname, bool force_clear ) if ( !force_clear ) { - tdb = tdb_open_log( tdbpath, 0, TDB_DEFAULT, O_RDWR , 0 ); + tdb = tdb_open_log( tdbpath, 0, TDB_DEFAULT, read_only ? O_RDONLY : O_RDWR , 0 ); if ( tdb ) { vers_id = tdb_fetch_int32( tdb, EVT_VERSION ); @@ -437,148 +445,6 @@ int elog_close_tdb( ELOG_TDB *etdb, bool force_close ) return 0; } - -/******************************************************************* - write an eventlog entry. Note that we have to lock, read next - eventlog, increment, write, write the record, unlock - - coming into this, ee has the eventlog record, and the auxilliary date - (computer name, etc.) filled into the other structure. Before packing - into a record, this routine will calc the appropriate padding, etc., - and then blast out the record in a form that can be read back in -*******************************************************************/ - -#define MARGIN 512 - -int write_eventlog_tdb( TDB_CONTEXT * the_tdb, Eventlog_entry * ee ) -{ - int32 next_record; - uint8 *packed_ee; - TALLOC_CTX *mem_ctx = NULL; - TDB_DATA kbuf, ebuf; - uint32_t n_packed; - - if ( !ee ) - return 0; - - mem_ctx = talloc_init( "write_eventlog_tdb" ); - - if ( mem_ctx == NULL ) - return 0; - - /* discard any entries that have bogus time, which usually indicates a bogus entry as well. */ - if ( ee->record.time_generated == 0 ) - return 0; - - /* todo - check for sanity in next_record */ - - fixup_eventlog_entry( ee ); - - if ( !can_write_to_eventlog( the_tdb, ee->record.length ) ) { - DEBUG( 3, ( "Can't write to Eventlog, no room \n" ) ); - talloc_destroy( mem_ctx ); - return 0; - } - - /* alloc mem for the packed version */ - packed_ee = (uint8 *)TALLOC( mem_ctx, ee->record.length + MARGIN ); - if ( !packed_ee ) { - talloc_destroy( mem_ctx ); - return 0; - } - - /* need to read the record number and insert it into the entry here */ - - /* lock */ - tdb_lock_bystring_with_timeout( the_tdb, EVT_NEXT_RECORD, 1 ); - /* read */ - next_record = tdb_fetch_int32( the_tdb, EVT_NEXT_RECORD ); - - n_packed = - tdb_pack( (uint8 *)packed_ee, ee->record.length + MARGIN, - "ddddddwwwwddddddBBdBBBd", ee->record.length, - ee->record.reserved1, next_record, - ee->record.time_generated, ee->record.time_written, - ee->record.event_id, ee->record.event_type, - ee->record.num_strings, ee->record.event_category, - ee->record.reserved2, - ee->record.closing_record_number, - ee->record.string_offset, - ee->record.user_sid_length, - ee->record.user_sid_offset, ee->record.data_length, - ee->record.data_offset, - ee->data_record.source_name_len, - ee->data_record.source_name, - ee->data_record.computer_name_len, - ee->data_record.computer_name, - ee->data_record.sid_padding, - ee->record.user_sid_length, ee->data_record.sid, - ee->data_record.strings_len, - ee->data_record.strings, - ee->data_record.user_data_len, - ee->data_record.user_data, - ee->data_record.data_padding ); - - /*DEBUG(3,("write_eventlog_tdb: packed into %d\n",n_packed)); */ - - /* increment the record count */ - - kbuf.dsize = sizeof( int32 ); - kbuf.dptr = (uint8 * ) & next_record; - - ebuf.dsize = n_packed; - ebuf.dptr = (uint8 *)packed_ee; - - if ( tdb_store( the_tdb, kbuf, ebuf, 0 ) ) { - /* DEBUG(1,("write_eventlog_tdb: Can't write record %d to eventlog\n",next_record)); */ - tdb_unlock_bystring( the_tdb, EVT_NEXT_RECORD ); - talloc_destroy( mem_ctx ); - return 0; - } - next_record++; - tdb_store_int32( the_tdb, EVT_NEXT_RECORD, next_record ); - tdb_unlock_bystring( the_tdb, EVT_NEXT_RECORD ); - talloc_destroy( mem_ctx ); - return ( next_record - 1 ); -} - -/******************************************************************* - calculate the correct fields etc for an eventlog entry -*******************************************************************/ - -void fixup_eventlog_entry( Eventlog_entry * ee ) -{ - /* fix up the eventlog entry structure as necessary */ - - ee->data_record.sid_padding = - ( ( 4 - - ( ( ee->data_record.source_name_len + - ee->data_record.computer_name_len ) % 4 ) ) % 4 ); - ee->data_record.data_padding = - ( 4 - - ( ( ee->data_record.strings_len + - ee->data_record.user_data_len ) % 4 ) ) % 4; - ee->record.length = sizeof( Eventlog_record ); - ee->record.length += ee->data_record.source_name_len; - ee->record.length += ee->data_record.computer_name_len; - if ( ee->record.user_sid_length == 0 ) { - /* Should not pad to a DWORD boundary for writing out the sid if there is - no SID, so just propagate the padding to pad the data */ - ee->data_record.data_padding += ee->data_record.sid_padding; - ee->data_record.sid_padding = 0; - } - /* DEBUG(10, ("sid_padding is [%d].\n", ee->data_record.sid_padding)); */ - /* DEBUG(10, ("data_padding is [%d].\n", ee->data_record.data_padding)); */ - - ee->record.length += ee->data_record.sid_padding; - ee->record.length += ee->record.user_sid_length; - ee->record.length += ee->data_record.strings_len; - ee->record.length += ee->data_record.user_data_len; - ee->record.length += ee->data_record.data_padding; - /* need another copy of length at the end of the data */ - ee->record.length += sizeof( ee->record.length ); -} - /******************************************************************** Note that it's a pretty good idea to initialize the Eventlog_entry structure to zero's before calling parse_logentry on an batch of @@ -587,9 +453,8 @@ void fixup_eventlog_entry( Eventlog_entry * ee ) going in. ********************************************************************/ -bool parse_logentry( char *line, Eventlog_entry * entry, bool * eor ) +bool parse_logentry( TALLOC_CTX *mem_ctx, char *line, struct eventlog_Record_tdb *entry, bool * eor ) { - TALLOC_CTX *ctx = talloc_tos(); char *start = NULL, *stop = NULL; start = line; @@ -609,32 +474,32 @@ bool parse_logentry( char *line, Eventlog_entry * entry, bool * eor ) if ( 0 == strncmp( start, "LEN", stop - start ) ) { /* This will get recomputed later anyway -- probably not necessary */ - entry->record.length = atoi( stop + 1 ); + entry->size = atoi( stop + 1 ); } else if ( 0 == strncmp( start, "RS1", stop - start ) ) { /* For now all these reserved entries seem to have the same value, which can be hardcoded to int(1699505740) for now */ - entry->record.reserved1 = atoi( stop + 1 ); + entry->reserved = talloc_strdup(mem_ctx, "eLfL"); } else if ( 0 == strncmp( start, "RCN", stop - start ) ) { - entry->record.record_number = atoi( stop + 1 ); + entry->record_number = atoi( stop + 1 ); } else if ( 0 == strncmp( start, "TMG", stop - start ) ) { - entry->record.time_generated = atoi( stop + 1 ); + entry->time_generated = atoi( stop + 1 ); } else if ( 0 == strncmp( start, "TMW", stop - start ) ) { - entry->record.time_written = atoi( stop + 1 ); + entry->time_written = atoi( stop + 1 ); } else if ( 0 == strncmp( start, "EID", stop - start ) ) { - entry->record.event_id = atoi( stop + 1 ); + entry->event_id = atoi( stop + 1 ); } else if ( 0 == strncmp( start, "ETP", stop - start ) ) { if ( strstr( start, "ERROR" ) ) { - entry->record.event_type = EVENTLOG_ERROR_TYPE; + entry->event_type = EVENTLOG_ERROR_TYPE; } else if ( strstr( start, "WARNING" ) ) { - entry->record.event_type = EVENTLOG_WARNING_TYPE; + entry->event_type = EVENTLOG_WARNING_TYPE; } else if ( strstr( start, "INFO" ) ) { - entry->record.event_type = EVENTLOG_INFORMATION_TYPE; + entry->event_type = EVENTLOG_INFORMATION_TYPE; } else if ( strstr( start, "AUDIT_SUCCESS" ) ) { - entry->record.event_type = EVENTLOG_AUDIT_SUCCESS; + entry->event_type = EVENTLOG_AUDIT_SUCCESS; } else if ( strstr( start, "AUDIT_FAILURE" ) ) { - entry->record.event_type = EVENTLOG_AUDIT_FAILURE; + entry->event_type = EVENTLOG_AUDIT_FAILURE; } else if ( strstr( start, "SUCCESS" ) ) { - entry->record.event_type = EVENTLOG_SUCCESS; + entry->event_type = EVENTLOG_SUCCESS; } else { /* some other eventlog type -- currently not defined in MSDN docs, so error out */ return False; @@ -644,27 +509,26 @@ bool parse_logentry( char *line, Eventlog_entry * entry, bool * eor ) /* else if(0 == strncmp(start, "NST", stop - start)) { - entry->record.num_strings = atoi(stop + 1); + entry->num_of_strings = atoi(stop + 1); } */ else if ( 0 == strncmp( start, "ECT", stop - start ) ) { - entry->record.event_category = atoi( stop + 1 ); + entry->event_category = atoi( stop + 1 ); } else if ( 0 == strncmp( start, "RS2", stop - start ) ) { - entry->record.reserved2 = atoi( stop + 1 ); + entry->reserved_flags = atoi( stop + 1 ); } else if ( 0 == strncmp( start, "CRN", stop - start ) ) { - entry->record.closing_record_number = atoi( stop + 1 ); + entry->closing_record_number = atoi( stop + 1 ); } else if ( 0 == strncmp( start, "USL", stop - start ) ) { - entry->record.user_sid_length = atoi( stop + 1 ); + entry->sid_length = atoi( stop + 1 ); } else if ( 0 == strncmp( start, "SRC", stop - start ) ) { stop++; while ( isspace( stop[0] ) ) { stop++; } - entry->data_record.source_name_len = rpcstr_push_talloc(ctx, - &entry->data_record.source_name, - stop); - if (entry->data_record.source_name_len == (uint32_t)-1 || - entry->data_record.source_name == NULL) { + entry->source_name_len = strlen_m_term(stop); + entry->source_name = talloc_strdup(mem_ctx, stop); + if (entry->source_name_len == (uint32_t)-1 || + entry->source_name == NULL) { return false; } } else if ( 0 == strncmp( start, "SRN", stop - start ) ) { @@ -672,54 +536,43 @@ bool parse_logentry( char *line, Eventlog_entry * entry, bool * eor ) while ( isspace( stop[0] ) ) { stop++; } - entry->data_record.computer_name_len = rpcstr_push_talloc(ctx, - &entry->data_record.computer_name, - stop); - if (entry->data_record.computer_name_len == (uint32_t)-1 || - entry->data_record.computer_name == NULL) { + entry->computer_name_len = strlen_m_term(stop); + entry->computer_name = talloc_strdup(mem_ctx, stop); + if (entry->computer_name_len == (uint32_t)-1 || + entry->computer_name == NULL) { return false; } } else if ( 0 == strncmp( start, "SID", stop - start ) ) { + smb_ucs2_t *dummy = NULL; stop++; while ( isspace( stop[0] ) ) { stop++; } - entry->record.user_sid_length = rpcstr_push_talloc(ctx, - &entry->data_record.sid, + entry->sid_length = rpcstr_push_talloc(mem_ctx, + &dummy, stop); - if (entry->record.user_sid_length == (uint32_t)-1 || - entry->data_record.sid == NULL) { + entry->sid = data_blob_talloc(mem_ctx, dummy, entry->sid_length); + if (entry->sid_length == (uint32_t)-1 || + entry->sid.data == NULL) { return false; } } else if ( 0 == strncmp( start, "STR", stop - start ) ) { - smb_ucs2_t *temp = NULL; size_t tmp_len; - uint32_t old_len; /* skip past initial ":" */ stop++; /* now skip any other leading whitespace */ while ( isspace(stop[0])) { stop++; } - tmp_len = rpcstr_push_talloc(ctx, - &temp, - stop); - if (tmp_len == (size_t)-1 || !temp) { + tmp_len = strlen_m_term(stop); + if (tmp_len == (size_t)-1) { return false; } - old_len = entry->data_record.strings_len; - entry->data_record.strings = (smb_ucs2_t *)TALLOC_REALLOC_ARRAY(ctx, - entry->data_record.strings, - char, - old_len + tmp_len); - if (!entry->data_record.strings) { + if (!add_string_to_array(mem_ctx, stop, &entry->strings, + (int *)&entry->num_of_strings)) { return false; } - memcpy(((char *)entry->data_record.strings) + old_len, - temp, - tmp_len); - entry->data_record.strings_len += tmp_len; - entry->record.num_strings++; + entry->strings_len += tmp_len; } else if ( 0 == strncmp( start, "DAT", stop - start ) ) { /* skip past initial ":" */ stop++; @@ -727,10 +580,9 @@ bool parse_logentry( char *line, Eventlog_entry * entry, bool * eor ) while ( isspace( stop[0] ) ) { stop++; } - entry->data_record.user_data_len = strlen(stop); - entry->data_record.user_data = talloc_strdup(ctx, - stop); - if (!entry->data_record.user_data) { + entry->data_length = strlen_m(stop); + entry->data = data_blob_talloc(mem_ctx, stop, entry->data_length); + if (!entry->data.data) { return false; } } else { @@ -742,3 +594,359 @@ bool parse_logentry( char *line, Eventlog_entry * entry, bool * eor ) } return true; } + +/******************************************************************* + calculate the correct fields etc for an eventlog entry +*******************************************************************/ + +size_t fixup_eventlog_record_tdb(struct eventlog_Record_tdb *r) +{ + size_t size = 56; /* static size of integers before buffers start */ + + r->source_name_len = strlen_m_term(r->source_name) * 2; + r->computer_name_len = strlen_m_term(r->computer_name) * 2; + r->strings_len = ndr_size_string_array(r->strings, + r->num_of_strings, LIBNDR_FLAG_STR_NULLTERM) * 2; + + /* fix up the eventlog entry structure as necessary */ + r->sid_padding = ( ( 4 - ( ( r->source_name_len + r->computer_name_len ) % 4 ) ) % 4 ); + r->padding = ( 4 - ( ( r->strings_len + r->data_length ) % 4 ) ) % 4; + + if (r->sid_length == 0) { + /* Should not pad to a DWORD boundary for writing out the sid if there is + no SID, so just propagate the padding to pad the data */ + r->padding += r->sid_padding; + r->sid_padding = 0; + } + + size += r->source_name_len; + size += r->computer_name_len; + size += r->sid_padding; + size += r->sid_length; + size += r->strings_len; + size += r->data_length; + size += r->padding; + /* need another copy of length at the end of the data */ + size += sizeof(r->size); + + r->size = size; + + return size; +} + + +/******************************************************************** + ********************************************************************/ + +struct eventlog_Record_tdb *evlog_pull_record_tdb(TALLOC_CTX *mem_ctx, + TDB_CONTEXT *tdb, + uint32_t record_number) +{ + struct eventlog_Record_tdb *r; + TDB_DATA data, key; + + int32_t srecno; + enum ndr_err_code ndr_err; + DATA_BLOB blob; + + srecno = record_number; + key.dptr = (unsigned char *)&srecno; + key.dsize = sizeof(int32_t); + + data = tdb_fetch(tdb, key); + if (data.dsize == 0) { + DEBUG(8,("evlog_pull_record_tdb: " + "Can't find a record for the key, record %d\n", + record_number)); + return NULL; + } + + r = talloc_zero(mem_ctx, struct eventlog_Record_tdb); + if (!r) { + goto done; + } + + blob = data_blob_const(data.dptr, data.dsize); + + ndr_err = ndr_pull_struct_blob(&blob, mem_ctx, NULL, r, + (ndr_pull_flags_fn_t)ndr_pull_eventlog_Record_tdb); + + if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { + DEBUG(10,("evlog_pull_record_tdb: failed to decode record %d\n", + record_number)); + TALLOC_FREE(r); + goto done; + } + + if (DEBUGLEVEL >= 10) { + NDR_PRINT_DEBUG(eventlog_Record_tdb, r); + } + + DEBUG(10,("evlog_pull_record_tdb: retrieved entry for record %d\n", + record_number)); + done: + SAFE_FREE(data.dptr); + + return r; +} + +/******************************************************************** + ********************************************************************/ + +struct EVENTLOGRECORD *evlog_pull_record(TALLOC_CTX *mem_ctx, + TDB_CONTEXT *tdb, + uint32_t record_number) +{ + struct eventlog_Record_tdb *t; + struct EVENTLOGRECORD *r; + NTSTATUS status; + + r = talloc_zero(mem_ctx, struct EVENTLOGRECORD); + if (!r) { + return NULL; + } + + t = evlog_pull_record_tdb(r, tdb, record_number); + if (!t) { + talloc_free(r); + return NULL; + } + + status = evlog_tdb_entry_to_evt_entry(r, t, r); + if (!NT_STATUS_IS_OK(status)) { + talloc_free(r); + return NULL; + } + + r->Length = r->Length2 = ndr_size_EVENTLOGRECORD(r, NULL, 0); + + return r; +} + +/******************************************************************** + write an eventlog entry. Note that we have to lock, read next + eventlog, increment, write, write the record, unlock + + coming into this, ee has the eventlog record, and the auxilliary date + (computer name, etc.) filled into the other structure. Before packing + into a record, this routine will calc the appropriate padding, etc., + and then blast out the record in a form that can be read back in + ********************************************************************/ + +NTSTATUS evlog_push_record_tdb(TALLOC_CTX *mem_ctx, + TDB_CONTEXT *tdb, + struct eventlog_Record_tdb *r, + uint32_t *record_number) +{ + TDB_DATA kbuf, ebuf; + DATA_BLOB blob; + enum ndr_err_code ndr_err; + int ret; + + if (!r) { + return NT_STATUS_INVALID_PARAMETER; + } + + if (!can_write_to_eventlog(tdb, r->size)) { + return NT_STATUS_EVENTLOG_CANT_START; + } + + /* need to read the record number and insert it into the entry here */ + + /* lock */ + ret = tdb_lock_bystring_with_timeout(tdb, EVT_NEXT_RECORD, 1); + if (ret == -1) { + return NT_STATUS_LOCK_NOT_GRANTED; + } + + /* read */ + r->record_number = tdb_fetch_int32(tdb, EVT_NEXT_RECORD); + + ndr_err = ndr_push_struct_blob(&blob, mem_ctx, NULL, r, + (ndr_push_flags_fn_t)ndr_push_eventlog_Record_tdb); + if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { + tdb_unlock_bystring(tdb, EVT_NEXT_RECORD); + return ndr_map_error2ntstatus(ndr_err); + } + + /* increment the record count */ + + kbuf.dsize = sizeof(int32_t); + kbuf.dptr = (uint8_t *)&r->record_number; + + ebuf.dsize = blob.length; + ebuf.dptr = blob.data; + + ret = tdb_store(tdb, kbuf, ebuf, 0); + if (ret == -1) { + tdb_unlock_bystring(tdb, EVT_NEXT_RECORD); + return NT_STATUS_EVENTLOG_FILE_CORRUPT; + } + + ret = tdb_store_int32(tdb, EVT_NEXT_RECORD, r->record_number + 1); + if (ret == -1) { + tdb_unlock_bystring(tdb, EVT_NEXT_RECORD); + return NT_STATUS_EVENTLOG_FILE_CORRUPT; + } + tdb_unlock_bystring(tdb, EVT_NEXT_RECORD); + + if (record_number) { + *record_number = r->record_number; + } + + return NT_STATUS_OK; +} + +/******************************************************************** + ********************************************************************/ + +NTSTATUS evlog_push_record(TALLOC_CTX *mem_ctx, + TDB_CONTEXT *tdb, + struct EVENTLOGRECORD *r, + uint32_t *record_number) +{ + struct eventlog_Record_tdb *t; + NTSTATUS status; + + t = talloc_zero(mem_ctx, struct eventlog_Record_tdb); + if (!t) { + return NT_STATUS_NO_MEMORY; + } + + status = evlog_evt_entry_to_tdb_entry(t, r, t); + if (!NT_STATUS_IS_OK(status)) { + talloc_free(t); + return status; + } + + status = evlog_push_record_tdb(mem_ctx, tdb, t, record_number); + talloc_free(t); + + return status; +} + +/******************************************************************** + ********************************************************************/ + +NTSTATUS evlog_evt_entry_to_tdb_entry(TALLOC_CTX *mem_ctx, + const struct EVENTLOGRECORD *e, + struct eventlog_Record_tdb *t) +{ + uint32_t i; + + ZERO_STRUCTP(t); + + t->size = e->Length; + t->reserved = e->Reserved; + t->record_number = e->RecordNumber; + t->time_generated = e->TimeGenerated; + t->time_written = e->TimeWritten; + t->event_id = e->EventID; + t->event_type = e->EventType; + t->num_of_strings = e->NumStrings; + t->event_category = e->EventCategory; + t->reserved_flags = e->ReservedFlags; + t->closing_record_number = e->ClosingRecordNumber; + + t->stringoffset = e->StringOffset; + t->sid_length = e->UserSidLength; + t->sid_offset = e->UserSidOffset; + t->data_length = e->DataLength; + t->data_offset = e->DataOffset; + + t->source_name_len = 2 * strlen_m_term(e->SourceName); + t->source_name = talloc_strdup(mem_ctx, e->SourceName); + NT_STATUS_HAVE_NO_MEMORY(t->source_name); + + t->computer_name_len = 2 * strlen_m_term(e->Computername); + t->computer_name = talloc_strdup(mem_ctx, e->Computername); + NT_STATUS_HAVE_NO_MEMORY(t->computer_name); + + /* t->sid_padding; */ + if (e->UserSidLength > 0) { + const char *sid_str = NULL; + smb_ucs2_t *dummy = NULL; + sid_str = sid_string_talloc(mem_ctx, &e->UserSid); + t->sid_length = rpcstr_push_talloc(mem_ctx, &dummy, sid_str); + if (t->sid_length == -1) { + return NT_STATUS_NO_MEMORY; + } + t->sid = data_blob_talloc(mem_ctx, (uint8_t *)dummy, t->sid_length); + NT_STATUS_HAVE_NO_MEMORY(t->sid.data); + } + + t->strings = talloc_array(mem_ctx, const char *, e->NumStrings); + for (i=0; i < e->NumStrings; i++) { + t->strings[i] = talloc_strdup(t->strings, e->Strings[i]); + NT_STATUS_HAVE_NO_MEMORY(t->strings[i]); + } + + t->strings_len = 2 * ndr_size_string_array(t->strings, t->num_of_strings, LIBNDR_FLAG_STR_NULLTERM); + t->data = data_blob_talloc(mem_ctx, e->Data, e->DataLength); + /* t->padding = r->Pad; */ + + return NT_STATUS_OK; +} + +/******************************************************************** + ********************************************************************/ + +NTSTATUS evlog_tdb_entry_to_evt_entry(TALLOC_CTX *mem_ctx, + const struct eventlog_Record_tdb *t, + struct EVENTLOGRECORD *e) +{ + uint32_t i; + + ZERO_STRUCTP(e); + + e->Length = t->size; + e->Reserved = t->reserved; + e->RecordNumber = t->record_number; + e->TimeGenerated = t->time_generated; + e->TimeWritten = t->time_written; + e->EventID = t->event_id; + e->EventType = t->event_type; + e->NumStrings = t->num_of_strings; + e->EventCategory = t->event_category; + e->ReservedFlags = t->reserved_flags; + e->ClosingRecordNumber = t->closing_record_number; + + e->StringOffset = t->stringoffset; + e->UserSidLength = t->sid_length; + e->UserSidOffset = t->sid_offset; + e->DataLength = t->data_length; + e->DataOffset = t->data_offset; + + e->SourceName = talloc_strdup(mem_ctx, t->source_name); + NT_STATUS_HAVE_NO_MEMORY(e->SourceName); + + e->Computername = talloc_strdup(mem_ctx, t->computer_name); + NT_STATUS_HAVE_NO_MEMORY(e->Computername); + + if (t->sid_length > 0) { + const char *sid_str = NULL; + size_t len; + if (!convert_string_talloc(mem_ctx, CH_UTF16, CH_UNIX, + t->sid.data, t->sid.length, + &sid_str, &len, false)) { + return NT_STATUS_INVALID_SID; + } + if (len > 0) { + e->UserSid = *string_sid_talloc(mem_ctx, sid_str); + } + } + + e->Strings = talloc_array(mem_ctx, const char *, t->num_of_strings); + for (i=0; i < t->num_of_strings; i++) { + e->Strings[i] = talloc_strdup(e->Strings, t->strings[i]); + NT_STATUS_HAVE_NO_MEMORY(e->Strings[i]); + } + + e->Data = (uint8_t *)talloc_memdup(mem_ctx, t->data.data, t->data_length); + e->Pad = talloc_strdup(mem_ctx, ""); + NT_STATUS_HAVE_NO_MEMORY(e->Pad); + + e->Length2 = t->size; + + return NT_STATUS_OK; +} diff --git a/source3/rpc_server/srv_eventlog_nt.c b/source3/rpc_server/srv_eventlog_nt.c index a687025ba6..697457888e 100644 --- a/source3/rpc_server/srv_eventlog_nt.c +++ b/source3/rpc_server/srv_eventlog_nt.c @@ -4,6 +4,7 @@ * Copyright (C) Marcin Krzysztof Porwit 2005, * Copyright (C) Brian Moran 2005, * Copyright (C) Gerald (Jerry) Carter 2005. + * Copyright (C) Guenther Deschner 2009. * * 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 @@ -194,7 +195,7 @@ static NTSTATUS elog_open( pipes_struct * p, const char *logname, POLICY_HND *hn in a single process */ become_root(); - elog->etdb = elog_open_tdb( elog->logname, False ); + elog->etdb = elog_open_tdb( elog->logname, False, False ); unbecome_root(); if ( !elog->etdb ) { @@ -214,7 +215,7 @@ static NTSTATUS elog_open( pipes_struct * p, const char *logname, POLICY_HND *hn } become_root(); - elog->etdb = elog_open_tdb( elog->logname, False ); + elog->etdb = elog_open_tdb( elog->logname, False, False ); unbecome_root(); } @@ -276,140 +277,6 @@ static int elog_size( EVENTLOG_INFO *info ) } /******************************************************************** - For the given tdb, get the next eventlog record into the passed - Eventlog_entry. returns NULL if it can't get the record for some reason. - ********************************************************************/ - -static Eventlog_entry *get_eventlog_record(TALLOC_CTX *mem_ctx, - TDB_CONTEXT *tdb, - int recno) -{ - Eventlog_entry *ee = NULL; - TDB_DATA ret, key; - - int32_t srecno; - int32_t reclen; - int len; - - char *wpsource = NULL; - char *wpcomputer = NULL; - char *wpsid = NULL; - char *wpstrs = NULL; - char *puserdata = NULL; - - key.dsize = sizeof(int32_t); - - srecno = recno; - key.dptr = (unsigned char *)&srecno; - - ret = tdb_fetch( tdb, key ); - - if ( ret.dsize == 0 ) { - DEBUG( 8, - ( "Can't find a record for the key, record %d\n", - recno ) ); - return NULL; - } - - len = tdb_unpack( ret.dptr, ret.dsize, "d", &reclen ); - - DEBUG( 10, ( "Unpacking record %d, size is %d\n", srecno, len ) ); - - if ( !len ) - return NULL; - - ee = TALLOC_ARRAY(mem_ctx, Eventlog_entry, 1); - if (!ee) { - return NULL; - } - ZERO_STRUCTP(ee); - - len = tdb_unpack( ret.dptr, ret.dsize, "ddddddwwwwddddddBBdBBBd", - &ee->record.length, &ee->record.reserved1, - &ee->record.record_number, - &ee->record.time_generated, - &ee->record.time_written, &ee->record.event_id, - &ee->record.event_type, &ee->record.num_strings, - &ee->record.event_category, &ee->record.reserved2, - &ee->record.closing_record_number, - &ee->record.string_offset, - &ee->record.user_sid_length, - &ee->record.user_sid_offset, - &ee->record.data_length, &ee->record.data_offset, - &ee->data_record.source_name_len, &wpsource, - &ee->data_record.computer_name_len, &wpcomputer, - &ee->data_record.sid_padding, - &ee->record.user_sid_length, &wpsid, - &ee->data_record.strings_len, &wpstrs, - &ee->data_record.user_data_len, &puserdata, - &ee->data_record.data_padding ); - DEBUG( 10, - ( "Read record %d, len in tdb was %d\n", - ee->record.record_number, len ) ); - - /* have to do the following because the tdb_unpack allocs a buff, stuffs a pointer to the buff - into it's 2nd argment for 'B' */ - - if (wpcomputer) { - ee->data_record.computer_name = (smb_ucs2_t *)TALLOC_MEMDUP( - ee, wpcomputer, ee->data_record.computer_name_len); - if (!ee->data_record.computer_name) { - TALLOC_FREE(ee); - goto out; - } - } - if (wpsource) { - ee->data_record.source_name = (smb_ucs2_t *)TALLOC_MEMDUP( - ee, wpsource, ee->data_record.source_name_len); - if (!ee->data_record.source_name) { - TALLOC_FREE(ee); - goto out; - } - } - - if (wpsid) { - ee->data_record.sid = (smb_ucs2_t *)TALLOC_MEMDUP( - ee, wpsid, ee->record.user_sid_length); - if (!ee->data_record.sid) { - TALLOC_FREE(ee); - goto out; - } - } - if (wpstrs) { - ee->data_record.strings = (smb_ucs2_t *)TALLOC_MEMDUP( - ee, wpstrs, ee->data_record.strings_len); - if (!ee->data_record.strings) { - TALLOC_FREE(ee); - goto out; - } - } - - if (puserdata) { - ee->data_record.user_data = (char *)TALLOC_MEMDUP( - ee, puserdata, ee->data_record.user_data_len); - if (!ee->data_record.user_data) { - TALLOC_FREE(ee); - goto out; - } - } - - out: - - SAFE_FREE(wpcomputer); - SAFE_FREE(wpsource); - SAFE_FREE(wpsid); - SAFE_FREE(wpstrs); - SAFE_FREE(puserdata); - - DEBUG( 10, ( "get_eventlog_record: read back %d\n", len ) ); - DEBUG( 10, - ( "get_eventlog_record: computer_name %d is ", - ee->data_record.computer_name_len ) ); - SAFE_FREE(ret.dptr); - return ee; -} - -/******************************************************************** note that this can only be called AFTER the table is constructed, since it uses the table to find the tdb handle ********************************************************************/ @@ -484,124 +351,6 @@ done: } /******************************************************************** - ********************************************************************/ - -static Eventlog_entry *read_package_entry( TALLOC_CTX *mem_ctx, - Eventlog_entry * entry ) -{ - uint8 *offset; - Eventlog_entry *ee_new = NULL; - - ee_new = TALLOC_ZERO_ARRAY(mem_ctx, Eventlog_entry, 1 ); - if ( ee_new == NULL ) { - return NULL; - } - - entry->data_record.sid_padding = - ( ( 4 - - ( ( entry->data_record.source_name_len + - entry->data_record.computer_name_len ) % 4 ) ) % 4 ); - entry->data_record.data_padding = - ( 4 - - ( ( entry->data_record.strings_len + - entry->data_record.user_data_len ) % 4 ) ) % 4; - entry->record.length = sizeof( Eventlog_record ); - entry->record.length += entry->data_record.source_name_len; - entry->record.length += entry->data_record.computer_name_len; - if ( entry->record.user_sid_length == 0 ) { - /* Should not pad to a DWORD boundary for writing out the sid if there is - no SID, so just propagate the padding to pad the data */ - entry->data_record.data_padding += - entry->data_record.sid_padding; - entry->data_record.sid_padding = 0; - } - DEBUG( 10, - ( "sid_padding is [%d].\n", entry->data_record.sid_padding ) ); - DEBUG( 10, - ( "data_padding is [%d].\n", - entry->data_record.data_padding ) ); - - entry->record.length += entry->data_record.sid_padding; - entry->record.length += entry->record.user_sid_length; - entry->record.length += entry->data_record.strings_len; - entry->record.length += entry->data_record.user_data_len; - entry->record.length += entry->data_record.data_padding; - /* need another copy of length at the end of the data */ - entry->record.length += sizeof( entry->record.length ); - DEBUG( 10, - ( "entry->record.length is [%d].\n", entry->record.length ) ); - entry->data = - TALLOC_ZERO_ARRAY(mem_ctx, uint8_t, - entry->record.length - - sizeof( Eventlog_record ) - - sizeof( entry->record.length )); - if ( entry->data == NULL ) { - return NULL; - } - offset = entry->data; - memcpy( offset, entry->data_record.source_name, - entry->data_record.source_name_len ); - offset += entry->data_record.source_name_len; - memcpy( offset, entry->data_record.computer_name, - entry->data_record.computer_name_len ); - offset += entry->data_record.computer_name_len; - /* SID needs to be DWORD-aligned */ - offset += entry->data_record.sid_padding; - entry->record.user_sid_offset = - sizeof( Eventlog_record ) + ( offset - entry->data ); - memcpy( offset, entry->data_record.sid, - entry->record.user_sid_length ); - offset += entry->record.user_sid_length; - /* Now do the strings */ - entry->record.string_offset = - sizeof( Eventlog_record ) + ( offset - entry->data ); - memcpy( offset, entry->data_record.strings, - entry->data_record.strings_len ); - offset += entry->data_record.strings_len; - /* Now do the data */ - entry->record.data_length = entry->data_record.user_data_len; - entry->record.data_offset = - sizeof( Eventlog_record ) + ( offset - entry->data ); - memcpy( offset, entry->data_record.user_data, - entry->data_record.user_data_len ); - offset += entry->data_record.user_data_len; - - memcpy( &( ee_new->record ), &entry->record, - sizeof( Eventlog_record ) ); - memcpy( &( ee_new->data_record ), &entry->data_record, - sizeof( Eventlog_data_record ) ); - ee_new->data = entry->data; - - return ee_new; -} - -/******************************************************************** - ********************************************************************/ - -static bool add_record_to_resp( EVENTLOG_R_READ_EVENTLOG * r_u, - Eventlog_entry * ee_new ) -{ - Eventlog_entry *insert_point; - - insert_point = r_u->entry; - - if ( NULL == insert_point ) { - r_u->entry = ee_new; - ee_new->next = NULL; - } else { - while ( ( NULL != insert_point->next ) ) { - insert_point = insert_point->next; - } - ee_new->next = NULL; - insert_point->next = ee_new; - } - r_u->num_records++; - r_u->num_bytes_in_resp += ee_new->record.length; - - return True; -} - -/******************************************************************** _eventlog_OpenEventLogW ********************************************************************/ @@ -677,7 +426,7 @@ NTSTATUS _eventlog_ClearEventLogW(pipes_struct *p, elog_close_tdb( info->etdb, True ); become_root(); - info->etdb = elog_open_tdb( info->logname, True ); + info->etdb = elog_open_tdb( info->logname, True, False ); unbecome_root(); if ( !info->etdb ) @@ -706,98 +455,117 @@ NTSTATUS _eventlog_CloseEventLog(pipes_struct * p, } /******************************************************************** + _eventlog_ReadEventLogW ********************************************************************/ -NTSTATUS _eventlog_read_eventlog( pipes_struct * p, - EVENTLOG_Q_READ_EVENTLOG * q_u, - EVENTLOG_R_READ_EVENTLOG * r_u ) +NTSTATUS _eventlog_ReadEventLogW(pipes_struct *p, + struct eventlog_ReadEventLogW *r) { - EVENTLOG_INFO *info = find_eventlog_info_by_hnd( p, &q_u->handle ); - Eventlog_entry *entry = NULL, *ee_new = NULL; - uint32 num_records_read = 0; + EVENTLOG_INFO *info = find_eventlog_info_by_hnd( p, r->in.handle ); + uint32_t num_records_read = 0; int bytes_left, record_number; - uint32 elog_read_type, elog_read_dir; + uint32_t elog_read_type, elog_read_dir; - if (info == NULL) { + if (!info) { return NT_STATUS_INVALID_HANDLE; } - info->flags = q_u->flags; + info->flags = r->in.flags; + bytes_left = r->in.number_of_bytes; - bytes_left = q_u->max_read_size; - - if ( !info->etdb ) + if (!info->etdb) { return NT_STATUS_ACCESS_DENIED; + } /* check for valid flags. Can't use the sequential and seek flags together */ - elog_read_type = q_u->flags & (EVENTLOG_SEQUENTIAL_READ|EVENTLOG_SEEK_READ); - elog_read_dir = q_u->flags & (EVENTLOG_FORWARDS_READ|EVENTLOG_BACKWARDS_READ); + elog_read_type = r->in.flags & (EVENTLOG_SEQUENTIAL_READ|EVENTLOG_SEEK_READ); + elog_read_dir = r->in.flags & (EVENTLOG_FORWARDS_READ|EVENTLOG_BACKWARDS_READ); - if ( elog_read_type == (EVENTLOG_SEQUENTIAL_READ|EVENTLOG_SEEK_READ) - || elog_read_dir == (EVENTLOG_FORWARDS_READ|EVENTLOG_BACKWARDS_READ) ) + if (r->in.flags == 0 || + elog_read_type == (EVENTLOG_SEQUENTIAL_READ|EVENTLOG_SEEK_READ) || + elog_read_dir == (EVENTLOG_FORWARDS_READ|EVENTLOG_BACKWARDS_READ)) { - DEBUG(3,("_eventlog_read_eventlog: Invalid flags [0x%x] for ReadEventLog\n", q_u->flags)); + DEBUG(3,("_eventlog_ReadEventLogW: " + "Invalid flags [0x%08x] for ReadEventLog\n", + r->in.flags)); return NT_STATUS_INVALID_PARAMETER; } /* a sequential read should ignore the offset */ - if ( elog_read_type & EVENTLOG_SEQUENTIAL_READ ) + if (elog_read_type & EVENTLOG_SEQUENTIAL_READ) { record_number = info->current_record; - else - record_number = q_u->offset; + } else { + record_number = r->in.offset; + } + + if (r->in.number_of_bytes == 0) { + struct EVENTLOGRECORD *e; + e = evlog_pull_record(p->mem_ctx, ELOG_TDB_CTX(info->etdb), + record_number); + if (!e) { + return NT_STATUS_END_OF_FILE; + } + *r->out.real_size = e->Length; + return NT_STATUS_BUFFER_TOO_SMALL; + } - while ( bytes_left > 0 ) { + while (bytes_left > 0) { - /* assume that when the record fetch fails, that we are done */ + DATA_BLOB blob; + enum ndr_err_code ndr_err; + struct EVENTLOGRECORD *e; - entry = get_eventlog_record (p->mem_ctx, ELOG_TDB_CTX(info->etdb), record_number); - if (!entry) { + e = evlog_pull_record(p->mem_ctx, ELOG_TDB_CTX(info->etdb), + record_number); + if (!e) { break; } - DEBUG( 8, ( "Retrieved record %d\n", record_number ) ); - - /* Now see if there is enough room to add */ - - if ( !(ee_new = read_package_entry( p->mem_ctx, entry )) ) - return NT_STATUS_NO_MEMORY; + ndr_err = ndr_push_struct_blob(&blob, p->mem_ctx, NULL, e, + (ndr_push_flags_fn_t)ndr_push_EVENTLOGRECORD); + if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { + return ndr_map_error2ntstatus(ndr_err); + } - if ( r_u->num_bytes_in_resp + ee_new->record.length > q_u->max_read_size ) { - r_u->bytes_in_next_record = ee_new->record.length; + if (DEBUGLEVEL >= 10) { + NDR_PRINT_DEBUG(EVENTLOGRECORD, e); + } - /* response would be too big to fit in client-size buffer */ + if (blob.length > r->in.number_of_bytes) { + *r->out.real_size = blob.length; + return NT_STATUS_BUFFER_TOO_SMALL; + } - bytes_left = 0; + if (*r->out.sent_size + blob.length > r->in.number_of_bytes) { break; } - add_record_to_resp( r_u, ee_new ); - bytes_left -= ee_new->record.length; - TALLOC_FREE(entry); - num_records_read = r_u->num_records - num_records_read; + bytes_left -= blob.length; - DEBUG( 10, ( "_eventlog_read_eventlog: read [%d] records for a total " - "of [%d] records using [%d] bytes out of a max of [%d].\n", - num_records_read, r_u->num_records, - r_u->num_bytes_in_resp, - q_u->max_read_size ) ); - - if ( info->flags & EVENTLOG_FORWARDS_READ ) + if (info->flags & EVENTLOG_FORWARDS_READ) { record_number++; - else + } else { record_number--; + } /* update the eventlog record pointer */ info->current_record = record_number; + + memcpy(&r->out.data[*(r->out.sent_size)], + blob.data, blob.length); + *(r->out.sent_size) += blob.length; + + num_records_read++; } - /* crazy by WinXP uses NT_STATUS_BUFFER_TOO_SMALL to - say when there are no more records */ + if (r->in.offset == 0 && record_number == 0 && *r->out.sent_size == 0) { + return NT_STATUS_END_OF_FILE; + } - return (num_records_read ? NT_STATUS_OK : NT_STATUS_BUFFER_TOO_SMALL); + return NT_STATUS_OK; } /******************************************************************** @@ -872,12 +640,6 @@ NTSTATUS _eventlog_OpenBackupEventLogW(pipes_struct *p, struct eventlog_OpenBack return NT_STATUS_NOT_IMPLEMENTED; } -NTSTATUS _eventlog_ReadEventLogW(pipes_struct *p, struct eventlog_ReadEventLogW *r) -{ - p->rng_fault_state = True; - return NT_STATUS_NOT_IMPLEMENTED; -} - NTSTATUS _eventlog_ReportEventW(pipes_struct *p, struct eventlog_ReportEventW *r) { p->rng_fault_state = True; diff --git a/source3/rpc_server/srv_lsa_hnd.c b/source3/rpc_server/srv_lsa_hnd.c index 5f7c8d9f1a..2779b8aa18 100644 --- a/source3/rpc_server/srv_lsa_hnd.c +++ b/source3/rpc_server/srv_lsa_hnd.c @@ -34,9 +34,10 @@ pipe is open. JRA. ****************************************************************************/ -static bool is_samr_lsa_pipe(const char *pipe_name) +static bool is_samr_lsa_pipe(const struct ndr_syntax_id *syntax) { - return (strstr(pipe_name, "samr") || strstr(pipe_name, "lsa")); + return (ndr_syntax_id_equal(syntax, &ndr_table_samr.syntax_id) + || ndr_syntax_id_equal(syntax, &ndr_table_lsarpc.syntax_id)); } /**************************************************************************** @@ -44,7 +45,7 @@ static bool is_samr_lsa_pipe(const char *pipe_name) pipes of the same name. ****************************************************************************/ -bool init_pipe_handle_list(pipes_struct *p, const char *pipe_name) +bool init_pipe_handle_list(pipes_struct *p, const struct ndr_syntax_id *syntax) { pipes_struct *plist; struct handle_list *hl; @@ -52,11 +53,11 @@ bool init_pipe_handle_list(pipes_struct *p, const char *pipe_name) for (plist = get_first_internal_pipe(); plist; plist = get_next_internal_pipe(plist)) { - if (strequal(plist->name, pipe_name)) { + if (ndr_syntax_id_equal(syntax, &plist->syntax)) { break; } - if (is_samr_lsa_pipe(plist->name) - && is_samr_lsa_pipe(pipe_name)) { + if (is_samr_lsa_pipe(&plist->syntax) + && is_samr_lsa_pipe(syntax)) { /* * samr and lsa share a handle space (same process * under Windows?) @@ -80,7 +81,8 @@ bool init_pipe_handle_list(pipes_struct *p, const char *pipe_name) } ZERO_STRUCTP(hl); - DEBUG(10,("init_pipe_handles: created handle list for pipe %s\n", pipe_name )); + DEBUG(10,("init_pipe_handles: created handle list for " + "pipe %s\n", get_pipe_name_from_iface(syntax))); } /* @@ -96,7 +98,8 @@ bool init_pipe_handle_list(pipes_struct *p, const char *pipe_name) p->pipe_handles = hl; DEBUG(10,("init_pipe_handles: pipe_handles ref count = %lu for pipe %s\n", - (unsigned long)p->pipe_handles->pipe_ref_count, pipe_name )); + (unsigned long)p->pipe_handles->pipe_ref_count, + get_pipe_name_from_iface(syntax))); return True; } @@ -242,7 +245,8 @@ void close_policy_by_pipe(pipes_struct *p) p->pipe_handles->count = 0; SAFE_FREE(p->pipe_handles); - DEBUG(10,("close_policy_by_pipe: deleted handle list for pipe %s\n", p->name )); + DEBUG(10,("close_policy_by_pipe: deleted handle list for " + "pipe %s\n", get_pipe_name_from_iface(&p->syntax))); } } diff --git a/source3/rpc_server/srv_pipe.c b/source3/rpc_server/srv_pipe.c index 343342a06c..924226bc4f 100644 --- a/source3/rpc_server/srv_pipe.c +++ b/source3/rpc_server/srv_pipe.c @@ -610,7 +610,8 @@ static bool pipe_ntlmssp_verify_final(pipes_struct *p, DATA_BLOB *p_resp_blob) AUTH_NTLMSSP_STATE *a = p->auth.a_u.auth_ntlmssp_state; bool ret; - DEBUG(5,("pipe_ntlmssp_verify_final: pipe %s checking user details\n", p->name)); + DEBUG(5,("pipe_ntlmssp_verify_final: pipe %s checking user details\n", + get_pipe_name_from_iface(&p->syntax))); ZERO_STRUCT(reply); @@ -634,7 +635,7 @@ static bool pipe_ntlmssp_verify_final(pipes_struct *p, DATA_BLOB *p_resp_blob) if (!(a->ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_SIGN)) { DEBUG(0,("pipe_ntlmssp_verify_final: pipe %s : packet integrity requested " "but client declined signing.\n", - p->name )); + get_pipe_name_from_iface(&p->syntax))); return False; } } @@ -642,7 +643,7 @@ static bool pipe_ntlmssp_verify_final(pipes_struct *p, DATA_BLOB *p_resp_blob) if (!(a->ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_SEAL)) { DEBUG(0,("pipe_ntlmssp_verify_final: pipe %s : packet privacy requested " "but client declined sealing.\n", - p->name )); + get_pipe_name_from_iface(&p->syntax))); return False; } } @@ -962,14 +963,14 @@ bool check_bind_req(struct pipes_struct *p, RPC_IFACE* abstract, int i=0; struct pipe_rpc_fns *context_fns; - DEBUG(3,("check_bind_req for %s\n", p->name)); + DEBUG(3,("check_bind_req for %s\n", + get_pipe_name_from_iface(&p->syntax))); /* we have to check all now since win2k introduced a new UUID on the lsaprpc pipe */ for (i=0; i<rpc_lookup_size; i++) { DEBUGADD(10, ("checking %s\n", rpc_lookup[i].pipe.clnt)); - if (strequal(rpc_lookup[i].pipe.clnt, p->name) - && ndr_syntax_id_equal( + if (ndr_syntax_id_equal( abstract, &rpc_lookup[i].rpc_interface) && ndr_syntax_id_equal( transfer, &ndr_transfer_syntax)) { @@ -1056,7 +1057,7 @@ NTSTATUS rpc_srv_register(int version, const char *clnt, const char *srv, * @param[in] cli_filename The pipe name requested by the client * @result Do we want to serve this? */ -bool is_known_pipename(const char *cli_filename) +bool is_known_pipename(const char *cli_filename, struct ndr_syntax_id *syntax) { const char *pipename = cli_filename; int i; @@ -1076,6 +1077,7 @@ bool is_known_pipename(const char *cli_filename) for (i=0; i<rpc_lookup_size; i++) { if (strequal(pipename, rpc_lookup[i].pipe.clnt)) { + *syntax = rpc_lookup[i].rpc_interface; return true; } } @@ -1145,7 +1147,7 @@ static bool pipe_spnego_auth_bind_negotiate(pipes_struct *p, prs_struct *rpc_in_ } DEBUG(3,("pipe_spnego_auth_bind_negotiate: Got secblob of size %lu\n", (unsigned long)secblob.length)); - if ( got_kerberos_mechanism && ((lp_security()==SEC_ADS) || lp_use_kerberos_keytab()) ) { + if ( got_kerberos_mechanism && ((lp_security()==SEC_ADS) || USE_KERBEROS_KEYTAB) ) { bool ret = pipe_spnego_auth_bind_kerberos(p, rpc_in_p, pauth_info, &secblob, pout_auth); data_blob_free(&secblob); data_blob_free(&blob); @@ -1530,7 +1532,8 @@ bool api_pipe_bind_req(pipes_struct *p, prs_struct *rpc_in_p) /* No rebinds on a bound pipe - use alter context. */ if (p->pipe_bound) { - DEBUG(2,("api_pipe_bind_req: rejecting bind request on bound pipe %s.\n", p->pipe_srv_name)); + DEBUG(2,("api_pipe_bind_req: rejecting bind request on bound " + "pipe %s.\n", get_pipe_name_from_iface(&p->syntax))); return setup_bind_nak(p); } @@ -1589,16 +1592,20 @@ bool api_pipe_bind_req(pipes_struct *p, prs_struct *rpc_in_p) &hdr_rb.rpc_context[0].abstract)) { DEBUG(3, ("api_pipe_bind_req: \\PIPE\\%s -> \\PIPE\\%s\n", rpc_lookup[i].pipe.clnt, rpc_lookup[i].pipe.srv)); - fstrcpy(p->name, rpc_lookup[i].pipe.clnt); - fstrcpy(p->pipe_srv_name, rpc_lookup[i].pipe.srv); break; } } if (i == rpc_lookup_size) { - if (NT_STATUS_IS_ERR(smb_probe_module("rpc", p->name))) { + NTSTATUS status; + + status = smb_probe_module( + "rpc", get_pipe_name_from_iface( + &hdr_rb.rpc_context[0].abstract)); + + if (NT_STATUS_IS_ERR(status)) { DEBUG(3,("api_pipe_bind_req: Unknown pipe name %s in bind request.\n", - p->name )); + get_pipe_name_from_iface(&hdr_rb.rpc_context[0].abstract))); prs_mem_free(&outgoing_rpc); prs_mem_free(&out_hdr_ba); prs_mem_free(&out_auth); @@ -1607,23 +1614,26 @@ bool api_pipe_bind_req(pipes_struct *p, prs_struct *rpc_in_p) } for (i = 0; i < rpc_lookup_size; i++) { - if (strequal(rpc_lookup[i].pipe.clnt, p->name)) { + if (strequal(rpc_lookup[i].pipe.clnt, + get_pipe_name_from_iface(&p->syntax))) { DEBUG(3, ("api_pipe_bind_req: \\PIPE\\%s -> \\PIPE\\%s\n", rpc_lookup[i].pipe.clnt, rpc_lookup[i].pipe.srv)); - fstrcpy(p->pipe_srv_name, rpc_lookup[i].pipe.srv); break; } } if (i == rpc_lookup_size) { - DEBUG(0, ("module %s doesn't provide functions for pipe %s!\n", p->name, p->name)); + DEBUG(0, ("module %s doesn't provide functions for " + "pipe %s!\n", + get_pipe_name_from_iface(&p->syntax), + get_pipe_name_from_iface(&p->syntax))); goto err_exit; } } /* name has to be \PIPE\xxxxx */ fstrcpy(ack_pipe_name, "\\PIPE\\"); - fstrcat(ack_pipe_name, p->pipe_srv_name); + fstrcat(ack_pipe_name, rpc_lookup[i].pipe.srv); DEBUG(5,("api_pipe_bind_req: make response. %d\n", __LINE__)); @@ -2233,7 +2243,7 @@ void free_pipe_rpc_context( PIPE_RPC_FNS *list ) return; } -static bool api_rpcTNP(pipes_struct *p, const char *rpc_name, +static bool api_rpcTNP(pipes_struct *p, const struct api_struct *api_rpc_cmds, int n_cmds); /**************************************************************************** @@ -2258,7 +2268,8 @@ bool api_pipe_request(pipes_struct *p) changed_user = True; } - DEBUG(5, ("Requested \\PIPE\\%s\n", p->name)); + DEBUG(5, ("Requested \\PIPE\\%s\n", + get_pipe_name_from_iface(&p->syntax))); /* get the set of RPC functions for this context */ @@ -2266,12 +2277,13 @@ bool api_pipe_request(pipes_struct *p) if ( pipe_fns ) { TALLOC_CTX *frame = talloc_stackframe(); - ret = api_rpcTNP(p, p->name, pipe_fns->cmds, pipe_fns->n_cmds); + ret = api_rpcTNP(p, pipe_fns->cmds, pipe_fns->n_cmds); TALLOC_FREE(frame); } else { DEBUG(0,("api_pipe_request: No rpc function table associated with context [%d] on pipe [%s]\n", - p->hdr_req.context_id, p->name)); + p->hdr_req.context_id, + get_pipe_name_from_iface(&p->syntax))); } if (changed_user) { @@ -2285,18 +2297,22 @@ bool api_pipe_request(pipes_struct *p) Calls the underlying RPC function for a named pipe. ********************************************************************/ -static bool api_rpcTNP(pipes_struct *p, const char *rpc_name, +static bool api_rpcTNP(pipes_struct *p, const struct api_struct *api_rpc_cmds, int n_cmds) { int fn_num; - fstring name; uint32 offset1, offset2; /* interpret the command */ - DEBUG(4,("api_rpcTNP: %s op 0x%x - ", rpc_name, p->hdr_req.opnum)); + DEBUG(4,("api_rpcTNP: %s op 0x%x - ", + get_pipe_name_from_iface(&p->syntax), p->hdr_req.opnum)); - slprintf(name, sizeof(name)-1, "in_%s", rpc_name); - prs_dump(name, p->hdr_req.opnum, &p->in_data.data); + if (DEBUGLEVEL >= 50) { + fstring name; + slprintf(name, sizeof(name)-1, "in_%s", + get_pipe_name_from_iface(&p->syntax)); + prs_dump(name, p->hdr_req.opnum, &p->in_data.data); + } for (fn_num = 0; fn_num < n_cmds; fn_num++) { if (api_rpc_cmds[fn_num].opnum == p->hdr_req.opnum && api_rpc_cmds[fn_num].fn != NULL) { @@ -2322,7 +2338,9 @@ static bool api_rpcTNP(pipes_struct *p, const char *rpc_name, fn_num, api_rpc_cmds[fn_num].fn)); /* do the actual command */ if(!api_rpc_cmds[fn_num].fn(p)) { - DEBUG(0,("api_rpcTNP: %s: %s failed.\n", rpc_name, api_rpc_cmds[fn_num].name)); + DEBUG(0,("api_rpcTNP: %s: %s failed.\n", + get_pipe_name_from_iface(&p->syntax), + api_rpc_cmds[fn_num].name)); prs_mem_free(&p->out_data.rdata); return False; } @@ -2341,13 +2359,18 @@ static bool api_rpcTNP(pipes_struct *p, const char *rpc_name, return True; } - slprintf(name, sizeof(name)-1, "out_%s", rpc_name); offset2 = prs_offset(&p->out_data.rdata); prs_set_offset(&p->out_data.rdata, offset1); - prs_dump(name, p->hdr_req.opnum, &p->out_data.rdata); + if (DEBUGLEVEL >= 50) { + fstring name; + slprintf(name, sizeof(name)-1, "out_%s", + get_pipe_name_from_iface(&p->syntax)); + prs_dump(name, p->hdr_req.opnum, &p->out_data.rdata); + } prs_set_offset(&p->out_data.rdata, offset2); - DEBUG(5,("api_rpcTNP: called %s successfully\n", rpc_name)); + DEBUG(5,("api_rpcTNP: called %s successfully\n", + get_pipe_name_from_iface(&p->syntax))); /* Check for buffer underflow in rpc parsing */ diff --git a/source3/rpc_server/srv_pipe_hnd.c b/source3/rpc_server/srv_pipe_hnd.c index 0753476230..4cbe8d67a3 100644 --- a/source3/rpc_server/srv_pipe_hnd.c +++ b/source3/rpc_server/srv_pipe_hnd.c @@ -90,13 +90,14 @@ static bool pipe_init_outgoing_data(pipes_struct *p) ****************************************************************************/ static struct pipes_struct *make_internal_rpc_pipe_p(TALLOC_CTX *mem_ctx, - const char *pipe_name, + const struct ndr_syntax_id *syntax, const char *client_address, struct auth_serversupplied_info *server_info) { pipes_struct *p; - DEBUG(4,("Create pipe requested %s\n", pipe_name)); + DEBUG(4,("Create pipe requested %s\n", + get_pipe_name_from_iface(syntax))); p = TALLOC_ZERO_P(mem_ctx, struct pipes_struct); @@ -105,13 +106,15 @@ static struct pipes_struct *make_internal_rpc_pipe_p(TALLOC_CTX *mem_ctx, return NULL; } - if ((p->mem_ctx = talloc_init("pipe %s %p", pipe_name, p)) == NULL) { + if ((p->mem_ctx = talloc_init("pipe %s %p", + get_pipe_name_from_iface(syntax), + p)) == NULL) { DEBUG(0,("open_rpc_pipe_p: talloc_init failed.\n")); TALLOC_FREE(p); return NULL; } - if (!init_pipe_handle_list(p, pipe_name)) { + if (!init_pipe_handle_list(p, syntax)) { DEBUG(0,("open_rpc_pipe_p: init_pipe_handles failed.\n")); talloc_destroy(p->mem_ctx); TALLOC_FREE(p); @@ -152,11 +155,11 @@ static struct pipes_struct *make_internal_rpc_pipe_p(TALLOC_CTX *mem_ctx, * Initialize the outgoing RPC data buffer with no memory. */ prs_init_empty(&p->out_data.rdata, p->mem_ctx, MARSHALL); - - fstrcpy(p->name, pipe_name); - + + p->syntax = *syntax; + DEBUG(4,("Created internal pipe %s (pipes_open=%d)\n", - pipe_name, pipes_open)); + get_pipe_name_from_iface(syntax), pipes_open)); talloc_set_destructor(p, close_internal_rpc_pipe_hnd); @@ -174,7 +177,7 @@ static void set_incoming_fault(pipes_struct *p) p->in_data.pdu_received_len = 0; p->fault_state = True; DEBUG(10, ("set_incoming_fault: Setting fault state on pipe %s\n", - p->name)); + get_pipe_name_from_iface(&p->syntax))); } /**************************************************************************** @@ -324,7 +327,8 @@ static void free_pipe_context(pipes_struct *p) "%lu\n", (unsigned long)talloc_total_size(p->mem_ctx) )); talloc_free_children(p->mem_ctx); } else { - p->mem_ctx = talloc_init("pipe %s %p", p->name, p); + p->mem_ctx = talloc_init( + "pipe %s %p", get_pipe_name_from_iface(&p->syntax), p); if (p->mem_ctx == NULL) { p->fault_state = True; } @@ -492,7 +496,7 @@ static void process_complete_pdu(pipes_struct *p) if(p->fault_state) { DEBUG(10,("process_complete_pdu: pipe %s in fault state.\n", - p->name )); + get_pipe_name_from_iface(&p->syntax))); set_incoming_fault(p); setup_fault_pdu(p, NT_STATUS(DCERPC_FAULT_OP_RNG_ERROR)); return; @@ -520,12 +524,13 @@ static void process_complete_pdu(pipes_struct *p) case RPC_PING: /* CL request - ignore... */ DEBUG(0,("process_complete_pdu: Error. Connectionless packet type %u received on pipe %s.\n", - (unsigned int)p->hdr.pkt_type, p->name)); + (unsigned int)p->hdr.pkt_type, + get_pipe_name_from_iface(&p->syntax))); break; case RPC_RESPONSE: /* No responses here. */ DEBUG(0,("process_complete_pdu: Error. RPC_RESPONSE received from client on pipe %s.\n", - p->name )); + get_pipe_name_from_iface(&p->syntax))); break; case RPC_FAULT: @@ -537,7 +542,8 @@ static void process_complete_pdu(pipes_struct *p) case RPC_FACK: case RPC_CANCEL_ACK: DEBUG(0,("process_complete_pdu: Error. Connectionless packet type %u received on pipe %s.\n", - (unsigned int)p->hdr.pkt_type, p->name)); + (unsigned int)p->hdr.pkt_type, + get_pipe_name_from_iface(&p->syntax))); break; case RPC_BIND: @@ -552,7 +558,8 @@ static void process_complete_pdu(pipes_struct *p) case RPC_BINDACK: case RPC_BINDNACK: DEBUG(0,("process_complete_pdu: Error. RPC_BINDACK/RPC_BINDNACK packet type %u received on pipe %s.\n", - (unsigned int)p->hdr.pkt_type, p->name)); + (unsigned int)p->hdr.pkt_type, + get_pipe_name_from_iface(&p->syntax))); break; @@ -567,7 +574,7 @@ static void process_complete_pdu(pipes_struct *p) case RPC_ALTCONTRESP: DEBUG(0,("process_complete_pdu: Error. RPC_ALTCONTRESP on pipe %s: Should only be server -> client.\n", - p->name)); + get_pipe_name_from_iface(&p->syntax))); break; case RPC_AUTH3: @@ -581,7 +588,7 @@ static void process_complete_pdu(pipes_struct *p) case RPC_SHUTDOWN: DEBUG(0,("process_complete_pdu: Error. RPC_SHUTDOWN on pipe %s: Should only be server -> client.\n", - p->name)); + get_pipe_name_from_iface(&p->syntax))); break; case RPC_CO_CANCEL: @@ -619,7 +626,8 @@ static void process_complete_pdu(pipes_struct *p) prs_set_endian_data( &p->in_data.data, RPC_LITTLE_ENDIAN); if (!reply) { - DEBUG(3,("process_complete_pdu: DCE/RPC fault sent on pipe %s\n", p->pipe_srv_name)); + DEBUG(3,("process_complete_pdu: DCE/RPC fault sent on " + "pipe %s\n", get_pipe_name_from_iface(&p->syntax))); set_incoming_fault(p); setup_fault_pdu(p, NT_STATUS(DCERPC_FAULT_OP_RNG_ERROR)); prs_mem_free(&rpc_in); @@ -773,7 +781,8 @@ static ssize_t read_from_internal_pipe(struct pipes_struct *p, char *data, size_ return -1; } - DEBUG(6,(" name: %s len: %u\n", p->name, (unsigned int)n)); + DEBUG(6,(" name: %s len: %u\n", get_pipe_name_from_iface(&p->syntax), + (unsigned int)n)); /* * We cannot return more than one PDU length per @@ -787,8 +796,10 @@ static ssize_t read_from_internal_pipe(struct pipes_struct *p, char *data, size_ */ if(n > RPC_MAX_PDU_FRAG_LEN) { - DEBUG(5,("read_from_pipe: too large read (%u) requested on \ -pipe %s. We can only service %d sized reads.\n", (unsigned int)n, p->name, RPC_MAX_PDU_FRAG_LEN )); + DEBUG(5,("read_from_pipe: too large read (%u) requested on " + "pipe %s. We can only service %d sized reads.\n", + (unsigned int)n, get_pipe_name_from_iface(&p->syntax), + RPC_MAX_PDU_FRAG_LEN )); n = RPC_MAX_PDU_FRAG_LEN; } @@ -803,9 +814,12 @@ pipe %s. We can only service %d sized reads.\n", (unsigned int)n, p->name, RPC_M if((pdu_remaining = p->out_data.current_pdu_len - p->out_data.current_pdu_sent) > 0) { data_returned = (ssize_t)MIN(n, pdu_remaining); - DEBUG(10,("read_from_pipe: %s: current_pdu_len = %u, current_pdu_sent = %u \ -returning %d bytes.\n", p->name, (unsigned int)p->out_data.current_pdu_len, - (unsigned int)p->out_data.current_pdu_sent, (int)data_returned)); + DEBUG(10,("read_from_pipe: %s: current_pdu_len = %u, " + "current_pdu_sent = %u returning %d bytes.\n", + get_pipe_name_from_iface(&p->syntax), + (unsigned int)p->out_data.current_pdu_len, + (unsigned int)p->out_data.current_pdu_sent, + (int)data_returned)); memcpy( data, &p->out_data.current_pdu[p->out_data.current_pdu_sent], (size_t)data_returned); p->out_data.current_pdu_sent += (uint32)data_returned; @@ -817,9 +831,11 @@ returning %d bytes.\n", p->name, (unsigned int)p->out_data.current_pdu_len, * may of course be zero if this is the first return fragment. */ - DEBUG(10,("read_from_pipe: %s: fault_state = %d : data_sent_length \ -= %u, prs_offset(&p->out_data.rdata) = %u.\n", - p->name, (int)p->fault_state, (unsigned int)p->out_data.data_sent_length, (unsigned int)prs_offset(&p->out_data.rdata) )); + DEBUG(10,("read_from_pipe: %s: fault_state = %d : data_sent_length " + "= %u, prs_offset(&p->out_data.rdata) = %u.\n", + get_pipe_name_from_iface(&p->syntax), (int)p->fault_state, + (unsigned int)p->out_data.data_sent_length, + (unsigned int)prs_offset(&p->out_data.rdata) )); if(p->out_data.data_sent_length >= prs_offset(&p->out_data.rdata)) { /* @@ -837,7 +853,8 @@ returning %d bytes.\n", p->name, (unsigned int)p->out_data.current_pdu_len, */ if(!create_next_pdu(p)) { - DEBUG(0,("read_from_pipe: %s: create_next_pdu failed.\n", p->name)); + DEBUG(0,("read_from_pipe: %s: create_next_pdu failed.\n", + get_pipe_name_from_iface(&p->syntax))); return -1; } @@ -1086,13 +1103,14 @@ NTSTATUS np_open(TALLOC_CTX *mem_ctx, const char *name, handle->private_data = p; } else { struct pipes_struct *p; + struct ndr_syntax_id syntax; - if (!is_known_pipename(name)) { + if (!is_known_pipename(name, &syntax)) { TALLOC_FREE(handle); return NT_STATUS_OBJECT_NAME_NOT_FOUND; } - p = make_internal_rpc_pipe_p(handle, name, client_address, + p = make_internal_rpc_pipe_p(handle, &syntax, client_address, server_info); handle->type = FAKE_FILE_TYPE_NAMED_PIPE; @@ -1109,66 +1127,235 @@ NTSTATUS np_open(TALLOC_CTX *mem_ctx, const char *name, return NT_STATUS_OK; } -NTSTATUS np_write(struct fake_file_handle *handle, const uint8_t *data, - size_t len, ssize_t *nwritten) +struct np_write_state { + ssize_t nwritten; +}; + +static void np_write_done(struct async_req *subreq); + +struct async_req *np_write_send(TALLOC_CTX *mem_ctx, struct event_context *ev, + struct fake_file_handle *handle, + const uint8_t *data, size_t len) { - DEBUG(6, ("np_write: len: %d\n", (int)len)); + struct async_req *result, *subreq; + struct np_write_state *state; + NTSTATUS status; + + DEBUG(6, ("np_write_send: len: %d\n", (int)len)); dump_data(50, data, len); - switch (handle->type) { - case FAKE_FILE_TYPE_NAMED_PIPE: { + if (!async_req_setup(mem_ctx, &result, &state, + struct np_write_state)) { + return NULL; + } + + if (len == 0) { + state->nwritten = 0; + status = NT_STATUS_OK; + goto post_status; + } + + if (handle->type == FAKE_FILE_TYPE_NAMED_PIPE) { struct pipes_struct *p = talloc_get_type_abort( handle->private_data, struct pipes_struct); - *nwritten = write_to_internal_pipe(p, (char *)data, len); - break; + + state->nwritten = write_to_internal_pipe(p, (char *)data, len); + + status = (state->nwritten >= 0) + ? NT_STATUS_OK : NT_STATUS_UNEXPECTED_IO_ERROR; + goto post_status; } - case FAKE_FILE_TYPE_NAMED_PIPE_PROXY: { + + if (handle->type == FAKE_FILE_TYPE_NAMED_PIPE_PROXY) { struct np_proxy_state *p = talloc_get_type_abort( handle->private_data, struct np_proxy_state); - *nwritten = write_data(p->fd, (char *)data, len); - break; + + state->nwritten = len; + + subreq = sendall_send(state, ev, p->fd, data, len, 0); + if (subreq == NULL) { + goto fail; + } + subreq->async.fn = np_write_done; + subreq->async.priv = result; + return result; } - default: - return NT_STATUS_INVALID_HANDLE; - break; + + status = NT_STATUS_INVALID_HANDLE; + post_status: + if (async_post_ntstatus(result, ev, status)) { + return result; } + fail: + TALLOC_FREE(result); + return NULL; +} + +static void np_write_done(struct async_req *subreq) +{ + struct async_req *req = talloc_get_type_abort( + subreq->async.priv, struct async_req); + NTSTATUS status; + + status = sendall_recv(subreq); + if (!NT_STATUS_IS_OK(status)) { + async_req_nterror(req, status); + return; + } + async_req_done(req); +} + +NTSTATUS np_write_recv(struct async_req *req, ssize_t *pnwritten) +{ + struct np_write_state *state = talloc_get_type_abort( + req->private_data, struct np_write_state); + NTSTATUS status; - return ((*nwritten) >= 0) - ? NT_STATUS_OK : NT_STATUS_UNEXPECTED_IO_ERROR; + if (async_req_is_nterror(req, &status)) { + return status; + } + *pnwritten = state->nwritten; + return NT_STATUS_OK; } -NTSTATUS np_read(struct fake_file_handle *handle, uint8_t *data, size_t len, - ssize_t *nread, bool *is_data_outstanding) +struct np_read_state { + ssize_t nread; + bool is_data_outstanding; + int fd; +}; + +static void np_read_done(struct async_req *subreq); + +struct async_req *np_read_send(TALLOC_CTX *mem_ctx, struct event_context *ev, + struct fake_file_handle *handle, + uint8_t *data, size_t len) { - switch (handle->type) { - case FAKE_FILE_TYPE_NAMED_PIPE: { + struct async_req *result, *subreq; + struct np_read_state *state; + NTSTATUS status; + + if (!async_req_setup(mem_ctx, &result, &state, + struct np_read_state)) { + return NULL; + } + + if (handle->type == FAKE_FILE_TYPE_NAMED_PIPE) { struct pipes_struct *p = talloc_get_type_abort( handle->private_data, struct pipes_struct); - *nread = read_from_internal_pipe(p, (char *)data, len, - is_data_outstanding); - break; + + state->nread = read_from_internal_pipe( + p, (char *)data, len, &state->is_data_outstanding); + + status = (state->nread >= 0) + ? NT_STATUS_OK : NT_STATUS_UNEXPECTED_IO_ERROR; + goto post_status; } - case FAKE_FILE_TYPE_NAMED_PIPE_PROXY: { + + if (handle->type == FAKE_FILE_TYPE_NAMED_PIPE_PROXY) { struct np_proxy_state *p = talloc_get_type_abort( handle->private_data, struct np_proxy_state); - int available = 0; - *nread = sys_read(p->fd, (char *)data, len); + state->fd = p->fd; - /* - * We don't look at the ioctl result. We don't really care - * if there is data available, because this is racy anyway. - */ - ioctl(p->fd, FIONREAD, &available); - *is_data_outstanding = (available > 0); + subreq = async_recv(state, ev, p->fd, data, len, 0); + if (subreq == NULL) { + goto fail; + } + subreq->async.fn = np_read_done; + subreq->async.priv = result; + return result; + } + + status = NT_STATUS_INVALID_HANDLE; + post_status: + if (async_post_ntstatus(result, ev, status)) { + return result; + } + fail: + TALLOC_FREE(result); + return NULL; +} + +static void np_read_done(struct async_req *subreq) +{ + struct async_req *req = talloc_get_type_abort( + subreq->async.priv, struct async_req); + struct np_read_state *state = talloc_get_type_abort( + req->private_data, struct np_read_state); + ssize_t result; + int sys_errno; + int available = 0; + + result = async_syscall_result_ssize_t(subreq, &sys_errno); + if (result == -1) { + async_req_nterror(req, map_nt_error_from_unix(sys_errno)); + return; + } + if (result == 0) { + async_req_nterror(req, NT_STATUS_END_OF_FILE); + return; + } + + state->nread = result; - break; + /* + * We don't look at the ioctl result. We don't really care if there is + * data available, because this is racy anyway. + */ + ioctl(state->fd, FIONREAD, &available); + state->is_data_outstanding = (available > 0); + + async_req_done(req); +} + +NTSTATUS np_read_recv(struct async_req *req, ssize_t *nread, + bool *is_data_outstanding) +{ + struct np_read_state *state = talloc_get_type_abort( + req->private_data, struct np_read_state); + NTSTATUS status; + + if (async_req_is_nterror(req, &status)) { + return status; + } + *nread = state->nread; + *is_data_outstanding = state->is_data_outstanding; + return NT_STATUS_OK; +} + +/** + * Create a new RPC client context which uses a local dispatch function. + */ +NTSTATUS rpc_pipe_open_internal(TALLOC_CTX *mem_ctx, + const struct ndr_syntax_id *abstract_syntax, + NTSTATUS (*dispatch) (struct rpc_pipe_client *cli, + TALLOC_CTX *mem_ctx, + const struct ndr_interface_table *table, + uint32_t opnum, void *r), + struct auth_serversupplied_info *serversupplied_info, + struct rpc_pipe_client **presult) +{ + struct rpc_pipe_client *result; + + result = TALLOC_ZERO_P(mem_ctx, struct rpc_pipe_client); + if (result == NULL) { + return NT_STATUS_NO_MEMORY; } - default: - return NT_STATUS_INVALID_HANDLE; - break; + + result->abstract_syntax = *abstract_syntax; + result->transfer_syntax = ndr_transfer_syntax; + result->dispatch = dispatch; + + result->pipes_struct = make_internal_rpc_pipe_p( + result, abstract_syntax, "", serversupplied_info); + if (result->pipes_struct == NULL) { + TALLOC_FREE(result); + return NT_STATUS_NO_MEMORY; } - return ((*nread) >= 0) - ? NT_STATUS_OK : NT_STATUS_UNEXPECTED_IO_ERROR; + result->max_xmit_frag = -1; + result->max_recv_frag = -1; + + *presult = result; + return NT_STATUS_OK; } diff --git a/source3/rpc_server/srv_spoolss_nt.c b/source3/rpc_server/srv_spoolss_nt.c index ba2fe774b8..e61d343731 100644 --- a/source3/rpc_server/srv_spoolss_nt.c +++ b/source3/rpc_server/srv_spoolss_nt.c @@ -1701,7 +1701,7 @@ WERROR _spoolss_open_printer_ex( pipes_struct *p, SPOOL_Q_OPEN_PRINTER_EX *q_u, /* check smb.conf parameters and the the sec_desc */ - if ( !check_access(smbd_server_fd(), lp_hostsallow(snum), lp_hostsdeny(snum)) ) { + if ( !check_access(get_client_fd(), lp_hostsallow(snum), lp_hostsdeny(snum)) ) { DEBUG(3, ("access DENIED (hosts allow/deny) for printer open\n")); return WERR_ACCESS_DENIED; } diff --git a/source3/rpcclient/cmd_eventlog.c b/source3/rpcclient/cmd_eventlog.c index 905b147ce6..e212452e5d 100644 --- a/source3/rpcclient/cmd_eventlog.c +++ b/source3/rpcclient/cmd_eventlog.c @@ -55,7 +55,7 @@ static NTSTATUS cmd_eventlog_readlog(struct rpc_pipe_client *cli, int argc, const char **argv) { - NTSTATUS status; + NTSTATUS status = NT_STATUS_OK; struct policy_handle handle; uint32_t flags = EVENTLOG_BACKWARDS_READ | @@ -67,7 +67,7 @@ static NTSTATUS cmd_eventlog_readlog(struct rpc_pipe_client *cli, uint32_t real_size = 0; if (argc < 2 || argc > 4) { - printf("Usage: %s logname [offset]\n", argv[0]); + printf("Usage: %s logname [offset] [number_of_bytes]\n", argv[0]); return NT_STATUS_OK; } @@ -75,12 +75,27 @@ static NTSTATUS cmd_eventlog_readlog(struct rpc_pipe_client *cli, offset = atoi(argv[2]); } + if (argc >= 4) { + number_of_bytes = atoi(argv[3]); + data = talloc_array(mem_ctx, uint8_t, number_of_bytes); + if (!data) { + goto done; + } + } + status = get_eventlog_handle(cli, mem_ctx, argv[1], &handle); if (!NT_STATUS_IS_OK(status)) { return status; } - while (1) { + do { + + enum ndr_err_code ndr_err; + DATA_BLOB blob; + struct EVENTLOGRECORD r; + uint32_t size = 0; + uint32_t pos = 0; + status = rpccli_eventlog_ReadEventLogW(cli, mem_ctx, &handle, flags, @@ -93,35 +108,53 @@ static NTSTATUS cmd_eventlog_readlog(struct rpc_pipe_client *cli, real_size > 0 ) { number_of_bytes = real_size; data = talloc_array(mem_ctx, uint8_t, real_size); - continue; + if (!data) { + goto done; + } + status = rpccli_eventlog_ReadEventLogW(cli, mem_ctx, + &handle, + flags, + offset, + number_of_bytes, + data, + &sent_size, + &real_size); } - number_of_bytes = 0; - - if (!NT_STATUS_IS_OK(status)) { + if (!NT_STATUS_EQUAL(status, NT_STATUS_END_OF_FILE) && + !NT_STATUS_IS_OK(status)) { goto done; } - { - enum ndr_err_code ndr_err; - DATA_BLOB blob; - struct eventlog_Record rec; + number_of_bytes = 0; + + size = IVAL(data, pos); - blob = data_blob_const(data, sent_size); + while (size > 0) { - ndr_err = ndr_pull_struct_blob_all(&blob, mem_ctx, NULL, - &rec, - (ndr_pull_flags_fn_t)ndr_pull_eventlog_Record); + blob = data_blob_const(data + pos, size); + /* dump_data(0, blob.data, blob.length); */ + ndr_err = ndr_pull_struct_blob_all(&blob, mem_ctx, NULL, &r, + (ndr_pull_flags_fn_t)ndr_pull_EVENTLOGRECORD); if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { status = ndr_map_error2ntstatus(ndr_err); goto done; } - NDR_PRINT_DEBUG(eventlog_Record, &rec); + NDR_PRINT_DEBUG(EVENTLOGRECORD, &r); + + pos += size; + + if (pos + 4 > sent_size) { + break; + } + + size = IVAL(data, pos); } offset++; - } + + } while (NT_STATUS_IS_OK(status)); done: rpccli_eventlog_CloseEventLog(cli, mem_ctx, &handle); diff --git a/source3/rpcclient/rpcclient.c b/source3/rpcclient/rpcclient.c index 050e78d274..9a02c129b5 100644 --- a/source3/rpcclient/rpcclient.c +++ b/source3/rpcclient/rpcclient.c @@ -619,16 +619,14 @@ static NTSTATUS do_cmd(struct cli_state *cli, default: DEBUG(0, ("Could not initialise %s. Invalid " "auth type %u\n", - cli_get_pipe_name_from_iface( - debug_ctx(), + get_pipe_name_from_iface( cmd_entry->interface), pipe_default_auth_type )); return NT_STATUS_UNSUCCESSFUL; } if (!NT_STATUS_IS_OK(ntresult)) { DEBUG(0, ("Could not initialise %s. Error was %s\n", - cli_get_pipe_name_from_iface( - debug_ctx(), + get_pipe_name_from_iface( cmd_entry->interface), nt_errstr(ntresult) )); return ntresult; @@ -657,8 +655,7 @@ static NTSTATUS do_cmd(struct cli_state *cli, if (!NT_STATUS_IS_OK(ntresult)) { DEBUG(0, ("Could not initialise credentials for %s.\n", - cli_get_pipe_name_from_iface( - debug_ctx(), + get_pipe_name_from_iface( cmd_entry->interface))); return ntresult; } diff --git a/source3/samba4-templates.mk b/source3/samba4-templates.mk index ecebce6d1d..0024a7531f 100644 --- a/source3/samba4-templates.mk +++ b/source3/samba4-templates.mk @@ -19,9 +19,9 @@ endef # Link a binary # Arguments: target file, depends, flags define binary_link_template -$(1)4: $(2) $(LIBREPLACE_OBJ) ; +$(1)4: $(2) ; @echo Linking $$@ - @$$(BNLD) $$(BNLD_FLAGS) $$(INTERN_LDFLAGS) -o $$@ $$(INSTALL_LINK_FLAGS) $(3) $$(LIBS) $$(LIBREPLACE_OBJ) + @$$(BNLD) $$(BNLD_FLAGS) $$(INTERN_LDFLAGS) -o $$@ $$(INSTALL_LINK_FLAGS) $(3) $$(LIBS) clean:: @rm -f $(1) @@ -32,9 +32,9 @@ endef # Link a host-machine binary # Arguments: target file, depends, flags define host_binary_link_template -$(1)4: $(2) $(LIBREPLACE_OBJ) ; +$(1)4: $(2) ; @echo Linking $$@ - @$$(HOSTLD) $$(HOSTLD_FLAGS) -L$${builddir}/bin/static -o $$@ $$(INSTALL_LINK_FLAGS) $(3) $$(LIBREPLACE_OBJ) + @$$(HOSTLD) $$(HOSTLD_FLAGS) -L$${builddir}/bin/static -o $$@ $$(INSTALL_LINK_FLAGS) $(3) clean:: rm -f $(1) diff --git a/source3/samba4.m4 b/source3/samba4.m4 index 421ace0dbb..8107f816ad 100644 --- a/source3/samba4.m4 +++ b/source3/samba4.m4 @@ -1,5 +1,6 @@ AC_SUBST(BLDSHARED) -smbtorture4_path=bin/smbtorture4 +smbtorture4_path="bin/smbtorture4" +smbtorture4_option="-t bin/smbtorture4" m4_include(build/m4/public.m4) m4_include(../m4/check_python.m4) @@ -18,6 +19,24 @@ AC_MSG_RESULT($pythondir) AC_SUBST(pythondir) +SMB_EXT_LIB(LIBREPLACE_EXT, [${LIBDL} ${CRYPT_LIBS}]) +SMB_ENABLE(LIBREPLACE_EXT) + +SMB_EXT_LIB(LIBREPLACE_NETWORK, [${LIBREPLACE_NETWORK_LIBS}]) +SMB_ENABLE(LIBREPLACE_NETWORK) + +SMB_SUBSYSTEM(LIBREPLACE, + [${LIBREPLACE_OBJS}], + [LIBREPLACE_EXT LIBREPLACE_NETWORK], + [-I../lib/replace]) + +LIBREPLACE_HOSTCC_OBJS=`echo ${LIBREPLACE_OBJS} |sed -e 's/\.o/\.ho/g'` + +SMB_SUBSYSTEM(LIBREPLACE_HOSTCC, + [${LIBREPLACE_HOSTCC_OBJS}], + [], + [-I../lib/replace]) + m4_include(lib/smbreadline/readline.m4) m4_include(heimdal_build/internal.m4) m4_include(../lib/util/fault.m4) @@ -71,7 +90,7 @@ SMB_EXT_LIB_FROM_PKGCONFIG(LIBTEVENT, tevent >= 0.9.2, SMB_INCLUDE_MK(../lib/tevent/python.mk) -SMB_EXT_LIB_FROM_PKGCONFIG(LIBLDB, ldb = 0.9.1, +SMB_EXT_LIB_FROM_PKGCONFIG(LIBLDB, ldb = 0.9.3, [ SMB_INCLUDE_MK(lib/ldb/ldb_ildap/config.mk) SMB_INCLUDE_MK(lib/ldb/tools/config.mk) diff --git a/source3/samba4.mk b/source3/samba4.mk index 49afa3a2e2..b7df7a58da 100644 --- a/source3/samba4.mk +++ b/source3/samba4.mk @@ -111,6 +111,7 @@ ntptrsrcdir := $(samba4srcdir)/ntptr clientsrcdir := $(samba4srcdir)/client libclisrcdir := $(samba4srcdir)/libcli libclinbtsrcdir := $(samba4srcdir)/../libcli/nbt +libclicommonsrcdir := $(samba4srcdir)/../libcli pyscriptsrcdir := $(samba4srcdir)/scripting/python kdcsrcdir := $(samba4srcdir)/kdc smbreadlinesrcdir := $(samba4srcdir)/lib/smbreadline @@ -170,9 +171,9 @@ everything:: $(patsubst %,%4,$(BINARIES)) setup: @ln -sf ../source4/setup setup -LD_LIBPATH_OVERRIDE = $(LIB_PATH_VAR)="$(builddir)/bin/shared" +S4_LD_LIBPATH_OVERRIDE = $(LIB_PATH_VAR)="$(builddir)/bin/shared" -SELFTEST4 = $(LD_LIBPATH_OVERRIDE) EXEEXT="4" $(PERL) $(selftestdir)/selftest.pl --prefix=st4 \ +SELFTEST4 = $(S4_LD_LIBPATH_OVERRIDE) EXEEXT="4" $(PERL) $(selftestdir)/selftest.pl --prefix=st4 \ --builddir=$(builddir) --srcdir=$(samba4srcdir) \ --exeext=4 \ --expected-failures=$(samba4srcdir)/selftest/knownfail \ diff --git a/source3/script/tests/selftest.sh b/source3/script/tests/selftest.sh index 94fd791b51..94621841f5 100755 --- a/source3/script/tests/selftest.sh +++ b/source3/script/tests/selftest.sh @@ -1,17 +1,44 @@ #!/bin/sh -if [ $# != 3 -a $# != 4 ]; then - echo "$0 <directory> <all | quick> <smbtorture4> [<shrdir>]" +if [ $# -lt 2 ]; then + echo "$0 <directory> <all | quick> [-t <smbtorture4>] [-s <shrdir>] " \ + "[-c <custom conf>]" exit 1 fi -SMBTORTURE4=$3 -SUBTESTS=$2 +## +## Setup the required args +## +DIRECTORY=$1; shift; +SUBTESTS=$1; shift; + +## +## Parse oprtional args +## +while getopts s:c:t: f +do + case $f in + t) SMBTORTURE4=$OPTARG;; + s) ALT_SHRDIR_ARG=$OPTARG;; + c) CUSTOM_CONF_ARG=$OPTARG;; + esac +done + +echo "Running selftest with the following" +echo "Selftest Directory: $DIRECTORY" +echo "Subtests to Run: $SUBTESTS" +echo "smbtorture4 Path: $SMBTORTURE4" +echo "Alternative Share Dir: $ALT_SHRDIR_ARG" +echo "Custom Configuration: $CUSTOM_CONF_ARG" + +if [ $CUSTOM_CONF_ARG ]; then + INCLUDE_CUSTOM_CONF="include = $CUSTOM_CONF_ARG" +fi ## ## create the test directory ## -PREFIX=`echo $1 | sed s+//+/+` +PREFIX=`echo $DIRECTORY | sed s+//+/+` mkdir -p $PREFIX || exit $? OLD_PWD=`pwd` cd $PREFIX || exit $? @@ -68,7 +95,10 @@ export WINBINDD_SOCKET_DIR WINBINDD_PRIV_PIPE_DIR PATH=bin:$PATH export PATH -SAMBA4BINDIR=`dirname $SMBTORTURE4` +if [ $SMBTORTURE4 ]; then + SAMBA4BINDIR=`dirname $SMBTORTURE4` +fi + SAMBA4SHAREDDIR="$SAMBA4BINDIR/shared" export SAMBA4SHAREDDIR @@ -116,8 +146,8 @@ chmod 755 $WINBINDD_SOCKET_DIR ## ## Create an alternate shrdir if one was specified. ## -if [ $# = 4 ]; then - ALT_SHRDIR=`echo $4 | sed s+//+/+` +if [ $ALT_SHRDIR_ARG ]; then + ALT_SHRDIR=`echo $ALT_SHRDIR_ARG | sed s+//+/+` mkdir -p $ALT_SHRDIR || exit $? OLD_PWD=`pwd` cd $ALT_SHRDIR || exit $? @@ -140,8 +170,6 @@ cat >$COMMONCONFFILE<<EOF private dir = $PRIVATEDIR pid directory = $PIDDIR lock directory = $LOCKDIR - state directory = $LOCKDIR - cache directory = $LOCKDIR log file = $LOGDIR/log.%m log level = 0 @@ -177,6 +205,9 @@ cat >$SERVERCONFFILE<<EOF panic action = $SCRIPTDIR/gdb_backtrace %d %\$(MAKE_TEST_BINARY) include = $COMMONCONFFILE + state directory = $LOCKDIR + cache directory = $LOCKDIR + passdb backend = tdbsam domain master = yes @@ -200,8 +231,6 @@ cat >$SERVERCONFFILE<<EOF # min receivefile size = 4000 -[tmp] - path = $SHRDIR read only = no smbd:sharedelay = 100000 smbd:writetimeupdatedelay = 500000 @@ -209,6 +238,12 @@ cat >$SERVERCONFFILE<<EOF map system = yes create mask = 755 vfs objects = $BINDIR/xattr_tdb.so $BINDIR/streams_depot.so + + #Include user defined custom parameters if set + $INCLUDE_CUSTOM_CONF + +[tmp] + path = $SHRDIR [hideunread] copy = tmp hide unreadable = yes diff --git a/source3/script/tests/test_functions.sh b/source3/script/tests/test_functions.sh index 407d46aa9e..bddae18c10 100644 --- a/source3/script/tests/test_functions.sh +++ b/source3/script/tests/test_functions.sh @@ -1,3 +1,4 @@ +TEST_FUNCTIONS_SH="INCLUDED" samba3_stop_sig_term() { RET=0 @@ -197,13 +198,13 @@ testit() { TEST_PCAP="$PREFIX/test_${shname}_${UNIQUE_PID}.pcap" trap "rm -f $TEST_LOG $TEST_PCAP" EXIT - if [ -z "$nmbd_log_size" ]; then + samba3_nmbd_test_log && if [ -z "$nmbd_log_size" ]; then nmbd_log_size=`wc -l < $NMBD_TEST_LOG`; fi - if [ -z "$winbindd_log_size" ]; then + samba3_winbindd_test_log && if [ -z "$winbindd_log_size" ]; then winbindd_log_size=`wc -l < $WINBINDD_TEST_LOG`; fi - if [ -z "$smbd_log_size" ]; then + samba3_smbd_test_log && if [ -z "$smbd_log_size" ]; then smbd_log_size=`wc -l < $SMBD_TEST_LOG`; fi diff --git a/source3/script/tests/test_local_s3.sh b/source3/script/tests/test_local_s3.sh index aed8637abd..1840779085 100755 --- a/source3/script/tests/test_local_s3.sh +++ b/source3/script/tests/test_local_s3.sh @@ -9,8 +9,10 @@ EOF exit 1; fi +test x"$TEST_FUNCTIONS_SH" != x"INCLUDED" && { incdir=`dirname $0` . $incdir/test_functions.sh +} failed=0 diff --git a/source3/script/tests/test_net_misc.sh b/source3/script/tests/test_net_misc.sh index 0a0636ac8a..8d092f4fe1 100755 --- a/source3/script/tests/test_net_misc.sh +++ b/source3/script/tests/test_net_misc.sh @@ -7,8 +7,10 @@ NET="$VALGRIND ${NET:-$BINDIR/net} $CONFIGURATION" NETTIME="${NET} time" NETLOOKUP="${NET} lookup" +test x"$TEST_FUNCTIONS_SH" != x"INCLUDED" && { incdir=`dirname $0` . $incdir/test_functions.sh +} failed=0 @@ -16,7 +18,7 @@ test_time() { PARAM="$1" - ${NETTIME} ${PARAM} -S localhost2 + ${NETTIME} -S ${SERVER} ${PARAM} } test_lookup() diff --git a/source3/script/tests/test_net_registry.sh b/source3/script/tests/test_net_registry.sh index 5edcb061ee..52a78bc339 100755 --- a/source3/script/tests/test_net_registry.sh +++ b/source3/script/tests/test_net_registry.sh @@ -13,8 +13,10 @@ else NETREG="${NET} registry" fi +test x"$TEST_FUNCTIONS_SH" != x"INCLUDED" && { incdir=`dirname $0` . $incdir/test_functions.sh +} failed=0 @@ -361,8 +363,11 @@ take_administrative_rights() if test "x${RPC}" = "xrpc" ; then testit "giving user ${USERNAME} administrative rights" \ - give_administrative_rights || \ - failed=`expr $failed + 1` + give_administrative_rights + if [ "x$?" != "x0" ] ; then + failed=`expr $failed + 1` + testok $0 $failed + fi fi testit "enumerate HKLM" \ diff --git a/source3/script/tests/test_net_s3.sh b/source3/script/tests/test_net_s3.sh index f7dc2b7e10..a0e83a65b1 100755 --- a/source3/script/tests/test_net_s3.sh +++ b/source3/script/tests/test_net_s3.sh @@ -2,8 +2,10 @@ # tests for the "net" command +test x"$TEST_FUNCTIONS_SH" != x"INCLUDED" && { incdir=`dirname $0` . $incdir/test_functions.sh +} failed=0 diff --git a/source3/script/tests/test_ntlm_auth_s3.sh b/source3/script/tests/test_ntlm_auth_s3.sh index 6c97f2e650..c7ebc03c80 100755 --- a/source3/script/tests/test_ntlm_auth_s3.sh +++ b/source3/script/tests/test_ntlm_auth_s3.sh @@ -1,7 +1,9 @@ #!/bin/sh +test x"$TEST_FUNCTIONS_SH" != x"INCLUDED" && { incdir=`dirname $0` . $incdir/test_functions.sh +} failed=0 diff --git a/source3/script/tests/test_posix_s3.sh b/source3/script/tests/test_posix_s3.sh index 3e9998666c..0885b139bb 100755 --- a/source3/script/tests/test_posix_s3.sh +++ b/source3/script/tests/test_posix_s3.sh @@ -16,8 +16,10 @@ start="$4" shift 4 ADDARGS="$*" +test x"$TEST_FUNCTIONS_SH" != x"INCLUDED" && { incdir=`dirname $0` . $incdir/test_functions.sh +} base="BASE-ATTR BASE-CHARSET BASE-CHKPATH BASE-DEFER_OPEN BASE-DELAYWRITE BASE-DELETE" base="$base BASE-DENY1 BASE-DENY2 BASE-DENY3 BASE-DENYDOS BASE-DIR1 BASE-DIR2" diff --git a/source3/script/tests/test_smbclient_s3.sh b/source3/script/tests/test_smbclient_s3.sh index c10aed0ee6..f60c7d7c0b 100755 --- a/source3/script/tests/test_smbclient_s3.sh +++ b/source3/script/tests/test_smbclient_s3.sh @@ -2,21 +2,25 @@ # this runs the file serving tests that are expected to pass with samba3 -if [ $# -lt 2 ]; then +if [ $# -lt 4 ]; then cat <<EOF -Usage: test_smbclient_s3.sh SERVER SERVER_IP +Usage: test_smbclient_s3.sh SERVER SERVER_IP USERNAME PASSWORD EOF exit 1; fi SERVER="$1" SERVER_IP="$2" +USERNAME="$3" +PASSWORD="$4" SMBCLIENT="$VALGRIND ${SMBCLIENT:-$BINDIR/smbclient} $CONFIGURATION" -shift 2 +shift 4 ADDARGS="$*" +test x"$TEST_FUNCTIONS_SH" != x"INCLUDED" && { incdir=`dirname $0` . $incdir/test_functions.sh +} failed=0 @@ -25,9 +29,18 @@ test_noninteractive_no_prompt() { prompt="smb" - echo du | \ - $SMBCLIENT $CONFIGURATION "$@" -U$USERNAME%$PASSWORD //$SERVER/tmp -I SERVER_IP $ADDARGS 2>&1 | \ - grep $prompt + cmd='echo du | $SMBCLIENT $CONFIGURATION "$@" -U$USERNAME%$PASSWORD //$SERVER/tmp -I $SERVER_IP $ADDARGS 2>&1' + eval echo "$cmd" + out=`eval $cmd` + + if [ $? != 0 ] ; then + echo "$out" + echo "command failed" + false + return + fi + + echo "$out" | grep $prompt >/dev/null 2>&1 if [ $? = 0 ] ; then # got a prompt .. fail @@ -49,18 +62,26 @@ du quit EOF - CLI_FORCE_INTERACTIVE=yes \ - $SMBCLIENT $CONFIGURATION "$@" -U$USERNAME%$PASSWORD //$SERVER/tmp -I $SERVER_IP \ - $ADDARGS < $tmpfile 2>/dev/null | \ - grep $prompt + cmd='CLI_FORCE_INTERACTIVE=yes $SMBCLIENT $CONFIGURATION "$@" -U$USERNAME%$PASSWORD //$SERVER/tmp -I $SERVER_IP $ADDARGS < $tmpfile 2>&1' + eval echo "$cmd" + out=`eval $cmd` + ret=$? + rm -f $tmpfile + + if [ $ret != 0 ] ; then + echo "$out" + echo "command failed" + false + return + fi + + echo "$out" | grep $prompt >/dev/null 2>&1 if [ $? = 0 ] ; then # got a prompt .. succeed - rm -f $tmpfile true else echo failed to match interactive prompt on stdout - rm -f $tmpfile false fi } diff --git a/source3/script/tests/test_smbtorture_s3.sh b/source3/script/tests/test_smbtorture_s3.sh index 2ec20dc6ac..842277b357 100755 --- a/source3/script/tests/test_smbtorture_s3.sh +++ b/source3/script/tests/test_smbtorture_s3.sh @@ -16,8 +16,10 @@ start="$4" shift 4 ADDARGS="$*" +test x"$TEST_FUNCTIONS_SH" != x"INCLUDED" && { incdir=`dirname $0` . $incdir/test_functions.sh +} tests="FDPASS LOCK1 LOCK2 LOCK3 LOCK4 LOCK5 LOCK6 LOCK7" #tests="$tests UNLINK BROWSE ATTR TRANS2 MAXFID TORTURE " diff --git a/source3/script/tests/test_testparm_s3.sh b/source3/script/tests/test_testparm_s3.sh index 6ea2794537..c88fc2d9d5 100755 --- a/source3/script/tests/test_testparm_s3.sh +++ b/source3/script/tests/test_testparm_s3.sh @@ -8,8 +8,10 @@ TEMP_CONFFILE=${LIBDIR}/smb.conf.tmp TESTPARM="$VALGRIND ${TESTPARM:-$BINDIR/testparm} --suppress-prompt --skip-logic-checks" +test x"$TEST_FUNCTIONS_SH" != x"INCLUDED" && { incdir=`dirname $0` . $incdir/test_functions.sh +} failed=0 diff --git a/source3/script/tests/test_wbinfo_s3.sh b/source3/script/tests/test_wbinfo_s3.sh index e3bf1b9e70..fa6e20fc72 100755 --- a/source3/script/tests/test_wbinfo_s3.sh +++ b/source3/script/tests/test_wbinfo_s3.sh @@ -14,8 +14,10 @@ password="$4" shift 4 ADDARGS="$*" +test x"$TEST_FUNCTIONS_SH" != x"INCLUDED" && { incdir=`dirname $0` . $incdir/test_functions.sh +} OLDIFS=$IFS; diff --git a/source3/script/tests/tests_all.sh b/source3/script/tests/tests_all.sh index 2b46da0e77..11d315b198 100755 --- a/source3/script/tests/tests_all.sh +++ b/source3/script/tests/tests_all.sh @@ -20,13 +20,13 @@ smbtorture_s3_encrypted() { smbclient_s3() { echo "RUNNING TESTS smbclient_s3" - $SCRIPTDIR/test_smbclient_s3.sh $SERVER $SERVER_IP \ + $SCRIPTDIR/test_smbclient_s3.sh $SERVER $SERVER_IP $USERNAME $PASSWORD \ || failed=`expr $failed + $?` } smbclient_s3_encrypted() { echo "RUNNING TESTS smbclient_s3_encrypted" - $SCRIPTDIR/test_smbclient_s3.sh $SERVER $SERVER_IP "-e" \ + $SCRIPTDIR/test_smbclient_s3.sh $SERVER $SERVER_IP $USERNAME $PASSWORD "-e" \ || failed=`expr $failed + $?` } diff --git a/source3/script/tests/tests_smbclient_s3.sh b/source3/script/tests/tests_smbclient_s3.sh index d48a692d4b..40edf2296f 100644 --- a/source3/script/tests/tests_smbclient_s3.sh +++ b/source3/script/tests/tests_smbclient_s3.sh @@ -1 +1 @@ -. $SCRIPTDIR/test_smbclient_s3.sh $SERVER $SERVER_IP +. $SCRIPTDIR/test_smbclient_s3.sh $SERVER $SERVER_IP $USERNAME $PASSWORD diff --git a/source3/selftest/tests.sh b/source3/selftest/tests.sh index 98568b6bb3..f88dab0337 100755 --- a/source3/selftest/tests.sh +++ b/source3/selftest/tests.sh @@ -44,27 +44,127 @@ normalize_testname() { echo $name | tr "A-Z-" "a-z." } +TEST_FUNCTIONS_SH="INCLUDED" +testit() { + name=$1 + shift 1 + cmdline="$*" + + plantest "`normalize_testname $testitprefix$name`" $testitenv $cmdline + return +} + +testok() { + true + return +} + BINDIR=`dirname $0`/../bin +export BINDIR + SCRIPTDIR=`dirname $0`/../script/tests export SCRIPTDIR -plantest "talloctort" none $VALGRIND $BINDIR/talloctort -plantest "replacetort" none $VALGRIND $BINDIR/replacetort -plantest "tdbtorture" none $VALGRIND $BINDIR/tdbtorture -plantest "smbconftort" none $VALGRIND $BINDIR/smbconftort $CONFIGURATION - -tests="FDPASS LOCK1 LOCK2 LOCK3 LOCK4 LOCK5 LOCK6 LOCK7" -tests="$tests UNLINK BROWSE ATTR TRANS2 TORTURE " -tests="$tests OPLOCK1 OPLOCK2 OPLOCK3" -tests="$tests DIR DIR1 TCON TCONDEV RW1 RW2 RW3" -tests="$tests OPEN XCOPY RENAME DELETE PROPERTIES W2K" -tests="$tests TCON2 IOCTL CHKPATH FDSESS LOCAL-SUBSTITUTE" - -for t in $tests; do - name=`normalize_testname $t` - plantest "$name" dc $VALGRIND $BINDIR/smbtorture //\$SERVER/tmp -U\$USERNAME%\$PASSWORD $t -done - -plantest "blackbox.smbclient" dc BINDIR="$BINDIR" script/tests/test_smbclient_s3.sh \$SERVER \$SERVER_IP -plantest "blackbox.wbinfo" dc BINDIR="$BINDIR" script/tests/test_wbinfo_s3.sh \$DOMAIN \$SERVER \$USERNAME \$PASSWORD -plantest "blackbox.net" dc BINDIR="$BINDIR" SCRIPTDIR="$SCRIPTDIR" script/tests/test_net_s3.sh +CONFIGURATION="--configfile \$SMB_CONF_PATH" +export CONFIGURATION + +CONFFILE="\$SMB_CONF_PATH" +export CONFFILE + +SERVER="\$SERVER" +export SERVER + +USERNAME="\$USERNAME" +export USERNAME + +PASSWORD="\$PASSWORD" +export PASSWORD + +( + shift $# + testitprefix="local_s3." + testitenv="none" + . $SCRIPTDIR/test_local_s3.sh +) + +( + shift $# + testitprefix="smbtorture_s3.plain." + testitenv="dc" + . $SCRIPTDIR/test_smbtorture_s3.sh //\$SERVER_IP/tmp \$USERNAME \$PASSWORD "" "" +) + +( + shift $# + testitprefix="smbtorture_s3.crypt." + testitenv="dc" + . $SCRIPTDIR/test_smbtorture_s3.sh //\$SERVER_IP/tmp \$USERNAME \$PASSWORD "" "-e" +) + +( + shift $# + testitprefix="wbinfo_s3." + testitenv="dc:local" + . $SCRIPTDIR/test_wbinfo_s3.sh \$WORKGROUP \$SERVER \$USERNAME \$PASSWORD +) + +( + shift $# + testitprefix="ntlm_auth_s3." + testitenv="dc:local" + . $SCRIPTDIR/test_ntlm_auth_s3.sh +) + +# plain +plantest "blackbox.smbclient_s3.plain" dc BINDIR="$BINDIR" script/tests/test_smbclient_s3.sh \$SERVER \$SERVER_IP \$USERNAME \$PASSWORD +plantest "blackbox.smbclient_s3.plain member creds" member BINDIR="$BINDIR" script/tests/test_smbclient_s3.sh \$SERVER \$SERVER_IP \$SERVER\\\\\$USERNAME \$PASSWORD +plantest "blackbox.smbclient_s3.plain domain creds" member BINDIR="$BINDIR" script/tests/test_smbclient_s3.sh \$SERVER \$SERVER_IP \$DOMAIN\\\\\$DC_USERNAME \$DC_PASSWORD + +# encrypted +plantest "blackbox.smbclient_s3.crypt" dc BINDIR="$BINDIR" script/tests/test_smbclient_s3.sh \$SERVER \$SERVER_IP \$USERNAME \$PASSWORD "-e" + +# these don't work yet +#plantest "blackbox.smbclient_s3.crypt member creds" member BINDIR="$BINDIR" script/tests/test_smbclient_s3.sh \$SERVER \$SERVER_IP \$SERVER\\\\\$USERNAME \$PASSWORD "-e" +#plantest "blackbox.smbclient_s3.crypt domain creds" member BINDIR="$BINDIR" script/tests/test_smbclient_s3.sh \$SERVER \$SERVER_IP \$DOMAIN\\\\\$DC_USERNAME \$DC_PASSWORD "-e" + +plantest "blackbox.net_s3" dc:local BINDIR="$BINDIR" SCRIPTDIR="$SCRIPTDIR" SERVERCONFFILE="\$SMB_CONF_PATH" script/tests/test_net_s3.sh + +( + shift $# + testitprefix="posix_s3." + testitenv="dc:local" + + SMBTORTURE4BINARY=$SMBTORTURE4 + TORTURE4_OPTIONS="" + TORTURE4_OPTIONS="$TORTURE4_OPTIONS --configfile=\$SMB_CONF_PATH" + TORTURE4_OPTIONS="$TORTURE4_OPTIONS --maximum-runtime=$SELFTEST_MAXTIME" + TORTURE4_OPTIONS="$TORTURE4_OPTIONS --target=$SELFTEST_TARGET" + TORTURE4_OPTIONS="$TORTURE4_OPTIONS --basedir=$SELFTEST_PREFIX" + if [ -n "$SELFTEST_VERBOSE" ]; then + TORTURE4_OPTIONS="$TORTURE4_OPTIONS --option=torture:progress=no" + fi + TORTURE_OPTIONS="$TORTURE4_OPTIONS --format=subunit" + if [ -n "$SELFTEST_QUICK" ]; then + TORTURE4_OPTIONS="$TORTURE4_OPTIONS --option=torture:quick=yes" + fi + + # This is an ugly hack... + TORTURE4_OPTIONS="$TORTURE4_OPTIONS --option=torture:localdir=$SELFTEST_PREFIX/dc/share" + + if [ -x "$SMBTORTURE4" ]; then + LIB_PATH_VAR_VAR="\$`echo $LIB_PATH_VAR`" + S4_LIB_PREFIX=`eval echo "$LIB_PATH_VAR=\"$SAMBA4SHAREDDIR:$LIB_PATH_VAR_VAR\""` + SMBTORTURE4="$S4_LIB_PREFIX $SMBTORTURE4" + SMBTORTURE4VERSION=`eval $SMBTORTURE4 --version` + fi + if [ -n "$SMBTORTURE4" -a -n "$SMBTORTURE4VERSION" ];then + echo "Using SMBTORTURE4: $SMBTORTURE4BINARY" + echo "Version: $SMBTORTURE4VERSION" + . $SCRIPTDIR/test_posix_s3.sh //\$SERVER_IP/tmp \$USERNAME \$PASSWORD "" "" + else + echo "Skip Tests with Samba4's smbtorture" + echo "Try to compile with --with-smbtorture4-path=PATH to enable" + fi + +) + diff --git a/source3/services/services_db.c b/source3/services/services_db.c index e41524851f..6d1b5d5b95 100644 --- a/source3/services/services_db.c +++ b/source3/services/services_db.c @@ -567,7 +567,8 @@ bool svcctl_set_secdesc( TALLOC_CTX *ctx, const char *name, SEC_DESC *sec_desc, WERROR wresult; char *path = NULL; REGVAL_CTR *values = NULL; - prs_struct ps; + DATA_BLOB blob; + NTSTATUS status; bool ret = False; /* now add the security descriptor */ @@ -593,21 +594,18 @@ bool svcctl_set_secdesc( TALLOC_CTX *ctx, const char *name, SEC_DESC *sec_desc, /* stream the printer security descriptor */ - if (!prs_init( &ps, RPC_MAX_PDU_FRAG_LEN, key, MARSHALL)) { - DEBUG(0,("svcctl_set_secdesc: prs_init() failed!\n")); + status = marshall_sec_desc(ctx, sec_desc, &blob.data, &blob.length); + if (!NT_STATUS_IS_OK(status)) { + DEBUG(0,("svcctl_set_secdesc: ndr_push_struct_blob() failed!\n")); TALLOC_FREE( key ); return False; } - if ( sec_io_desc("sec_desc", &sec_desc, &ps, 0 ) ) { - uint32 offset = prs_offset( &ps ); - regval_ctr_addvalue( values, "Security", REG_BINARY, prs_data_p(&ps), offset ); - ret = store_reg_values( key, values ); - } + regval_ctr_addvalue( values, "Security", REG_BINARY, (const char *)blob.data, blob.length); + ret = store_reg_values( key, values ); /* cleanup */ - prs_mem_free( &ps ); TALLOC_FREE( key); return ret; diff --git a/source3/smbd/aio.c b/source3/smbd/aio.c index 54ae45a789..64d512d675 100644 --- a/source3/smbd/aio.c +++ b/source3/smbd/aio.c @@ -109,58 +109,6 @@ static struct aio_extra *find_aio_ex(uint16 mid) *****************************************************************************/ /**************************************************************************** - Signal handler when an aio request completes. -*****************************************************************************/ - -void aio_request_done(uint16_t mid) -{ - if (aio_signals_received < aio_pending_size) { - aio_pending_array[aio_signals_received] = mid; - aio_signals_received++; - } - /* Else signal is lost. */ -} - -static void signal_handler(int sig, siginfo_t *info, void *unused) -{ - aio_request_done(info->si_value.sival_int); - sys_select_signal(RT_SIGNAL_AIO); -} - -/**************************************************************************** - Is there a signal waiting ? -*****************************************************************************/ - -bool aio_finished(void) -{ - return (aio_signals_received != 0); -} - -/**************************************************************************** - Initialize the signal handler for aio read/write. -*****************************************************************************/ - -void initialize_async_io_handler(void) -{ - struct sigaction act; - - aio_pending_size = lp_maxmux(); - aio_pending_array = SMB_MALLOC_ARRAY(uint16, aio_pending_size); - SMB_ASSERT(aio_pending_array != NULL); - - ZERO_STRUCT(act); - act.sa_sigaction = signal_handler; - act.sa_flags = SA_SIGINFO; - sigemptyset( &act.sa_mask ); - if (sigaction(RT_SIGNAL_AIO, &act, NULL) != 0) { - DEBUG(0,("Failed to setup RT_SIGNAL_AIO handler\n")); - } - - /* the signal can start off blocked due to a bug in bash */ - BlockSignals(False, RT_SIGNAL_AIO); -} - -/**************************************************************************** Set up an aio request from a SMBreadX call. *****************************************************************************/ @@ -193,8 +141,7 @@ bool schedule_aio_read_and_X(connection_struct *conn, /* Only do this on non-chained and non-chaining reads not using the * write cache. */ - if (chain_size !=0 || (CVAL(req->vwv+0, 0) != 0xFF) - || (lp_write_cache_size(SNUM(conn)) != 0) ) { + if (req_is_in_chain(req) || (lp_write_cache_size(SNUM(conn)) != 0)) { return False; } @@ -290,8 +237,7 @@ bool schedule_aio_write_and_X(connection_struct *conn, /* Only do this on non-chained and non-chaining reads not using the * write cache. */ - if (chain_size !=0 || (CVAL(req->vwv+0, 0) != 0xFF) - || (lp_write_cache_size(SNUM(conn)) != 0) ) { + if (req_is_in_chain(req) || (lp_write_cache_size(SNUM(conn)) != 0)) { return False; } @@ -573,57 +519,47 @@ static bool handle_aio_completed(struct aio_extra *aio_ex, int *perr) Returns non-zero errno if fail or zero if all ok. *****************************************************************************/ -int process_aio_queue(void) +void smbd_aio_complete_mid(unsigned int mid) { - int i; + files_struct *fsp = NULL; + struct aio_extra *aio_ex = find_aio_ex(mid); int ret = 0; - BlockSignals(True, RT_SIGNAL_AIO); - - DEBUG(10,("process_aio_queue: signals_received = %d\n", - (int)aio_signals_received)); - DEBUG(10,("process_aio_queue: outstanding_aio_calls = %d\n", - outstanding_aio_calls)); + DEBUG(10,("smbd_aio_complete_mid: mid[%u]\n", mid)); - if (!aio_signals_received) { - BlockSignals(False, RT_SIGNAL_AIO); - return 0; + if (!aio_ex) { + DEBUG(3,("smbd_aio_complete_mid: Can't find record to " + "match mid %u.\n", mid)); + srv_cancel_sign_response(mid); + return; } - /* Drain all the complete aio_reads. */ - for (i = 0; i < aio_signals_received; i++) { - uint16 mid = aio_pending_array[i]; - files_struct *fsp = NULL; - struct aio_extra *aio_ex = find_aio_ex(mid); - - if (!aio_ex) { - DEBUG(3,("process_aio_queue: Can't find record to " - "match mid %u.\n", (unsigned int)mid)); - srv_cancel_sign_response(mid); - continue; - } + fsp = aio_ex->fsp; + if (fsp == NULL) { + /* file was closed whilst I/O was outstanding. Just + * ignore. */ + DEBUG( 3,( "smbd_aio_complete_mid: file closed whilst " + "aio outstanding (mid[%u]).\n", mid)); + srv_cancel_sign_response(mid); + return; + } - fsp = aio_ex->fsp; - if (fsp == NULL) { - /* file was closed whilst I/O was outstanding. Just - * ignore. */ - DEBUG( 3,( "process_aio_queue: file closed whilst " - "aio outstanding.\n")); - srv_cancel_sign_response(mid); - continue; - } + if (!handle_aio_completed(aio_ex, &ret)) { + return; + } - if (!handle_aio_completed(aio_ex, &ret)) { - continue; - } + TALLOC_FREE(aio_ex); +} - TALLOC_FREE(aio_ex); - } +static void smbd_aio_signal_handler(struct tevent_context *ev_ctx, + struct tevent_signal *se, + int signum, int count, + void *_info, void *private_data) +{ + siginfo_t *info = (siginfo_t *)_info; + unsigned int mid = (unsigned int)info->si_value.sival_int; - outstanding_aio_calls -= aio_signals_received; - aio_signals_received = 0; - BlockSignals(False, RT_SIGNAL_AIO); - return ret; + smbd_aio_complete_mid(mid); } /**************************************************************************** @@ -755,19 +691,28 @@ void cancel_aio_by_fsp(files_struct *fsp) } } -#else -bool aio_finished(void) -{ - return False; -} +/**************************************************************************** + Initialize the signal handler for aio read/write. +*****************************************************************************/ void initialize_async_io_handler(void) { + aio_signal_event = tevent_add_signal(smbd_event_context(), + smbd_event_context(), + RT_SIGNAL_AIO, SA_SIGINFO, + smbd_aio_signal_handler, + NULL); + if (!aio_signal_event) { + exit_server("Failed to setup RT_SIGNAL_AIO handler"); + } + + /* tevent supports 100 signal with SA_SIGINFO */ + aio_pending_size = 100; } -int process_aio_queue(void) +#else +void initialize_async_io_handler(void) { - return False; } bool schedule_aio_read_and_X(connection_struct *conn, @@ -795,4 +740,7 @@ int wait_for_aio_completion(files_struct *fsp) { return ENOSYS; } + +void smbd_aio_complete_mid(unsigned int mid); + #endif diff --git a/source3/smbd/blocking.c b/source3/smbd/blocking.c index 9936fb219f..ac1ff00858 100644 --- a/source3/smbd/blocking.c +++ b/source3/smbd/blocking.c @@ -47,11 +47,6 @@ typedef struct blocking_lock_record { Determine if this is a secondary element of a chained SMB. **************************************************************************/ -static bool in_chained_smb(void) -{ - return (chain_size != 0); -} - static void received_unlock_msg(struct messaging_context *msg, void *private_data, uint32_t msg_type, @@ -144,7 +139,7 @@ bool push_blocking_lock_request( struct byte_range_lock *br_lck, blocking_lock_record *blr; NTSTATUS status; - if(in_chained_smb() ) { + if(req_is_in_chain(req)) { DEBUG(0,("push_blocking_lock_request: cannot queue a chained request (currently).\n")); return False; } diff --git a/source3/smbd/dnsregister.c b/source3/smbd/dnsregister.c index c092251fee..2fd95f9fb7 100644 --- a/source3/smbd/dnsregister.c +++ b/source3/smbd/dnsregister.c @@ -35,18 +35,16 @@ #include <dns_sd.h> struct dns_reg_state { + struct tevent_context *event_ctx; + uint16_t port; DNSServiceRef srv_ref; - struct timed_event *retry_handler; + struct tevent_timer *te; + int fd; + struct tevent_fd *fde; }; -void dns_register_close(struct dns_reg_state **dns_state_ptr) +static int dns_reg_state_destructor(struct dns_reg_state *dns_state) { - struct dns_reg_state *dns_state = *dns_state_ptr; - - if (dns_state == NULL) { - return; - } - if (dns_state->srv_ref != NULL) { /* Close connection to the mDNS daemon */ DNSServiceRefDeallocate(dns_state->srv_ref); @@ -54,81 +52,52 @@ void dns_register_close(struct dns_reg_state **dns_state_ptr) } /* Clear event handler */ - if (dns_state->retry_handler != NULL) { - TALLOC_FREE(dns_state->retry_handler); - dns_state->retry_handler = NULL; - } + TALLOC_FREE(dns_state->te); + TALLOC_FREE(dns_state->fde); + dns_state->fd = -1; - talloc_free(dns_state); - *dns_state_ptr = NULL; + return 0; } -static void dns_register_smbd_retry(struct event_context *ctx, - struct timed_event *te, - const struct timeval *now, - void *private_data) +static void dns_register_smbd_retry(struct tevent_context *ctx, + struct tevent_timer *te, + struct timeval now, + void *private_data); +static void dns_register_smbd_fde_handler(struct tevent_context *ev, + struct tevent_fd *fde, + uint16_t flags, + void *private_data); + +static bool dns_register_smbd_schedule(struct dns_reg_state *dns_state, + struct timeval tval) { - struct dns_reg_state *dns_state = (struct dns_reg_state *)private_data; - - /* Clear previous registration state to force new - * registration attempt. Clears event handler. - */ - dns_register_close(&dns_state); -} - -static void schedule_dns_register_smbd_retry(struct dns_reg_state *dns_state, - struct timeval *timeout) -{ - struct timed_event * event; - - dns_state->srv_ref = NULL; - event= event_add_timed(smbd_event_context(), - NULL, - timeval_current_ofs(DNS_REG_RETRY_INTERVAL, 0), - dns_register_smbd_retry, - dns_state); + dns_reg_state_destructor(dns_state); + + dns_state->te = tevent_add_timer(dns_state->event_ctx, + dns_state, + tval, + dns_register_smbd_retry, + dns_state); + if (!dns_state->te) { + return false; + } - dns_state->retry_handler = event; - get_timed_events_timeout(smbd_event_context(), timeout); + return true; } -/* Kick off a mDNS request to register the "_smb._tcp" on the specified port. - * We really ought to register on all the ports we are listening on. This will - * have to be an exercise for some-one who knows the DNS registration API a bit - * better. - */ -void dns_register_smbd(struct dns_reg_state ** dns_state_ptr, - unsigned port, - int *maxfd, - fd_set *listen_set, - struct timeval *timeout) +static void dns_register_smbd_retry(struct tevent_context *ctx, + struct tevent_timer *te, + struct timeval now, + void *private_data) { - int mdnsd_conn_fd; + struct dns_reg_state *dns_state = talloc_get_type_abort(private_data, + struct dns_reg_state); DNSServiceErrorType err; - struct dns_reg_state *dns_state = *dns_state_ptr; - - if (dns_state == NULL) { - *dns_state_ptr = dns_state = talloc(NULL, struct dns_reg_state); - if (dns_state == NULL) { - return; - } - } - - /* Quit if a re-try attempt has been scheduled. */ - if (dns_state->retry_handler != NULL) { - return; - } - /* If a registration is active add conn - * fd to select listen_set and return - */ - if (dns_state->srv_ref != NULL) { - mdnsd_conn_fd = DNSServiceRefSockFD(dns_state->srv_ref); - FD_SET(mdnsd_conn_fd, listen_set); - return; - } + dns_reg_state_destructor(dns_state); - DEBUG(6, ("registering _smb._tcp service on port %d\n", port)); + DEBUG(6, ("registering _smb._tcp service on port %d\n", + dns_state->port)); /* Register service with DNS. Connects with the mDNS * daemon running on the local system to perform DNS @@ -140,7 +109,7 @@ void dns_register_smbd(struct dns_reg_state ** dns_state_ptr, "_smb._tcp" /* service type */, NULL /* domain */, "" /* SRV target host name */, - htons(port), + htons(dns_state->port), 0 /* TXT record len */, NULL /* TXT record data */, NULL /* callback func */, @@ -150,62 +119,81 @@ void dns_register_smbd(struct dns_reg_state ** dns_state_ptr, /* Failed to register service. Schedule a re-try attempt. */ DEBUG(3, ("unable to register with mDNS (err %d)\n", err)); - schedule_dns_register_smbd_retry(dns_state, timeout); - return; + goto retry; + } + + dns_state->fd = DNSServiceRefSockFD(dns_state->srv_ref); + if (dns_state->fd == -1) { + goto retry; } - mdnsd_conn_fd = DNSServiceRefSockFD(dns_state->srv_ref); - FD_SET(mdnsd_conn_fd, listen_set); - *maxfd = MAX(*maxfd, mdnsd_conn_fd); - *timeout = timeval_zero(); + dns_state->fde = tevent_add_fd(dns_state->event_ctx, + dns_state, + dns_state->fd, + TEVENT_FD_READ, + dns_register_smbd_fde_handler, + dns_state); + if (!dns_state->fde) { + goto retry; + } + return; + retry: + dns_register_smbd_schedule(dns_state, + timeval_current_ofs(DNS_REG_RETRY_INTERVAL, 0)); } /* Processes reply from mDNS daemon. Returns true if a reply was received */ -bool dns_register_smbd_reply(struct dns_reg_state *dns_state, - fd_set *lfds, struct timeval *timeout) +static void dns_register_smbd_fde_handler(struct tevent_context *ev, + struct tevent_fd *fde, + uint16_t flags, + void *private_data) { - int mdnsd_conn_fd = -1; + struct dns_reg_state *dns_state = talloc_get_type_abort(private_data, + struct dns_reg_state); + DNSServiceErrorType err; - if (dns_state->srv_ref == NULL) { - return false; + err = DNSServiceProcessResult(dns_state->srv_ref); + if (err != kDNSServiceErr_NoError) { + DEBUG(3, ("failed to process mDNS result (err %d), re-trying\n", + err)); + goto retry; } - mdnsd_conn_fd = DNSServiceRefSockFD(dns_state->srv_ref); + talloc_free(dns_state); + return; - /* Process reply from daemon. Handles any errors. */ - if ((mdnsd_conn_fd != -1) && (FD_ISSET(mdnsd_conn_fd,lfds)) ) { - DNSServiceErrorType err; - - err = DNSServiceProcessResult(dns_state->srv_ref); - if (err != kDNSServiceErr_NoError) { - DEBUG(3, ("failed to process mDNS result (err %d), re-trying\n", - err)); - schedule_dns_register_smbd_retry(dns_state, timeout); - } + retry: + dns_register_smbd_schedule(dns_state, + timeval_current_ofs(DNS_REG_RETRY_INTERVAL, 0)); +} - return true; +bool smbd_setup_mdns_registration(struct tevent_context *ev, + TALLOC_CTX *mem_ctx, + uint16_t port) +{ + struct dns_reg_state *dns_state; + + dns_state = talloc_zero(mem_ctx, struct dns_reg_state); + if (dns_state == NULL) { + return false; } + dns_state->event_ctx = ev; + dns_state->port = port; + dns_state->fd = -1; + + talloc_set_destructor(dns_state, dns_reg_state_destructor); - return false; + return dns_register_smbd_schedule(dns_state, timeval_zero()); } #else /* WITH_DNSSD_SUPPORT */ - void dns_register_smbd(struct dns_reg_state ** dns_state_ptr, - unsigned port, - int *maxfd, - fd_set *listen_set, - struct timeval *timeout) -{} - - void dns_register_close(struct dns_reg_state ** dns_state_ptr) -{} - - bool dns_register_smbd_reply(struct dns_reg_state *dns_state, - fd_set *lfds, struct timeval *timeout) +bool smbd_setup_mdns_registration(struct tevent_context *ev, + TALLOC_CTX *mem_ctx, + uint16_t port) { - return false; + return true; } #endif /* WITH_DNSSD_SUPPORT */ diff --git a/source3/smbd/file_access.c b/source3/smbd/file_access.c index d44e63a89a..fe7ba1cc46 100644 --- a/source3/smbd/file_access.c +++ b/source3/smbd/file_access.c @@ -113,16 +113,11 @@ bool can_delete_file_in_directory(connection_struct *conn, const char *fname) * having the DELETE bit on the file itself and second if that does * not help, by the DELETE_CHILD bit on the containing directory. * - * Here we check the other way round because with just posix - * permissions looking at the file itself will never grant DELETE, so - * by looking at the directory first we save one get_acl call. + * Here we only check the directory permissions, we will + * check the file DELETE permission separately. */ - if (can_access_file_acl(conn, dname, FILE_DELETE_CHILD)) { - return true; - } - - return can_access_file_acl(conn, fname, DELETE_ACCESS); + return can_access_file_acl(conn, dname, FILE_DELETE_CHILD); } /**************************************************************************** diff --git a/source3/smbd/filename.c b/source3/smbd/filename.c index d240ecfa64..003cb0ffd4 100644 --- a/source3/smbd/filename.c +++ b/source3/smbd/filename.c @@ -126,7 +126,9 @@ NTSTATUS unix_convert(TALLOC_CTX *ctx, char *stream = NULL; bool component_was_mangled = False; bool name_has_wildcard = False; + bool posix_pathnames = false; NTSTATUS result; + int ret = -1; SET_STAT_INVALID(*pst); *pp_conv_path = NULL; @@ -225,7 +227,9 @@ NTSTATUS unix_convert(TALLOC_CTX *ctx, } } - if (!lp_posix_pathnames()) { + posix_pathnames = lp_posix_pathnames(); + + if (!posix_pathnames) { stream = strchr_m(name, ':'); if (stream != NULL) { @@ -268,7 +272,13 @@ NTSTATUS unix_convert(TALLOC_CTX *ctx, * stat the name - if it exists then we are all done! */ - if (SMB_VFS_STAT(conn,name,&st) == 0) { + if (posix_pathnames) { + ret = SMB_VFS_LSTAT(conn,name,&st); + } else { + ret = SMB_VFS_STAT(conn,name,&st); + } + + if (ret == 0) { /* Ensure we catch all names with in "/." this is disallowed under Windows. */ const char *p = strstr(name, "/."); /* mb safe. */ @@ -380,7 +390,13 @@ NTSTATUS unix_convert(TALLOC_CTX *ctx, * Check if the name exists up to this point. */ - if (SMB_VFS_STAT(conn,name, &st) == 0) { + if (posix_pathnames) { + ret = SMB_VFS_LSTAT(conn,name, &st); + } else { + ret = SMB_VFS_STAT(conn,name, &st); + } + + if (ret == 0) { /* * It exists. it must either be a directory or this must * be the last part of the path for it to be OK. @@ -598,7 +614,13 @@ NTSTATUS unix_convert(TALLOC_CTX *ctx, * if it exists. JRA. */ - if (SMB_VFS_STAT(conn,name, &st) == 0) { + if (posix_pathnames) { + ret = SMB_VFS_LSTAT(conn,name, &st); + } else { + ret = SMB_VFS_STAT(conn,name, &st); + } + + if (ret == 0) { *pst = st; } else { SET_STAT_INVALID(st); diff --git a/source3/smbd/globals.c b/source3/smbd/globals.c index c5681223f9..3f8cb411e5 100644 --- a/source3/smbd/globals.c +++ b/source3/smbd/globals.c @@ -22,10 +22,9 @@ #if defined(WITH_AIO) struct aio_extra *aio_list_head = NULL; +struct tevent_signal *aio_signal_event = NULL; int aio_pending_size = 0; -sig_atomic_t aio_signals_received = 0; int outstanding_aio_calls = 0; -uint16 *aio_pending_array = NULL; #endif /* dlink list we store pending lock records on. */ @@ -125,8 +124,6 @@ int max_send = BUFFER_SIZE; * Can be modified by the max xmit parameter. */ int max_recv = BUFFER_SIZE; -SIG_ATOMIC_T reload_after_sighup = 0; -SIG_ATOMIC_T got_sig_term = 0; uint16 last_session_tag = UID_FIELD_INVALID; int trans_num = 0; char *orig_inbuf = NULL; @@ -172,11 +169,6 @@ struct vfs_init_function_entry *backends = NULL; char *sparse_buf = NULL; char *LastDir = NULL; -#if HAVE_KERNEL_OPLOCKS_LINUX -SIG_ATOMIC_T oplock_signals_received = 0; -SIG_ATOMIC_T fd_pending_array[FD_PENDING_SIZE]; -#endif - /* Current number of oplocks we have outstanding. */ int32_t exclusive_oplocks_open = 0; int32_t level_II_oplocks_open = 0; @@ -186,7 +178,6 @@ struct kernel_oplocks *koplocks = NULL; struct notify_mid_map *notify_changes_by_mid = NULL; int am_parent = 1; -SIG_ATOMIC_T got_sig_cld = 0; int server_fd = -1; struct event_context *smbd_event_ctx = NULL; struct messaging_context *smbd_msg_ctx = NULL; @@ -205,8 +196,4 @@ void smbd_init_globals(void) ZERO_STRUCT(conn_ctx_stack); ZERO_STRUCT(sec_ctx_stack); - -#if HAVE_KERNEL_OPLOCKS_LINUX - ZERO_STRUCT(fd_pending_array); -#endif } diff --git a/source3/smbd/globals.h b/source3/smbd/globals.h index 2c4f8b5821..6ac92ed3dd 100644 --- a/source3/smbd/globals.h +++ b/source3/smbd/globals.h @@ -20,10 +20,9 @@ #if defined(WITH_AIO) struct aio_extra; extern struct aio_extra *aio_list_head; +extern struct tevent_signal *aio_signal_event; extern int aio_pending_size; -extern sig_atomic_t aio_signals_received; extern int outstanding_aio_calls; -extern uint16_t *aio_pending_array; #endif /* dlink list we store pending lock records on. */ @@ -124,8 +123,6 @@ extern int max_send; * Can be modified by the max xmit parameter. */ extern int max_recv; -extern SIG_ATOMIC_T reload_after_sighup; -extern SIG_ATOMIC_T got_sig_term; extern uint16 last_session_tag; extern int trans_num; extern char *orig_inbuf; @@ -184,12 +181,6 @@ extern struct vfs_init_function_entry *backends; extern char *sparse_buf; extern char *LastDir; -#if HAVE_KERNEL_OPLOCKS_LINUX -extern SIG_ATOMIC_T oplock_signals_received; -#define FD_PENDING_SIZE 100 -extern SIG_ATOMIC_T fd_pending_array[FD_PENDING_SIZE]; -#endif - /* Current number of oplocks we have outstanding. */ extern int32_t exclusive_oplocks_open; extern int32_t level_II_oplocks_open; @@ -199,7 +190,6 @@ extern struct kernel_oplocks *koplocks; extern struct notify_mid_map *notify_changes_by_mid; extern int am_parent; -extern SIG_ATOMIC_T got_sig_cld; extern int server_fd; extern struct event_context *smbd_event_ctx; extern struct messaging_context *smbd_msg_ctx; diff --git a/source3/smbd/ipc.c b/source3/smbd/ipc.c index 7c150561b1..9c7528dfa7 100644 --- a/source3/smbd/ipc.c +++ b/source3/smbd/ipc.c @@ -204,40 +204,137 @@ void send_trans_reply(connection_struct *conn, Start the first part of an RPC reply which began with an SMBtrans request. ****************************************************************************/ -static void api_rpc_trans_reply(connection_struct *conn, - struct smb_request *req, - files_struct *fsp, - int max_trans_reply) +struct dcerpc_cmd_state { + struct fake_file_handle *handle; + uint8_t *data; + size_t num_data; + size_t max_read; +}; + +static void api_dcerpc_cmd_write_done(struct async_req *subreq); +static void api_dcerpc_cmd_read_done(struct async_req *subreq); + +static void api_dcerpc_cmd(connection_struct *conn, struct smb_request *req, + files_struct *fsp, uint8_t *data, size_t length, + size_t max_read) { - bool is_data_outstanding; - uint8_t *rdata = SMB_MALLOC_ARRAY(uint8_t, max_trans_reply); - ssize_t data_len; - NTSTATUS status; + struct async_req *subreq; + struct dcerpc_cmd_state *state; + + if (!fsp_is_np(fsp)) { + api_no_reply(conn, req); + return; + } - if(rdata == NULL) { - DEBUG(0,("api_rpc_trans_reply: malloc fail.\n")); + state = talloc(req, struct dcerpc_cmd_state); + if (state == NULL) { reply_nterror(req, NT_STATUS_NO_MEMORY); return; } + req->async_priv = state; - if (!fsp_is_np(fsp)) { - SAFE_FREE(rdata); - api_no_reply(conn,req); + state->handle = fsp->fake_file_handle; + + /* + * This memdup severely sucks. But doing it properly essentially means + * to rewrite lanman.c, something which I don't really want to do now. + */ + state->data = (uint8_t *)talloc_memdup(state, data, length); + if (state->data == NULL) { + reply_nterror(req, NT_STATUS_NO_MEMORY); return; } + state->num_data = length; + state->max_read = max_read; + + subreq = np_write_send(state, smbd_event_context(), state->handle, + state->data, length); + if (subreq == NULL) { + TALLOC_FREE(state); + reply_nterror(req, NT_STATUS_NO_MEMORY); + return; + } + subreq->async.fn = api_dcerpc_cmd_write_done; + subreq->async.priv = talloc_move(conn, &req); +} + +static void api_dcerpc_cmd_write_done(struct async_req *subreq) +{ + struct smb_request *req = talloc_get_type_abort( + subreq->async.priv, struct smb_request); + struct dcerpc_cmd_state *state = talloc_get_type_abort( + req->async_priv, struct dcerpc_cmd_state); + NTSTATUS status; + ssize_t nwritten = -1; + + status = np_write_recv(subreq, &nwritten); + TALLOC_FREE(subreq); + if (!NT_STATUS_IS_OK(status) || (nwritten != state->num_data)) { + DEBUG(10, ("Could not write to pipe: %s (%d/%d)\n", + nt_errstr(status), (int)state->num_data, + (int)nwritten)); + reply_nterror(req, NT_STATUS_PIPE_NOT_AVAILABLE); + goto send; + } + + state->data = TALLOC_REALLOC_ARRAY(state, state->data, uint8_t, + state->max_read); + if (state->data == NULL) { + reply_nterror(req, NT_STATUS_NO_MEMORY); + goto send; + } + + subreq = np_read_send(req->conn, smbd_event_context(), + state->handle, state->data, state->max_read); + if (subreq == NULL) { + reply_nterror(req, NT_STATUS_NO_MEMORY); + goto send; + } + + subreq->async.fn = api_dcerpc_cmd_read_done; + subreq->async.priv = req; + return; + + send: + if (!srv_send_smb( + smbd_server_fd(), (char *)req->outbuf, + IS_CONN_ENCRYPTED(req->conn) || req->encrypted)) { + exit_server_cleanly("construct_reply: srv_send_smb failed."); + } + TALLOC_FREE(req); +} + +static void api_dcerpc_cmd_read_done(struct async_req *subreq) +{ + struct smb_request *req = talloc_get_type_abort( + subreq->async.priv, struct smb_request); + struct dcerpc_cmd_state *state = talloc_get_type_abort( + req->async_priv, struct dcerpc_cmd_state); + NTSTATUS status; + ssize_t nread; + bool is_data_outstanding; + + status = np_read_recv(subreq, &nread, &is_data_outstanding); + TALLOC_FREE(subreq); - status = np_read(fsp->fake_file_handle, rdata, max_trans_reply, - &data_len, &is_data_outstanding); if (!NT_STATUS_IS_OK(status)) { - SAFE_FREE(rdata); - api_no_reply(conn,req); + DEBUG(10, ("Could not read from to pipe: %s\n", + nt_errstr(status))); + reply_nterror(req, status); + + if (!srv_send_smb(smbd_server_fd(), (char *)req->outbuf, + IS_CONN_ENCRYPTED(req->conn) + ||req->encrypted)) { + exit_server_cleanly("construct_reply: srv_send_smb " + "failed."); + } + TALLOC_FREE(req); return; } - send_trans_reply(conn, req, NULL, 0, (char *)rdata, data_len, + send_trans_reply(req->conn, req, NULL, 0, (char *)state->data, nread, is_data_outstanding); - SAFE_FREE(rdata); - return; + TALLOC_FREE(req); } /**************************************************************************** @@ -310,7 +407,6 @@ static void api_fd_reply(connection_struct *conn, uint16 vuid, struct files_struct *fsp; int pnum; int subcommand; - NTSTATUS status; DEBUG(5,("api_fd_reply\n")); @@ -360,14 +456,8 @@ static void api_fd_reply(connection_struct *conn, uint16 vuid, switch (subcommand) { case TRANSACT_DCERPCCMD: { /* dce/rpc command */ - ssize_t nwritten; - status = np_write(fsp->fake_file_handle, data, tdscnt, - &nwritten); - if (!NT_STATUS_IS_OK(status)) { - api_no_reply(conn, req); - return; - } - api_rpc_trans_reply(conn, req, fsp, mdrcnt); + api_dcerpc_cmd(conn, req, fsp, (uint8_t *)data, tdscnt, + mdrcnt); break; } case TRANSACT_WAITNAMEDPIPEHANDLESTATE: diff --git a/source3/smbd/lanman.c b/source3/smbd/lanman.c index c8e35783c0..4807e62436 100644 --- a/source3/smbd/lanman.c +++ b/source3/smbd/lanman.c @@ -6,17 +6,17 @@ SMB Version handling Copyright (C) John H Terpstra 1995-1998 - + 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/>. */ @@ -876,9 +876,9 @@ static bool api_DosPrintQGetInfo(connection_struct *conn, uint16 vuid, /* remove any trailing username */ if ((p = strchr_m(QueueName,'%'))) *p = 0; - + DEBUG(3,("api_DosPrintQGetInfo uLevel=%d name=%s\n",uLevel,QueueName)); - + /* check it's a supported varient */ if (!prefix_ok(str1,"zWrLh")) return False; @@ -899,11 +899,11 @@ static bool api_DosPrintQGetInfo(connection_struct *conn, uint16 vuid, SSVAL(*rparam,4,0); return(True); } - + snum = find_service(QueueName); if ( !(lp_snum_ok(snum) && lp_print_ok(snum)) ) return False; - + if (uLevel==52) { count = get_printerdrivernumber(snum); DEBUG(3,("api_DosPrintQGetInfo: Driver files count: %d\n",count)); @@ -934,7 +934,7 @@ static bool api_DosPrintQGetInfo(connection_struct *conn, uint16 vuid, } *rdata_len = desc.usedlen; - + /* * We must set the return code to ERRbuftoosmall * in order to support lanman style printing with Win NT/2k @@ -942,7 +942,7 @@ static bool api_DosPrintQGetInfo(connection_struct *conn, uint16 vuid, */ if (!mdrcnt && lp_disable_spoolss()) desc.errcode = ERRbuftoosmall; - + *rdata_len = desc.usedlen; *rparam_len = 6; *rparam = smb_realloc_limit(*rparam,*rparam_len); @@ -954,7 +954,7 @@ static bool api_DosPrintQGetInfo(connection_struct *conn, uint16 vuid, SSVALS(*rparam,0,desc.errcode); SSVAL(*rparam,2,0); SSVAL(*rparam,4,desc.neededlen); - + DEBUG(4,("printqgetinfo: errorcode %d\n",desc.errcode)); SAFE_FREE(queue); @@ -986,7 +986,7 @@ static bool api_DosPrintQEnum(connection_struct *conn, uint16 vuid, print_status_struct *status = NULL; int *subcntarr = NULL; int queuecnt = 0, subcnt = 0, succnt = 0; - + if (!param_format || !output_format1 || !p) { return False; } @@ -994,7 +994,7 @@ static bool api_DosPrintQEnum(connection_struct *conn, uint16 vuid, memset((char *)&desc,'\0',sizeof(desc)); DEBUG(3,("DosPrintQEnum uLevel=%d\n",uLevel)); - + if (!prefix_ok(param_format,"WrLeh")) { return False; } @@ -1071,7 +1071,7 @@ static bool api_DosPrintQEnum(connection_struct *conn, uint16 vuid, } SAFE_FREE(subcntarr); - + *rdata_len = desc.usedlen; *rparam_len = 8; *rparam = smb_realloc_limit(*rparam,*rparam_len); @@ -1082,7 +1082,7 @@ static bool api_DosPrintQEnum(connection_struct *conn, uint16 vuid, SSVAL(*rparam,2,0); SSVAL(*rparam,4,succnt); SSVAL(*rparam,6,queuecnt); - + for (i = 0; i < queuecnt; i++) { if (queue) { SAFE_FREE(queue[i]); @@ -1091,7 +1091,7 @@ static bool api_DosPrintQEnum(connection_struct *conn, uint16 vuid, SAFE_FREE(queue); SAFE_FREE(status); - + return True; err: @@ -1248,11 +1248,11 @@ static int get_server_info(uint32 servertype, DEBUG(4,("s: dom mismatch ")); ok = False; } - + if (!strequal(domain, s->domain) && !(servertype & SV_TYPE_DOMAIN_ENUM)) { ok = False; } - + /* We should never return a server type with a SV_TYPE_LOCAL_LIST_ONLY set. */ s->type &= ~SV_TYPE_LOCAL_LIST_ONLY; @@ -1266,7 +1266,7 @@ static int get_server_info(uint32 servertype, s->name, s->type, s->comment, s->domain)); } } - + TALLOC_FREE(lines); return count; } @@ -1284,7 +1284,7 @@ static int fill_srv_info(struct srv_info_struct *service, char* p2; int l2; int len; - + switch (uLevel) { case 0: struct_len = 16; @@ -1295,7 +1295,7 @@ static int fill_srv_info(struct srv_info_struct *service, default: return -1; } - + if (!buf) { len = 0; switch (uLevel) { @@ -1308,7 +1308,7 @@ static int fill_srv_info(struct srv_info_struct *service, *stringspace = len; return struct_len + len; } - + len = struct_len; p = *buf; if (*buflen < struct_len) { @@ -1324,7 +1324,7 @@ static int fill_srv_info(struct srv_info_struct *service, if (!baseaddr) { baseaddr = p; } - + switch (uLevel) { case 0: push_ascii(p,service->name, MAX_NETBIOSNAME_LEN, STR_TERMINATE); @@ -1416,7 +1416,7 @@ static bool api_RNetServerEnum(connection_struct *conn, uint16 vuid, if (!check_server_info(uLevel,str2)) { return False; } - + DEBUG(4, ("server request level: %s %8x ", str2, servertype)); DEBUG(4, ("domains_req:%s ", BOOLSTR(domain_request))); DEBUG(4, ("local_only:%s\n", BOOLSTR(local_request))); @@ -1454,7 +1454,7 @@ static bool api_RNetServerEnum(connection_struct *conn, uint16 vuid, data_len += fill_srv_info(s,uLevel,0,&f_len,0,&s_len,0); DEBUG(4,("fill_srv_info %20s %8x %25s %15s\n", s->name, s->type, s->comment, s->domain)); - + if (data_len <= buf_len) { counted++; fixed_len += f_len; @@ -1470,7 +1470,7 @@ static bool api_RNetServerEnum(connection_struct *conn, uint16 vuid, if (!*rdata) { return False; } - + p2 = (*rdata) + fixed_len; /* auxilliary data (strings) will go here */ p = *rdata; f_len = fixed_len; @@ -1493,7 +1493,7 @@ static bool api_RNetServerEnum(connection_struct *conn, uint16 vuid, count2--; } } - + *rparam_len = 8; *rparam = smb_realloc_limit(*rparam,*rparam_len); if (!*rparam) { @@ -1540,9 +1540,9 @@ static bool api_RNetGroupGetUsers(connection_struct *conn, uint16 vuid, if (!prefix_ok(str1,"zWrLeh")) { return False; } - + *rdata_len = 0; - + *rparam_len = 8; *rparam = smb_realloc_limit(*rparam,*rparam_len); if (!*rparam) { @@ -1599,7 +1599,7 @@ static int fill_share_info(connection_struct *conn, int snum, int uLevel, char* p2; int l2; int len; - + switch( uLevel ) { case 0: struct_len = 13; @@ -1616,8 +1616,7 @@ static int fill_share_info(connection_struct *conn, int snum, int uLevel, default: return -1; } - - + if (!buf) { len = 0; @@ -1635,7 +1634,7 @@ static int fill_share_info(connection_struct *conn, int snum, int uLevel, } return struct_len + len; } - + len = struct_len; p = *buf; if ((*buflen) < struct_len) { @@ -1653,9 +1652,9 @@ static int fill_share_info(connection_struct *conn, int snum, int uLevel, if (!baseaddr) { baseaddr = p; } - + push_ascii(p,lp_servicename(snum),13, STR_TERMINATE); - + if (uLevel > 0) { int type; @@ -1671,7 +1670,7 @@ static int fill_share_info(connection_struct *conn, int snum, int uLevel, SIVAL(p,16,PTR_DIFF(p2,baseaddr)); len += CopyExpanded(conn,snum,&p2,lp_comment(snum),&l2); } - + if (uLevel > 1) { SSVAL(p,20,ACCESS_READ|ACCESS_WRITE|ACCESS_CREATE); /* permissions */ SSVALS(p,22,-1); /* max uses */ @@ -1680,7 +1679,7 @@ static int fill_share_info(connection_struct *conn, int snum, int uLevel, len += CopyAndAdvance(&p2,lp_pathname(snum),&l2); memset(p+30,0,SHPWLEN+2); /* passwd (reserved), pad field */ } - + if (uLevel > 2) { memset(p+40,0,SHPWLEN+2); SSVAL(p,50,0); @@ -1691,7 +1690,7 @@ static int fill_share_info(connection_struct *conn, int snum, int uLevel, SSVAL(p,64,0); SSVAL(p,66,0); } - + if (stringbuf) { (*buf) = p + struct_len; (*buflen) -= struct_len; @@ -1718,7 +1717,7 @@ static bool api_RNetShareGetInfo(connection_struct *conn,uint16 vuid, char *p = skip_string(param,tpscnt,netname); int uLevel = get_safe_SVAL(param,tpscnt,p,0,-1); int snum; - + if (!str1 || !str2 || !netname || !p) { return False; } @@ -1727,7 +1726,7 @@ static bool api_RNetShareGetInfo(connection_struct *conn,uint16 vuid, if (snum < 0) { return False; } - + /* check it's a supported varient */ if (!prefix_ok(str1,"zWrLh")) { return False; @@ -1735,7 +1734,7 @@ static bool api_RNetShareGetInfo(connection_struct *conn,uint16 vuid, if (!check_share_info(uLevel,str2)) { return False; } - + *rdata = smb_realloc_limit(*rdata,mdrcnt); if (!*rdata) { return False; @@ -1745,7 +1744,7 @@ static bool api_RNetShareGetInfo(connection_struct *conn,uint16 vuid, if (*rdata_len < 0) { return False; } - + *rparam_len = 6; *rparam = smb_realloc_limit(*rparam,*rparam_len); if (!*rparam) { @@ -1754,7 +1753,7 @@ static bool api_RNetShareGetInfo(connection_struct *conn,uint16 vuid, SSVAL(*rparam,0,NERR_Success); SSVAL(*rparam,2,0); /* converter word */ SSVAL(*rparam,4,*rdata_len); - + return True; } @@ -1790,7 +1789,7 @@ static bool api_RNetShareEnum( connection_struct *conn, uint16 vuid, int i; int data_len, fixed_len, string_len; int f_len = 0, s_len = 0; - + if (!str1 || !str2 || !p) { return False; } @@ -1801,7 +1800,7 @@ static bool api_RNetShareEnum( connection_struct *conn, uint16 vuid, if (!check_share_info(uLevel,str2)) { return False; } - + /* Ensure all the usershares are loaded. */ become_root(); load_registry_shares(); @@ -1834,7 +1833,7 @@ static bool api_RNetShareEnum( connection_struct *conn, uint16 vuid, if (!*rdata) { return False; } - + p2 = (*rdata) + fixed_len; /* auxiliary data (strings) will go here */ p = *rdata; f_len = fixed_len; @@ -1853,7 +1852,7 @@ static bool api_RNetShareEnum( connection_struct *conn, uint16 vuid, } } } - + *rparam_len = 8; *rparam = smb_realloc_limit(*rparam,*rparam_len); if (!*rparam) { @@ -1863,7 +1862,7 @@ static bool api_RNetShareEnum( connection_struct *conn, uint16 vuid, SSVAL(*rparam,2,0); SSVAL(*rparam,4,counted); SSVAL(*rparam,6,total); - + DEBUG(3,("RNetShareEnum gave %d entries of %d (%d %d %d %d)\n", counted,total,uLevel, buf_len,*rdata_len,mdrcnt)); @@ -2004,7 +2003,7 @@ static bool api_RNetShareAdd(connection_struct *conn,uint16 vuid, SSVAL(*rparam,2,0); /* converter word */ SSVAL(*rparam,4,*rdata_len); *rdata_len = 0; - + return True; error_exit: @@ -2042,7 +2041,7 @@ static bool api_RNetGroupEnum(connection_struct *conn,uint16 vuid, struct samr_displayentry *entries; int num_entries; - + if (!str1 || !str2 || !p) { return False; } @@ -2282,8 +2281,11 @@ static bool api_RNetUserEnum(connection_struct *conn, uint16 vuid, int num_users=0; int errflags=0; int i, resume_context, cli_buf_size; - struct pdb_search *search; - struct samr_displayentry *users; + uint32_t resume_handle; + + struct rpc_pipe_client *samr_pipe; + struct policy_handle samr_handle, domain_handle; + NTSTATUS status; char *str1 = get_safe_str_ptr(param,tpscnt,param,2); char *str2 = skip_string(param,tpscnt,str1); @@ -2328,40 +2330,88 @@ static bool api_RNetUserEnum(connection_struct *conn, uint16 vuid, p = *rdata; endp = *rdata + *rdata_len; - become_root(); - search = pdb_search_users(ACB_NORMAL); - unbecome_root(); - if (search == NULL) { - DEBUG(0, ("api_RNetUserEnum:unable to open sam database.\n")); - return False; + status = rpc_pipe_open_internal( + talloc_tos(), &ndr_table_samr.syntax_id, rpc_samr_dispatch, + conn->server_info, &samr_pipe); + if (!NT_STATUS_IS_OK(status)) { + DEBUG(0, ("api_RNetUserEnum: Could not connect to samr: %s\n", + nt_errstr(status))); + return false; } - become_root(); - num_users = pdb_search_entries(search, resume_context, 0xffffffff, - &users); - unbecome_root(); + status = rpccli_samr_Connect2(samr_pipe, talloc_tos(), global_myname(), + SAMR_ACCESS_OPEN_DOMAIN, &samr_handle); + if (!NT_STATUS_IS_OK(status)) { + DEBUG(0, ("api_RNetUserEnum: samr_Connect2 failed: %s\n", + nt_errstr(status))); + return false; + } + + status = rpccli_samr_OpenDomain(samr_pipe, talloc_tos(), &samr_handle, + SAMR_DOMAIN_ACCESS_ENUM_ACCOUNTS, + get_global_sam_sid(), &domain_handle); + if (!NT_STATUS_IS_OK(status)) { + DEBUG(0, ("api_RNetUserEnum: samr_OpenDomain failed: %s\n", + nt_errstr(status))); + return false; + } errflags=NERR_Success; - for (i=0; i<num_users; i++) { - const char *name = users[i].account_name; + resume_handle = 0; - if(((PTR_DIFF(p,*rdata)+21)<=*rdata_len)&&(strlen(name)<=21)) { - strlcpy(p,name,PTR_DIFF(endp,p)); - DEBUG(10,("api_RNetUserEnum:adding entry %d username " - "%s\n",count_sent,p)); - p += 21; - count_sent++; - } else { - /* set overflow error */ - DEBUG(10,("api_RNetUserEnum:overflow on entry %d " - "username %s\n",count_sent,name)); - errflags=234; + while (true) { + struct samr_SamArray *sam_entries; + uint32_t num_entries; + + status = rpccli_samr_EnumDomainUsers(samr_pipe, talloc_tos(), + &domain_handle, + &resume_handle, + 0, &sam_entries, 1, + &num_entries); + + if (!NT_STATUS_IS_OK(status)) { + DEBUG(10, ("rpccli_samr_EnumDomainUsers returned " + "%s\n", nt_errstr(status))); + break; + } + + if (num_entries == 0) { + DEBUG(10, ("rpccli_samr_EnumDomainUsers returned " + "no entries -- done\n")); + break; + } + + for (i=0; i<num_entries; i++) { + const char *name; + + name = sam_entries->entries[i].name.string; + + if(((PTR_DIFF(p,*rdata)+21)<=*rdata_len) + &&(strlen(name)<=21)) { + strlcpy(p,name,PTR_DIFF(endp,p)); + DEBUG(10,("api_RNetUserEnum:adding entry %d " + "username %s\n",count_sent,p)); + p += 21; + count_sent++; + } else { + /* set overflow error */ + DEBUG(10,("api_RNetUserEnum:overflow on entry %d " + "username %s\n",count_sent,name)); + errflags=234; + break; + } + } + + if (errflags != NERR_Success) { break; } + + TALLOC_FREE(sam_entries); } - pdb_search_destroy(search); + rpccli_samr_Close(samr_pipe, talloc_tos(), &domain_handle); + rpccli_samr_Close(samr_pipe, talloc_tos(), &samr_handle); *rdata_len = PTR_DIFF(p,*rdata); @@ -2538,7 +2588,7 @@ static bool api_SetUserPassword(connection_struct *conn,uint16 vuid, memset((char *)pass1,'\0',sizeof(fstring)); memset((char *)pass2,'\0',sizeof(fstring)); - + return(True); } @@ -2677,7 +2727,7 @@ static bool api_RDosPrintJobDel(connection_struct *conn,uint16 vuid, } errcode = NERR_notsupported; - + switch (function) { case 81: /* delete */ if (print_job_delete(conn->server_info, snum, jobid, &werr)) @@ -2695,7 +2745,7 @@ static bool api_RDosPrintJobDel(connection_struct *conn,uint16 vuid, if (!W_ERROR_IS_OK(werr)) errcode = W_ERROR_V(werr); - + out: SSVAL(*rparam,0,errcode); SSVAL(*rparam,2,0); /* converter word */ @@ -2845,9 +2895,9 @@ static bool api_PrintJobInfo(connection_struct *conn, uint16 vuid, sharename)); return False; } - + *rdata_len = 0; - + /* check it's a supported varient */ if ((strcmp(str1,"WWsTP")) || (!check_printjob_info(&desc,uLevel,str2))) @@ -2884,7 +2934,7 @@ static bool api_PrintJobInfo(connection_struct *conn, uint16 vuid, out: SSVALS(*rparam,0,errcode); SSVAL(*rparam,2,0); /* converter word */ - + return(True); } @@ -3638,7 +3688,7 @@ static bool api_WWkstaUserLogon(connection_struct *conn,uint16 vuid, desc.buflen = mdrcnt; desc.subformat = NULL; desc.format = str2; - + if (init_package(&desc,1,0)) { PACKI(&desc,"W",0); /* code */ PACKS(&desc,"B21",name); /* eff. name */ @@ -3870,11 +3920,11 @@ static bool api_WPrintJobEnumerate(connection_struct *conn, uint16 vuid, if (strcmp(str1,"zWrLeh") != 0) { return False; } - + if (uLevel > 2) { return False; /* defined only for uLevel 0,1,2 */ } - + if (!check_printjob_info(&desc,uLevel,str2)) { return False; } diff --git a/source3/smbd/mangle_hash.c b/source3/smbd/mangle_hash.c index ebd93ff5d0..96fe4d2cab 100644 --- a/source3/smbd/mangle_hash.c +++ b/source3/smbd/mangle_hash.c @@ -53,7 +53,7 @@ * */ -static const char basechars[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ_-!@#$%"; +static const char basechars[43]="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ_-!@#$%"; #define MANGLE_BASE (sizeof(basechars)/sizeof(char)-1) #define mangle(V) ((char)(basechars[(V) % MANGLE_BASE])) diff --git a/source3/smbd/mangle_hash2.c b/source3/smbd/mangle_hash2.c index 859e5e7227..3a3939c511 100644 --- a/source3/smbd/mangle_hash2.c +++ b/source3/smbd/mangle_hash2.c @@ -85,7 +85,7 @@ #define FLAG_CHECK(c, flag) (char_flags[(unsigned char)(c)] & (flag)) /* these are the characters we use in the 8.3 hash. Must be 36 chars long */ -static const char * const basechars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; +static const char basechars[36] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; #define base_forward(v) basechars[v] /* the list of reserved dos names - all of these are illegal */ diff --git a/source3/smbd/negprot.c b/source3/smbd/negprot.c index 729d144ea1..57608a9b40 100644 --- a/source3/smbd/negprot.c +++ b/source3/smbd/negprot.c @@ -212,7 +212,7 @@ static DATA_BLOB negprot_spnego(void) */ - if (lp_security() != SEC_ADS && !lp_use_kerberos_keytab()) { + if (lp_security() != SEC_ADS && !USE_KERBEROS_KEYTAB) { #if 0 /* Code for PocketPC client */ blob = data_blob(guid, 16); diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index 1ee3edbdbe..0ad4df6e90 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -621,7 +621,7 @@ void reply_ntcreate_and_X(struct smb_request *req) p += 8; SIVAL(p,0,fattr); /* File Attributes. */ p += 4; - SOFF_T(p, 0, get_allocation_size(conn,fsp,&sbuf)); + SOFF_T(p, 0, SMB_VFS_GET_ALLOC_SIZE(conn,fsp,&sbuf)); p += 8; SOFF_T(p,0,file_len); p += 8; @@ -1086,7 +1086,7 @@ static void call_nt_transact_create(connection_struct *conn, p += 8; SIVAL(p,0,fattr); /* File Attributes. */ p += 4; - SOFF_T(p, 0, get_allocation_size(conn,fsp,&sbuf)); + SOFF_T(p, 0, SMB_VFS_GET_ALLOC_SIZE(conn,fsp,&sbuf)); p += 8; SOFF_T(p,0,file_len); p += 8; diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 7d23b92359..f7a52d7bd2 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -67,13 +67,15 @@ NTSTATUS smb1_file_se_access_check(const struct security_descriptor *sd, static NTSTATUS check_open_rights(struct connection_struct *conn, const char *fname, - uint32_t access_mask) + uint32_t access_mask, + uint32_t *access_granted) { /* Check if we have rights to open. */ NTSTATUS status; - uint32_t access_granted = 0; struct security_descriptor *sd; + *access_granted = 0; + status = SMB_VFS_GET_NT_ACL(conn, fname, (OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION | @@ -90,9 +92,17 @@ static NTSTATUS check_open_rights(struct connection_struct *conn, status = smb1_file_se_access_check(sd, conn->server_info->ptok, access_mask, - &access_granted); + access_granted); TALLOC_FREE(sd); + + DEBUG(10,("check_open_rights: file %s requesting " + "0x%x returning 0x%x (%s)\n", + fname, + (unsigned int)access_mask, + (unsigned int)*access_granted, + nt_errstr(status) )); + return status; } @@ -415,14 +425,49 @@ static NTSTATUS open_file(files_struct *fsp, } else { fsp->fh->fd = -1; /* What we used to call a stat open. */ if (file_existed) { + uint32_t access_granted = 0; + status = check_open_rights(conn, path, - access_mask); + access_mask, + &access_granted); if (!NT_STATUS_IS_OK(status)) { - DEBUG(10, ("open_file: Access denied on " - "file %s\n", - path)); - return status; + if (NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) { + if ((access_mask & DELETE_ACCESS) && + (access_granted == DELETE_ACCESS) && + can_delete_file_in_directory(conn, path)) { + /* Were we trying to do a stat open + * for delete and didn't get DELETE + * access (only) ? Check if the + * directory allows DELETE_CHILD. + * See here: + * http://blogs.msdn.com/oldnewthing/archive/2004/06/04/148426.aspx + * for details. */ + + DEBUG(10,("open_file: overrode ACCESS_DENIED " + "on file %s\n", + path )); + } else { + DEBUG(10, ("open_file: Access denied on " + "file %s\n", + path)); + return status; + } + } else if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND) && + fsp->posix_open && + S_ISLNK(psbuf->st_mode)) { + /* This is a POSIX stat open for delete + * or rename on a symlink that points + * nowhere. Allow. */ + DEBUG(10, ("open_file: allowing POSIX open " + "on bad symlink %s\n", + path )); + } else { + DEBUG(10, ("open_file: check_open_rights " + "on file %s returned %s\n", + path, nt_errstr(status) )); + return status; + } } } } @@ -2395,9 +2440,11 @@ static NTSTATUS open_directory(connection_struct *conn, } if (info == FILE_WAS_OPENED) { + uint32_t access_granted = 0; status = check_open_rights(conn, fname, - access_mask); + access_mask, + &access_granted); if (!NT_STATUS_IS_OK(status)) { DEBUG(10, ("open_directory: check_open_rights on " "file %s failed with %s\n", @@ -2826,8 +2873,11 @@ static NTSTATUS create_file_unixpath(connection_struct *conn, && (create_disposition != FILE_CREATE) && (share_access & FILE_SHARE_DELETE) && (access_mask & DELETE_ACCESS) - && (!can_delete_file_in_directory(conn, fname))) { + && (!(can_delete_file_in_directory(conn, fname) || + can_access_file_acl(conn, fname, DELETE_ACCESS)))) { status = NT_STATUS_ACCESS_DENIED; + DEBUG(10,("create_file_unixpath: open file %s " + "for delete ACCESS_DENIED\n", fname )); goto fail; } diff --git a/source3/smbd/oplock.c b/source3/smbd/oplock.c index e4b5016538..788d2f7238 100644 --- a/source3/smbd/oplock.c +++ b/source3/smbd/oplock.c @@ -32,61 +32,23 @@ int32 get_number_of_exclusive_open_oplocks(void) return exclusive_oplocks_open; } -/**************************************************************************** - Return True if an oplock message is pending. -****************************************************************************/ - -bool oplock_message_waiting(void) -{ - if (koplocks && koplocks->ops->msg_waiting(koplocks)) { - return True; - } - - return False; -} - -/**************************************************************************** - Find out if there are any kernel oplock messages waiting and process them - if so. pfds is the fd_set from the main select loop (which contains any - kernel oplock fd if that's what the system uses (IRIX). If may be NULL if - we're calling this in a shutting down state. -****************************************************************************/ - -void process_kernel_oplocks(struct messaging_context *msg_ctx) +/* + * helper function used by the kernel oplock backends to post the break message + */ +void break_kernel_oplock(struct messaging_context *msg_ctx, files_struct *fsp) { - /* - * We need to check for kernel oplocks before going into the select - * here, as the EINTR generated by the linux kernel oplock may have - * already been eaten. JRA. - */ - - if (!koplocks) { - return; - } + uint8_t msg[MSG_SMB_KERNEL_BREAK_SIZE]; - while (koplocks->ops->msg_waiting(koplocks)) { - files_struct *fsp; - char msg[MSG_SMB_KERNEL_BREAK_SIZE]; + /* Put the kernel break info into the message. */ + push_file_id_16((char *)msg, &fsp->file_id); + SIVAL(msg,16,fsp->fh->gen_id); - fsp = koplocks->ops->receive_message(koplocks); + /* Don't need to be root here as we're only ever + sending to ourselves. */ - if (fsp == NULL) { - DEBUG(3, ("Kernel oplock message announced, but none " - "received\n")); - return; - } - - /* Put the kernel break info into the message. */ - push_file_id_16(msg, &fsp->file_id); - SIVAL(msg,16,fsp->fh->gen_id); - - /* Don't need to be root here as we're only ever - sending to ourselves. */ - - messaging_send_buf(msg_ctx, procid_self(), - MSG_SMB_KERNEL_BREAK, - (uint8 *)&msg, MSG_SMB_KERNEL_BREAK_SIZE); - } + messaging_send_buf(msg_ctx, procid_self(), + MSG_SMB_KERNEL_BREAK, + msg, MSG_SMB_KERNEL_BREAK_SIZE); } /**************************************************************************** diff --git a/source3/smbd/oplock_irix.c b/source3/smbd/oplock_irix.c index 0cfa960425..d7f45e67de 100644 --- a/source3/smbd/oplock_irix.c +++ b/source3/smbd/oplock_irix.c @@ -252,13 +252,6 @@ static void irix_release_kernel_oplock(struct kernel_oplocks *_ctx, } } -static bool irix_oplock_msg_waiting(struct kernel_oplocks *_ctx) -{ - struct irix_oplocks_context *ctx = talloc_get_type(_ctx->private_data, - struct irix_oplocks_context); - return ctx->pending; -} - static void irix_oplocks_read_fde_handler(struct event_context *ev, struct fd_event *fde, uint16_t flags, @@ -266,10 +259,10 @@ static void irix_oplocks_read_fde_handler(struct event_context *ev, { struct irix_oplocks_context *ctx = talloc_get_type(private_data, struct irix_oplocks_context); + files_struct *fsp; - ctx->pending = true; - process_kernel_oplocks(smbd_messaging_context()); - ctx->pending = false; + fsp = irix_oplock_receive_message(ctx->ctx); + break_kernel_oplock(smbd_messaging_context(), fsp); } /**************************************************************************** @@ -277,10 +270,8 @@ static void irix_oplocks_read_fde_handler(struct event_context *ev, ****************************************************************************/ static const struct kernel_oplocks_ops irix_koplocks = { - .receive_message = irix_oplock_receive_message, .set_oplock = irix_set_kernel_oplock, .release_oplock = irix_release_kernel_oplock, - .msg_waiting = irix_oplock_msg_waiting }; struct kernel_oplocks *irix_init_kernel_oplocks(TALLOC_CTX *mem_ctx) diff --git a/source3/smbd/oplock_linux.c b/source3/smbd/oplock_linux.c index 8087167ff4..51cce0ed48 100644 --- a/source3/smbd/oplock_linux.c +++ b/source3/smbd/oplock_linux.c @@ -43,19 +43,6 @@ #define F_SETSIG 10 #endif -/**************************************************************************** - Handle a LEASE signal, incrementing the signals_received and blocking the signal. -****************************************************************************/ - -static void signal_handler(int sig, siginfo_t *info, void *unused) -{ - if (oplock_signals_received < FD_PENDING_SIZE - 1) { - fd_pending_array[oplock_signals_received] = (SIG_ATOMIC_T)info->si_fd; - oplock_signals_received++; - } /* Else signal is lost. */ - sys_select_signal(RT_SIGNAL_LEASE); -} - /* * public function to get linux lease capability. Needed by some VFS modules (eg. gpfs.c) */ @@ -101,24 +88,17 @@ int linux_setlease(int fd, int leasetype) * oplock break protocol. ****************************************************************************/ -static files_struct *linux_oplock_receive_message(struct kernel_oplocks *ctx) +static void linux_oplock_signal_handler(struct tevent_context *ev_ctx, + struct tevent_signal *se, + int signum, int count, + void *_info, void *private_data) { - int fd; + siginfo_t *info = (siginfo_t *)_info; + int fd = info->si_fd; files_struct *fsp; - BlockSignals(True, RT_SIGNAL_LEASE); - fd = fd_pending_array[0]; fsp = file_find_fd(fd); - fd_pending_array[0] = (SIG_ATOMIC_T)-1; - if (oplock_signals_received > 1) - memmove(CONST_DISCARD(void *, &fd_pending_array[0]), - CONST_DISCARD(void *, &fd_pending_array[1]), - sizeof(SIG_ATOMIC_T)*(oplock_signals_received-1)); - oplock_signals_received--; - /* now we can receive more signals */ - BlockSignals(False, RT_SIGNAL_LEASE); - - return fsp; + break_kernel_oplock(smbd_messaging_context(), fsp); } /**************************************************************************** @@ -180,15 +160,6 @@ static void linux_release_kernel_oplock(struct kernel_oplocks *ctx, } /**************************************************************************** - See if a oplock message is waiting. -****************************************************************************/ - -static bool linux_oplock_msg_waiting(struct kernel_oplocks *ctx) -{ - return oplock_signals_received != 0; -} - -/**************************************************************************** See if the kernel supports oplocks. ****************************************************************************/ @@ -208,16 +179,14 @@ static bool linux_oplocks_available(void) ****************************************************************************/ static const struct kernel_oplocks_ops linux_koplocks = { - .receive_message = linux_oplock_receive_message, .set_oplock = linux_set_kernel_oplock, .release_oplock = linux_release_kernel_oplock, - .msg_waiting = linux_oplock_msg_waiting }; struct kernel_oplocks *linux_init_kernel_oplocks(TALLOC_CTX *mem_ctx) { - struct sigaction act; struct kernel_oplocks *ctx; + struct tevent_signal *se; if (!linux_oplocks_available()) { DEBUG(3,("Linux kernel oplocks not available\n")); @@ -232,19 +201,18 @@ struct kernel_oplocks *linux_init_kernel_oplocks(TALLOC_CTX *mem_ctx) ctx->ops = &linux_koplocks; - ZERO_STRUCT(act); - - act.sa_handler = NULL; - act.sa_sigaction = signal_handler; - act.sa_flags = SA_SIGINFO; - sigemptyset( &act.sa_mask ); - if (sigaction(RT_SIGNAL_LEASE, &act, NULL) != 0) { - DEBUG(0,("Failed to setup RT_SIGNAL_LEASE handler\n")); + se = tevent_add_signal(smbd_event_context(), + ctx, + RT_SIGNAL_LEASE, SA_SIGINFO, + linux_oplock_signal_handler, + ctx); + if (!se) { + DEBUG(0,("Failed to setup RT_SIGNAL_LEASE handler")); + TALLOC_FREE(ctx); return NULL; } - /* the signal can start off blocked due to a bug in bash */ - BlockSignals(False, RT_SIGNAL_LEASE); + ctx->private_data = se; DEBUG(3,("Linux kernel oplocks enabled\n")); diff --git a/source3/smbd/pipes.c b/source3/smbd/pipes.c index b148cff045..f287adc92d 100644 --- a/source3/smbd/pipes.c +++ b/source3/smbd/pipes.c @@ -144,12 +144,18 @@ void reply_open_pipe_and_X(connection_struct *conn, struct smb_request *req) Reply to a write on a pipe. ****************************************************************************/ +struct pipe_write_state { + size_t numtowrite; +}; + +static void pipe_write_done(struct async_req *subreq); + void reply_pipe_write(struct smb_request *req) { files_struct *fsp = file_fsp(req, SVAL(req->vwv+0, 0)); - size_t numtowrite = SVAL(req->vwv+1, 0); - ssize_t nwritten; const uint8_t *data; + struct pipe_write_state *state; + struct async_req *subreq; if (!fsp_is_np(fsp)) { reply_doserror(req, ERRDOS, ERRbadfid); @@ -161,39 +167,59 @@ void reply_pipe_write(struct smb_request *req) return; } + state = talloc(req, struct pipe_write_state); + if (state == NULL) { + reply_nterror(req, NT_STATUS_NO_MEMORY); + return; + } + req->async_priv = state; + + state->numtowrite = SVAL(req->vwv+1, 0); + data = req->buf + 3; - if (numtowrite == 0) { - nwritten = 0; - } else { - NTSTATUS status; - if (!fsp_is_np(fsp)) { - reply_nterror(req, NT_STATUS_INVALID_HANDLE); - return; - } - DEBUG(6, ("reply_pipe_write: %x name: %s len: %d\n", - (int)fsp->fnum, fsp->fsp_name, (int)numtowrite)); - status = np_write(fsp->fake_file_handle, data, numtowrite, - &nwritten); - if (!NT_STATUS_IS_OK(status)) { - reply_nterror(req, status); - return; - } + DEBUG(6, ("reply_pipe_write: %x name: %s len: %d\n", (int)fsp->fnum, + fsp->fsp_name, (int)state->numtowrite)); + + subreq = np_write_send(state, smbd_event_context(), + fsp->fake_file_handle, data, state->numtowrite); + if (subreq == NULL) { + TALLOC_FREE(state); + reply_nterror(req, NT_STATUS_NO_MEMORY); + return; } + subreq->async.fn = pipe_write_done; + subreq->async.priv = talloc_move(req->conn, &req); +} + +static void pipe_write_done(struct async_req *subreq) +{ + struct smb_request *req = talloc_get_type_abort( + subreq->async.priv, struct smb_request); + struct pipe_write_state *state = talloc_get_type_abort( + req->async_priv, struct pipe_write_state); + NTSTATUS status; + ssize_t nwritten = -1; - if ((nwritten == 0 && numtowrite != 0) || (nwritten < 0)) { + status = np_write_recv(subreq, &nwritten); + TALLOC_FREE(subreq); + if ((nwritten == 0 && state->numtowrite != 0) || (nwritten < 0)) { reply_unixerror(req, ERRDOS, ERRnoaccess); - return; + goto send; } reply_outbuf(req, 1, 0); SSVAL(req->outbuf,smb_vwv0,nwritten); - - DEBUG(3,("write-IPC pnum=%04x nwritten=%d\n", fsp->fnum, - (int)nwritten)); - return; + DEBUG(3,("write-IPC nwritten=%d\n", (int)nwritten)); + + send: + if (!srv_send_smb(smbd_server_fd(), (char *)req->outbuf, + IS_CONN_ENCRYPTED(req->conn)||req->encrypted)) { + exit_server_cleanly("construct_reply: srv_send_smb failed."); + } + TALLOC_FREE(req); } /**************************************************************************** @@ -203,16 +229,20 @@ void reply_pipe_write(struct smb_request *req) wrinkles to handle pipes. ****************************************************************************/ +struct pipe_write_andx_state { + bool pipe_start_message_raw; + size_t numtowrite; +}; + +static void pipe_write_andx_done(struct async_req *subreq); + void reply_pipe_write_and_X(struct smb_request *req) { files_struct *fsp = file_fsp(req, SVAL(req->vwv+2, 0)); - size_t numtowrite = SVAL(req->vwv+10, 0); - ssize_t nwritten; int smb_doff = SVAL(req->vwv+11, 0); - bool pipe_start_message_raw = - ((SVAL(req->vwv+7, 0) & (PIPE_START_MESSAGE|PIPE_RAW_MODE)) - == (PIPE_START_MESSAGE|PIPE_RAW_MODE)); uint8_t *data; + struct pipe_write_andx_state *state; + struct async_req *subreq; if (!fsp_is_np(fsp)) { reply_doserror(req, ERRDOS, ERRbadfid); @@ -224,55 +254,76 @@ void reply_pipe_write_and_X(struct smb_request *req) return; } + state = talloc(req, struct pipe_write_andx_state); + if (state == NULL) { + reply_nterror(req, NT_STATUS_NO_MEMORY); + return; + } + req->async_priv = state; + + state->numtowrite = SVAL(req->vwv+10, 0); + state->pipe_start_message_raw = + ((SVAL(req->vwv+7, 0) & (PIPE_START_MESSAGE|PIPE_RAW_MODE)) + == (PIPE_START_MESSAGE|PIPE_RAW_MODE)); + DEBUG(6, ("reply_pipe_write_and_X: %x name: %s len: %d\n", - (int)fsp->fnum, fsp->fsp_name, (int)numtowrite)); + (int)fsp->fnum, fsp->fsp_name, (int)state->numtowrite)); data = (uint8_t *)smb_base(req->inbuf) + smb_doff; - if (numtowrite == 0) { - nwritten = 0; - } else { - NTSTATUS status; - - if(pipe_start_message_raw) { - /* - * For the start of a message in named pipe byte mode, - * the first two bytes are a length-of-pdu field. Ignore - * them (we don't trust the client). JRA. - */ - if(numtowrite < 2) { - DEBUG(0,("reply_pipe_write_and_X: start of " - "message set and not enough data " - "sent.(%u)\n", - (unsigned int)numtowrite )); - reply_unixerror(req, ERRDOS, ERRnoaccess); - return; - } - - data += 2; - numtowrite -= 2; - } - status = np_write(fsp->fake_file_handle, data, numtowrite, - &nwritten); - if (!NT_STATUS_IS_OK(status)) { - reply_nterror(req, status); + if (state->pipe_start_message_raw) { + /* + * For the start of a message in named pipe byte mode, + * the first two bytes are a length-of-pdu field. Ignore + * them (we don't trust the client). JRA. + */ + if (state->numtowrite < 2) { + DEBUG(0,("reply_pipe_write_and_X: start of message " + "set and not enough data sent.(%u)\n", + (unsigned int)state->numtowrite )); + reply_unixerror(req, ERRDOS, ERRnoaccess); return; } + + data += 2; + state->numtowrite -= 2; } - if ((nwritten == 0 && numtowrite != 0) || (nwritten < 0)) { - reply_unixerror(req, ERRDOS,ERRnoaccess); + subreq = np_write_send(state, smbd_event_context(), + fsp->fake_file_handle, data, state->numtowrite); + if (subreq == NULL) { + TALLOC_FREE(state); + reply_nterror(req, NT_STATUS_NO_MEMORY); return; } + subreq->async.fn = pipe_write_andx_done; + subreq->async.priv = talloc_move(req->conn, &req); +} + +static void pipe_write_andx_done(struct async_req *subreq) +{ + struct smb_request *req = talloc_get_type_abort( + subreq->async.priv, struct smb_request); + struct pipe_write_andx_state *state = talloc_get_type_abort( + req->async_priv, struct pipe_write_andx_state); + NTSTATUS status; + ssize_t nwritten = -1; + + status = np_write_recv(subreq, &nwritten); + TALLOC_FREE(subreq); + if (!NT_STATUS_IS_OK(status) || (nwritten != state->numtowrite)) { + reply_unixerror(req, ERRDOS,ERRnoaccess); + goto done; + } reply_outbuf(req, 6, 0); - nwritten = (pipe_start_message_raw ? nwritten + 2 : nwritten); + nwritten = (state->pipe_start_message_raw ? nwritten + 2 : nwritten); SSVAL(req->outbuf,smb_vwv2,nwritten); - - DEBUG(3,("writeX-IPC pnum=%04x nwritten=%d\n", fsp->fnum, - (int)nwritten)); + DEBUG(3,("writeX-IPC nwritten=%d\n", (int)nwritten)); + + done: chain_reply(req); } @@ -282,15 +333,20 @@ void reply_pipe_write_and_X(struct smb_request *req) wrinkles to handle pipes. ****************************************************************************/ +struct pipe_read_andx_state { + uint8_t *outbuf; + int smb_mincnt; + int smb_maxcnt; +}; + +static void pipe_read_andx_done(struct async_req *subreq); + void reply_pipe_read_and_X(struct smb_request *req) { files_struct *fsp = file_fsp(req, SVAL(req->vwv+0, 0)); - int smb_maxcnt = SVAL(req->vwv+5, 0); - int smb_mincnt = SVAL(req->vwv+6, 0); - ssize_t nread; uint8_t *data; - bool unused; - NTSTATUS status; + struct pipe_read_andx_state *state; + struct async_req *subreq; /* we don't use the offset given to use for pipe reads. This is deliberate, instead we always return the next lump of @@ -309,18 +365,56 @@ void reply_pipe_read_and_X(struct smb_request *req) return; } - reply_outbuf(req, 12, smb_maxcnt); + state = talloc(req, struct pipe_read_andx_state); + if (state == NULL) { + reply_nterror(req, NT_STATUS_NO_MEMORY); + return; + } + req->async_priv = state; + state->smb_maxcnt = SVAL(req->vwv+5, 0); + state->smb_mincnt = SVAL(req->vwv+6, 0); + + reply_outbuf(req, 12, state->smb_maxcnt); data = (uint8_t *)smb_buf(req->outbuf); - status = np_read(fsp->fake_file_handle, data, smb_maxcnt, &nread, - &unused); + /* + * We have to tell the upper layers that we're async. + */ + state->outbuf = req->outbuf; + req->outbuf = NULL; + + subreq = np_read_send(state, smbd_event_context(), + fsp->fake_file_handle, data, + state->smb_maxcnt); + if (subreq == NULL) { + reply_nterror(req, NT_STATUS_NO_MEMORY); + return; + } + subreq->async.fn = pipe_read_andx_done; + subreq->async.priv = talloc_move(req->conn, &req); +} +static void pipe_read_andx_done(struct async_req *subreq) +{ + struct smb_request *req = talloc_get_type_abort( + subreq->async.priv, struct smb_request); + struct pipe_read_andx_state *state = talloc_get_type_abort( + req->async_priv, struct pipe_read_andx_state); + NTSTATUS status; + ssize_t nread; + bool is_data_outstanding; + + status = np_read_recv(subreq, &nread, &is_data_outstanding); + TALLOC_FREE(subreq); if (!NT_STATUS_IS_OK(status)) { - reply_doserror(req, ERRDOS, ERRnoaccess); - return; + reply_nterror(req, status); + goto done; } + req->outbuf = state->outbuf; + state->outbuf = NULL; + srv_set_message((char *)req->outbuf, 12, nread, False); SSVAL(req->outbuf,smb_vwv5,nread); @@ -329,10 +423,11 @@ void reply_pipe_read_and_X(struct smb_request *req) + 1 /* the wct field */ + 12 * sizeof(uint16_t) /* vwv */ + 2); /* the buflen field */ - SSVAL(req->outbuf,smb_vwv11,smb_maxcnt); + SSVAL(req->outbuf,smb_vwv11,state->smb_maxcnt); - DEBUG(3,("readX-IPC pnum=%04x min=%d max=%d nread=%d\n", - fsp->fnum, smb_mincnt, smb_maxcnt, (int)nread)); + DEBUG(3,("readX-IPC min=%d max=%d nread=%d\n", + state->smb_mincnt, state->smb_maxcnt, (int)nread)); + done: chain_reply(req); } diff --git a/source3/smbd/posix_acls.c b/source3/smbd/posix_acls.c index 72f5c94bc5..7ea6e39fcb 100644 --- a/source3/smbd/posix_acls.c +++ b/source3/smbd/posix_acls.c @@ -1,7 +1,7 @@ /* Unix SMB/CIFS implementation. SMB NT Security Descriptor / Unix permission conversion. - Copyright (C) Jeremy Allison 1994-2000. + Copyright (C) Jeremy Allison 1994-2009. Copyright (C) Andreas Gruenbacher 2002. This program is free software; you can redistribute it and/or modify @@ -47,30 +47,65 @@ typedef struct canon_ace { enum ace_owner owner_type; enum ace_attribute attr; posix_id unix_ug; - bool inherited; + uint8_t ace_flags; /* From windows ACE entry. */ } canon_ace; #define ALL_ACE_PERMS (S_IRUSR|S_IWUSR|S_IXUSR) /* * EA format of user.SAMBA_PAI (Samba_Posix_Acl_Interitance) - * attribute on disk. + * attribute on disk - version 1. + * All values are little endian. * - * | 1 | 1 | 2 | 2 | .... + * | 1 | 1 | 2 | 2 | .... * +------+------+-------------+---------------------+-------------+--------------------+ * | vers | flag | num_entries | num_default_entries | ..entries.. | default_entries... | * +------+------+-------------+---------------------+-------------+--------------------+ + * + * Entry format is : + * + * | 1 | 4 | + * +------+-------------------+ + * | value| uid/gid or world | + * | type | value | + * +------+-------------------+ + * + * Version 2 format. Stores extra Windows metadata about an ACL. + * + * | 1 | 2 | 2 | 2 | .... + * +------+----------+-------------+---------------------+-------------+--------------------+ + * | vers | ace | num_entries | num_default_entries | ..entries.. | default_entries... | + * | 2 | type | | | | | + * +------+----------+-------------+---------------------+-------------+--------------------+ + * + * Entry format is : + * + * | 1 | 1 | 4 | + * +------+------+-------------------+ + * | ace | value| uid/gid or world | + * | flag | type | value | + * +------+-------------------+------+ + * */ -#define PAI_VERSION_OFFSET 0 -#define PAI_FLAG_OFFSET 1 -#define PAI_NUM_ENTRIES_OFFSET 2 -#define PAI_NUM_DEFAULT_ENTRIES_OFFSET 4 -#define PAI_ENTRIES_BASE 6 +#define PAI_VERSION_OFFSET 0 + +#define PAI_V1_FLAG_OFFSET 1 +#define PAI_V1_NUM_ENTRIES_OFFSET 2 +#define PAI_V1_NUM_DEFAULT_ENTRIES_OFFSET 4 +#define PAI_V1_ENTRIES_BASE 6 +#define PAI_V1_ACL_FLAG_PROTECTED 0x1 +#define PAI_V1_ENTRY_LENGTH 5 + +#define PAI_V1_VERSION 1 -#define PAI_VERSION 1 -#define PAI_ACL_FLAG_PROTECTED 0x1 -#define PAI_ENTRY_LENGTH 5 +#define PAI_V2_TYPE_OFFSET 1 +#define PAI_V2_NUM_ENTRIES_OFFSET 3 +#define PAI_V2_NUM_DEFAULT_ENTRIES_OFFSET 5 +#define PAI_V2_ENTRIES_BASE 7 +#define PAI_V2_ENTRY_LENGTH 6 + +#define PAI_V2_VERSION 2 /* * In memory format of user.SAMBA_PAI attribute. @@ -78,12 +113,13 @@ typedef struct canon_ace { struct pai_entry { struct pai_entry *next, *prev; + uint8_t ace_flags; enum ace_owner owner_type; posix_id unix_ug; }; struct pai_val { - bool pai_protected; + uint16_t sd_type; unsigned int num_entries; struct pai_entry *entry_list; unsigned int num_def_entries; @@ -94,19 +130,19 @@ struct pai_val { Return a uint32 of the pai_entry principal. ************************************************************************/ -static uint32 get_pai_entry_val(struct pai_entry *paie) +static uint32_t get_pai_entry_val(struct pai_entry *paie) { switch (paie->owner_type) { case UID_ACE: DEBUG(10,("get_pai_entry_val: uid = %u\n", (unsigned int)paie->unix_ug.uid )); - return (uint32)paie->unix_ug.uid; + return (uint32_t)paie->unix_ug.uid; case GID_ACE: DEBUG(10,("get_pai_entry_val: gid = %u\n", (unsigned int)paie->unix_ug.gid )); - return (uint32)paie->unix_ug.gid; + return (uint32_t)paie->unix_ug.gid; case WORLD_ACE: default: DEBUG(10,("get_pai_entry_val: world ace\n")); - return (uint32)-1; + return (uint32_t)-1; } } @@ -114,41 +150,30 @@ static uint32 get_pai_entry_val(struct pai_entry *paie) Return a uint32 of the entry principal. ************************************************************************/ -static uint32 get_entry_val(canon_ace *ace_entry) +static uint32_t get_entry_val(canon_ace *ace_entry) { switch (ace_entry->owner_type) { case UID_ACE: DEBUG(10,("get_entry_val: uid = %u\n", (unsigned int)ace_entry->unix_ug.uid )); - return (uint32)ace_entry->unix_ug.uid; + return (uint32_t)ace_entry->unix_ug.uid; case GID_ACE: DEBUG(10,("get_entry_val: gid = %u\n", (unsigned int)ace_entry->unix_ug.gid )); - return (uint32)ace_entry->unix_ug.gid; + return (uint32_t)ace_entry->unix_ug.gid; case WORLD_ACE: default: DEBUG(10,("get_entry_val: world ace\n")); - return (uint32)-1; + return (uint32_t)-1; } } /************************************************************************ - Count the inherited entries. -************************************************************************/ - -static unsigned int num_inherited_entries(canon_ace *ace_list) -{ - unsigned int num_entries = 0; - - for (; ace_list; ace_list = ace_list->next) - if (ace_list->inherited) - num_entries++; - return num_entries; -} - -/************************************************************************ - Create the on-disk format. Caller must free. + Create the on-disk format (always v2 now). Caller must free. ************************************************************************/ -static char *create_pai_buf(canon_ace *file_ace_list, canon_ace *dir_ace_list, bool pai_protected, size_t *store_size) +static char *create_pai_buf_v2(canon_ace *file_ace_list, + canon_ace *dir_ace_list, + uint16_t sd_type, + size_t *store_size) { char *pai_buf = NULL; canon_ace *ace_list = NULL; @@ -156,17 +181,18 @@ static char *create_pai_buf(canon_ace *file_ace_list, canon_ace *dir_ace_list, b unsigned int num_entries = 0; unsigned int num_def_entries = 0; - for (ace_list = file_ace_list; ace_list; ace_list = ace_list->next) - if (ace_list->inherited) - num_entries++; + for (ace_list = file_ace_list; ace_list; ace_list = ace_list->next) { + num_entries++; + } - for (ace_list = dir_ace_list; ace_list; ace_list = ace_list->next) - if (ace_list->inherited) - num_def_entries++; + for (ace_list = dir_ace_list; ace_list; ace_list = ace_list->next) { + num_def_entries++; + } - DEBUG(10,("create_pai_buf: num_entries = %u, num_def_entries = %u\n", num_entries, num_def_entries )); + DEBUG(10,("create_pai_buf_v2: num_entries = %u, num_def_entries = %u\n", num_entries, num_def_entries )); - *store_size = PAI_ENTRIES_BASE + ((num_entries + num_def_entries)*PAI_ENTRY_LENGTH); + *store_size = PAI_V2_ENTRIES_BASE + + ((num_entries + num_def_entries)*PAI_V2_ENTRY_LENGTH); pai_buf = (char *)SMB_MALLOC(*store_size); if (!pai_buf) { @@ -174,34 +200,32 @@ static char *create_pai_buf(canon_ace *file_ace_list, canon_ace *dir_ace_list, b } /* Set up the header. */ - memset(pai_buf, '\0', PAI_ENTRIES_BASE); - SCVAL(pai_buf,PAI_VERSION_OFFSET,PAI_VERSION); - SCVAL(pai_buf,PAI_FLAG_OFFSET,(pai_protected ? PAI_ACL_FLAG_PROTECTED : 0)); - SSVAL(pai_buf,PAI_NUM_ENTRIES_OFFSET,num_entries); - SSVAL(pai_buf,PAI_NUM_DEFAULT_ENTRIES_OFFSET,num_def_entries); + memset(pai_buf, '\0', PAI_V2_ENTRIES_BASE); + SCVAL(pai_buf,PAI_VERSION_OFFSET,PAI_V2_VERSION); + SSVAL(pai_buf,PAI_V2_TYPE_OFFSET, sd_type); + SSVAL(pai_buf,PAI_V2_NUM_ENTRIES_OFFSET,num_entries); + SSVAL(pai_buf,PAI_V2_NUM_DEFAULT_ENTRIES_OFFSET,num_def_entries); - entry_offset = pai_buf + PAI_ENTRIES_BASE; + entry_offset = pai_buf + PAI_V2_ENTRIES_BASE; for (ace_list = file_ace_list; ace_list; ace_list = ace_list->next) { - if (ace_list->inherited) { - uint8 type_val = (unsigned char)ace_list->owner_type; - uint32 entry_val = get_entry_val(ace_list); + uint8_t type_val = (uint8_t)ace_list->owner_type; + uint32_t entry_val = get_entry_val(ace_list); - SCVAL(entry_offset,0,type_val); - SIVAL(entry_offset,1,entry_val); - entry_offset += PAI_ENTRY_LENGTH; - } + SCVAL(entry_offset,0,ace_list->ace_flags); + SCVAL(entry_offset,1,type_val); + SIVAL(entry_offset,2,entry_val); + entry_offset += PAI_V2_ENTRY_LENGTH; } for (ace_list = dir_ace_list; ace_list; ace_list = ace_list->next) { - if (ace_list->inherited) { - uint8 type_val = (unsigned char)ace_list->owner_type; - uint32 entry_val = get_entry_val(ace_list); + uint8_t type_val = (uint8_t)ace_list->owner_type; + uint32_t entry_val = get_entry_val(ace_list); - SCVAL(entry_offset,0,type_val); - SIVAL(entry_offset,1,entry_val); - entry_offset += PAI_ENTRY_LENGTH; - } + SCVAL(entry_offset,0,ace_list->ace_flags); + SCVAL(entry_offset,1,type_val); + SIVAL(entry_offset,2,entry_val); + entry_offset += PAI_V2_ENTRY_LENGTH; } return pai_buf; @@ -211,44 +235,39 @@ static char *create_pai_buf(canon_ace *file_ace_list, canon_ace *dir_ace_list, b Store the user.SAMBA_PAI attribute on disk. ************************************************************************/ -static void store_inheritance_attributes(files_struct *fsp, canon_ace *file_ace_list, - canon_ace *dir_ace_list, bool pai_protected) +static void store_inheritance_attributes(files_struct *fsp, + canon_ace *file_ace_list, + canon_ace *dir_ace_list, + uint16_t sd_type) { int ret; size_t store_size; char *pai_buf; - if (!lp_map_acl_inherit(SNUM(fsp->conn))) - return; - - /* - * Don't store if this ACL isn't protected and - * none of the entries in it are marked as inherited. - */ - - if (!pai_protected && num_inherited_entries(file_ace_list) == 0 && num_inherited_entries(dir_ace_list) == 0) { - /* Instead just remove the attribute if it exists. */ - if (fsp->fh->fd != -1) - SMB_VFS_FREMOVEXATTR(fsp, SAMBA_POSIX_INHERITANCE_EA_NAME); - else - SMB_VFS_REMOVEXATTR(fsp->conn, fsp->fsp_name, SAMBA_POSIX_INHERITANCE_EA_NAME); + if (!lp_map_acl_inherit(SNUM(fsp->conn))) { return; } - pai_buf = create_pai_buf(file_ace_list, dir_ace_list, pai_protected, &store_size); + pai_buf = create_pai_buf_v2(file_ace_list, dir_ace_list, + sd_type, &store_size); - if (fsp->fh->fd != -1) + if (fsp->fh->fd != -1) { ret = SMB_VFS_FSETXATTR(fsp, SAMBA_POSIX_INHERITANCE_EA_NAME, pai_buf, store_size, 0); - else + } else { ret = SMB_VFS_SETXATTR(fsp->conn,fsp->fsp_name, SAMBA_POSIX_INHERITANCE_EA_NAME, pai_buf, store_size, 0); + } SAFE_FREE(pai_buf); - DEBUG(10,("store_inheritance_attribute:%s for file %s\n", pai_protected ? " (protected)" : "", fsp->fsp_name)); - if (ret == -1 && !no_acl_syscall_error(errno)) + DEBUG(10,("store_inheritance_attribute: type 0x%x for file %s\n", + (unsigned int)sd_type, + fsp->fsp_name)); + + if (ret == -1 && !no_acl_syscall_error(errno)) { DEBUG(1,("store_inheritance_attribute: Error %s\n", strerror(errno) )); + } } /************************************************************************ @@ -272,161 +291,290 @@ static void free_inherited_info(struct pai_val *pal) } /************************************************************************ - Was this ACL protected ? -************************************************************************/ - -static bool get_protected_flag(struct pai_val *pal) -{ - if (!pal) - return False; - return pal->pai_protected; -} - -/************************************************************************ - Was this ACE inherited ? + Get any stored ACE flags. ************************************************************************/ -static bool get_inherited_flag(struct pai_val *pal, canon_ace *ace_entry, bool default_ace) +static uint16_t get_pai_flags(struct pai_val *pal, canon_ace *ace_entry, bool default_ace) { struct pai_entry *paie; - if (!pal) - return False; + if (!pal) { + return 0; + } /* If the entry exists it is inherited. */ for (paie = (default_ace ? pal->def_entry_list : pal->entry_list); paie; paie = paie->next) { if (ace_entry->owner_type == paie->owner_type && get_entry_val(ace_entry) == get_pai_entry_val(paie)) - return True; + return paie->ace_flags; } - return False; + return 0; } /************************************************************************ - Ensure an attribute just read is valid. + Ensure an attribute just read is valid - v1. ************************************************************************/ -static bool check_pai_ok(char *pai_buf, size_t pai_buf_data_size) +static bool check_pai_ok_v1(const char *pai_buf, size_t pai_buf_data_size) { uint16 num_entries; uint16 num_def_entries; - if (pai_buf_data_size < PAI_ENTRIES_BASE) { + if (pai_buf_data_size < PAI_V1_ENTRIES_BASE) { /* Corrupted - too small. */ - return False; + return false; } - if (CVAL(pai_buf,PAI_VERSION_OFFSET) != PAI_VERSION) - return False; + if (CVAL(pai_buf,PAI_VERSION_OFFSET) != PAI_V1_VERSION) { + return false; + } - num_entries = SVAL(pai_buf,PAI_NUM_ENTRIES_OFFSET); - num_def_entries = SVAL(pai_buf,PAI_NUM_DEFAULT_ENTRIES_OFFSET); + num_entries = SVAL(pai_buf,PAI_V1_NUM_ENTRIES_OFFSET); + num_def_entries = SVAL(pai_buf,PAI_V1_NUM_DEFAULT_ENTRIES_OFFSET); /* Check the entry lists match. */ /* Each entry is 5 bytes (type plus 4 bytes of uid or gid). */ - if (((num_entries + num_def_entries)*PAI_ENTRY_LENGTH) + PAI_ENTRIES_BASE != pai_buf_data_size) - return False; + if (((num_entries + num_def_entries)*PAI_V1_ENTRY_LENGTH) + + PAI_V1_ENTRIES_BASE != pai_buf_data_size) { + return false; + } - return True; + return true; +} + +/************************************************************************ + Ensure an attribute just read is valid - v2. +************************************************************************/ + +static bool check_pai_ok_v2(const char *pai_buf, size_t pai_buf_data_size) +{ + uint16 num_entries; + uint16 num_def_entries; + + if (pai_buf_data_size < PAI_V2_ENTRIES_BASE) { + /* Corrupted - too small. */ + return false; + } + + if (CVAL(pai_buf,PAI_VERSION_OFFSET) != PAI_V2_VERSION) { + return false; + } + + num_entries = SVAL(pai_buf,PAI_V2_NUM_ENTRIES_OFFSET); + num_def_entries = SVAL(pai_buf,PAI_V2_NUM_DEFAULT_ENTRIES_OFFSET); + + /* Check the entry lists match. */ + /* Each entry is 6 bytes (flags + type + 4 bytes of uid or gid). */ + + if (((num_entries + num_def_entries)*PAI_V2_ENTRY_LENGTH) + + PAI_V2_ENTRIES_BASE != pai_buf_data_size) { + return false; + } + + return true; } +/************************************************************************ + Decode the owner. +************************************************************************/ + +static bool get_pai_owner_type(struct pai_entry *paie, const char *entry_offset) +{ + paie->owner_type = (enum ace_owner)CVAL(entry_offset,0); + switch( paie->owner_type) { + case UID_ACE: + paie->unix_ug.uid = (uid_t)IVAL(entry_offset,1); + DEBUG(10,("get_pai_owner_type: uid = %u\n", + (unsigned int)paie->unix_ug.uid )); + break; + case GID_ACE: + paie->unix_ug.gid = (gid_t)IVAL(entry_offset,1); + DEBUG(10,("get_pai_owner_type: gid = %u\n", + (unsigned int)paie->unix_ug.gid )); + break; + case WORLD_ACE: + paie->unix_ug.world = -1; + DEBUG(10,("get_pai_owner_type: world ace\n")); + break; + default: + return false; + } + return true; +} /************************************************************************ - Convert to in-memory format. + Process v2 entries. ************************************************************************/ -static struct pai_val *create_pai_val(char *buf, size_t size) +static const char *create_pai_v1_entries(struct pai_val *paiv, + const char *entry_offset, + bool def_entry) { - char *entry_offset; - struct pai_val *paiv = NULL; int i; - if (!check_pai_ok(buf, size)) + for (i = 0; i < paiv->num_entries; i++) { + struct pai_entry *paie = SMB_MALLOC_P(struct pai_entry); + if (!paie) { + return NULL; + } + + paie->ace_flags = SEC_ACE_FLAG_INHERITED_ACE; + if (!get_pai_owner_type(paie, entry_offset)) { + return NULL; + } + + if (!def_entry) { + DLIST_ADD(paiv->entry_list, paie); + } else { + DLIST_ADD(paiv->def_entry_list, paie); + } + entry_offset += PAI_V1_ENTRY_LENGTH; + } + return entry_offset; +} + +/************************************************************************ + Convert to in-memory format from version 1. +************************************************************************/ + +static struct pai_val *create_pai_val_v1(const char *buf, size_t size) +{ + const char *entry_offset; + struct pai_val *paiv = NULL; + + if (!check_pai_ok_v1(buf, size)) { return NULL; + } paiv = SMB_MALLOC_P(struct pai_val); - if (!paiv) + if (!paiv) { return NULL; + } memset(paiv, '\0', sizeof(struct pai_val)); - paiv->pai_protected = (CVAL(buf,PAI_FLAG_OFFSET) == PAI_ACL_FLAG_PROTECTED); + paiv->sd_type = (CVAL(buf,PAI_V1_FLAG_OFFSET) == PAI_V1_ACL_FLAG_PROTECTED) ? + SE_DESC_DACL_PROTECTED : 0; - paiv->num_entries = SVAL(buf,PAI_NUM_ENTRIES_OFFSET); - paiv->num_def_entries = SVAL(buf,PAI_NUM_DEFAULT_ENTRIES_OFFSET); + paiv->num_entries = SVAL(buf,PAI_V1_NUM_ENTRIES_OFFSET); + paiv->num_def_entries = SVAL(buf,PAI_V1_NUM_DEFAULT_ENTRIES_OFFSET); - entry_offset = buf + PAI_ENTRIES_BASE; + entry_offset = buf + PAI_V1_ENTRIES_BASE; - DEBUG(10,("create_pai_val:%s num_entries = %u, num_def_entries = %u\n", - paiv->pai_protected ? " (pai_protected)" : "", paiv->num_entries, paiv->num_def_entries )); + DEBUG(10,("create_pai_val: num_entries = %u, num_def_entries = %u\n", + paiv->num_entries, paiv->num_def_entries )); - for (i = 0; i < paiv->num_entries; i++) { - struct pai_entry *paie; + entry_offset = create_pai_v1_entries(paiv, entry_offset, false); + if (entry_offset == NULL) { + free_inherited_info(paiv); + return NULL; + } + entry_offset = create_pai_v1_entries(paiv, entry_offset, true); + if (entry_offset == NULL) { + free_inherited_info(paiv); + return NULL; + } + + return paiv; +} + +/************************************************************************ + Process v2 entries. +************************************************************************/ + +static const char *create_pai_v2_entries(struct pai_val *paiv, + const char *entry_offset, + bool def_entry) +{ + int i; - paie = SMB_MALLOC_P(struct pai_entry); + for (i = 0; i < paiv->num_entries; i++) { + struct pai_entry *paie = SMB_MALLOC_P(struct pai_entry); if (!paie) { - free_inherited_info(paiv); return NULL; } - paie->owner_type = (enum ace_owner)CVAL(entry_offset,0); - switch( paie->owner_type) { - case UID_ACE: - paie->unix_ug.uid = (uid_t)IVAL(entry_offset,1); - DEBUG(10,("create_pai_val: uid = %u\n", (unsigned int)paie->unix_ug.uid )); - break; - case GID_ACE: - paie->unix_ug.gid = (gid_t)IVAL(entry_offset,1); - DEBUG(10,("create_pai_val: gid = %u\n", (unsigned int)paie->unix_ug.gid )); - break; - case WORLD_ACE: - paie->unix_ug.world = -1; - DEBUG(10,("create_pai_val: world ace\n")); - break; - default: - free_inherited_info(paiv); - return NULL; - } - entry_offset += PAI_ENTRY_LENGTH; - DLIST_ADD(paiv->entry_list, paie); - } + paie->ace_flags = CVAL(entry_offset,0); - for (i = 0; i < paiv->num_def_entries; i++) { - struct pai_entry *paie; + entry_offset++; - paie = SMB_MALLOC_P(struct pai_entry); - if (!paie) { - free_inherited_info(paiv); + if (!get_pai_owner_type(paie, entry_offset)) { return NULL; } - - paie->owner_type = (enum ace_owner)CVAL(entry_offset,0); - switch( paie->owner_type) { - case UID_ACE: - paie->unix_ug.uid = (uid_t)IVAL(entry_offset,1); - DEBUG(10,("create_pai_val: (def) uid = %u\n", (unsigned int)paie->unix_ug.uid )); - break; - case GID_ACE: - paie->unix_ug.gid = (gid_t)IVAL(entry_offset,1); - DEBUG(10,("create_pai_val: (def) gid = %u\n", (unsigned int)paie->unix_ug.gid )); - break; - case WORLD_ACE: - paie->unix_ug.world = -1; - DEBUG(10,("create_pai_val: (def) world ace\n")); - break; - default: - free_inherited_info(paiv); - return NULL; + if (!def_entry) { + DLIST_ADD(paiv->entry_list, paie); + } else { + DLIST_ADD(paiv->def_entry_list, paie); } - entry_offset += PAI_ENTRY_LENGTH; - DLIST_ADD(paiv->def_entry_list, paie); + entry_offset += PAI_V2_ENTRY_LENGTH; + } + return entry_offset; +} + +/************************************************************************ + Convert to in-memory format from version 2. +************************************************************************/ + +static struct pai_val *create_pai_val_v2(const char *buf, size_t size) +{ + const char *entry_offset; + struct pai_val *paiv = NULL; + + if (!check_pai_ok_v2(buf, size)) { + return NULL; + } + + paiv = SMB_MALLOC_P(struct pai_val); + if (!paiv) { + return NULL; + } + + memset(paiv, '\0', sizeof(struct pai_val)); + + paiv->sd_type = SVAL(buf,PAI_V2_TYPE_OFFSET); + + paiv->num_entries = SVAL(buf,PAI_V2_NUM_ENTRIES_OFFSET); + paiv->num_def_entries = SVAL(buf,PAI_V2_NUM_DEFAULT_ENTRIES_OFFSET); + + entry_offset = buf + PAI_V2_ENTRIES_BASE; + + DEBUG(10,("create_pai_val_v2: num_entries = %u, num_def_entries = %u\n", + paiv->num_entries, paiv->num_def_entries )); + + entry_offset = create_pai_v2_entries(paiv, entry_offset, false); + if (entry_offset == NULL) { + free_inherited_info(paiv); + return NULL; + } + entry_offset = create_pai_v2_entries(paiv, entry_offset, true); + if (entry_offset == NULL) { + free_inherited_info(paiv); + return NULL; } return paiv; } /************************************************************************ + Convert to in-memory format - from either version 1 or 2. +************************************************************************/ + +static struct pai_val *create_pai_val(const char *buf, size_t size) +{ + if (size < 1) { + return NULL; + } + if (CVAL(buf,PAI_VERSION_OFFSET) == PAI_V1_VERSION) { + return create_pai_val_v1(buf, size); + } else if (CVAL(buf,PAI_VERSION_OFFSET) == PAI_V2_VERSION) { + return create_pai_val_v2(buf, size); + } else { + return NULL; + } +} + +/************************************************************************ Load the user.SAMBA_PAI attribute. ************************************************************************/ @@ -437,19 +585,22 @@ static struct pai_val *fload_inherited_info(files_struct *fsp) struct pai_val *paiv = NULL; ssize_t ret; - if (!lp_map_acl_inherit(SNUM(fsp->conn))) + if (!lp_map_acl_inherit(SNUM(fsp->conn))) { return NULL; + } - if ((pai_buf = (char *)SMB_MALLOC(pai_buf_size)) == NULL) + if ((pai_buf = (char *)SMB_MALLOC(pai_buf_size)) == NULL) { return NULL; + } do { - if (fsp->fh->fd != -1) + if (fsp->fh->fd != -1) { ret = SMB_VFS_FGETXATTR(fsp, SAMBA_POSIX_INHERITANCE_EA_NAME, pai_buf, pai_buf_size); - else + } else { ret = SMB_VFS_GETXATTR(fsp->conn,fsp->fsp_name,SAMBA_POSIX_INHERITANCE_EA_NAME, pai_buf, pai_buf_size); + } if (ret == -1) { if (errno != ERANGE) { @@ -483,8 +634,11 @@ static struct pai_val *fload_inherited_info(files_struct *fsp) paiv = create_pai_val(pai_buf, ret); - if (paiv && paiv->pai_protected) - DEBUG(10,("load_inherited_info: ACL is protected for file %s\n", fsp->fsp_name)); + if (paiv) { + DEBUG(10,("load_inherited_info: ACL type is 0x%x for file %s\n", + (unsigned int)paiv->sd_type, + fsp->fsp_name)); + } SAFE_FREE(pai_buf); return paiv; @@ -547,8 +701,10 @@ static struct pai_val *load_inherited_info(const struct connection_struct *conn, paiv = create_pai_val(pai_buf, ret); - if (paiv && paiv->pai_protected) { - DEBUG(10,("load_inherited_info: ACL is protected for file %s\n", fname)); + if (paiv) { + DEBUG(10,("load_inherited_info: ACL type 0x%x for file %s\n", + (unsigned int)paiv->sd_type, + fname)); } SAFE_FREE(pai_buf); @@ -641,8 +797,8 @@ static void print_canon_ace(canon_ace *pace, int num) dbgtext( "MASK " ); break; } - if (pace->inherited) - dbgtext( "(inherited) "); + + dbgtext( "ace_flags = 0x%x ", (unsigned int)pace->ace_flags); dbgtext( "perms "); dbgtext( "%c", pace->perms & S_IRUSR ? 'r' : '-'); dbgtext( "%c", pace->perms & S_IWUSR ? 'w' : '-'); @@ -1519,7 +1675,9 @@ static bool create_canon_ace_lists(files_struct *fsp, current_ace->perms |= map_nt_perms( &psa->access_mask, S_IRUSR); current_ace->attr = (psa->type == SEC_ACE_TYPE_ACCESS_ALLOWED) ? ALLOW_ACE : DENY_ACE; - current_ace->inherited = ((psa->flags & SEC_ACE_FLAG_INHERITED_ACE) ? True : False); + + /* Store the ace_flag. */ + current_ace->ace_flags = psa->flags; /* * Now add the created ace to either the file list, the directory @@ -2160,7 +2318,7 @@ static void arrange_posix_perms(const char *filename, canon_ace **pp_list_head) other_ace = ace; } } - + if (!owner_ace || !other_ace) { DEBUG(0,("arrange_posix_perms: Invalid POSIX permissions for file %s, missing owner or other.\n", filename )); @@ -2184,7 +2342,7 @@ static void arrange_posix_perms(const char *filename, canon_ace **pp_list_head) *pp_list_head = list_head; } - + /**************************************************************************** Create a linked list of canonical ACE entries. ****************************************************************************/ @@ -2297,7 +2455,7 @@ static canon_ace *canonicalise_acl(struct connection_struct *conn, ace->trustee = sid; ace->unix_ug = unix_ug; ace->owner_type = owner_type; - ace->inherited = get_inherited_flag(pal, ace, (the_acl_type == SMB_ACL_TYPE_DEFAULT)); + ace->ace_flags = get_pai_flags(pal, ace, (the_acl_type == SMB_ACL_TYPE_DEFAULT)); DLIST_ADD(list_head, ace); } @@ -2968,8 +3126,7 @@ static NTSTATUS posix_get_nt_acl_common(struct connection_struct *conn, &ace->trustee, nt_acl_type, acc, - ace->inherited ? - SEC_ACE_FLAG_INHERITED_ACE : 0); + ace->ace_flags); } /* The User must have access to a profile share - even @@ -2990,11 +3147,10 @@ static NTSTATUS posix_get_nt_acl_common(struct connection_struct *conn, &ace->trustee, nt_acl_type, acc, + ace->ace_flags | SEC_ACE_FLAG_OBJECT_INHERIT| SEC_ACE_FLAG_CONTAINER_INHERIT| - SEC_ACE_FLAG_INHERIT_ONLY| - (ace->inherited ? - SEC_ACE_FLAG_INHERITED_ACE : 0)); + SEC_ACE_FLAG_INHERIT_ONLY); } /* The User must have access to a profile share - even @@ -3045,8 +3201,10 @@ static NTSTATUS posix_get_nt_acl_common(struct connection_struct *conn, * flag doesn't seem to bother Windows NT. * Always set this if map acl inherit is turned off. */ - if (get_protected_flag(pal) || !lp_map_acl_inherit(SNUM(conn))) { - psd->type |= SE_DESC_DACL_PROTECTED; + if (pal == NULL || !lp_map_acl_inherit(SNUM(conn))) { + psd->type |= SEC_DESC_DACL_PROTECTED; + } else { + psd->type |= pal->sd_type; } if (psd->dacl) { @@ -3236,7 +3394,7 @@ NTSTATUS append_parent_acl(files_struct *fsp, int info; unsigned int i, j; SEC_DESC *psd = dup_sec_desc(talloc_tos(), pcsd); - bool is_dacl_protected = (pcsd->type & SE_DESC_DACL_PROTECTED); + bool is_dacl_protected = (pcsd->type & SEC_DESC_DACL_PROTECTED); ZERO_STRUCT(sbuf); @@ -3617,8 +3775,10 @@ NTSTATUS set_nt_acl(files_struct *fsp, uint32 security_info_sent, const SEC_DESC if (set_acl_as_root) { become_root(); } - store_inheritance_attributes(fsp, file_ace_list, dir_ace_list, - (psd->type & SE_DESC_DACL_PROTECTED) ? True : False); + store_inheritance_attributes(fsp, + file_ace_list, + dir_ace_list, + psd->type); if (set_acl_as_root) { unbecome_root(); } diff --git a/source3/smbd/process.c b/source3/smbd/process.c index a025bb4197..c9fc1fbb6a 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -692,57 +692,55 @@ struct idle_event *event_add_idle(struct event_context *event_ctx, return result; } -/**************************************************************************** - Do all async processing in here. This includes kernel oplock messages, change - notify events etc. -****************************************************************************/ - -static void async_processing(void) +static void smbd_sig_term_handler(struct tevent_context *ev, + struct tevent_signal *se, + int signum, + int count, + void *siginfo, + void *private_data) { - DEBUG(10,("async_processing: Doing async processing.\n")); - - process_aio_queue(); - - process_kernel_oplocks(smbd_messaging_context()); - - /* Do the aio check again after receive_local_message as it does a - select and may have eaten our signal. */ - /* Is this till true? -- vl */ - process_aio_queue(); + exit_server_cleanly("termination signal"); +} - if (got_sig_term) { - exit_server_cleanly("termination signal"); - } +void smbd_setup_sig_term_handler(void) +{ + struct tevent_signal *se; - /* check for sighup processing */ - if (reload_after_sighup) { - change_to_root_user(); - DEBUG(1,("Reloading services after SIGHUP\n")); - reload_services(False); - reload_after_sighup = 0; + se = tevent_add_signal(smbd_event_context(), + smbd_event_context(), + SIGTERM, 0, + smbd_sig_term_handler, + NULL); + if (!se) { + exit_server("failed to setup SIGTERM handler"); } } -/**************************************************************************** - Do a select on an two fd's - with timeout. - - If a local udp message has been pushed onto the - queue (this can only happen during oplock break - processing) call async_processing() - - If a pending smb message has been pushed onto the - queue (this can only happen during oplock break - processing) return this next. +static void smbd_sig_hup_handler(struct tevent_context *ev, + struct tevent_signal *se, + int signum, + int count, + void *siginfo, + void *private_data) +{ + change_to_root_user(); + DEBUG(1,("Reloading services after SIGHUP\n")); + reload_services(False); +} - If the first smbfd is ready then read an smb from it. - if the second (loopback UDP) fd is ready then read a message - from it and setup the buffer header to identify the length - and from address. - Returns False on timeout or error. - Else returns True. +void smbd_setup_sig_hup_handler(void) +{ + struct tevent_signal *se; -The timeout is in milliseconds -****************************************************************************/ + se = tevent_add_signal(smbd_event_context(), + smbd_event_context(), + SIGHUP, 0, + smbd_sig_hup_handler, + NULL); + if (!se) { + exit_server("failed to setup SIGHUP handler"); + } +} static NTSTATUS smbd_server_connection_loop_once(struct smbd_server_connection *conn) { @@ -762,26 +760,6 @@ static NTSTATUS smbd_server_connection_loop_once(struct smbd_server_connection * FD_ZERO(&w_fds); /* - * Ensure we process oplock break messages by preference. - * We have to do this before the select, after the select - * and if the select returns EINTR. This is due to the fact - * that the selects called from async_processing can eat an EINTR - * caused by a signal (we can't take the break message there). - * This is hideously complex - *MUST* be simplified for 3.0 ! JRA. - */ - - if (oplock_message_waiting()) { - DEBUG(10,("receive_message_or_smb: oplock_message is waiting.\n")); - async_processing(); - /* - * After async processing we must go and do the select again, as - * the state of the flag in fds for the server file descriptor is - * indeterminate - we may have done I/O on it in the oplock processing. JRA. - */ - return NT_STATUS_RETRY; - } - - /* * Are there any timed events waiting ? If so, ensure we don't * select for longer than it would take to wait for them. */ @@ -814,20 +792,6 @@ static NTSTATUS smbd_server_connection_loop_once(struct smbd_server_connection * return NT_STATUS_RETRY; } - /* if we get EINTR then maybe we have received an oplock - signal - treat this as select returning 1. This is ugly, but - is the best we can do until the oplock code knows more about - signals */ - if (selrtn == -1 && errno == EINTR) { - async_processing(); - /* - * After async processing we must go and do the select again, as - * the state of the flag in fds for the server file descriptor is - * indeterminate - we may have done I/O on it in the oplock processing. JRA. - */ - return NT_STATUS_RETRY; - } - /* Check if error */ if (selrtn == -1) { /* something is wrong. Maybe the socket is dead? */ @@ -866,31 +830,6 @@ NTSTATUS allow_new_trans(struct trans_state *list, int mid) return NT_STATUS_OK; } -/**************************************************************************** - We're terminating and have closed all our files/connections etc. - If there are any pending local messages we need to respond to them - before termination so that other smbds don't think we just died whilst - holding oplocks. -****************************************************************************/ - -void respond_to_all_remaining_local_messages(void) -{ - /* - * Assert we have no exclusive open oplocks. - */ - - if(get_number_of_exclusive_open_oplocks()) { - DEBUG(0,("respond_to_all_remaining_local_messages: PANIC : we have %d exclusive oplocks.\n", - get_number_of_exclusive_open_oplocks() )); - return; - } - - process_kernel_oplocks(smbd_messaging_context()); - - return; -} - - /* These flags determine some of the permissions required to do an operation @@ -1420,8 +1359,6 @@ static void construct_reply(char *inbuf, int size, size_t unread_bytes, bool enc connection_struct *conn; struct smb_request *req; - chain_size = 0; - if (!(req = talloc(talloc_tos(), struct smb_request))) { smb_panic("could not allocate smb_request"); } @@ -1830,9 +1767,8 @@ void check_reload(time_t t) mypid = getpid(); } - if (reload_after_sighup || (t >= last_smb_conf_reload_time+SMBD_RELOAD_CHECK)) { + if (t >= last_smb_conf_reload_time+SMBD_RELOAD_CHECK) { reload_services(True); - reload_after_sighup = False; last_smb_conf_reload_time = t; } @@ -1903,12 +1839,135 @@ static void smbd_server_connection_handler(struct event_context *ev, } } + +/**************************************************************************** +received when we should release a specific IP +****************************************************************************/ +static void release_ip(const char *ip, void *priv) +{ + 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)); + /* note we must exit with non-zero status so the unclean handler gets + called in the parent, so that the brl database is tickled */ + _exit(1); + } +} + +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) +{ + release_ip((char *)data->data, NULL); +} + +#ifdef CLUSTER_SUPPORT +static int client_get_tcp_info(struct sockaddr_storage *server, + struct sockaddr_storage *client) +{ + socklen_t length; + if (server_fd == -1) { + return -1; + } + length = sizeof(*server); + if (getsockname(server_fd, (struct sockaddr *)server, &length) != 0) { + return -1; + } + length = sizeof(*client); + if (getpeername(server_fd, (struct sockaddr *)client, &length) != 0) { + return -1; + } + return 0; +} +#endif + +/* + * Send keepalive packets to our client + */ +static bool keepalive_fn(const struct timeval *now, void *private_data) +{ + if (!send_keepalive(smbd_server_fd())) { + DEBUG( 2, ( "Keepalive failed - exiting.\n" ) ); + return False; + } + return True; +} + +/* + * Do the recurring check if we're idle + */ +static bool deadtime_fn(const struct timeval *now, void *private_data) +{ + if ((conn_num_open() == 0) + || (conn_idle_all(now->tv_sec))) { + DEBUG( 2, ( "Closing idle connection\n" ) ); + messaging_send(smbd_messaging_context(), procid_self(), + MSG_SHUTDOWN, &data_blob_null); + return False; + } + + return True; +} + +/* + * Do the recurring log file and smb.conf reload checks. + */ + +static bool housekeeping_fn(const struct timeval *now, void *private_data) +{ + change_to_root_user(); + + /* update printer queue caches if necessary */ + update_monitored_printq_cache(); + + /* check if we need to reload services */ + check_reload(time(NULL)); + + /* Change machine password if neccessary. */ + attempt_machine_password_change(); + + /* + * Force a log file check. + */ + force_check_log_size(); + check_log_size(); + return true; +} + /**************************************************************************** Process commands from the client ****************************************************************************/ void smbd_process(void) { + TALLOC_CTX *frame = talloc_stackframe(); + char remaddr[INET6_ADDRSTRLEN]; + + smbd_server_conn = talloc_zero(smbd_event_context(), struct smbd_server_connection); + if (!smbd_server_conn) { + exit_server("failed to create smbd_server_connection"); + } + + /* Ensure child is set to blocking mode */ + set_blocking(smbd_server_fd(),True); + + set_socket_options(smbd_server_fd(),"SO_KEEPALIVE"); + set_socket_options(smbd_server_fd(), lp_socket_options()); + + /* this is needed so that we get decent entries + in smbstatus for port 445 connects */ + set_remote_machine_name(get_peer_addr(smbd_server_fd(), + remaddr, + sizeof(remaddr)), + false); + reload_services(true); + /* * Before the first packet, check the global hosts allow/ hosts deny * parameters before doing any parsing of packets passed to us by the @@ -1931,12 +1990,96 @@ void smbd_process(void) exit_server_cleanly("connection denied"); } - max_recv = MIN(lp_maxxmit(),BUFFER_SIZE); + static_init_rpc; - smbd_server_conn = talloc_zero(smbd_event_context(), struct smbd_server_connection); - if (!smbd_server_conn) { - exit_server("failed to create smbd_server_connection"); + init_modules(); + + if (!init_account_policy()) { + exit_server("Could not open account policy tdb.\n"); + } + + if (*lp_rootdir()) { + if (chroot(lp_rootdir()) != 0) { + DEBUG(0,("Failed changed root to %s\n", lp_rootdir())); + exit_server("Failed to chroot()"); + } + DEBUG(0,("Changed root to %s\n", lp_rootdir())); + } + + /* Setup oplocks */ + if (!init_oplocks(smbd_messaging_context())) + exit_server("Failed to init oplocks"); + + /* Setup aio signal handler. */ + initialize_async_io_handler(); + + /* 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); + messaging_register(smbd_messaging_context(), NULL, + MSG_SMB_CLOSE_FILE, msg_close_file); + + if ((lp_keepalive() != 0) + && !(event_add_idle(smbd_event_context(), NULL, + timeval_set(lp_keepalive(), 0), + "keepalive", keepalive_fn, + NULL))) { + DEBUG(0, ("Could not add keepalive event\n")); + exit(1); + } + + if (!(event_add_idle(smbd_event_context(), NULL, + timeval_set(IDLE_CLOSED_TIMEOUT, 0), + "deadtime", deadtime_fn, NULL))) { + DEBUG(0, ("Could not add deadtime event\n")); + exit(1); } + + if (!(event_add_idle(smbd_event_context(), NULL, + timeval_set(SMBD_SELECT_TIMEOUT, 0), + "housekeeping", housekeeping_fn, NULL))) { + DEBUG(0, ("Could not add housekeeping event\n")); + exit(1); + } + +#ifdef CLUSTER_SUPPORT + + if (lp_clustering()) { + /* + * We need to tell ctdb about our client's TCP + * connection, so that for failover ctdbd can send + * tickle acks, triggering a reconnection by the + * client. + */ + + struct sockaddr_storage srv, clnt; + + if (client_get_tcp_info(&srv, &clnt) == 0) { + + NTSTATUS status; + + status = ctdbd_register_ips( + messaging_ctdbd_connection(), + &srv, &clnt, release_ip, NULL); + + if (!NT_STATUS_IS_OK(status)) { + DEBUG(0, ("ctdbd_register_ips failed: %s\n", + nt_errstr(status))); + } + } else + { + DEBUG(0,("Unable to get tcp info for " + "CTDB_CONTROL_TCP_CLIENT: %s\n", + strerror(errno))); + } + } + +#endif + + max_recv = MIN(lp_maxxmit(),BUFFER_SIZE); + smbd_server_conn->fde = event_add_fd(smbd_event_context(), smbd_server_conn, smbd_server_fd(), @@ -1947,9 +2090,12 @@ void smbd_process(void) exit_server("failed to create smbd_server_connection fde"); } + TALLOC_FREE(frame); + while (True) { NTSTATUS status; - TALLOC_CTX *frame = talloc_stackframe_pool(8192); + + frame = talloc_stackframe_pool(8192); errno = 0; @@ -1958,9 +2104,35 @@ void smbd_process(void) !NT_STATUS_IS_OK(status)) { DEBUG(3, ("smbd_server_connection_loop_once failed: %s," " exiting\n", nt_errstr(status))); - return; + break; } TALLOC_FREE(frame); } + + exit_server_cleanly(NULL); +} + +bool req_is_in_chain(struct smb_request *req) +{ + if (req->vwv != (uint16_t *)(req->inbuf+smb_vwv)) { + /* + * We're right now handling a subsequent request, so we must + * be in a chain + */ + return true; + } + + if (!is_andx_req(req->cmd)) { + return false; + } + + if (req->wct < 2) { + /* + * Okay, an illegal request, but definitely not chained :-) + */ + return false; + } + + return (CVAL(req->vwv+0, 0) != 0xFF); } diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 52dab0a013..bb5fadd465 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -1816,7 +1816,7 @@ void reply_open_and_X(struct smb_request *req) END_PROFILE(SMBopenX); return; } - sbuf.st_size = get_allocation_size(conn,fsp,&sbuf); + sbuf.st_size = SMB_VFS_GET_ALLOC_SIZE(conn,fsp,&sbuf); } fattr = dos_mode(conn,fsp->fsp_name,&sbuf); @@ -2728,11 +2728,12 @@ static void reply_readbraw_error(void) Use sendfile in readbraw. ****************************************************************************/ -void send_file_readbraw(connection_struct *conn, - files_struct *fsp, - SMB_OFF_T startpos, - size_t nread, - ssize_t mincount) +static void send_file_readbraw(connection_struct *conn, + struct smb_request *req, + files_struct *fsp, + SMB_OFF_T startpos, + size_t nread, + ssize_t mincount) { char *outbuf = NULL; ssize_t ret=0; @@ -2745,7 +2746,7 @@ void send_file_readbraw(connection_struct *conn, * reply_readbraw has already checked the length. */ - if ( (chain_size == 0) && (nread > 0) && (fsp->base_fsp == NULL) && + if ( !req_is_in_chain(req) && (nread > 0) && (fsp->base_fsp == NULL) && (fsp->wcp == NULL) && lp_use_sendfile(SNUM(conn)) ) { ssize_t sendfile_read = -1; char header[4]; @@ -2963,7 +2964,7 @@ void reply_readbraw(struct smb_request *req) (unsigned long)mincount, (unsigned long)nread ) ); - send_file_readbraw(conn, fsp, startpos, nread, mincount); + send_file_readbraw(conn, req, fsp, startpos, nread, mincount); DEBUG(5,("reply_readbraw finished\n")); END_PROFILE(SMBreadbraw); @@ -3229,7 +3230,7 @@ static void send_file_readX(connection_struct *conn, struct smb_request *req, * on a train in Germany :-). JRA. */ - if ((chain_size == 0) && (CVAL(req->vwv+0, 0) == 0xFF) && + if (!req_is_in_chain(req) && !is_encrypted_packet(req->inbuf) && (fsp->base_fsp == NULL) && lp_use_sendfile(SNUM(conn)) && (fsp->wcp == NULL) ) { uint8 headerbuf[smb_size + 12 * 2]; @@ -5615,7 +5616,13 @@ NTSTATUS rename_internals_fsp(connection_struct *conn, return map_nt_error_from_unix(errno); } } else { - if (SMB_VFS_STAT(conn,fsp->fsp_name,&sbuf) == -1) { + int ret = -1; + if (fsp->posix_open) { + ret = SMB_VFS_LSTAT(conn,fsp->fsp_name,&sbuf); + } else { + ret = SMB_VFS_STAT(conn,fsp->fsp_name,&sbuf); + } + if (ret == -1) { return map_nt_error_from_unix(errno); } } @@ -5720,6 +5727,7 @@ NTSTATUS rename_internals(TALLOC_CTX *ctx, const char *dname; long offset = 0; int create_options = 0; + bool posix_pathnames = lp_posix_pathnames(); ZERO_STRUCT(sbuf1); ZERO_STRUCT(sbuf2); @@ -5831,7 +5839,11 @@ NTSTATUS rename_internals(TALLOC_CTX *ctx, } ZERO_STRUCT(sbuf1); - SMB_VFS_STAT(conn, directory, &sbuf1); + if (posix_pathnames) { + SMB_VFS_LSTAT(conn, directory, &sbuf1); + } else { + SMB_VFS_STAT(conn, directory, &sbuf1); + } if (S_ISDIR(sbuf1.st_mode)) { create_options |= FILE_DIRECTORY_FILE; @@ -5848,7 +5860,7 @@ NTSTATUS rename_internals(TALLOC_CTX *ctx, FILE_SHARE_WRITE), FILE_OPEN, /* create_disposition*/ create_options, /* create_options */ - 0, /* file_attributes */ + posix_pathnames ? FILE_FLAG_POSIX_SEMANTICS|0777 : 0, /* file_attributes */ 0, /* oplock_request */ 0, /* allocation_size */ NULL, /* sd */ @@ -5947,7 +5959,11 @@ NTSTATUS rename_internals(TALLOC_CTX *ctx, } ZERO_STRUCT(sbuf1); - SMB_VFS_STAT(conn, fname, &sbuf1); + if (posix_pathnames) { + SMB_VFS_LSTAT(conn, fname, &sbuf1); + } else { + SMB_VFS_STAT(conn, fname, &sbuf1); + } create_options = 0; @@ -5966,7 +5982,7 @@ NTSTATUS rename_internals(TALLOC_CTX *ctx, FILE_SHARE_WRITE), FILE_OPEN, /* create_disposition*/ create_options, /* create_options */ - 0, /* file_attributes */ + posix_pathnames ? FILE_FLAG_POSIX_SEMANTICS|0777 : 0, /* file_attributes */ 0, /* oplock_request */ 0, /* allocation_size */ NULL, /* sd */ @@ -7166,7 +7182,14 @@ void reply_setattrE(struct smb_request *req) return; } } else { - if (SMB_VFS_STAT(conn, fsp->fsp_name, &sbuf) == -1) { + int ret = -1; + + if (fsp->posix_open) { + ret = SMB_VFS_LSTAT(conn, fsp->fsp_name, &sbuf); + } else { + ret = SMB_VFS_STAT(conn, fsp->fsp_name, &sbuf); + } + if (ret == -1) { status = map_nt_error_from_unix(errno); reply_nterror(req, status); END_PROFILE(SMBsetattrE); @@ -7281,7 +7304,7 @@ void reply_getattrE(struct smb_request *req) SIVAL(req->outbuf, smb_vwv6, 0); SIVAL(req->outbuf, smb_vwv8, 0); } else { - uint32 allocation_size = get_allocation_size(conn,fsp, &sbuf); + uint32 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn,fsp, &sbuf); SIVAL(req->outbuf, smb_vwv6, (uint32)sbuf.st_size); SIVAL(req->outbuf, smb_vwv8, allocation_size); } diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 505763014e..5f6783e05c 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -45,26 +45,6 @@ int get_client_fd(void) return server_fd; } -#ifdef CLUSTER_SUPPORT -static int client_get_tcp_info(struct sockaddr_storage *server, - struct sockaddr_storage *client) -{ - socklen_t length; - if (server_fd == -1) { - return -1; - } - length = sizeof(*server); - if (getsockname(server_fd, (struct sockaddr *)server, &length) != 0) { - return -1; - } - length = sizeof(*client); - if (getpeername(server_fd, (struct sockaddr *)client, &length) != 0) { - return -1; - } - return 0; -} -#endif - struct event_context *smbd_event_context(void) { if (!smbd_event_ctx) { @@ -134,35 +114,6 @@ static void smb_stat_cache_delete(struct messaging_context *msg, } /**************************************************************************** - Terminate signal. -****************************************************************************/ - -static void sig_term(void) -{ - got_sig_term = 1; - sys_select_signal(SIGTERM); -} - -/**************************************************************************** - Catch a sighup. -****************************************************************************/ - -static void sig_hup(int sig) -{ - reload_after_sighup = 1; - sys_select_signal(SIGHUP); -} - -/**************************************************************************** - Catch a sigcld -****************************************************************************/ -static void sig_cld(int sig) -{ - got_sig_cld = 1; - sys_select_signal(SIGCLD); -} - -/**************************************************************************** Send a SIGTERM to our process group. *****************************************************************************/ @@ -185,27 +136,6 @@ static void msg_sam_sync(struct messaging_context *msg, DEBUG(10, ("** sam sync message received, ignoring\n")); } - -/**************************************************************************** - Open the socket communication - inetd. -****************************************************************************/ - -static bool open_sockets_inetd(void) -{ - /* Started from inetd. fd 0 is the socket. */ - /* We will abort gracefully when the client or remote system - goes away */ - smbd_set_server_fd(dup(0)); - - /* close our standard file descriptors */ - close_low_fds(False); /* Don't close stderr */ - - set_socket_options(smbd_server_fd(),"SO_KEEPALIVE"); - set_socket_options(smbd_server_fd(), lp_socket_options()); - - return True; -} - static void msg_exit_server(struct messaging_context *msg, void *private_data, uint32_t msg_type, @@ -321,46 +251,271 @@ static bool allowable_number_of_smbd_processes(void) return num_children < max_processes; } +static void smbd_sig_chld_handler(struct tevent_context *ev, + struct tevent_signal *se, + int signum, + int count, + void *siginfo, + void *private_data) +{ + pid_t pid; + int status; + + 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); + } +} + +static void smbd_setup_sig_chld_handler(void) +{ + struct tevent_signal *se; + + se = tevent_add_signal(smbd_event_context(), + smbd_event_context(), + SIGCHLD, 0, + smbd_sig_chld_handler, + NULL); + if (!se) { + exit_server("failed to setup SIGCHLD handler"); + } +} + +struct smbd_open_socket; + +struct smbd_parent_context { + bool interactive; + + /* the list of listening sockets */ + struct smbd_open_socket *sockets; +}; + +struct smbd_open_socket { + struct smbd_open_socket *prev, *next; + struct smbd_parent_context *parent; + int fd; + struct tevent_fd *fde; +}; + +static void smbd_open_socket_close_fn(struct tevent_context *ev, + struct tevent_fd *fde, + int fd, + void *private_data) +{ + /* this might be the socket_wrapper swrap_close() */ + close(fd); +} + +static void smbd_accept_connection(struct tevent_context *ev, + struct tevent_fd *fde, + uint16_t flags, + void *private_data) +{ + struct smbd_open_socket *s = talloc_get_type_abort(private_data, + struct smbd_open_socket); + struct sockaddr_storage addr; + socklen_t in_addrlen = sizeof(addr); + pid_t pid = 0; + + smbd_set_server_fd(accept(s->fd,(struct sockaddr *)&addr,&in_addrlen)); + + if (smbd_server_fd() == -1 && errno == EINTR) + return; + + if (smbd_server_fd() == -1) { + DEBUG(0,("open_sockets_smbd: accept: %s\n", + strerror(errno))); + return; + } + + if (s->parent->interactive) { + smbd_process(); + exit_server_cleanly("end of interactive mode"); + return; + } + + if (!allowable_number_of_smbd_processes()) { + close(smbd_server_fd()); + smbd_set_server_fd(-1); + return; + } + + pid = sys_fork(); + if (pid == 0) { + /* Child code ... */ + am_parent = 0; + + /* Stop zombies, the parent explicitly handles + * them, counting worker smbds. */ + CatchChild(); + + /* close our standard file + descriptors */ + close_low_fds(False); + + TALLOC_FREE(s->parent); + s = NULL; + + if (!reinit_after_fork( + smbd_messaging_context(), + smbd_event_context(), + true)) { + DEBUG(0,("reinit_after_fork() failed\n")); + smb_panic("reinit_after_fork() failed"); + } + + smbd_setup_sig_term_handler(); + smbd_setup_sig_hup_handler(); + + smbd_process(); + exit_server_cleanly("end of child"); + return; + } else if (pid < 0) { + DEBUG(0,("smbd_accept_connection: sys_fork() failed: %s\n", + strerror(errno))); + } + + /* The parent doesn't need this socket */ + close(smbd_server_fd()); + + /* Sun May 6 18:56:14 2001 ackley@cs.unm.edu: + Clear the closed fd info out of server_fd -- + and more importantly, out of client_fd in + util_sock.c, to avoid a possible + getpeername failure if we reopen the logs + and use %I in the filename. + */ + + smbd_set_server_fd(-1); + + if (pid != 0) { + add_child_pid(pid); + } + + /* Force parent to check log size after + * spawning child. Fix from + * klausr@ITAP.Physik.Uni-Stuttgart.De. The + * parent smbd will log to logserver.smb. It + * writes only two messages for each child + * started/finished. But each child writes, + * say, 50 messages also in logserver.smb, + * begining with the debug_count of the + * parent, before the child opens its own log + * file logserver.client. In a worst case + * scenario the size of logserver.smb would be + * checked after about 50*50=2500 messages + * (ca. 100kb). + * */ + force_check_log_size(); +} + +static bool smbd_open_one_socket(struct smbd_parent_context *parent, + const struct sockaddr_storage *ifss, + uint16_t port) +{ + struct smbd_open_socket *s; + + s = talloc(parent, struct smbd_open_socket); + if (!s) { + return false; + } + + s->parent = parent; + s->fd = open_socket_in(SOCK_STREAM, + port, + parent->sockets == NULL ? 0 : 2, + ifss, + true); + if (s->fd == -1) { + DEBUG(0,("smbd_open_once_socket: open_socket_in: " + "%s\n", strerror(errno))); + close(s->fd); + TALLOC_FREE(s); + /* + * We ignore an error here, as we've done before + */ + return true; + } + + /* ready to listen */ + set_socket_options(s->fd, "SO_KEEPALIVE"); + set_socket_options(s->fd, lp_socket_options()); + + /* Set server socket to + * non-blocking for the accept. */ + set_blocking(s->fd, False); + + if (listen(s->fd, SMBD_LISTEN_BACKLOG) == -1) { + DEBUG(0,("open_sockets_smbd: listen: " + "%s\n", strerror(errno))); + close(s->fd); + TALLOC_FREE(s); + return false; + } + + s->fde = tevent_add_fd(smbd_event_context(), + s, + s->fd, TEVENT_FD_READ, + smbd_accept_connection, + s); + if (!s->fde) { + DEBUG(0,("open_sockets_smbd: " + "tevent_add_fd: %s\n", + strerror(errno))); + close(s->fd); + TALLOC_FREE(s); + return false; + } + tevent_fd_set_close_fn(s->fde, smbd_open_socket_close_fn); + + DLIST_ADD_END(parent->sockets, s, struct smbd_open_socket *); + + return true; +} + /**************************************************************************** Open the socket communication. ****************************************************************************/ -static bool open_sockets_smbd(bool is_daemon, bool interactive, const char *smb_ports) +static bool open_sockets_smbd(struct smbd_parent_context *parent, + const char *smb_ports) { int num_interfaces = iface_count(); - int num_sockets = 0; - int fd_listenset[FD_SETSIZE]; - fd_set listen_set; - int s; - int maxfd = 0; int i; char *ports; - struct dns_reg_state * dns_reg = NULL; unsigned dns_port = 0; - if (!is_daemon) { - return open_sockets_inetd(); - } - #ifdef HAVE_ATEXIT atexit(killkids); #endif /* Stop zombies */ - CatchSignal(SIGCLD, sig_cld); - - FD_ZERO(&listen_set); + smbd_setup_sig_chld_handler(); /* use a reasonable default set of ports - listing on 445 and 139 */ if (!smb_ports) { ports = lp_smb_ports(); if (!ports || !*ports) { - ports = smb_xstrdup(SMB_PORTS); + ports = talloc_strdup(talloc_tos(), SMB_PORTS); } else { - ports = smb_xstrdup(ports); + ports = talloc_strdup(talloc_tos(), ports); } } else { - ports = smb_xstrdup(smb_ports); + ports = talloc_strdup(talloc_tos(), smb_ports); } if (lp_interfaces() && lp_bind_interfaces_only()) { @@ -372,7 +527,6 @@ static bool open_sockets_smbd(bool is_daemon, bool interactive, const char *smb_ /* Now open a listen socket for each of the interfaces. */ for(i = 0; i < num_interfaces; i++) { - TALLOC_CTX *frame = NULL; const struct sockaddr_storage *ifss = iface_n_sockaddr_storage(i); char *tok; @@ -385,64 +539,22 @@ static bool open_sockets_smbd(bool is_daemon, bool interactive, const char *smb_ continue; } - frame = talloc_stackframe(); for (ptr=ports; - next_token_talloc(frame,&ptr, &tok, " \t,");) { + next_token_talloc(talloc_tos(),&ptr, &tok, " \t,");) { unsigned port = atoi(tok); if (port == 0 || port > 0xffff) { continue; } - /* Keep the first port for mDNS service - * registration. - */ - if (dns_port == 0) { - dns_port = port; - } - - s = fd_listenset[num_sockets] = - open_socket_in(SOCK_STREAM, - port, - num_sockets == 0 ? 0 : 2, - ifss, - true); - if(s == -1) { - continue; - } - - /* ready to listen */ - set_socket_options(s,"SO_KEEPALIVE"); - set_socket_options(s,lp_socket_options()); - - /* Set server socket to - * non-blocking for the accept. */ - set_blocking(s,False); - - if (listen(s, SMBD_LISTEN_BACKLOG) == -1) { - DEBUG(0,("open_sockets_smbd: listen: " - "%s\n", strerror(errno))); - close(s); - TALLOC_FREE(frame); - return False; - } - FD_SET(s,&listen_set); - maxfd = MAX( maxfd, s); - - num_sockets++; - if (num_sockets >= FD_SETSIZE) { - DEBUG(0,("open_sockets_smbd: Too " - "many sockets to bind to\n")); - TALLOC_FREE(frame); - return False; + if (!smbd_open_one_socket(parent, ifss, port)) { + return false; } } - TALLOC_FREE(frame); } } else { /* Just bind to 0.0.0.0 - accept connections from anywhere. */ - TALLOC_CTX *frame = talloc_stackframe(); char *tok; const char *ptr; const char *sock_addr = lp_socket_address(); @@ -459,8 +571,8 @@ static bool open_sockets_smbd(bool is_daemon, bool interactive, const char *smb_ } for (sock_ptr=sock_addr; - next_token_talloc(frame, &sock_ptr, &sock_tok, " \t,"); ) { - for (ptr=ports; next_token_talloc(frame, &ptr, &tok, " \t,"); ) { + next_token_talloc(talloc_tos(), &sock_ptr, &sock_tok, " \t,"); ) { + for (ptr=ports; next_token_talloc(talloc_tos(), &ptr, &tok, " \t,"); ) { struct sockaddr_storage ss; unsigned port = atoi(tok); @@ -481,52 +593,14 @@ static bool open_sockets_smbd(bool is_daemon, bool interactive, const char *smb_ continue; } - s = open_socket_in(SOCK_STREAM, - port, - num_sockets == 0 ? 0 : 2, - &ss, - true); - if (s == -1) { - continue; - } - - /* ready to listen */ - set_socket_options(s,"SO_KEEPALIVE"); - set_socket_options(s,lp_socket_options()); - - /* Set server socket to non-blocking - * for the accept. */ - set_blocking(s,False); - - if (listen(s, SMBD_LISTEN_BACKLOG) == -1) { - DEBUG(0,("open_sockets_smbd: " - "listen: %s\n", - strerror(errno))); - close(s); - TALLOC_FREE(frame); - return False; - } - - fd_listenset[num_sockets] = s; - FD_SET(s,&listen_set); - maxfd = MAX( maxfd, s); - - num_sockets++; - - if (num_sockets >= FD_SETSIZE) { - DEBUG(0,("open_sockets_smbd: Too " - "many sockets to bind to\n")); - TALLOC_FREE(frame); - return False; + if (!smbd_open_one_socket(parent, &ss, port)) { + return false; } } } - TALLOC_FREE(frame); } - SAFE_FREE(ports); - - if (num_sockets == 0) { + if (parent->sockets == NULL) { DEBUG(0,("open_sockets_smbd: No " "sockets available to bind to.\n")); return false; @@ -565,57 +639,37 @@ static bool open_sockets_smbd(bool is_daemon, bool interactive, const char *smb_ MSG_SMB_INJECT_FAULT, msg_inject_fault); #endif + if (dns_port != 0) { + smbd_setup_mdns_registration(smbd_event_context(), + parent, dns_port); + } + + return true; +} + +static void smbd_parent_loop(struct smbd_parent_context *parent) +{ /* now accept incoming connections - forking a new process for each incoming connection */ DEBUG(2,("waiting for a connection\n")); while (1) { struct timeval now, idle_timeout; fd_set r_fds, w_fds; + int maxfd = 0; int num; - - if (got_sig_cld) { - pid_t pid; - int status; - - got_sig_cld = False; - - 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); - } - } + TALLOC_CTX *frame = talloc_stackframe(); if (run_events(smbd_event_context(), 0, NULL, NULL)) { + TALLOC_FREE(frame); continue; } idle_timeout = timeval_zero(); - memcpy((char *)&r_fds, (char *)&listen_set, - sizeof(listen_set)); FD_ZERO(&w_fds); + FD_ZERO(&r_fds); GetTimeOfDay(&now); - /* Kick off our mDNS registration. */ - if (dns_port != 0) { - dns_register_smbd(&dns_reg, dns_port, &maxfd, - &r_fds, &idle_timeout); - } - event_add_to_select_args(smbd_event_context(), &now, &r_fds, &w_fds, &idle_timeout, &maxfd); @@ -624,26 +678,13 @@ static bool open_sockets_smbd(bool is_daemon, bool interactive, const char *smb_ timeval_is_zero(&idle_timeout) ? NULL : &idle_timeout); - if (run_events(smbd_event_context(), num, &r_fds, &w_fds)) { - continue; - } - - if (num == -1 && errno == EINTR) { - if (got_sig_term) { - exit_server_cleanly(NULL); - } - - /* check for sighup processing */ - if (reload_after_sighup) { - change_to_root_user(); - DEBUG(1,("Reloading services after SIGHUP\n")); - reload_services(False); - reload_after_sighup = 0; - } + /* check if we need to reload services */ + check_reload(time(NULL)); + if (run_events(smbd_event_context(), num, &r_fds, &w_fds)) { + TALLOC_FREE(frame); continue; } - /* If the idle timeout fired and we don't have any connected * users, exit gracefully. We should be running under a process @@ -652,128 +693,7 @@ static bool open_sockets_smbd(bool is_daemon, bool interactive, const char *smb_ 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)) { - --num; - } - - /* check if we need to reload services */ - check_reload(time(NULL)); - - /* Find the sockets that are read-ready - - accept on these. */ - for( ; num > 0; num--) { - struct sockaddr addr; - socklen_t in_addrlen = sizeof(addr); - pid_t child = 0; - - s = -1; - for(i = 0; i < num_sockets; i++) { - if(FD_ISSET(fd_listenset[i],&r_fds)) { - s = fd_listenset[i]; - /* Clear this so we don't look - at it again. */ - FD_CLR(fd_listenset[i],&r_fds); - break; - } - } - - smbd_set_server_fd(accept(s,&addr,&in_addrlen)); - - if (smbd_server_fd() == -1 && errno == EINTR) - continue; - - if (smbd_server_fd() == -1) { - DEBUG(2,("open_sockets_smbd: accept: %s\n", - strerror(errno))); - continue; - } - - /* Ensure child is set to blocking mode */ - set_blocking(smbd_server_fd(),True); - - if (smbd_server_fd() != -1 && interactive) - return True; - - if (allowable_number_of_smbd_processes() && - smbd_server_fd() != -1 && - ((child = sys_fork())==0)) { - char remaddr[INET6_ADDRSTRLEN]; - - /* Child code ... */ - - /* Stop zombies, the parent explicitly handles - * them, counting worker smbds. */ - CatchChild(); - - /* close the listening socket(s) */ - for(i = 0; i < num_sockets; i++) - close(fd_listenset[i]); - - /* close our mDNS daemon handle */ - dns_register_close(&dns_reg); - - /* close our standard file - descriptors */ - close_low_fds(False); - am_parent = 0; - - set_socket_options(smbd_server_fd(),"SO_KEEPALIVE"); - set_socket_options(smbd_server_fd(), - lp_socket_options()); - - /* this is needed so that we get decent entries - in smbstatus for port 445 connects */ - set_remote_machine_name(get_peer_addr(smbd_server_fd(), - remaddr, - sizeof(remaddr)), - false); - - if (!reinit_after_fork( - smbd_messaging_context(), - smbd_event_context(), - true)) { - DEBUG(0,("reinit_after_fork() failed\n")); - smb_panic("reinit_after_fork() failed"); - } - - return True; - } - /* The parent doesn't need this socket */ - close(smbd_server_fd()); - - /* Sun May 6 18:56:14 2001 ackley@cs.unm.edu: - Clear the closed fd info out of server_fd -- - and more importantly, out of client_fd in - util_sock.c, to avoid a possible - getpeername failure if we reopen the logs - and use %I in the filename. - */ - - smbd_set_server_fd(-1); - - if (child != 0) { - add_child_pid(child); - } - - /* Force parent to check log size after - * spawning child. Fix from - * klausr@ITAP.Physik.Uni-Stuttgart.De. The - * parent smbd will log to logserver.smb. It - * writes only two messages for each child - * started/finished. But each child writes, - * say, 50 messages also in logserver.smb, - * begining with the debug_count of the - * parent, before the child opens its own log - * file logserver.client. In a worst case - * scenario the size of logserver.smb would be - * checked after about 50*50=2500 messages - * (ca. 100kb). - * */ - force_check_log_size(); - - } /* end for num */ + TALLOC_FREE(frame); } /* end while 1 */ /* NOTREACHED return True; */ @@ -897,8 +817,6 @@ static void exit_server_common(enum server_exit_reason how, /* delete our entry in the connections database. */ yield_connection(NULL,""); - respond_to_all_remaining_local_messages(); - #ifdef WITH_DFS if (dcelogin_atmost_once) { dfs_unlogin(); @@ -963,34 +881,6 @@ void exit_server_fault(void) exit_server("critical server fault"); } - -/**************************************************************************** -received when we should release a specific IP -****************************************************************************/ -static void release_ip(const char *ip, void *priv) -{ - 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)); - /* note we must exit with non-zero status so the unclean handler gets - called in the parent, so that the brl database is tickled */ - _exit(1); - } -} - -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) -{ - release_ip((char *)data->data, NULL); -} - /**************************************************************************** Initialise connect, service and file structs. ****************************************************************************/ @@ -1017,59 +907,6 @@ static bool init_structs(void ) return True; } -/* - * Send keepalive packets to our client - */ -static bool keepalive_fn(const struct timeval *now, void *private_data) -{ - if (!send_keepalive(smbd_server_fd())) { - DEBUG( 2, ( "Keepalive failed - exiting.\n" ) ); - return False; - } - return True; -} - -/* - * Do the recurring check if we're idle - */ -static bool deadtime_fn(const struct timeval *now, void *private_data) -{ - if ((conn_num_open() == 0) - || (conn_idle_all(now->tv_sec))) { - DEBUG( 2, ( "Closing idle connection\n" ) ); - messaging_send(smbd_messaging_context(), procid_self(), - MSG_SHUTDOWN, &data_blob_null); - return False; - } - - return True; -} - -/* - * Do the recurring log file and smb.conf reload checks. - */ - -static bool housekeeping_fn(const struct timeval *now, void *private_data) -{ - change_to_root_user(); - - /* update printer queue caches if necessary */ - update_monitored_printq_cache(); - - /* check if we need to reload services */ - check_reload(time(NULL)); - - /* Change machine password if neccessary. */ - attempt_machine_password_change(); - - /* - * Force a log file check. - */ - force_check_log_size(); - check_log_size(); - return true; -} - /**************************************************************************** main program. ****************************************************************************/ @@ -1114,6 +951,7 @@ extern void build_options(bool screen); POPT_COMMON_DYNCONFIG POPT_TABLEEND }; + struct smbd_parent_context *parent = NULL; TALLOC_CTX *frame = talloc_stackframe(); /* Setup tos. */ smbd_init_globals(); @@ -1199,9 +1037,6 @@ extern void build_options(bool screen); fault_setup((void (*)(void *))exit_server_fault); dump_core_setup("smbd"); - CatchSignal(SIGTERM , SIGNAL_CAST sig_term); - CatchSignal(SIGHUP,SIGNAL_CAST sig_hup); - /* we are never interested in SIGPIPE */ BlockSignals(True,SIGPIPE); @@ -1311,6 +1146,9 @@ extern void build_options(bool screen); exit(1); } + smbd_setup_sig_term_handler(); + smbd_setup_sig_hup_handler(); + /* Setup all the TDB's - including CLEAR_IF_FIRST tdb's. */ if (smbd_memcache() == NULL) { @@ -1372,111 +1210,36 @@ extern void build_options(bool screen); start_background_queue(); } - if (!open_sockets_smbd(is_daemon, interactive, ports)) - exit(1); - - /* - * everything after this point is run after the fork() - */ - - static_init_rpc; - - init_modules(); - - /* Possibly reload the services file. Only worth doing in - * daemon mode. In inetd mode, we know we only just loaded this. - */ - if (is_daemon) { - reload_services(True); - } - - if (!init_account_policy()) { - DEBUG(0,("Could not open account policy tdb.\n")); - exit(1); - } + if (!is_daemon) { + /* inetd mode */ + TALLOC_FREE(frame); - if (*lp_rootdir()) { - if (chroot(lp_rootdir()) == 0) - DEBUG(2,("Changed root to %s\n", lp_rootdir())); - } + /* Started from inetd. fd 0 is the socket. */ + /* We will abort gracefully when the client or remote system + goes away */ + smbd_set_server_fd(dup(0)); - /* Setup oplocks */ - if (!init_oplocks(smbd_messaging_context())) - exit(1); + /* close our standard file descriptors */ + close_low_fds(False); /* Don't close stderr */ - /* Setup aio signal handler. */ - initialize_async_io_handler(); + smbd_process(); - /* 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); - messaging_register(smbd_messaging_context(), NULL, - MSG_SMB_CLOSE_FILE, msg_close_file); - - if ((lp_keepalive() != 0) - && !(event_add_idle(smbd_event_context(), NULL, - timeval_set(lp_keepalive(), 0), - "keepalive", keepalive_fn, - NULL))) { - DEBUG(0, ("Could not add keepalive event\n")); - exit(1); + exit_server_cleanly(NULL); + return(0); } - if (!(event_add_idle(smbd_event_context(), NULL, - timeval_set(IDLE_CLOSED_TIMEOUT, 0), - "deadtime", deadtime_fn, NULL))) { - DEBUG(0, ("Could not add deadtime event\n")); - exit(1); + parent = talloc_zero(smbd_event_context(), struct smbd_parent_context); + if (!parent) { + exit_server("talloc(struct smbd_parent_context) failed"); } + parent->interactive = interactive; - if (!(event_add_idle(smbd_event_context(), NULL, - timeval_set(SMBD_SELECT_TIMEOUT, 0), - "housekeeping", housekeeping_fn, NULL))) { - DEBUG(0, ("Could not add housekeeping event\n")); - exit(1); - } - -#ifdef CLUSTER_SUPPORT - - if (lp_clustering()) { - /* - * We need to tell ctdb about our client's TCP - * connection, so that for failover ctdbd can send - * tickle acks, triggering a reconnection by the - * client. - */ - - struct sockaddr_storage srv, clnt; - - if (client_get_tcp_info(&srv, &clnt) == 0) { - - NTSTATUS status; - - status = ctdbd_register_ips( - messaging_ctdbd_connection(), - &srv, &clnt, release_ip, NULL); - - if (!NT_STATUS_IS_OK(status)) { - DEBUG(0, ("ctdbd_register_ips failed: %s\n", - nt_errstr(status))); - } - } else - { - DEBUG(0,("Unable to get tcp info for " - "CTDB_CONTROL_TCP_CLIENT: %s\n", - strerror(errno))); - } - } - -#endif + if (!open_sockets_smbd(parent, ports)) + exit_server("open_sockets_smbd() failed"); TALLOC_FREE(frame); - smbd_process(); - - namecache_shutdown(); + smbd_parent_loop(parent); exit_server_cleanly(NULL); return(0); diff --git a/source3/smbd/sesssetup.c b/source3/smbd/sesssetup.c index a2ad56bea1..7a03ef7f3c 100644 --- a/source3/smbd/sesssetup.c +++ b/source3/smbd/sesssetup.c @@ -795,7 +795,7 @@ static void reply_spnego_negotiate(struct smb_request *req, #ifdef HAVE_KRB5 if (kerb_mech && ((lp_security()==SEC_ADS) || - lp_use_kerberos_keytab()) ) { + USE_KERBEROS_KEYTAB) ) { bool destroy_vuid = True; reply_spnego_kerberos(req, &secblob, kerb_mech, vuid, &destroy_vuid); @@ -887,7 +887,7 @@ static void reply_spnego_auth(struct smb_request *req, (unsigned long)secblob.length)); #ifdef HAVE_KRB5 if (kerb_mech && ((lp_security()==SEC_ADS) || - lp_use_kerberos_keytab()) ) { + USE_KERBEROS_KEYTAB)) { bool destroy_vuid = True; reply_spnego_kerberos(req, &secblob, kerb_mech, vuid, &destroy_vuid); diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 1b161d5338..6c082a8273 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -29,7 +29,6 @@ extern enum protocol_types Protocol; -#define get_file_size(sbuf) ((sbuf).st_size) #define DIR_ENTRY_SAFETY_MARGIN 4096 static char *store_file_unix_basic(connection_struct *conn, @@ -59,31 +58,6 @@ uint64_t smb_roundup(connection_struct *conn, uint64_t val) return val; } -/******************************************************************** - Given a stat buffer return the allocated size on disk, taking into - account sparse files. -********************************************************************/ - -uint64_t get_allocation_size(connection_struct *conn, files_struct *fsp, const SMB_STRUCT_STAT *sbuf) -{ - uint64_t ret; - - if(S_ISDIR(sbuf->st_mode)) { - return 0; - } - -#if defined(HAVE_STAT_ST_BLOCKS) && defined(STAT_ST_BLOCKSIZE) - ret = (uint64_t)STAT_ST_BLOCKSIZE * (uint64_t)sbuf->st_blocks; -#else - ret = (uint64_t)get_file_size(*sbuf); -#endif - - if (fsp && fsp->initial_allocation_size) - ret = MAX(ret,fsp->initial_allocation_size); - - return smb_roundup(conn, ret); -} - /**************************************************************************** Utility functions for dealing with extended attributes. ****************************************************************************/ @@ -1034,7 +1008,7 @@ static void call_trans2open(connection_struct *conn, return; } - size = get_file_size(sbuf); + size = get_file_size_stat(&sbuf); fattr = dos_mode(conn,fsp->fsp_name,&sbuf); mtime = sbuf.st_mtime; inode = sbuf.st_ino; @@ -1424,9 +1398,9 @@ static bool get_lanman2_dir_entry(TALLOC_CTX *ctx, } if (!(mode & aDIR)) { - file_size = get_file_size(sbuf); + file_size = get_file_size_stat(&sbuf); } - allocation_size = get_allocation_size(conn,NULL,&sbuf); + allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn,NULL,&sbuf); mdate_ts = get_mtimespec(&sbuf); adate_ts = get_atimespec(&sbuf); @@ -3523,10 +3497,10 @@ static char *store_file_unix_basic(connection_struct *conn, DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n")); DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf->st_mode)); - SOFF_T(pdata,0,get_file_size(*psbuf)); /* File size 64 Bit */ + SOFF_T(pdata,0,get_file_size_stat(psbuf)); /* File size 64 Bit */ pdata += 8; - SOFF_T(pdata,0,get_allocation_size(conn,fsp,psbuf)); /* Number of bytes used on disk - 64 Bit */ + SOFF_T(pdata,0,SMB_VFS_GET_ALLOC_SIZE(conn,fsp,psbuf)); /* Number of bytes used on disk - 64 Bit */ pdata += 8; put_long_date_timespec(pdata,get_ctimespec(psbuf)); /* Change Time 64 Bit */ @@ -4094,7 +4068,7 @@ static void call_trans2qfilepathinfo(connection_struct *conn, fullpathname = fname; if (!(mode & aDIR)) - file_size = get_file_size(sbuf); + file_size = get_file_size_stat(&sbuf); /* Pull out any data sent here before we realloc. */ switch (info_level) { @@ -4180,7 +4154,7 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd mtime_ts = get_mtimespec(&sbuf); atime_ts = get_atimespec(&sbuf); - allocation_size = get_allocation_size(conn,fsp,&sbuf); + allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn,fsp,&sbuf); if (!fsp) { /* Do we have this path open ? */ @@ -4188,7 +4162,7 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd fileid = vfs_file_id_from_sbuf(conn, &sbuf); fsp1 = file_find_di_first(fileid); if (fsp1 && fsp1->initial_allocation_size) { - allocation_size = get_allocation_size(conn, fsp1, &sbuf); + allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp1, &sbuf); } } @@ -5044,7 +5018,7 @@ static NTSTATUS smb_set_file_size(connection_struct *conn, DEBUG(6,("smb_set_file_size: size: %.0f ", (double)size)); - if (size == get_file_size(*psbuf)) { + if (size == get_file_size_stat(psbuf)) { return NT_STATUS_OK; } @@ -5832,7 +5806,7 @@ static NTSTATUS smb_set_file_allocation_info(connection_struct *conn, if (fsp && fsp->fh->fd != -1) { /* Open file handle. */ /* Only change if needed. */ - if (allocation_size != get_file_size(*psbuf)) { + if (allocation_size != get_file_size_stat(psbuf)) { if (vfs_allocate_file_space(fsp, allocation_size) == -1) { return map_nt_error_from_unix(errno); } @@ -5874,7 +5848,7 @@ static NTSTATUS smb_set_file_allocation_info(connection_struct *conn, } /* Only change if needed. */ - if (allocation_size != get_file_size(*psbuf)) { + if (allocation_size != get_file_size_stat(psbuf)) { if (vfs_allocate_file_space(new_fsp, allocation_size) == -1) { status = map_nt_error_from_unix(errno); close_file(req, new_fsp, NORMAL_CLOSE); @@ -6101,7 +6075,7 @@ size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n", /* Ensure we don't try and change anything else. */ raw_unixmode = SMB_MODE_NO_CHANGE; - size = get_file_size(*psbuf); + size = get_file_size_stat(psbuf); ft.atime = get_atimespec(psbuf); ft.mtime = get_mtimespec(psbuf); /* @@ -6117,7 +6091,7 @@ size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n", * */ if (!size) { - size = get_file_size(*psbuf); + size = get_file_size_stat(psbuf); } #endif diff --git a/source3/torture/locktest.c b/source3/torture/locktest.c index 1bff95f4f3..4e8dcdd09a 100644 --- a/source3/torture/locktest.c +++ b/source3/torture/locktest.c @@ -257,9 +257,10 @@ static struct cli_state *connect_one(char *share, int snum) DEBUG(4,(" session setup ok\n")); - if (!cli_send_tconX(c, share, "?????", - password[snum], strlen(password[snum])+1)) { - DEBUG(0,("tree connect failed: %s\n", cli_errstr(c))); + status = cli_tcon_andx(c, share, "?????", password[snum], + strlen(password[snum])+1); + if (!NT_STATUS_IS_OK(status)) { + DEBUG(0,("tree connect failed: %s\n", nt_errstr(status))); cli_shutdown(c); return NULL; } diff --git a/source3/torture/masktest.c b/source3/torture/masktest.c index 2c3bda1d43..fb562c8075 100644 --- a/source3/torture/masktest.c +++ b/source3/torture/masktest.c @@ -249,9 +249,10 @@ static struct cli_state *connect_one(char *share) DEBUG(4,(" session setup ok\n")); - if (!cli_send_tconX(c, share, "?????", - password, strlen(password)+1)) { - DEBUG(0,("tree connect failed: %s\n", cli_errstr(c))); + status = cli_tcon_andx(c, share, "?????", password, + strlen(password)+1); + if (!NT_STATUS_IS_OK(status)) { + DEBUG(0,("tree connect failed: %s\n", nt_errstr(status))); cli_shutdown(c); return NULL; } diff --git a/source3/torture/torture.c b/source3/torture/torture.c index 8a1a61e79a..1210a36a39 100644 --- a/source3/torture/torture.c +++ b/source3/torture/torture.c @@ -1101,6 +1101,7 @@ static bool run_tcon_test(int dummy) uint16 vuid1, vuid2; char buf[4]; bool ret = True; + NTSTATUS status; memset(buf, '\0', sizeof(buf)); @@ -1127,10 +1128,11 @@ static bool run_tcon_test(int dummy) return False; } - if (!cli_send_tconX(cli, share, "?????", - password, strlen(password)+1)) { + status = cli_tcon_andx(cli, share, "?????", + password, strlen(password)+1); + if (!NT_STATUS_IS_OK(status)) { printf("%s refused 2nd tree connect (%s)\n", host, - cli_errstr(cli)); + nt_errstr(status)); cli_shutdown(cli); return False; } @@ -1239,14 +1241,14 @@ static bool tcon_devtest(struct cli_state *cli, const char *return_devtype, NTSTATUS expected_error) { - bool status; + NTSTATUS status; bool ret; - status = cli_send_tconX(cli, myshare, devtype, - password, strlen(password)+1); + status = cli_tcon_andx(cli, myshare, devtype, + password, strlen(password)+1); if (NT_STATUS_IS_OK(expected_error)) { - if (status) { + if (NT_STATUS_IS_OK(status)) { if (strcmp(cli->dev, return_devtype) == 0) { ret = True; } else { @@ -1264,7 +1266,7 @@ static bool tcon_devtest(struct cli_state *cli, } cli_tdis(cli); } else { - if (status) { + if (NT_STATUS_IS_OK(status)) { printf("tconx to share %s with type %s " "should have failed but succeeded\n", myshare, devtype); @@ -2157,7 +2159,7 @@ static bool run_fdsesstest(int dummy) return False; saved_cnum = cli->cnum; - if (!cli_send_tconX(cli, share, "?????", "", 1)) + if (!NT_STATUS_IS_OK(cli_tcon_andx(cli, share, "?????", "", 1))) return False; new_cnum = cli->cnum; cli->cnum = saved_cnum; @@ -5831,6 +5833,11 @@ static void usage(void) load_case_tables(); + if (is_default_dyn_CONFIGFILE()) { + if(getenv("SMB_CONF_PATH")) { + set_dyn_CONFIGFILE(getenv("SMB_CONF_PATH")); + } + } lp_load(get_dyn_CONFIGFILE(),True,False,False,True); load_interfaces(); diff --git a/source3/utils/eventlogadm.c b/source3/utils/eventlogadm.c index 5fed4d1a39..d134ea8fea 100644 --- a/source3/utils/eventlogadm.c +++ b/source3/utils/eventlogadm.c @@ -5,6 +5,7 @@ * * * Copyright (C) Brian Moran 2005. + * Copyright (C) Guenther Deschner 2009. * * 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 @@ -37,6 +38,7 @@ static void usage( char *s ) printf( "\nUsage: %s [OPTION]\n\n", s ); printf( " -o write <Eventlog Name> \t\t\t\t\tWrites records to eventlog from STDIN\n" ); printf( " -o addsource <EventlogName> <sourcename> <msgfileDLLname> \tAdds the specified source & DLL eventlog registry entry\n" ); + printf( " -o dump <Eventlog Name> <starting_record>\t\t\t\t\tDump stored eventlog entries on STDOUT\n" ); printf( "\nMiscellaneous options:\n" ); printf( " -d\t\t\t\t\t\t\t\tturn debug on\n" ); printf( " -h\t\t\t\t\t\t\t\tdisplay help\n\n" ); @@ -83,12 +85,14 @@ static int DoWriteCommand( int argc, char **argv, bool debugflag, char *exename FILE *f1; char *argfname; ELOG_TDB *etdb; + NTSTATUS status; /* fixed constants are bad bad bad */ char linein[1024]; bool is_eor; - Eventlog_entry ee; - int rcnum; + struct eventlog_Record_tdb ee; + uint32_t record_number; + TALLOC_CTX *mem_ctx = talloc_tos(); f1 = stdin; if ( !f1 ) { @@ -103,7 +107,7 @@ static int DoWriteCommand( int argc, char **argv, bool debugflag, char *exename argfname = argv[0]; - if ( !( etdb = elog_open_tdb( argfname, False ) ) ) { + if ( !( etdb = elog_open_tdb( argfname, False, False ) ) ) { printf( "can't open the eventlog TDB (%s)\n", argfname ); return -1; } @@ -122,26 +126,29 @@ static int DoWriteCommand( int argc, char **argv, bool debugflag, char *exename is_eor = False; - parse_logentry( ( char * ) &linein, &ee, &is_eor ); + parse_logentry( mem_ctx, ( char * ) &linein, &ee, &is_eor ); /* should we do something with the return code? */ if ( is_eor ) { - fixup_eventlog_entry( &ee ); + fixup_eventlog_record_tdb( &ee ); if ( opt_debug ) - printf( "record number [%d], tg [%d] , tw [%d]\n", ee.record.record_number, ee.record.time_generated, ee.record.time_written ); + printf( "record number [%d], tg [%d] , tw [%d]\n", + ee.record_number, (int)ee.time_generated, (int)ee.time_written ); - if ( ee.record.time_generated != 0 ) { + if ( ee.time_generated != 0 ) { /* printf("Writing to the event log\n"); */ - rcnum = write_eventlog_tdb( ELOG_TDB_CTX(etdb), &ee ); - if ( !rcnum ) { - printf( "Can't write to the event log\n" ); + status = evlog_push_record_tdb( mem_ctx, ELOG_TDB_CTX(etdb), + &ee, &record_number ); + if ( !NT_STATUS_IS_OK(status) ) { + printf( "Can't write to the event log: %s\n", + nt_errstr(status) ); } else { if ( opt_debug ) printf( "Wrote record %d\n", - rcnum ); + record_number ); } } else { if ( opt_debug ) @@ -156,6 +163,54 @@ static int DoWriteCommand( int argc, char **argv, bool debugflag, char *exename return 0; } +static int DoDumpCommand(int argc, char **argv, bool debugflag, char *exename) +{ + ELOG_TDB *etdb; + TALLOC_CTX *mem_ctx = talloc_tos(); + const char *tdb_filename; + uint32_t count = 1; + + if (argc > 2) { + return -1; + } + + tdb_filename = argv[0]; + + if (argc > 1) { + count = atoi(argv[1]); + } + + etdb = elog_open_tdb(argv[0], false, true); + if (!etdb) { + printf("can't open the eventlog TDB (%s)\n", argv[0]); + return -1; + } + + while (1) { + + struct eventlog_Record_tdb *r; + char *s; + + r = evlog_pull_record_tdb(mem_ctx, etdb->tdb, count); + if (!r) { + break; + } + + printf("displaying record: %d\n", count); + + s = NDR_PRINT_STRUCT_STRING(mem_ctx, eventlog_Record_tdb, r); + if (s) { + printf("%s\n", s); + talloc_free(s); + } + count++; + } + + elog_close_tdb(etdb, false); + + return 0; +} + /* would be nice to use the popT stuff here, however doing so forces us to drag in a lot of other infrastructure */ int main( int argc, char *argv[] ) @@ -221,6 +276,10 @@ int main( int argc, char *argv[] ) rc = DoWriteCommand( argc, argv, opt_debug, exename ); break; } + if ( !StrCaseCmp( opname, "dump" ) ) { + rc = DoDumpCommand( argc, argv, opt_debug, exename ); + break; + } printf( "unknown command [%s]\n", opname ); usage( exename ); exit( 1 ); diff --git a/source3/utils/net.c b/source3/utils/net.c index c9525ab2eb..d483198a9e 100644 --- a/source3/utils/net.c +++ b/source3/utils/net.c @@ -589,6 +589,14 @@ static struct functable net_func[] = { " Use 'net help lua' to get more information about 'net " "lua' commands." }, + { "eventlog", + net_eventlog, + NET_TRANSPORT_LOCAL, + "Dump Win32 *.evt eventlog files", + " Use 'net help eventlog' to get more information about 'net " + "eventlog' commands." + }, + #ifdef WITH_FAKE_KASERVER { "afs", net_afs, diff --git a/source3/utils/net_ads.c b/source3/utils/net_ads.c index 766f3216f0..86fb9f6782 100644 --- a/source3/utils/net_ads.c +++ b/source3/utils/net_ads.c @@ -1920,7 +1920,7 @@ int net_ads_changetrustpw(struct net_context *c, int argc, const char **argv) d_printf("Password change for principal %s succeeded.\n", host_principal); - if (lp_use_kerberos_keytab()) { + if (USE_SYSTEM_KEYTAB) { d_printf("Attempting to update system keytab with new password.\n"); if (ads_keytab_create_default(ads)) { d_printf("Failed to update system keytab.\n"); @@ -2241,9 +2241,9 @@ int net_ads_keytab(struct net_context *c, int argc, const char **argv) {NULL, NULL, 0, NULL, NULL} }; - if (!lp_use_kerberos_keytab()) { - d_printf("\nWarning: \"use kerberos keytab\" must be set to \"true\" in order to \ -use keytab functions.\n"); + if (!USE_KERBEROS_KEYTAB) { + d_printf("\nWarning: \"kerberos method\" must be set to a " + "keytab method to use keytab functions.\n"); } return net_run_function(c, argc, argv, "net ads keytab", func); diff --git a/source3/utils/net_eventlog.c b/source3/utils/net_eventlog.c new file mode 100644 index 0000000000..197a7cd330 --- /dev/null +++ b/source3/utils/net_eventlog.c @@ -0,0 +1,313 @@ +/* + * Samba Unix/Linux SMB client library + * Distributed SMB/CIFS Server Management Utility + * Local win32 eventlog interface + * + * Copyright (C) Guenther Deschner 2009 + * + * 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 "utils/net.h" + +/** + * Dump an *evt win32 eventlog file + * + * @param argc Standard main() style argc. + * @param argv Standard main() style argv. Initial components are already + * stripped. + * + * @return A shell status integer (0 for success). + **/ + +static int net_eventlog_dump(struct net_context *c, int argc, + const char **argv) +{ + int ret = -1; + TALLOC_CTX *ctx = talloc_stackframe(); + enum ndr_err_code ndr_err; + DATA_BLOB blob; + struct EVENTLOG_EVT_FILE evt; + char *s; + + if (argc < 1 || c->display_usage) { + d_fprintf(stderr, "usage: net eventlog dump <file.evt>\n"); + goto done; + } + + blob.data = (uint8_t *)file_load(argv[0], &blob.length, 0, ctx); + if (!blob.data) { + d_fprintf(stderr, "failed to load evt file: %s\n", argv[0]); + goto done; + } + + ndr_err = ndr_pull_struct_blob(&blob, ctx, NULL, &evt, + (ndr_pull_flags_fn_t)ndr_pull_EVENTLOG_EVT_FILE); + if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { + d_fprintf(stderr, "evt pull failed: %s\n", ndr_errstr(ndr_err)); + goto done; + } + + s = NDR_PRINT_STRUCT_STRING(ctx, EVENTLOG_EVT_FILE, &evt); + if (s) { + printf("%s\n", s); + } + + ret = 0; + done: + TALLOC_FREE(ctx); + return ret; +} + +/** + * Import an *evt win32 eventlog file to internal tdb representation + * + * @param argc Standard main() style argc. + * @param argv Standard main() style argv. Initial components are already + * stripped. + * + * @return A shell status integer (0 for success). + **/ + +static int net_eventlog_import(struct net_context *c, int argc, + const char **argv) +{ + int ret = -1; + TALLOC_CTX *ctx = talloc_stackframe(); + NTSTATUS status; + enum ndr_err_code ndr_err; + DATA_BLOB blob; + uint32_t num_records = 0; + uint32_t i; + ELOG_TDB *etdb = NULL; + + struct EVENTLOGHEADER evt_header; + struct EVENTLOG_EVT_FILE evt; + + if (argc < 2 || c->display_usage) { + d_fprintf(stderr, "usage: net eventlog import <file> <eventlog>\n"); + goto done; + } + + blob.data = (uint8_t *)file_load(argv[0], &blob.length, 0, ctx); + if (!blob.data) { + d_fprintf(stderr, "failed to load evt file: %s\n", argv[0]); + goto done; + } + + /* dump_data(0, blob.data, blob.length); */ + ndr_err = ndr_pull_struct_blob(&blob, ctx, NULL, &evt_header, + (ndr_pull_flags_fn_t)ndr_pull_EVENTLOGHEADER); + if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { + d_fprintf(stderr, "evt header pull failed: %s\n", ndr_errstr(ndr_err)); + goto done; + } + + if (evt_header.Flags & ELF_LOGFILE_HEADER_WRAP) { + d_fprintf(stderr, "input file is wrapped, cannot proceed\n"); + goto done; + } + + ndr_err = ndr_pull_struct_blob(&blob, ctx, NULL, &evt, + (ndr_pull_flags_fn_t)ndr_pull_EVENTLOG_EVT_FILE); + if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { + d_fprintf(stderr, "evt pull failed: %s\n", ndr_errstr(ndr_err)); + goto done; + } + + /* NDR_PRINT_DEBUG(EVENTLOG_EVT_FILE, &evt); */ + + etdb = elog_open_tdb(argv[1], false, false); + if (!etdb) { + d_fprintf(stderr, "can't open the eventlog TDB (%s)\n", argv[1]); + goto done; + } + + num_records = evt.hdr.CurrentRecordNumber - evt.hdr.OldestRecordNumber; + + for (i=0; i<num_records; i++) { + uint32_t record_number; + struct eventlog_Record_tdb e; + + status = evlog_evt_entry_to_tdb_entry(ctx, &evt.records[i], &e); + if (!NT_STATUS_IS_OK(status)) { + goto done; + } + + status = evlog_push_record_tdb(ctx, ELOG_TDB_CTX(etdb), + &e, &record_number); + if (!NT_STATUS_IS_OK(status)) { + d_fprintf(stderr, "can't write to the eventlog: %s\n", + nt_errstr(status)); + goto done; + } + } + + printf("wrote %d entries to tdb\n", i); + + ret = 0; + done: + + elog_close_tdb(etdb, false); + + TALLOC_FREE(ctx); + return ret; +} + +/** + * Export internal eventlog tdb representation to an *evt win32 eventlog file + * + * @param argc Standard main() style argc. + * @param argv Standard main() style argv. Initial components are already + * stripped. + * + * @return A shell status integer (0 for success). + **/ + +static int net_eventlog_export(struct net_context *c, int argc, + const char **argv) +{ + int ret = -1; + NTSTATUS status; + TALLOC_CTX *ctx = talloc_stackframe(); + enum ndr_err_code ndr_err; + DATA_BLOB blob; + uint32_t num_records = 0; + struct EVENTLOG_EVT_FILE evt; + ELOG_TDB *etdb = NULL; + uint32_t count = 1; + size_t endoffset = 0; + + if (argc < 2 || c->display_usage) { + d_fprintf(stderr, "usage: net eventlog export <file> <eventlog>\n"); + goto done; + } + + etdb = elog_open_tdb(argv[1], false, true); + if (!etdb) { + d_fprintf(stderr, "can't open the eventlog TDB (%s)\n", argv[1]); + goto done; + } + + ZERO_STRUCT(evt); + + while (1) { + + struct eventlog_Record_tdb *r; + struct EVENTLOGRECORD e; + + r = evlog_pull_record_tdb(ctx, etdb->tdb, count); + if (!r) { + break; + } + + status = evlog_tdb_entry_to_evt_entry(ctx, r, &e); + if (!NT_STATUS_IS_OK(status)) { + goto done; + } + + endoffset += ndr_size_EVENTLOGRECORD(&e, NULL, 0); + + ADD_TO_ARRAY(ctx, struct EVENTLOGRECORD, e, &evt.records, &num_records); + count++; + } + + evt.hdr.StartOffset = 0x30; + evt.hdr.EndOffset = evt.hdr.StartOffset + endoffset; + evt.hdr.CurrentRecordNumber = count; + evt.hdr.OldestRecordNumber = 1; + evt.hdr.MaxSize = tdb_fetch_int32(etdb->tdb, EVT_MAXSIZE); + evt.hdr.Flags = 0; + evt.hdr.Retention = tdb_fetch_int32(etdb->tdb, EVT_RETENTION); + + if (DEBUGLEVEL >= 10) { + NDR_PRINT_DEBUG(EVENTLOGHEADER, &evt.hdr); + } + + evt.eof.BeginRecord = 0x30; + evt.eof.EndRecord = evt.hdr.StartOffset + endoffset; + evt.eof.CurrentRecordNumber = evt.hdr.CurrentRecordNumber; + evt.eof.OldestRecordNumber = evt.hdr.OldestRecordNumber; + + if (DEBUGLEVEL >= 10) { + NDR_PRINT_DEBUG(EVENTLOGEOF, &evt.eof); + } + + ndr_err = ndr_push_struct_blob(&blob, ctx, NULL, &evt, + (ndr_push_flags_fn_t)ndr_push_EVENTLOG_EVT_FILE); + if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { + d_fprintf(stderr, "evt push failed: %s\n", ndr_errstr(ndr_err)); + goto done; + } + + if (!file_save(argv[0], blob.data, blob.length)) { + d_fprintf(stderr, "failed to save evt file: %s\n", argv[0]); + goto done; + } + + ret = 0; + done: + + elog_close_tdb(etdb, false); + + TALLOC_FREE(ctx); + return ret; +} + +/** + * 'net rpc eventlog' entrypoint. + * @param argc Standard main() style argc. + * @param argv Standard main() style argv. Initial components are already + * stripped. + **/ + +int net_eventlog(struct net_context *c, int argc, const char **argv) +{ + int ret = -1; + + struct functable func[] = { + { + "dump", + net_eventlog_dump, + NET_TRANSPORT_LOCAL, + "Dump eventlog", + "net eventlog dump\n" + " Dump win32 *.evt eventlog file" + }, + { + "import", + net_eventlog_import, + NET_TRANSPORT_LOCAL, + "Import eventlog", + "net eventlog import\n" + " Import win32 *.evt eventlog file" + }, + { + "export", + net_eventlog_export, + NET_TRANSPORT_LOCAL, + "Export eventlog", + "net eventlog export\n" + " Export win32 *.evt eventlog file" + }, + + + { NULL, NULL, 0, NULL, NULL } + }; + + ret = net_run_function(c, argc, argv, "net eventlog", func); + + return ret; +} diff --git a/source3/utils/net_proto.h b/source3/utils/net_proto.h index a65fbbb6eb..75ac032db9 100644 --- a/source3/utils/net_proto.h +++ b/source3/utils/net_proto.h @@ -427,6 +427,9 @@ int net_usershare(struct net_context *c, int argc, const char **argv); int net_lua(struct net_context *c, int argc, const char **argv); +/* The following definitions come from utils/net_eventlog.c */ + +int net_eventlog(struct net_context *c, int argc, const char **argv); /* The following definitions come from utils/net_util.c */ diff --git a/source3/utils/net_rpc.c b/source3/utils/net_rpc.c index 0f59f02746..c54d479413 100644 --- a/source3/utils/net_rpc.c +++ b/source3/utils/net_rpc.c @@ -181,8 +181,7 @@ int run_rpc_command(struct net_context *c, } if (!NT_STATUS_IS_OK(nt_status)) { DEBUG(0, ("Could not initialise pipe %s. Error was %s\n", - cli_get_pipe_name_from_iface( - debug_ctx(), interface), + get_pipe_name_from_iface(interface), nt_errstr(nt_status) )); cli_shutdown(cli); return -1; @@ -797,7 +796,7 @@ static int rpc_user_info(struct net_context *c, int argc, const char **argv) status = NetUserGetGroups(c->opt_host, argv[0], 0, - (uint8_t **)&u0, + (uint8_t **)(void *)&u0, (uint32_t)-1, &entries_read, &total_entries); @@ -1394,7 +1393,7 @@ static NTSTATUS rpc_group_delete_internals(struct net_context *c, struct samr_RidTypeArray *rids = NULL; /* char **names; */ int i; - /* DOM_GID *user_gids; */ + /* struct samr_RidWithAttribute *user_gids; */ struct samr_Ids group_rids, name_types; struct lsa_String lsa_acct_name; @@ -2997,7 +2996,7 @@ static int rpc_share_list(struct net_context *c, int argc, const char **argv) status = NetShareEnum(c->opt_host, level, - (uint8_t **)&i1, + (uint8_t **)(void *)&i1, (uint32_t)-1, &entries_read, &total_entries, @@ -3022,7 +3021,7 @@ static int rpc_share_list(struct net_context *c, int argc, const char **argv) static bool check_share_availability(struct cli_state *cli, const char *netname) { - if (!cli_send_tconX(cli, netname, "A:", "", 0)) { + if (!NT_STATUS_IS_OK(cli_tcon_andx(cli, netname, "A:", "", 0))) { d_printf("skipping [%s]: not a file share.\n", netname); return false; } @@ -4281,7 +4280,7 @@ static void show_userlist(struct rpc_pipe_client *pipe_hnd, cnum = cli->cnum; - if (!cli_send_tconX(cli, netname, "A:", "", 0)) { + if (!NT_STATUS_IS_OK(cli_tcon_andx(cli, netname, "A:", "", 0))) { return; } @@ -4378,7 +4377,6 @@ static NTSTATUS rpc_share_allowedusers_internals(struct net_context *c, { int ret; bool r; - ENUM_HND hnd; uint32 i; FILE *f; @@ -4411,8 +4409,6 @@ static NTSTATUS rpc_share_allowedusers_internals(struct net_context *c, for (i=0; i<num_tokens; i++) collect_alias_memberships(&tokens[i].token); - init_enum_hnd(&hnd, 0); - share_list.num_shares = 0; share_list.shares = NULL; @@ -4776,7 +4772,7 @@ static int rpc_file_user(struct net_context *c, int argc, const char **argv) NULL, username, 3, - (uint8_t **)&i3, + (uint8_t **)(void *)&i3, preferred_len, &entries_read, &total_entries, diff --git a/source3/utils/net_rpc_join.c b/source3/utils/net_rpc_join.c index 5651676693..0c363d373e 100644 --- a/source3/utils/net_rpc_join.c +++ b/source3/utils/net_rpc_join.c @@ -243,14 +243,17 @@ int net_rpc_join_newstyle(struct net_context *c, int argc, const char **argv) CHECK_RPC_ERR(rpccli_samr_Connect2(pipe_hnd, mem_ctx, pipe_hnd->desthost, - SEC_RIGHTS_MAXIMUM_ALLOWED, + SAMR_ACCESS_ENUM_DOMAINS + | SAMR_ACCESS_OPEN_DOMAIN, &sam_pol), "could not connect to SAM database"); CHECK_RPC_ERR(rpccli_samr_OpenDomain(pipe_hnd, mem_ctx, &sam_pol, - SEC_RIGHTS_MAXIMUM_ALLOWED, + SAMR_DOMAIN_ACCESS_LOOKUP_INFO_1 + | SAMR_DOMAIN_ACCESS_CREATE_USER + | SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT, domain_sid, &domain_pol), "could not open domain"); diff --git a/source3/utils/smbcacls.c b/source3/utils/smbcacls.c index f07b5011c8..c12778f8c7 100644 --- a/source3/utils/smbcacls.c +++ b/source3/utils/smbcacls.c @@ -76,8 +76,9 @@ static NTSTATUS cli_lsa_lookup_sid(struct cli_state *cli, char **domains; char **names; - if (!cli_send_tconX(cli, "IPC$", "?????", "", 0)) { - return cli_nt_error(cli); + status = cli_tcon_andx(cli, "IPC$", "?????", "", 0); + if (!NT_STATUS_IS_OK(status)) { + return status; } status = cli_rpc_pipe_open_noauth(cli, &ndr_table_lsarpc.syntax_id, @@ -124,8 +125,9 @@ static NTSTATUS cli_lsa_lookup_name(struct cli_state *cli, DOM_SID *sids; enum lsa_SidType *types; - if (!cli_send_tconX(cli, "IPC$", "?????", "", 0)) { - return cli_nt_error(cli); + status = cli_tcon_andx(cli, "IPC$", "?????", "", 0); + if (!NT_STATUS_IS_OK(status)) { + return status; } status = cli_rpc_pipe_open_noauth(cli, &ndr_table_lsarpc.syntax_id, diff --git a/source3/winbindd/idmap_tdb.c b/source3/winbindd/idmap_tdb.c index 99821ae501..481ac1b9ad 100644 --- a/source3/winbindd/idmap_tdb.c +++ b/source3/winbindd/idmap_tdb.c @@ -28,6 +28,11 @@ #undef DBGC_CLASS #define DBGC_CLASS DBGC_IDMAP +/* idmap version determines auto-conversion - this is the database + structure version specifier. */ + +#define IDMAP_VERSION 2 + /* High water mark keys */ #define HWM_GROUP "GROUP HWM" #define HWM_USER "USER HWM" diff --git a/source3/winbindd/winbindd.c b/source3/winbindd/winbindd.c index fad27ea224..5720bfc517 100644 --- a/source3/winbindd/winbindd.c +++ b/source3/winbindd/winbindd.c @@ -173,36 +173,161 @@ static void terminate(bool is_parent) exit(0); } -static SIG_ATOMIC_T do_sigterm = 0; +static void winbindd_sig_term_handler(struct tevent_context *ev, + struct tevent_signal *se, + int signum, + int count, + void *siginfo, + void *private_data) +{ + bool *is_parent = talloc_get_type_abort(private_data, bool); + + DEBUG(0,("Got sig[%d] terminate (is_parent=%d)\n", + signum, (int)*is_parent)); + terminate(*is_parent); +} -static void termination_handler(int signum) +bool winbindd_setup_sig_term_handler(bool parent) { - do_sigterm = 1; - sys_select_signal(signum); + struct tevent_signal *se; + bool *is_parent; + + is_parent = talloc(winbind_event_context(), bool); + if (!is_parent) { + return false; + } + + *is_parent = parent; + + se = tevent_add_signal(winbind_event_context(), + is_parent, + SIGTERM, 0, + winbindd_sig_term_handler, + is_parent); + if (!se) { + DEBUG(0,("failed to setup SIGTERM handler")); + talloc_free(is_parent); + return false; + } + + se = tevent_add_signal(winbind_event_context(), + is_parent, + SIGINT, 0, + winbindd_sig_term_handler, + is_parent); + if (!se) { + DEBUG(0,("failed to setup SIGINT handler")); + talloc_free(is_parent); + return false; + } + + se = tevent_add_signal(winbind_event_context(), + is_parent, + SIGQUIT, 0, + winbindd_sig_term_handler, + is_parent); + if (!se) { + DEBUG(0,("failed to setup SIGINT handler")); + talloc_free(is_parent); + return false; + } + + return true; } -static SIG_ATOMIC_T do_sigusr2 = 0; +static void winbindd_sig_hup_handler(struct tevent_context *ev, + struct tevent_signal *se, + int signum, + int count, + void *siginfo, + void *private_data) +{ + const char *file = (const char *)private_data; + + DEBUG(1,("Reloading services after SIGHUP\n")); + flush_caches(); + reload_services_file(file); +} -static void sigusr2_handler(int signum) +bool winbindd_setup_sig_hup_handler(const char *lfile) { - do_sigusr2 = 1; - sys_select_signal(SIGUSR2); + struct tevent_signal *se; + char *file = NULL; + + if (lfile) { + file = talloc_strdup(winbind_event_context(), + lfile); + if (!file) { + return false; + } + } + + se = tevent_add_signal(winbind_event_context(), + winbind_event_context(), + SIGHUP, 0, + winbindd_sig_hup_handler, + file); + if (!se) { + return false; + } + + return true; } -static SIG_ATOMIC_T do_sighup = 0; +static void winbindd_sig_chld_handler(struct tevent_context *ev, + struct tevent_signal *se, + int signum, + int count, + void *siginfo, + void *private_data) +{ + pid_t pid; + + while ((pid = sys_waitpid(-1, NULL, WNOHANG)) > 0) { + winbind_child_died(pid); + } +} -static void sighup_handler(int signum) +static bool winbindd_setup_sig_chld_handler(void) { - do_sighup = 1; - sys_select_signal(SIGHUP); + struct tevent_signal *se; + + se = tevent_add_signal(winbind_event_context(), + winbind_event_context(), + SIGCHLD, 0, + winbindd_sig_chld_handler, + NULL); + if (!se) { + return false; + } + + return true; } -static SIG_ATOMIC_T do_sigchld = 0; +static void winbindd_sig_usr2_handler(struct tevent_context *ev, + struct tevent_signal *se, + int signum, + int count, + void *siginfo, + void *private_data) +{ + print_winbindd_status(); +} -static void sigchld_handler(int signum) +static bool winbindd_setup_sig_usr2_handler(void) { - do_sigchld = 1; - sys_select_signal(SIGCHLD); + struct tevent_signal *se; + + se = tevent_add_signal(winbind_event_context(), + winbind_event_context(), + SIGCHLD, 0, + winbindd_sig_usr2_handler, + NULL); + if (!se) { + return false; + } + + return true; } /* React on 'smbcontrol winbindd reload-config' in the same way as on SIGHUP*/ @@ -224,7 +349,9 @@ static void msg_shutdown(struct messaging_context *msg, struct server_id server_id, DATA_BLOB *data) { - do_sigterm = 1; + /* only the parent waits for this message */ + DEBUG(0,("Got shutdown message\n")); + terminate(true); } @@ -797,27 +924,6 @@ static bool remove_idle_client(void) return False; } -/* check if HUP has been received and reload files */ -void winbind_check_sighup(const char *lfile) -{ - if (do_sighup) { - - DEBUG(3, ("got SIGHUP\n")); - - flush_caches(); - reload_services_file(lfile); - - do_sighup = 0; - } -} - -/* check if TERM has been received */ -void winbind_check_sigterm(bool is_parent) -{ - if (do_sigterm) - terminate(is_parent); -} - /* Process incoming clients on listen_sock. We use a tricky non-blocking, non-forking, non-threaded model which allows us to handle many simultaneous connections while remaining impervious to many denial of @@ -979,26 +1085,6 @@ static void process_loop(void) #if 0 winbindd_check_cache_size(time(NULL)); #endif - - /* Check signal handling things */ - - winbind_check_sigterm(true); - winbind_check_sighup(NULL); - - if (do_sigusr2) { - print_winbindd_status(); - do_sigusr2 = 0; - } - - if (do_sigchld) { - pid_t pid; - - do_sigchld = 0; - - while ((pid = sys_waitpid(-1, NULL, WNOHANG)) > 0) { - winbind_child_died(pid); - } - } } /* Main function */ @@ -1168,18 +1254,6 @@ int main(int argc, char **argv, char **envp) BlockSignals(False, SIGHUP); BlockSignals(False, SIGCHLD); - /* Setup signal handlers */ - - CatchSignal(SIGINT, termination_handler); /* Exit on these sigs */ - CatchSignal(SIGQUIT, termination_handler); - CatchSignal(SIGTERM, termination_handler); - CatchSignal(SIGCHLD, sigchld_handler); - - CatchSignal(SIGPIPE, SIG_IGN); /* Ignore sigpipe */ - - CatchSignal(SIGUSR2, sigusr2_handler); /* Debugging sigs */ - CatchSignal(SIGHUP, sighup_handler); - if (!interactive) become_daemon(Fork, no_process_group); @@ -1207,6 +1281,19 @@ int main(int argc, char **argv, char **envp) exit(1); } + /* Setup signal handlers */ + + if (!winbindd_setup_sig_term_handler(true)) + exit(1); + if (!winbindd_setup_sig_hup_handler(NULL)) + exit(1); + if (!winbindd_setup_sig_chld_handler()) + exit(1); + if (!winbindd_setup_sig_usr2_handler()) + exit(1); + + CatchSignal(SIGPIPE, SIG_IGN); /* Ignore sigpipe */ + /* * Ensure all cache and idmap caches are consistent * and initialized before we startup. diff --git a/source3/winbindd/winbindd_cache.c b/source3/winbindd/winbindd_cache.c index a0df81eb6e..8326aba40a 100644 --- a/source3/winbindd/winbindd_cache.c +++ b/source3/winbindd/winbindd_cache.c @@ -25,6 +25,7 @@ #include "includes.h" #include "winbindd.h" +#include "tdb_validate.h" #undef DBGC_CLASS #define DBGC_CLASS DBGC_WINBIND diff --git a/source3/winbindd/winbindd_cm.c b/source3/winbindd/winbindd_cm.c index ab1218c560..35768fe7f2 100644 --- a/source3/winbindd/winbindd_cm.c +++ b/source3/winbindd/winbindd_cm.c @@ -961,15 +961,10 @@ static NTSTATUS cm_prepare_connection(const struct winbindd_domain *domain, winbindd_set_locator_kdc_envs(domain); - if (!cli_send_tconX(*cli, "IPC$", "IPC", "", 0)) { - - result = cli_nt_error(*cli); + result = cli_tcon_andx(*cli, "IPC$", "IPC", "", 0); + if (!NT_STATUS_IS_OK(result)) { DEBUG(1,("failed tcon_X with %s\n", nt_errstr(result))); - - if (NT_STATUS_IS_OK(result)) - result = NT_STATUS_UNSUCCESSFUL; - goto done; } diff --git a/source3/winbindd/winbindd_dual.c b/source3/winbindd/winbindd_dual.c index c320e96746..d40bab94ef 100644 --- a/source3/winbindd/winbindd_dual.c +++ b/source3/winbindd/winbindd_dual.c @@ -1160,6 +1160,12 @@ bool winbindd_reinit_after_fork(const char *logfilename) reopen_logs(); } + if (!winbindd_setup_sig_term_handler(false)) + return false; + if (!winbindd_setup_sig_hup_handler(override_logfile ? NULL : + logfilename)) + return false; + /* Don't handle the same messages as our parent. */ messaging_deregister(winbind_messaging_context(), MSG_SMB_CONF_UPDATED, NULL); @@ -1354,7 +1360,7 @@ static bool fork_domain_child(struct winbindd_child *child) } if (child->domain && child->domain->primary && - !lp_use_kerberos_keytab() && + !USE_KERBEROS_KEYTAB && lp_server_role() == ROLE_DOMAIN_MEMBER) { struct timeval next_change; @@ -1379,11 +1385,6 @@ static bool fork_domain_child(struct winbindd_child *child) struct timeval now; TALLOC_CTX *frame = talloc_stackframe(); - /* check for signals */ - winbind_check_sigterm(false); - winbind_check_sighup(override_logfile ? NULL : - child->logfilename); - if (run_events(winbind_event_context(), 0, NULL, NULL)) { TALLOC_FREE(frame); continue; diff --git a/source3/winbindd/winbindd_group.c b/source3/winbindd/winbindd_group.c index bc532bbce7..9d9b264124 100644 --- a/source3/winbindd/winbindd_group.c +++ b/source3/winbindd/winbindd_group.c @@ -1353,8 +1353,10 @@ void winbindd_getgrent(struct winbindd_cli_state *state) sid_copy(&group_sid, &domain->sid); sid_append_rid(&group_sid, name_list[ent->sam_entry_index].rid); - if (!NT_STATUS_IS_OK(idmap_sid_to_gid(domain->name, &group_sid, - &group_gid))) { + if (!NT_STATUS_IS_OK(idmap_sid_to_gid(domain->have_idmap_config + ? domain->name : "", + &group_sid, &group_gid))) + { union unid_t id; enum lsa_SidType type; diff --git a/source3/winbindd/winbindd_proto.h b/source3/winbindd/winbindd_proto.h index 594f8be942..977ee9c6b1 100644 --- a/source3/winbindd/winbindd_proto.h +++ b/source3/winbindd/winbindd_proto.h @@ -63,8 +63,8 @@ void setup_async_write(struct winbindd_fd_event *event, void *data, size_t lengt void *private_data); void request_error(struct winbindd_cli_state *state); void request_ok(struct winbindd_cli_state *state); -void winbind_check_sighup(const char *lfile); -void winbind_check_sigterm(bool in_parent); +bool winbindd_setup_sig_term_handler(bool parent); +bool winbindd_setup_sig_hup_handler(const char *lfile); int main(int argc, char **argv, char **envp); /* The following definitions come from winbindd/winbindd_reqtrans.c */ @@ -498,7 +498,6 @@ void winbindd_lookupname(struct winbindd_cli_state *state); void winbindd_lookuprids(struct winbindd_cli_state *state); void winbindd_sid_to_uid(struct winbindd_cli_state *state); void winbindd_sid_to_gid(struct winbindd_cli_state *state); -void winbindd_sids_to_unixids(struct winbindd_cli_state *state); void winbindd_set_mapping(struct winbindd_cli_state *state); void winbindd_remove_mapping(struct winbindd_cli_state *state); void winbindd_set_hwm(struct winbindd_cli_state *state); diff --git a/source3/winbindd/winbindd_user.c b/source3/winbindd/winbindd_user.c index 5356e16a74..62fd4d7f07 100644 --- a/source3/winbindd/winbindd_user.c +++ b/source3/winbindd/winbindd_user.c @@ -80,9 +80,17 @@ static bool winbindd_fill_pwent(TALLOC_CTX *ctx, char *dom_name, char *user_name if (!pw || !dom_name || !user_name) return False; + domain = find_domain_from_name_noinit(dom_name); + if (domain == NULL) { + DEBUG(5,("winbindd_fill_pwent: Failed to find domain for %s. " + "Disabling name alias support\n", dom_name)); + nt_status = NT_STATUS_NO_SUCH_DOMAIN; + } + /* Resolve the uid number */ - if (!NT_STATUS_IS_OK(idmap_sid_to_uid(dom_name, user_sid, + if (!NT_STATUS_IS_OK(idmap_sid_to_uid(domain->have_idmap_config ? + dom_name : "", user_sid, &pw->pw_uid))) { DEBUG(1, ("error getting user id for sid %s\n", sid_string_dbg(user_sid))); @@ -91,26 +99,18 @@ static bool winbindd_fill_pwent(TALLOC_CTX *ctx, char *dom_name, char *user_name /* Resolve the gid number */ - if (!NT_STATUS_IS_OK(idmap_sid_to_gid(dom_name, group_sid, + if (!NT_STATUS_IS_OK(idmap_sid_to_gid(domain->have_idmap_config ? + dom_name : "", group_sid, &pw->pw_gid))) { DEBUG(1, ("error getting group id for sid %s\n", sid_string_dbg(group_sid))); return False; } - strlower_m(user_name); - /* Username */ - domain = find_domain_from_name_noinit(dom_name); - if (domain) { - nt_status = normalize_name_map(ctx, domain, user_name, - &mapped_name); - } else { - DEBUG(5,("winbindd_fill_pwent: Failed to find domain for %s. " - "Disabling name alias support\n", dom_name)); - nt_status = NT_STATUS_NO_SUCH_DOMAIN; - } + strlower_m(user_name); + nt_status = normalize_name_map(ctx, domain, user_name, &mapped_name); /* Basic removal of whitespace */ if (NT_STATUS_IS_OK(nt_status)) { |