diff options
Diffstat (limited to 'source3')
66 files changed, 2496 insertions, 2253 deletions
diff --git a/source3/Makefile.in b/source3/Makefile.in index cf74182f27..1c9c0c1204 100644 --- a/source3/Makefile.in +++ b/source3/Makefile.in @@ -73,6 +73,7 @@ WINBIND_NSS_EXTRA_LIBS=@WINBIND_NSS_EXTRA_LIBS@ WINBIND_NSS_PTHREAD=@WINBIND_NSS_PTHREAD@ PAM_WINBIND_EXTRA_LIBS=@PAM_WINBIND_EXTRA_LIBS@ DNSSD_LIBS=@DNSSD_LIBS@ +AVAHI_LIBS=@AVAHI_LIBS@ POPT_LIBS=@POPTLIBS@ LIBTALLOC_LIBS=@LIBTALLOC_LIBS@ LIBTDB_LIBS=@LIBTDB_LIBS@ @@ -158,7 +159,7 @@ CODEPAGEDIR = @codepagedir@ # the directory where pid files go PIDDIR = @piddir@ -FLAGS = -I. -I$(srcdir) @FLAGS1@ @SAMBA_CPPFLAGS@ $(CPPFLAGS) -I$(CTDBDIR)/include $(ISA) -I$(srcdir)/lib -I.. -D_SAMBA_BUILD_=3 -I../source4 +FLAGS = -I. -I$(srcdir) @FLAGS1@ @SAMBA_CPPFLAGS@ $(CPPFLAGS) $(ISA) -I$(srcdir)/lib -I.. -D_SAMBA_BUILD_=3 -I../source4 PATH_FLAGS = -DSMB_PASSWD_FILE=\"$(SMB_PASSWD_FILE)\" \ -DPRIVATE_DIR=\"$(PRIVATE_DIR)\" \ @@ -173,7 +174,6 @@ PATH_FLAGS = -DSMB_PASSWD_FILE=\"$(SMB_PASSWD_FILE)\" \ -DMODULESDIR=\"$(MODULESDIR)\" \ -DLOGFILEBASE=\"$(LOGFILEBASE)\" \ -DSHLIBEXT=\"@SHLIBEXT@\" \ - -DCTDBDIR=\"$(CTDBDIR)\" \ -DNCALRPCDIR=\"$(NCALRPCDIR)\" \ -DCONFIGDIR=\"$(CONFIGDIR)\" \ -DCODEPAGEDIR=\"$(CODEPAGEDIR)\" \ @@ -255,6 +255,8 @@ AFS_OBJ = lib/afs.o AFS_SETTOKEN_OBJ = lib/afs_settoken.o +AVAHI_OBJ = @AVAHI_OBJ@ + SERVER_MUTEX_OBJ = lib/server_mutex.o PASSCHANGE_OBJ = libsmb/passchange.o @@ -282,7 +284,8 @@ LIBNDR_OBJ = ../librpc/ndr/ndr_basic.o \ ../librpc/ndr/ndr_sec_helper.o \ librpc/ndr/ndr_string.o \ ../librpc/ndr/uuid.o \ - librpc/ndr/util.o + librpc/ndr/util.o \ + ../librpc/gen_ndr/ndr_dcerpc.o RPCCLIENT_NDR_OBJ = rpc_client/ndr.o @@ -316,7 +319,7 @@ RPC_PARSE_OBJ0 = rpc_parse/parse_prs.o rpc_parse/parse_misc.o # this includes only the low level parse code, not stuff # that requires knowledge of security contexts -RPC_PARSE_OBJ1 = $(RPC_PARSE_OBJ0) rpc_parse/parse_sec.o +RPC_PARSE_OBJ1 = $(RPC_PARSE_OBJ0) RPC_PARSE_OBJ2 = rpc_parse/parse_rpc.o \ rpc_client/init_netlogon.o \ @@ -364,7 +367,8 @@ LIB_OBJ = $(LIBSAMBAUTIL_OBJ) $(UTIL_OBJ) $(CRYPTO_OBJ) \ lib/util.o lib/util_sock.o lib/sock_exec.o lib/util_sec.o \ lib/substitute.o lib/dbwrap_util.o \ lib/ms_fnmatch.o lib/select.o lib/errmap_unix.o \ - lib/tallocmsg.o lib/dmallocmsg.o libsmb/smb_signing.o \ + lib/tallocmsg.o lib/dmallocmsg.o \ + libsmb/clisigning.o libsmb/smb_signing.o \ lib/iconv.o lib/pam_errors.o intl/lang_tdb.o \ lib/conn_tdb.o lib/adt_tree.o lib/gencache.o \ lib/module.o lib/events.o @LIBTEVENT_OBJ0@ \ @@ -687,6 +691,7 @@ VFS_ONEFS_OBJ = modules/vfs_onefs.o modules/onefs_acl.o modules/onefs_system.o \ VFS_ONEFS_SHADOW_COPY_OBJ = modules/vfs_onefs_shadow_copy.o modules/onefs_shadow_copy.o PERFCOUNT_ONEFS_OBJ = modules/perfcount_onefs.o PERFCOUNT_TEST_OBJ = modules/perfcount_test.o +VFS_DIRSORT_OBJ = modules/vfs_dirsort.o PLAINTEXT_AUTH_OBJ = auth/pampass.o auth/pass_check.o @@ -731,7 +736,7 @@ SMBD_OBJ_SRV = smbd/files.o smbd/chgpasswd.o smbd/connection.o \ smbd/change_trust_pw.o smbd/fake_file.o \ smbd/quotas.o smbd/ntquotas.o $(AFS_OBJ) smbd/msdfs.o \ $(AFS_SETTOKEN_OBJ) smbd/aio.o smbd/statvfs.o \ - smbd/dmapi.o \ + smbd/dmapi.o smbd/signing.o \ smbd/file_access.o \ smbd/dnsregister.o smbd/globals.o \ $(MANGLE_OBJ) @VFS_STATIC@ @@ -741,7 +746,7 @@ SMBD_OBJ_BASE = $(PARAM_WITHOUT_REG_OBJ) $(SMBD_OBJ_SRV) $(LIBSMB_OBJ) \ $(LOCKING_OBJ) $(PASSDB_OBJ) $(PRINTING_OBJ) $(PROFILE_OBJ) \ $(LIB_OBJ) $(PRINTBACKEND_OBJ) $(OPLOCK_OBJ) \ $(NOTIFY_OBJ) $(GROUPDB_OBJ) $(AUTH_OBJ) \ - $(LIBMSRPC_OBJ) $(LIBMSRPC_GEN_OBJ) \ + $(LIBMSRPC_OBJ) $(LIBMSRPC_GEN_OBJ) $(AVAHI_OBJ) \ $(LIBADS_OBJ) $(KRBCLIENT_OBJ) $(LIBADS_SERVER_OBJ) \ $(REG_FULL_OBJ) $(POPT_LIB_OBJ) $(BUILDOPT_OBJ) \ $(SMBLDAP_OBJ) $(LDB_OBJ) $(LIBNET_OBJ) @LIBWBCLIENT_STATIC@ \ @@ -1277,6 +1282,10 @@ everything:: all libtalloc libsmbclient libnetapi debug2html smbfilter talloctor .SUFFIXES: .SUFFIXES: .c .o .lo +.PHONY: showflags SHOWFLAGS + +showflags: SHOWFLAGS + SHOWFLAGS:: @echo "Using CFLAGS = $(CFLAGS)" @echo " PICFLAG = $(PICFLAG)" @@ -1385,7 +1394,7 @@ bin/smbd@EXEEXT@: $(BINARY_PREREQS) $(SMBD_OBJ) @LIBTALLOC_SHARED@ @LIBTDB_SHARE @echo Linking $@ @$(CC) -o $@ $(SMBD_OBJ) $(LDFLAGS) $(LDAP_LIBS) \ $(KRB5LIBS) $(DYNEXP) $(PRINT_LIBS) $(AUTH_LIBS) \ - $(ACL_LIBS) $(PASSDB_LIBS) $(LIBS) $(DNSSD_LIBS) \ + $(ACL_LIBS) $(PASSDB_LIBS) $(LIBS) $(DNSSD_LIBS) $(AVAHI_LIBS) \ $(POPT_LIBS) @SMBD_LIBS@ $(LIBTALLOC_LIBS) $(LIBTDB_LIBS) \ $(WINBIND_LIBS) $(ZLIB_LIBS) @@ -1433,19 +1442,19 @@ bin/smbspool@EXEEXT@: $(BINARY_PREREQS) $(CUPS_OBJ) @BUILD_POPT@ @LIBTALLOC_SHAR @$(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@ +bin/mount.cifs@EXEEXT@: $(BINARY_PREREQS) $(CIFS_MOUNT_OBJ) @echo Linking $@ - @$(CC) -o $@ $(CIFS_MOUNT_OBJ) $(DYNEXP) $(LDFLAGS) $(POPT_LIBS) + @$(CC) -o $@ $(CIFS_MOUNT_OBJ) $(DYNEXP) $(LDFLAGS) -bin/umount.cifs@EXEEXT@: $(BINARY_PREREQS) $(CIFS_UMOUNT_OBJ) @BUILD_POPT@ +bin/umount.cifs@EXEEXT@: $(BINARY_PREREQS) $(CIFS_UMOUNT_OBJ) @echo Linking $@ - @$(CC) -o $@ $(CIFS_UMOUNT_OBJ) $(DYNEXP) $(LDFLAGS) $(POPT_LIBS) + @$(CC) -o $@ $(CIFS_UMOUNT_OBJ) $(DYNEXP) $(LDFLAGS) -bin/cifs.upcall@EXEEXT@: $(BINARY_PREREQS) $(CIFS_UPCALL_OBJ) $(LIBSMBCLIENT_OBJ1) @BUILD_POPT@ @LIBTALLOC_SHARED@ @LIBTDB_SHARED@ @LIBWBCLIENT_SHARED@ +bin/cifs.upcall@EXEEXT@: $(BINARY_PREREQS) $(CIFS_UPCALL_OBJ) $(LIBSMBCLIENT_OBJ1) @LIBTALLOC_SHARED@ @LIBTDB_SHARED@ @LIBWBCLIENT_SHARED@ @echo Linking $@ @$(CC) -o $@ $(CIFS_UPCALL_OBJ) $(DYNEXP) $(LDFLAGS) \ -lkeyutils $(LIBS) $(LIBSMBCLIENT_OBJ1) $(KRB5LIBS) \ - $(LDAP_LIBS) $(POPT_LIBS) $(LIBTALLOC_LIBS) $(WINBIND_LIBS) \ + $(LDAP_LIBS) $(LIBTALLOC_LIBS) $(WINBIND_LIBS) \ $(LIBTDB_LIBS) $(NSCD_LIBS) bin/testparm@EXEEXT@: $(BINARY_PREREQS) $(TESTPARM_OBJ) @BUILD_POPT@ @LIBTALLOC_SHARED@ @LIBTDB_SHARED@ @@ -1571,7 +1580,7 @@ bin/pdbtest@EXEEXT@: $(BINARY_PREREQS) $(PDBTEST_OBJ) @BUILD_POPT@ @LIBTALLOC_SH bin/vfstest@EXEEXT@: $(BINARY_PREREQS) $(VFSTEST_OBJ) @BUILD_POPT@ @LIBTALLOC_SHARED@ @LIBTDB_SHARED@ @LIBWBCLIENT_SHARED@ @echo Linking $@ - @$(CC) -o $@ $(VFSTEST_OBJ) $(LDFLAGS) $(TERMLDFLAGS) \ + @$(CC) -o $@ $(VFSTEST_OBJ) $(LDFLAGS) $(TERMLDFLAGS) $(AVAHI_LIBS) \ $(TERMLIBS) $(DYNEXP) $(PRINT_LIBS) $(AUTH_LIBS) $(DNSSD_LIBS) \ $(ACL_LIBS) $(LIBS) $(POPT_LIBS) $(KRB5LIBS) $(LDAP_LIBS) \ @SMBD_LIBS@ $(NSCD_LIBS) $(LIBTALLOC_LIBS) $(LIBTDB_LIBS) \ @@ -1609,37 +1618,37 @@ bin/ldbedit: $(BINARY_PREREQS) $(LDBEDIT_OBJ) @BUILD_POPT@ @LIBTALLOC_SHARED@ @L @echo Linking $@ @$(CC) -o $@ $(LDBEDIT_OBJ) $(DYNEXP) $(LDFLAGS) \ $(LIBS) $(POPT_LIBS) $(LDAP_LIBS) \ - $(LIBTALLOC_LIBS) $(LIBTDB_LIBS) $(WINBIND_LIBS) + $(LIBTALLOC_LIBS) $(LIBTDB_LIBS) bin/ldbsearch: $(BINARY_PREREQS) $(LDBSEARCH_OBJ) @BUILD_POPT@ @LIBTALLOC_SHARED@ @LIBTDB_SHARED@ @LIBWBCLIENT_SHARED@ @echo Linking $@ @$(CC) -o $@ $(LDBSEARCH_OBJ) $(DYNEXP) $(LDFLAGS) \ $(LIBS) $(POPT_LIBS) $(LDAP_LIBS) \ - $(LIBTALLOC_LIBS) $(LIBTDB_LIBS) $(WINBIND_LIBS) + $(LIBTALLOC_LIBS) $(LIBTDB_LIBS) bin/ldbadd: $(BINARY_PREREQS) $(LDBADD_OBJ) @BUILD_POPT@ @LIBTALLOC_SHARED@ @LIBTDB_SHARED@ @LIBWBCLIENT_SHARED@ @echo Linking $@ @$(CC) -o $@ $(LDBADD_OBJ) $(DYNEXP) $(LDFLAGS) \ $(LIBS) $(POPT_LIBS) $(LDAP_LIBS) \ - $(LIBTALLOC_LIBS) $(LIBTDB_LIBS) $(WINBIND_LIBS) + $(LIBTALLOC_LIBS) $(LIBTDB_LIBS) bin/ldbmodify: $(BINARY_PREREQS) $(LDBMODIFY_OBJ) @BUILD_POPT@ @LIBTALLOC_SHARED@ @LIBTDB_SHARED@ @LIBWBCLIENT_SHARED@ @echo Linking $@ @$(CC) -o $@ $(LDBMODIFY_OBJ) $(DYNEXP) $(LDFLAGS) \ $(LIBS) $(POPT_LIBS) $(LDAP_LIBS) \ - $(LIBTALLOC_LIBS) $(LIBTDB_LIBS) $(WINBIND_LIBS) + $(LIBTALLOC_LIBS) $(LIBTDB_LIBS) bin/ldbdel: $(BINARY_PREREQS) $(LDBDEL_OBJ) @BUILD_POPT@ @LIBTALLOC_SHARED@ @LIBTDB_SHARED@ @LIBWBCLIENT_SHARED@ @echo Linking $@ @$(CC) -o $@ $(LDBDEL_OBJ) $(DYNEXP) $(LDFLAGS) \ $(LIBS) $(POPT_LIBS) $(LDAP_LIBS) \ - $(LIBTALLOC_LIBS) $(LIBTDB_LIBS) $(WINBIND_LIBS) + $(LIBTALLOC_LIBS) $(LIBTDB_LIBS) bin/ldbrename: $(BINARY_PREREQS) $(LDBRENAME_OBJ) @BUILD_POPT@ @LIBTALLOC_SHARED@ @LIBTDB_SHARED@ @LIBWBCLIENT_SHARED@ @echo Linking $@ @$(CC) $(FLAGS) -o $@ $(LDBRENAME_OBJ) $(DYNEXP) $(LDFLAGS) \ $(LIBS) $(POPT_LIBS) $(LDAP_LIBS) \ - $(LIBTALLOC_LIBS) $(LIBTDB_LIBS) $(WINBIND_LIBS) + $(LIBTALLOC_LIBS) $(LIBTDB_LIBS) bin/versiontest: $(BINARY_PREREQS) lib/version_test.o $(VERSION_OBJ) @echo Linking $@ @@ -2625,6 +2634,10 @@ bin/security.@SHLIBEXT@: $(BINARY_PREREQS) libgpo/gpext/security.o @echo "Building plugin $@" @$(SHLD_MODULE) libgpo/gpext/security.o +bin/dirsort.@SHLIBEXT@: $(BINARY_PREREQS) $(VFS_DIRSORT_OBJ) + @echo "Building plugin $@" + @$(SHLD_MODULE) $(VFS_DIRSORT_OBJ) + ######################################################### ## IdMap NSS plugins @@ -2648,7 +2661,7 @@ bin/ntlm_auth@EXEEXT@: $(BINARY_PREREQS) $(NTLM_AUTH_OBJ) $(PARAM_OBJ) \ bin/pam_smbpass.@SHLIBEXT@: $(BINARY_PREREQS) $(PAM_SMBPASS_OBJ) @LIBTALLOC_SHARED@ @LIBWBCLIENT_SHARED@ @LIBTDB_SHARED@ @echo "Linking shared library $@" @$(SHLD) $(LDSHFLAGS) -o $@ $(PAM_SMBPASS_OBJ) -lpam $(DYNEXP) \ - $(LIBS) $(LDAP_LIBS) $(KRB5LIBS) $(NSCD_LIBS) \ + $(LIBS) $(LDAP_LIBS) $(NSCD_LIBS) \ $(LIBTALLOC_LIBS) $(LIBTDB_LIBS) $(WINBIND_LIBS) bin/tdbbackup@EXEEXT@: $(BINARY_PREREQS) $(TDBBACKUP_OBJ) @LIBTALLOC_SHARED@ @LIBTDB_SHARED@ diff --git a/source3/configure.in b/source3/configure.in index dc5850aba1..1cf8d9ca4a 100644 --- a/source3/configure.in +++ b/source3/configure.in @@ -152,13 +152,11 @@ AC_SUBST(NSCD_LIBS) # do this here since AC_CACHE_CHECK apparently sets the CFLAGS to "-g -O2" # if it has no value. This prevent *very* large debug binaries from occurring # by default. -if test "x$CFLAGS" = x; then - CFLAGS="-O" -fi if test "x$debug" = "xyes" ; then CFLAGS="${CFLAGS} -g" -else - CFLAGS="${CFLAGS} -O" +fi +if test "x$CFLAGS" = x; then + CFLAGS="-O" fi m4_include(../lib/socket_wrapper/config.m4) @@ -879,7 +877,7 @@ fi AC_CHECK_FUNCS(dirfd) if test x"$ac_cv_func_dirfd" = x"yes"; then - default_shared_modules="$default_shared_modules vfs_syncops" + default_shared_modules="$default_shared_modules vfs_syncops vfs_dirsort" fi AC_CACHE_CHECK([for struct sigevent type],samba_cv_struct_sigevent, [ @@ -5975,10 +5973,10 @@ AC_SUBST(FLAGS1) # Check if user wants DNS service discovery support AC_ARG_ENABLE(dnssd, -[AS_HELP_STRING([--enable-dnssd], [Enable DNS service discovery support (default=auto)])]) +[AS_HELP_STRING([--enable-dnssd], [Enable DNS service discovery support (default=no)])]) AC_SUBST(DNSSD_LIBS) -if test x"$enable_dnssd" != x"no"; then +if test x"$enable_dnssd" == x"yes"; then have_dnssd_support=yes AC_CHECK_HEADERS(dns_sd.h) @@ -6007,6 +6005,42 @@ if test x"$enable_dnssd" != x"no"; then fi ################################################# +# Check if user wants avahi support + +AC_ARG_ENABLE(avahi, +[AS_HELP_STRING([--enable-avahi], [Enable Avahi support (default=auto)])]) + +AC_SUBST(AVAHI_LIBS) +if test x"$enable_avahi" != x"no"; then + have_avahi_support=yes + + AC_CHECK_HEADERS(avahi-common/watch.h) + if test x"$ac_cv_header_avahi_common_watch_h" != x"yes"; then + have_avahi_support=no + fi + + AC_CHECK_HEADERS(avahi-client/client.h) + if test x"$ac_cv_header_avahi_common_watch_h" != x"yes"; then + have_avahi_support=no + fi + + AC_CHECK_LIB_EXT(avahi-client, AVAHI_LIBS, avahi_client_new) + if test x"$ac_cv_lib_ext_avahi_client_avahi_client_new" != x"yes"; then + have_avahi_support=no + fi + + if test x"$have_avahi_support" = x"yes"; then + AC_DEFINE(WITH_AVAHI_SUPPORT, 1, + [Whether to enable avahi support]) + AC_SUBST(AVAHI_OBJ, "lib/avahi.o smbd/avahi_register.o") + else + if test x"$enable_avahi" = x"yes"; then + AC_MSG_ERROR(avahi support not available) + fi + fi +fi + +################################################# # Check to see if we should use the included iniparser AC_ARG_WITH(included-iniparser, @@ -6213,6 +6247,7 @@ SMB_MODULE(vfs_acl_tdb, \$(VFS_ACL_TDB_OBJ), "bin/acl_tdb.$SHLIBEXT", VFS) SMB_MODULE(vfs_smb_traffic_analyzer, \$(VFS_SMB_TRAFFIC_ANALYZER_OBJ), "bin/smb_traffic_analyzer.$SHLIBEXT", VFS) SMB_MODULE(vfs_onefs, \$(VFS_ONEFS), "bin/onefs.$SHLIBEXT", VFS) SMB_MODULE(vfs_onefs_shadow_copy, \$(VFS_ONEFS_SHADOW_COPY), "bin/onefs_shadow_copy.$SHLIBEXT", VFS) +SMB_MODULE(vfs_dirsort, \$(VFS_DIRSORT_OBJ), "bin/dirsort.$SHLIBEXT", VFS) SMB_SUBSYSTEM(VFS,smbd/vfs.o) diff --git a/source3/include/async_smb.h b/source3/include/async_smb.h index 7fc4ff7d27..2ac1101a1e 100644 --- a/source3/include/async_smb.h +++ b/source3/include/async_smb.h @@ -63,6 +63,8 @@ struct cli_request { */ uint16_t mid; + uint32_t seqnum; + /** * The bytes we have to ship to the server */ diff --git a/source3/include/client.h b/source3/include/client.h index 320a90e66b..73a1d7b554 100644 --- a/source3/include/client.h +++ b/source3/include/client.h @@ -71,26 +71,26 @@ struct rpc_cli_transport { /** * Trigger an async read from the server. May return a short read. */ - struct async_req *(*read_send)(TALLOC_CTX *mem_ctx, - struct event_context *ev, - uint8_t *data, size_t size, - void *priv); + struct tevent_req *(*read_send)(TALLOC_CTX *mem_ctx, + struct event_context *ev, + uint8_t *data, size_t size, + void *priv); /** * Get the result from the read_send operation. */ - NTSTATUS (*read_recv)(struct async_req *req, ssize_t *preceived); + NTSTATUS (*read_recv)(struct tevent_req *req, ssize_t *preceived); /** * Trigger an async write to the server. May return a short write. */ - struct async_req *(*write_send)(TALLOC_CTX *mem_ctx, - struct event_context *ev, - const uint8_t *data, size_t size, - void *priv); + struct tevent_req *(*write_send)(TALLOC_CTX *mem_ctx, + struct event_context *ev, + const uint8_t *data, size_t size, + void *priv); /** * Get the result from the read_send operation. */ - NTSTATUS (*write_recv)(struct async_req *req, ssize_t *psent); + NTSTATUS (*write_recv)(struct tevent_req *req, ssize_t *psent); /** * This is an optimization for the SMB transport. It models the @@ -98,15 +98,15 @@ struct rpc_cli_transport { * trip. The transport implementation is free to set this to NULL, * cli_pipe.c will fall back to the explicit write/read routines. */ - struct async_req *(*trans_send)(TALLOC_CTX *mem_ctx, - struct event_context *ev, - uint8_t *data, size_t data_len, - uint32_t max_rdata_len, - void *priv); + struct tevent_req *(*trans_send)(TALLOC_CTX *mem_ctx, + struct event_context *ev, + uint8_t *data, size_t data_len, + uint32_t max_rdata_len, + void *priv); /** * Get the result from the trans_send operation. */ - NTSTATUS (*trans_recv)(struct async_req *req, TALLOC_CTX *mem_ctx, + NTSTATUS (*trans_recv)(struct tevent_req *req, TALLOC_CTX *mem_ctx, uint8_t **prdata, uint32_t *prdata_len); void *priv; }; @@ -166,6 +166,13 @@ struct smb_trans_enc_state { } s; }; +struct cli_state_seqnum { + struct cli_state_seqnum *prev, *next; + uint16_t mid; + uint32_t seqnum; + bool persistent; +}; + struct cli_state { /** * A list of subsidiary connections for DFS. @@ -217,6 +224,7 @@ struct cli_state { size_t max_xmit; size_t max_mux; char *outbuf; + struct cli_state_seqnum *seqnum; char *inbuf; unsigned int bufsize; int initialised; @@ -231,7 +239,7 @@ struct cli_state { TALLOC_CTX *call_mem_ctx; #endif - smb_sign_info sign_info; + struct smb_signing_state *signing_state; struct smb_trans_enc_state *trans_enc_state; /* Setup if we're encrypting SMB's. */ diff --git a/source3/include/includes.h b/source3/include/includes.h index 4bf4b5c735..c883e17713 100644 --- a/source3/include/includes.h +++ b/source3/include/includes.h @@ -598,6 +598,7 @@ struct smb_iconv_convenience *lp_iconv_convenience(void *lp_ctx); #include "messages.h" #include "locking.h" #include "smb_perfcount.h" +#include "smb_signing.h" #include "smb.h" #include "nameserv.h" #include "secrets.h" diff --git a/source3/include/proto.h b/source3/include/proto.h index 9bffa4d319..77be0aba09 100644 --- a/source3/include/proto.h +++ b/source3/include/proto.h @@ -150,6 +150,10 @@ bool is_trusted_domain(const char* dom_name); NTSTATUS auth_winbind_init(void); +/* The following definitions come from auth/auth_wbc.c */ + +NTSTATUS auth_wbc_init(void); + /* The following definitions come from auth/pampass.c */ bool smb_pam_claim_session(char *user, char *tty, char *rhost); @@ -2410,6 +2414,10 @@ bool receive_getdc_response(TALLOC_CTX *mem_ctx, int cli_set_message(char *buf,int num_words,int num_bytes,bool zero); unsigned int cli_set_timeout(struct cli_state *cli, unsigned int timeout); void cli_set_port(struct cli_state *cli, int port); +bool cli_state_seqnum_persistent(struct cli_state *cli, + uint16_t mid); +bool cli_state_seqnum_remove(struct cli_state *cli, + uint16_t mid); bool cli_receive_smb(struct cli_state *cli); ssize_t cli_receive_smb_data(struct cli_state *cli, char *buffer, size_t len); bool cli_receive_smb_readX_header(struct cli_state *cli); @@ -3181,29 +3189,34 @@ void cli_free_enc_buffer(struct cli_state *cli, char *buf); NTSTATUS cli_decrypt_message(struct cli_state *cli); NTSTATUS cli_encrypt_message(struct cli_state *cli, char *buf, char **buf_out); -/* The following definitions come from libsmb/smb_signing.c */ +/* The following definitions come from libsmb/clisigning.c */ bool cli_simple_set_signing(struct cli_state *cli, const DATA_BLOB user_session_key, const DATA_BLOB response); -bool cli_null_set_signing(struct cli_state *cli); bool cli_temp_set_signing(struct cli_state *cli); -void cli_free_signing_context(struct cli_state *cli); -void cli_calculate_sign_mac(struct cli_state *cli, char *buf); -bool cli_check_sign_mac(struct cli_state *cli, char *buf); -bool client_set_trans_sign_state_on(struct cli_state *cli, uint16 mid); -bool client_set_trans_sign_state_off(struct cli_state *cli, uint16 mid); +void cli_calculate_sign_mac(struct cli_state *cli, char *buf, uint32_t *seqnum); +bool cli_check_sign_mac(struct cli_state *cli, const char *buf, uint32_t seqnum); bool client_is_signing_on(struct cli_state *cli); -bool srv_oplock_set_signing(bool onoff); -bool srv_check_sign_mac(const char *inbuf, bool must_be_ok); -void srv_calculate_sign_mac(char *outbuf); -void srv_defer_sign_response(uint16 mid); -void srv_cancel_sign_response(uint16 mid, bool cancel); -void srv_set_signing_negotiated(void); -bool srv_is_signing_active(void); -bool srv_is_signing_negotiated(void); -bool srv_signing_started(void); -void srv_set_signing(const DATA_BLOB user_session_key, const DATA_BLOB response); +bool client_is_signing_allowed(struct cli_state *cli); +bool client_is_signing_mandatory(struct cli_state *cli); +void cli_set_signing_negotiated(struct cli_state *cli); + +/* The following definitions come from smbd/signing.c */ + +struct smbd_server_connection; +bool srv_check_sign_mac(struct smbd_server_connection *conn, + const char *inbuf, uint32_t *seqnum); +void srv_calculate_sign_mac(struct smbd_server_connection *conn, + char *outbuf, uint32_t seqnum); +void srv_cancel_sign_response(struct smbd_server_connection *conn); +bool srv_init_signing(struct smbd_server_connection *conn); +void srv_set_signing_negotiated(struct smbd_server_connection *conn); +bool srv_is_signing_active(struct smbd_server_connection *conn); +bool srv_is_signing_negotiated(struct smbd_server_connection *conn); +void srv_set_signing(struct smbd_server_connection *conn, + const DATA_BLOB user_session_key, + const DATA_BLOB response); /* The following definitions come from libsmb/smbdes.c */ @@ -3779,6 +3792,8 @@ bool send_mailslot(bool unique, const char *mailslot,char *buf, size_t len, /* The following definitions come from nmbd/nmbd_processlogon.c */ +bool initialize_nmbd_proxy_logon(void); + void process_logon_packet(struct packet_struct *p, char *buf,int len, const char *mailslot); @@ -4345,7 +4360,7 @@ const char *lp_printcapname(void); bool lp_disable_spoolss( void ); void lp_set_spoolss_state( uint32 state ); uint32 lp_get_spoolss_state( void ); -bool lp_use_sendfile(int snum); +bool lp_use_sendfile(int snum, struct smb_signing_state *signing_state); void set_use_sendfile(int snum, bool val); void set_store_dos_attributes(int snum, bool val); void lp_set_mangling_method(const char *new_method); @@ -4828,7 +4843,7 @@ WERROR add_printer_data( NT_PRINTER_INFO_LEVEL_2 *p2, const char *key, const cha REGISTRY_VALUE* get_printer_data( NT_PRINTER_INFO_LEVEL_2 *p2, const char *key, const char *value ); WERROR mod_a_printer(NT_PRINTER_INFO_LEVEL *printer, uint32 level); bool set_driver_init(NT_PRINTER_INFO_LEVEL *printer, uint32 level); -bool del_driver_init(char *drivername); +bool del_driver_init(const char *drivername); WERROR save_driver_init(NT_PRINTER_INFO_LEVEL *printer, uint32 level, uint8 *data, uint32 data_len); WERROR get_a_printer( Printer_entry *print_hnd, NT_PRINTER_INFO_LEVEL **pp_printer, @@ -4840,8 +4855,8 @@ WERROR get_a_printer_search( Printer_entry *print_hnd, const char *sharename); uint32 free_a_printer(NT_PRINTER_INFO_LEVEL **pp_printer, uint32 level); uint32 add_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL driver, uint32 level); -WERROR get_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL *driver, uint32 level, - fstring drivername, const char *architecture, uint32 version); +WERROR get_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL *driver, uint32_t level, + const char *drivername, const char *architecture, uint32_t version); uint32 free_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL driver, uint32 level); bool printer_driver_in_use ( NT_PRINTER_DRIVER_INFO_LEVEL_3 *info_3 ); bool printer_driver_files_in_use ( NT_PRINTER_DRIVER_INFO_LEVEL_3 *info ); @@ -5241,22 +5256,22 @@ NTSTATUS rpccli_netlogon_set_trust_password(struct rpc_pipe_client *cli, /* The following definitions come from rpc_client/cli_pipe.c */ -struct async_req *rpc_api_pipe_req_send(TALLOC_CTX *mem_ctx, - struct event_context *ev, - struct rpc_pipe_client *cli, - uint8_t op_num, - prs_struct *req_data); -NTSTATUS rpc_api_pipe_req_recv(struct async_req *req, TALLOC_CTX *mem_ctx, +struct tevent_req *rpc_api_pipe_req_send(TALLOC_CTX *mem_ctx, + struct event_context *ev, + struct rpc_pipe_client *cli, + uint8_t op_num, + prs_struct *req_data); +NTSTATUS rpc_api_pipe_req_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx, prs_struct *reply_pdu); NTSTATUS rpc_api_pipe_req(TALLOC_CTX *mem_ctx, struct rpc_pipe_client *cli, uint8 op_num, prs_struct *in_data, prs_struct *out_data); -struct async_req *rpc_pipe_bind_send(TALLOC_CTX *mem_ctx, - struct event_context *ev, - struct rpc_pipe_client *cli, - struct cli_pipe_auth_data *auth); -NTSTATUS rpc_pipe_bind_recv(struct async_req *req); +struct tevent_req *rpc_pipe_bind_send(TALLOC_CTX *mem_ctx, + struct event_context *ev, + struct rpc_pipe_client *cli, + struct cli_pipe_auth_data *auth); +NTSTATUS rpc_pipe_bind_recv(struct tevent_req *req); NTSTATUS rpc_pipe_bind(struct rpc_pipe_client *cli, struct cli_pipe_auth_data *auth); unsigned int rpccli_set_timeout(struct rpc_pipe_client *cli, @@ -5678,10 +5693,8 @@ NTSTATUS cli_do_rpc_ndr(struct rpc_pipe_client *cli, bool smb_io_time(const char *desc, NTTIME *nttime, prs_struct *ps, int depth); bool smb_io_system_time(const char *desc, prs_struct *ps, int depth, SYSTEMTIME *systime); bool make_systemtime(SYSTEMTIME *systime, struct tm *unixtime); -bool smb_io_dom_sid(const char *desc, DOM_SID *sid, prs_struct *ps, int depth); bool smb_io_uuid(const char *desc, struct GUID *uuid, prs_struct *ps, int depth); -void init_unistr(UNISTR *str, const char *buf); void init_unistr2(UNISTR2 *str, const char *buf, enum unistr2_term_codes flags); /* The following definitions come from rpc_parse/parse_prs.c */ @@ -5803,11 +5816,6 @@ bool smb_io_rpc_auth_schannel_chk(const char *desc, int auth_len, RPC_AUTH_SCHANNEL_CHK * chk, prs_struct *ps, int depth); -/* The following definitions come from rpc_parse/parse_sec.c */ - -bool sec_io_desc(const char *desc, SEC_DESC **ppsd, prs_struct *ps, int depth); -bool sec_io_desc_buf(const char *desc, SEC_DESC_BUF **ppsdb, prs_struct *ps, int depth); - /* The following definitions come from rpc_server/srv_eventlog_lib.c */ TDB_CONTEXT *elog_init_tdb( char *tdbfilename ); @@ -6720,7 +6728,9 @@ SEC_DESC *get_nt_acl_no_snum( TALLOC_CTX *ctx, const char *fname); 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, +bool srv_send_smb(int fd, char *buffer, + bool no_signing, uint32_t seqnum, + bool do_encrypt, struct smb_perfcount_data *pcd); int srv_set_message(char *buf, int num_words, @@ -7217,6 +7227,16 @@ NTSTATUS idmap_sid_to_gid(const char *domname, DOM_SID *sid, gid_t *gid); NTSTATUS nss_info_template_init( void ); +/* The following definitions come from lib/avahi.c */ + +struct AvahiPoll *tevent_avahi_poll(TALLOC_CTX *mem_ctx, + struct tevent_context *ev); + +/* The following definitions come from smbd/avahi_register.c */ + +void *avahi_start_register(TALLOC_CTX *mem_ctx, struct tevent_context *ev, + uint16_t port); + /* Misc protos */ #endif /* _PROTO_H_ */ diff --git a/source3/include/rpc_dce.h b/source3/include/rpc_dce.h index 580b14f1d8..ca58040757 100644 --- a/source3/include/rpc_dce.h +++ b/source3/include/rpc_dce.h @@ -81,16 +81,6 @@ enum RPC_PKT_TYPE { #define RPC_PIPE_AUTH_SEAL_LEVEL 0x6 #endif -#define DCERPC_FAULT_OP_RNG_ERROR 0x1c010002 -#define DCERPC_FAULT_UNK_IF 0x1c010003 -#define DCERPC_FAULT_INVALID_TAG 0x1c000006 -#define DCERPC_FAULT_CONTEXT_MISMATCH 0x1c00001a -#define DCERPC_FAULT_OTHER 0x00000001 -#define DCERPC_FAULT_ACCESS_DENIED 0x00000005 -#define DCERPC_FAULT_CANT_PERFORM 0x000006d8 -#define DCERPC_FAULT_NDR 0x000006f7 - - /* Netlogon schannel auth type and level */ #define SCHANNEL_SIGN_SIGNATURE { 0x77, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00 } #define SCHANNEL_SEAL_SIGNATURE { 0x77, 0x00, 0x7a, 0x00, 0xff, 0xff, 0x00, 0x00 } diff --git a/source3/include/smb.h b/source3/include/smb.h index 281a218256..01e6ddf64c 100644 --- a/source3/include/smb.h +++ b/source3/include/smb.h @@ -252,6 +252,8 @@ struct id_map { #include "librpc/gen_ndr/drsuapi.h" #include "librpc/gen_ndr/drsblobs.h" #include "librpc/gen_ndr/spoolss.h" +#include "librpc/gen_ndr/dcerpc.h" +#include "librpc/gen_ndr/ndr_dcerpc.h" struct lsa_dom_info { bool valid; @@ -621,6 +623,7 @@ struct smb_request { uint16 flags2; uint16 smbpid; uint16 mid; + uint32_t seqnum; uint16 vuid; uint16 tid; uint8 wct; @@ -722,6 +725,7 @@ struct pending_message_list { struct timeval request_time; /* When was this first issued? */ struct timed_event *te; struct smb_perfcount_data pcd; + uint32_t seqnum; bool encrypted; DATA_BLOB buf; DATA_BLOB private_data; @@ -1847,21 +1851,6 @@ struct ip_service { /* Special name type used to cause a _kerberos DNS lookup. */ #define KDC_NAME_TYPE 0xDCDC -/* Used by the SMB signing functions. */ - -typedef struct smb_sign_info { - void (*sign_outgoing_message)(char *outbuf, struct smb_sign_info *si); - bool (*check_incoming_message)(const char *inbuf, struct smb_sign_info *si, bool must_be_ok); - void (*free_signing_context)(struct smb_sign_info *si); - void *signing_context; - - bool negotiated_smb_signing; - bool allow_smb_signing; - bool doing_signing; - bool mandatory_signing; - bool seen_valid; /* Have I ever seen a validly signed packet? */ -} smb_sign_info; - struct ea_struct { uint8 flags; char *name; diff --git a/source3/include/smb_signing.h b/source3/include/smb_signing.h new file mode 100644 index 0000000000..770c40cb35 --- /dev/null +++ b/source3/include/smb_signing.h @@ -0,0 +1,46 @@ +/* + Unix SMB/CIFS implementation. + SMB Signing Code + Copyright (C) Jeremy Allison 2003. + Copyright (C) Andrew Bartlett <abartlet@samba.org> 2002-2003 + Copyright (C) Stefan Metzmacher 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/>. +*/ + +#ifndef _SMB_SIGNING_H_ +#define _SMB_SIGNING_H_ + +struct smb_signing_state; + +struct smb_signing_state *smb_signing_init(TALLOC_CTX *mem_ctx, + bool allowed, + bool mandatory); +uint32_t smb_signing_next_seqnum(struct smb_signing_state *si, bool oneway); +void smb_signing_cancel_reply(struct smb_signing_state *si, bool oneway); +void smb_signing_sign_pdu(struct smb_signing_state *si, + uint8_t *outbuf, uint32_t seqnum); +bool smb_signing_check_pdu(struct smb_signing_state *si, + const uint8_t *inbuf, uint32_t seqnum); +bool smb_signing_set_bsrspyl(struct smb_signing_state *si); +bool smb_signing_activate(struct smb_signing_state *si, + const DATA_BLOB user_session_key, + const DATA_BLOB response); +bool smb_signing_is_active(struct smb_signing_state *si); +bool smb_signing_is_allowed(struct smb_signing_state *si); +bool smb_signing_is_mandatory(struct smb_signing_state *si); +bool smb_signing_set_negotiated(struct smb_signing_state *si); +bool smb_signing_is_negotiated(struct smb_signing_state *si); + +#endif /* _SMB_SIGNING_H_ */ diff --git a/source3/lib/avahi.c b/source3/lib/avahi.c new file mode 100644 index 0000000000..269b329e64 --- /dev/null +++ b/source3/lib/avahi.c @@ -0,0 +1,275 @@ +/* + Unix SMB/CIFS implementation. + Connect avahi to lib/tevents + 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" + +#include <avahi-common/watch.h> + +struct avahi_poll_context { + struct tevent_context *ev; + AvahiWatch **watches; + AvahiTimeout **timeouts; +}; + +struct AvahiWatch { + struct avahi_poll_context *ctx; + struct tevent_fd *fde; + int fd; + AvahiWatchEvent latest_event; + AvahiWatchCallback callback; + void *userdata; +}; + +struct AvahiTimeout { + struct avahi_poll_context *ctx; + struct tevent_timer *te; + AvahiTimeoutCallback callback; + void *userdata; +}; + +static uint16_t avahi_flags_map_to_tevent(AvahiWatchEvent event) +{ + return ((event & AVAHI_WATCH_IN) ? TEVENT_FD_READ : 0) + | ((event & AVAHI_WATCH_OUT) ? TEVENT_FD_WRITE : 0); +} + +static void avahi_fd_handler(struct tevent_context *ev, + struct tevent_fd *fde, uint16_t flags, + void *private_data); + +static AvahiWatch *avahi_watch_new(const AvahiPoll *api, int fd, + AvahiWatchEvent event, + AvahiWatchCallback callback, + void *userdata) +{ + struct avahi_poll_context *ctx = talloc_get_type_abort( + api->userdata, struct avahi_poll_context); + int num_watches = talloc_array_length(ctx->watches); + AvahiWatch **tmp, *watch_ctx; + + tmp = talloc_realloc(ctx, ctx->watches, AvahiWatch *, num_watches + 1); + if (tmp == NULL) { + return NULL; + } + ctx->watches = tmp; + + watch_ctx = talloc(tmp, AvahiWatch); + if (watch_ctx == NULL) { + goto fail; + } + ctx->watches[num_watches] = watch_ctx; + + watch_ctx->ctx = ctx; + watch_ctx->fde = tevent_add_fd(ctx->ev, watch_ctx, fd, + avahi_flags_map_to_tevent(event), + avahi_fd_handler, watch_ctx); + if (watch_ctx->fde == NULL) { + goto fail; + } + watch_ctx->callback = callback; + watch_ctx->userdata = userdata; + return watch_ctx; + + fail: + TALLOC_FREE(watch_ctx); + ctx->watches = talloc_realloc(ctx, ctx->watches, AvahiWatch *, + num_watches); + return NULL; +} + +static void avahi_fd_handler(struct tevent_context *ev, + struct tevent_fd *fde, uint16_t flags, + void *private_data) +{ + AvahiWatch *watch_ctx = talloc_get_type_abort(private_data, AvahiWatch); + + watch_ctx->latest_event = + ((flags & TEVENT_FD_READ) ? AVAHI_WATCH_IN : 0) + | ((flags & TEVENT_FD_WRITE) ? AVAHI_WATCH_OUT : 0); + + watch_ctx->callback(watch_ctx, watch_ctx->fd, watch_ctx->latest_event, + watch_ctx->userdata); +} + +static void avahi_watch_update(AvahiWatch *w, AvahiWatchEvent event) +{ + tevent_fd_set_flags(w->fde, avahi_flags_map_to_tevent(event)); +} + +static AvahiWatchEvent avahi_watch_get_events(AvahiWatch *w) +{ + return w->latest_event; +} + +static void avahi_watch_free(AvahiWatch *w) +{ + int i, num_watches; + AvahiWatch **watches = w->ctx->watches; + struct avahi_poll_context *ctx; + + num_watches = talloc_array_length(watches); + + for (i=0; i<num_watches; i++) { + if (w == watches[i]) { + break; + } + } + if (i == num_watches) { + return; + } + ctx = w->ctx; + TALLOC_FREE(w); + memmove(&watches[i], &watches[i+1], + sizeof(*watches) * (num_watches - i - 1)); + ctx->watches = talloc_realloc(ctx, watches, AvahiWatch *, + num_watches - 1); +} + +static void avahi_timeout_handler(struct tevent_context *ev, + struct tevent_timer *te, + struct timeval current_time, + void *private_data); + +static AvahiTimeout *avahi_timeout_new(const AvahiPoll *api, + const struct timeval *tv, + AvahiTimeoutCallback callback, + void *userdata) +{ + struct avahi_poll_context *ctx = talloc_get_type_abort( + api->userdata, struct avahi_poll_context); + int num_timeouts = talloc_array_length(ctx->timeouts); + AvahiTimeout **tmp, *timeout_ctx; + + tmp = talloc_realloc(ctx, ctx->timeouts, AvahiTimeout *, + num_timeouts + 1); + if (tmp == NULL) { + return NULL; + } + ctx->timeouts = tmp; + + timeout_ctx = talloc(tmp, AvahiTimeout); + if (timeout_ctx == NULL) { + goto fail; + } + ctx->timeouts[num_timeouts] = timeout_ctx; + + timeout_ctx->ctx = ctx; + if (tv == NULL) { + timeout_ctx->te = NULL; + } else { + timeout_ctx->te = tevent_add_timer(ctx->ev, timeout_ctx, + *tv, avahi_timeout_handler, + timeout_ctx); + if (timeout_ctx->te == NULL) { + goto fail; + } + } + timeout_ctx->callback = callback; + timeout_ctx->userdata = userdata; + return timeout_ctx; + + fail: + TALLOC_FREE(timeout_ctx); + ctx->timeouts = talloc_realloc(ctx, ctx->timeouts, AvahiTimeout *, + num_timeouts); + return NULL; +} + +static void avahi_timeout_handler(struct tevent_context *ev, + struct tevent_timer *te, + struct timeval current_time, + void *private_data) +{ + AvahiTimeout *timeout_ctx = talloc_get_type_abort( + private_data, AvahiTimeout); + + TALLOC_FREE(timeout_ctx->te); + timeout_ctx->callback(timeout_ctx, timeout_ctx->userdata); +} + +static void avahi_timeout_update(AvahiTimeout *t, const struct timeval *tv) +{ + TALLOC_FREE(t->te); + + if (tv == NULL) { + /* + * Disable this timer + */ + return; + } + + t->te = tevent_add_timer(t->ctx->ev, t, *tv, avahi_timeout_handler, t); + /* + * No failure mode defined here + */ + SMB_ASSERT(t->te != NULL); +} + +static void avahi_timeout_free(AvahiTimeout *t) +{ + int i, num_timeouts; + AvahiTimeout **timeouts = t->ctx->timeouts; + struct avahi_poll_context *ctx; + + num_timeouts = talloc_array_length(timeouts); + + for (i=0; i<num_timeouts; i++) { + if (t == timeouts[i]) { + break; + } + } + if (i == num_timeouts) { + return; + } + ctx = t->ctx; + TALLOC_FREE(t); + memmove(&timeouts[i], &timeouts[i+1], + sizeof(*timeouts) * (num_timeouts - i - 1)); + ctx->timeouts = talloc_realloc(ctx, timeouts, AvahiTimeout *, + num_timeouts - 1); +} + +struct AvahiPoll *tevent_avahi_poll(TALLOC_CTX *mem_ctx, + struct tevent_context *ev) +{ + struct AvahiPoll *result; + struct avahi_poll_context *ctx; + + result = talloc(mem_ctx, struct AvahiPoll); + if (result == NULL) { + return result; + } + ctx = talloc_zero(result, struct avahi_poll_context); + if (ctx == NULL) { + TALLOC_FREE(result); + return NULL; + } + ctx->ev = ev; + + result->watch_new = avahi_watch_new; + result->watch_update = avahi_watch_update; + result->watch_get_events = avahi_watch_get_events; + result->watch_free = avahi_watch_free; + result->timeout_new = avahi_timeout_new; + result->timeout_update = avahi_timeout_update; + result->timeout_free = avahi_timeout_free; + result->userdata = ctx; + + return result; +} diff --git a/source3/lib/netapi/cm.c b/source3/lib/netapi/cm.c index b676ae63dd..d28b2b2126 100644 --- a/source3/lib/netapi/cm.c +++ b/source3/lib/netapi/cm.c @@ -57,6 +57,11 @@ static WERROR libnetapi_open_ipc_connection(struct libnetapi_ctx *ctx, false, false, PROTOCOL_NT1, 0, 0x20); + if (cli_ipc) { + cli_set_username(cli_ipc, ctx->username); + cli_set_password(cli_ipc, ctx->password); + cli_set_domain(cli_ipc, ctx->workgroup); + } TALLOC_FREE(auth_info); if (!cli_ipc) { diff --git a/source3/lib/netapi/user.c b/source3/lib/netapi/user.c index e760a8b1de..1cbb883169 100644 --- a/source3/lib/netapi/user.c +++ b/source3/lib/netapi/user.c @@ -1497,6 +1497,9 @@ WERROR NetQueryDisplayInformation_r(struct libnetapi_ctx *ctx, NTSTATUS status = NT_STATUS_OK; WERROR werr; + WERROR werr_tmp; + + *r->out.entries_read = 0; ZERO_STRUCT(connect_handle); ZERO_STRUCT(domain_handle); @@ -1540,15 +1543,18 @@ WERROR NetQueryDisplayInformation_r(struct libnetapi_ctx *ctx, &total_size, &returned_size, &info); - if (!NT_STATUS_IS_OK(status)) { - werr = ntstatus_to_werror(status); + werr = ntstatus_to_werror(status); + if (NT_STATUS_IS_ERR(status)) { goto done; } - werr = convert_samr_dispinfo_to_NET_DISPLAY(ctx, &info, - r->in.level, - r->out.entries_read, - r->out.buffer); + werr_tmp = convert_samr_dispinfo_to_NET_DISPLAY(ctx, &info, + r->in.level, + r->out.entries_read, + r->out.buffer); + if (!W_ERROR_IS_OK(werr_tmp)) { + werr = werr_tmp; + } done: /* if last query */ if (NT_STATUS_IS_OK(status) || diff --git a/source3/lib/util_file.c b/source3/lib/util_file.c index c5a9b7c29a..50ff844762 100644 --- a/source3/lib/util_file.c +++ b/source3/lib/util_file.c @@ -39,7 +39,7 @@ static char *file_pload(const char *syscmd, size_t *size) total = 0; while ((n = read(fd, buf, sizeof(buf))) > 0) { - p = (char *)SMB_REALLOC(p, total + n + 1); + p = talloc_realloc(NULL, p, char, total + n + 1); if (!p) { DEBUG(0,("file_pload: failed to expand buffer!\n")); close(fd); diff --git a/source3/lib/wbclient.c b/source3/lib/wbclient.c index 3cf992c7de..c22e168454 100644 --- a/source3/lib/wbclient.c +++ b/source3/lib/wbclient.c @@ -449,8 +449,8 @@ static void wb_open_pipe_connect_nonpriv_done(struct tevent_req *subreq) ZERO_STRUCT(state->wb_req); state->wb_req.cmd = WINBINDD_INTERFACE_VERSION; - subreq = wb_int_trans_send(state, state->ev, NULL, state->wb_ctx->fd, - &state->wb_req); + subreq = wb_int_trans_send(state, state->ev, state->wb_ctx->queue, + state->wb_ctx->fd, &state->wb_req); if (tevent_req_nomem(subreq, req)) { return; } @@ -480,8 +480,8 @@ static void wb_open_pipe_ping_done(struct tevent_req *subreq) state->wb_req.cmd = WINBINDD_PRIV_PIPE_DIR; - subreq = wb_int_trans_send(state, state->ev, NULL, state->wb_ctx->fd, - &state->wb_req); + subreq = wb_int_trans_send(state, state->ev, state->wb_ctx->queue, + state->wb_ctx->fd, &state->wb_req); if (tevent_req_nomem(subreq, req)) { return; } @@ -673,8 +673,8 @@ static void wb_trans_connect_done(struct tevent_req *subreq) return; } - subreq = wb_int_trans_send(state, state->ev, NULL, state->wb_ctx->fd, - state->wb_req); + subreq = wb_int_trans_send(state, state->ev, state->wb_ctx->queue, + state->wb_ctx->fd, state->wb_req); if (tevent_req_nomem(subreq, req)) { return; } diff --git a/source3/libnet/libnet_samsync.c b/source3/libnet/libnet_samsync.c index 73d4439743..0c00b8518a 100644 --- a/source3/libnet/libnet_samsync.c +++ b/source3/libnet/libnet_samsync.c @@ -422,9 +422,6 @@ static NTSTATUS libnet_samsync_delta(TALLOC_CTX *mem_ctx, TALLOC_FREE(delta_enum_array); - /* Increment sync_context */ - sync_context += 1; - } while (NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES)); out: diff --git a/source3/libsmb/async_smb.c b/source3/libsmb/async_smb.c index 066ac7bdb8..86fd5c8bef 100644 --- a/source3/libsmb/async_smb.c +++ b/source3/libsmb/async_smb.c @@ -550,7 +550,7 @@ void cli_chain_uncork(struct cli_state *cli) _smb_setlen_large(((char *)req->outbuf), smblen); } - cli_calculate_sign_mac(cli, (char *)req->outbuf); + cli_calculate_sign_mac(cli, (char *)req->outbuf, &req->seqnum); if (cli_encryption_on(cli)) { NTSTATUS status; @@ -811,9 +811,16 @@ NTSTATUS cli_pull_reply(struct async_req *req, */ -static NTSTATUS validate_smb_crypto(struct cli_state *cli, char *pdu) +static NTSTATUS validate_smb_crypto(struct cli_state *cli, char *pdu, + struct cli_request **_req, + uint16_t *_mid) { NTSTATUS status; + struct cli_request *req = NULL; + uint16_t mid; + + *_req = NULL; + *_mid = 0; if ((IVAL(pdu, 4) != 0x424d53ff) /* 0xFF"SMB" */ && (SVAL(pdu, 4) != 0x45ff)) /* 0xFF"E" */ { @@ -846,11 +853,27 @@ static NTSTATUS validate_smb_crypto(struct cli_state *cli, char *pdu) } } - if (!cli_check_sign_mac(cli, pdu)) { + mid = SVAL(pdu, smb_mid); + + for (req = cli->outstanding_requests; req; req = req->next) { + if (req->mid == mid) { + break; + } + } + + if (!req) { + /* oplock breaks are not signed */ + goto done; + } + + if (!cli_check_sign_mac(cli, pdu, req->seqnum+1)) { DEBUG(10, ("cli_check_sign_mac failed\n")); return NT_STATUS_ACCESS_DENIED; } +done: + *_req = req; + *_mid = mid; return NT_STATUS_OK; } @@ -863,7 +886,7 @@ static void handle_incoming_pdu(struct cli_state *cli) { struct cli_request *req, *next; uint16_t mid; - size_t raw_pdu_len, buf_len, pdu_len, rest_len; + size_t raw_pdu_len, buf_len, rest_len; char *pdu; int i; NTSTATUS status; @@ -923,23 +946,13 @@ static void handle_incoming_pdu(struct cli_state *cli) } } - status = validate_smb_crypto(cli, pdu); + status = validate_smb_crypto(cli, pdu, &req, &mid); if (!NT_STATUS_IS_OK(status)) { goto invalidate_requests; } - mid = SVAL(pdu, smb_mid); - DEBUG(10, ("handle_incoming_pdu: got mid %d\n", mid)); - for (req = cli->outstanding_requests; req; req = req->next) { - if (req->mid == mid) { - break; - } - } - - pdu_len = smb_len(pdu) + 4; - if (req == NULL) { DEBUG(3, ("Request for mid %d not found, dumping PDU\n", mid)); diff --git a/source3/libsmb/cliconnect.c b/source3/libsmb/cliconnect.c index ebb01c44a6..aa1ca595a7 100644 --- a/source3/libsmb/cliconnect.c +++ b/source3/libsmb/cliconnect.c @@ -505,11 +505,7 @@ static NTSTATUS cli_session_setup_nt1(struct cli_state *cli, const char *user, ok = cli_simple_set_signing(cli, session_key, nt_response); #endif if (ok) { - /* 'resign' the last message, so we get the right sequence numbers - for checking the first reply from the server */ - cli_calculate_sign_mac(cli, cli->outbuf); - - if (!cli_check_sign_mac(cli, cli->inbuf)) { + if (!cli_check_sign_mac(cli, cli->inbuf, 1)) { result = NT_STATUS_ACCESS_DENIED; goto end; } @@ -747,11 +743,7 @@ static ADS_STATUS cli_session_setup_kerberos(struct cli_state *cli, const char * if (cli_simple_set_signing( cli, session_key_krb5, data_blob_null)) { - /* 'resign' the last message, so we get the right sequence numbers - for checking the first reply from the server */ - cli_calculate_sign_mac(cli, cli->outbuf); - - if (!cli_check_sign_mac(cli, cli->inbuf)) { + if (!cli_check_sign_mac(cli, cli->inbuf, 1)) { nt_status = NT_STATUS_ACCESS_DENIED; goto nt_error; } @@ -873,11 +865,7 @@ static NTSTATUS cli_session_setup_ntlmssp(struct cli_state *cli, const char *use if (cli_simple_set_signing( cli, ntlmssp_state->session_key, data_blob_null)) { - /* 'resign' the last message, so we get the right sequence numbers - for checking the first reply from the server */ - cli_calculate_sign_mac(cli, cli->outbuf); - - if (!cli_check_sign_mac(cli, cli->inbuf)) { + if (!cli_check_sign_mac(cli, cli->inbuf, 1)) { nt_status = NT_STATUS_ACCESS_DENIED; } } @@ -1540,13 +1528,16 @@ NTSTATUS cli_negprot_recv(struct async_req *req) cli->protocol = prots[protnum].prot; - if ((cli->protocol < PROTOCOL_NT1) && cli->sign_info.mandatory_signing) { + if ((cli->protocol < PROTOCOL_NT1) && + client_is_signing_mandatory(cli)) { DEBUG(0,("cli_negprot: SMB signing is mandatory and the selected protocol level doesn't support it.\n")); return NT_STATUS_ACCESS_DENIED; } if (cli->protocol >= PROTOCOL_NT1) { struct timespec ts; + bool negotiated_smb_signing = false; + /* NT protocol */ cli->sec_mode = CVAL(vwv + 1, 0); cli->max_mux = SVAL(vwv + 1, 1); @@ -1579,22 +1570,24 @@ NTSTATUS cli_negprot_recv(struct async_req *req) if (cli->sec_mode & NEGOTIATE_SECURITY_SIGNATURES_REQUIRED) { /* Fail if server says signing is mandatory and we don't want to support it. */ - if (!cli->sign_info.allow_smb_signing) { + if (!client_is_signing_allowed(cli)) { DEBUG(0,("cli_negprot: SMB signing is mandatory and we have disabled it.\n")); return NT_STATUS_ACCESS_DENIED; } - cli->sign_info.negotiated_smb_signing = True; - cli->sign_info.mandatory_signing = True; - } else if (cli->sign_info.mandatory_signing && cli->sign_info.allow_smb_signing) { + negotiated_smb_signing = true; + } else if (client_is_signing_mandatory(cli) && client_is_signing_allowed(cli)) { /* Fail if client says signing is mandatory and the server doesn't support it. */ if (!(cli->sec_mode & NEGOTIATE_SECURITY_SIGNATURES_ENABLED)) { DEBUG(1,("cli_negprot: SMB signing is mandatory and the server doesn't support it.\n")); return NT_STATUS_ACCESS_DENIED; } - cli->sign_info.negotiated_smb_signing = True; - cli->sign_info.mandatory_signing = True; + negotiated_smb_signing = true; } else if (cli->sec_mode & NEGOTIATE_SECURITY_SIGNATURES_ENABLED) { - cli->sign_info.negotiated_smb_signing = True; + negotiated_smb_signing = true; + } + + if (negotiated_smb_signing) { + cli_set_signing_negotiated(cli); } if (cli->capabilities & (CAP_LARGE_READX|CAP_LARGE_WRITEX)) { @@ -1841,10 +1834,9 @@ static NTSTATUS open_smb_socket(const struct sockaddr_storage *pss, tevent_req_set_callback(r445, smb_sock_connected, fd445); tevent_req_set_callback(r139, smb_sock_connected, fd139); - while ((fd139->fd == -1) - && tevent_req_is_in_progress(r139) - && (fd445->fd == -1) - && tevent_req_is_in_progress(r445)) { + while ((fd445->fd == -1) && (fd139->fd == -1) + && (tevent_req_is_in_progress(r139) + || tevent_req_is_in_progress(r445))) { event_loop_once(ev); } diff --git a/source3/libsmb/clientgen.c b/source3/libsmb/clientgen.c index c1ba4e5c4f..6186387076 100644 --- a/source3/libsmb/clientgen.c +++ b/source3/libsmb/clientgen.c @@ -135,6 +135,79 @@ static ssize_t client_receive_smb(struct cli_state *cli, size_t maxlen) return len; } +static bool cli_state_set_seqnum(struct cli_state *cli, uint16_t mid, uint32_t seqnum) +{ + struct cli_state_seqnum *c; + + for (c = cli->seqnum; c; c = c->next) { + if (c->mid == mid) { + c->seqnum = seqnum; + return true; + } + } + + c = talloc_zero(cli, struct cli_state_seqnum); + if (!c) { + return false; + } + + c->mid = mid; + c->seqnum = seqnum; + c->persistent = false; + DLIST_ADD_END(cli->seqnum, c, struct cli_state_seqnum *); + + return true; +} + +bool cli_state_seqnum_persistent(struct cli_state *cli, + uint16_t mid) +{ + struct cli_state_seqnum *c; + + for (c = cli->seqnum; c; c = c->next) { + if (c->mid == mid) { + c->persistent = true; + return true; + } + } + + return false; +} + +bool cli_state_seqnum_remove(struct cli_state *cli, + uint16_t mid) +{ + struct cli_state_seqnum *c; + + for (c = cli->seqnum; c; c = c->next) { + if (c->mid == mid) { + DLIST_REMOVE(cli->seqnum, c); + TALLOC_FREE(c); + return true; + } + } + + return false; +} + +static uint32_t cli_state_get_seqnum(struct cli_state *cli, uint16_t mid) +{ + struct cli_state_seqnum *c; + + for (c = cli->seqnum; c; c = c->next) { + if (c->mid == mid) { + uint32_t seqnum = c->seqnum; + if (!c->persistent) { + DLIST_REMOVE(cli->seqnum, c); + TALLOC_FREE(c); + } + return seqnum; + } + } + + return 0; +} + /**************************************************************************** Recv an smb. ****************************************************************************/ @@ -142,6 +215,8 @@ static ssize_t client_receive_smb(struct cli_state *cli, size_t maxlen) bool cli_receive_smb(struct cli_state *cli) { ssize_t len; + uint16_t mid; + uint32_t seqnum; /* fd == -1 causes segfaults -- Tom (tom@ninja.nl) */ if (cli->fd == -1) @@ -177,7 +252,10 @@ bool cli_receive_smb(struct cli_state *cli) return false; } - if (!cli_check_sign_mac(cli, cli->inbuf)) { + mid = SVAL(cli->inbuf,smb_mid); + seqnum = cli_state_get_seqnum(cli, mid); + + if (!cli_check_sign_mac(cli, cli->inbuf, seqnum+1)) { /* * If we get a signature failure in sessionsetup, then * the server sometimes just reflects the sent signature @@ -264,12 +342,20 @@ bool cli_send_smb(struct cli_state *cli) ssize_t ret; char *buf_out = cli->outbuf; bool enc_on = cli_encryption_on(cli); + uint32_t seqnum; /* fd == -1 causes segfaults -- Tom (tom@ninja.nl) */ if (cli->fd == -1) return false; - cli_calculate_sign_mac(cli, cli->outbuf); + cli_calculate_sign_mac(cli, cli->outbuf, &seqnum); + + if (!cli_state_set_seqnum(cli, cli->mid, seqnum)) { + DEBUG(0,("Failed to store mid[%u]/seqnum[%u]\n", + (unsigned int)cli->mid, + (unsigned int)seqnum)); + return false; + } if (enc_on) { NTSTATUS status = cli_encrypt_message(cli, cli->outbuf, @@ -506,6 +592,7 @@ struct cli_state *cli_initialise_ex(int signing_state) cli->bufsize = CLI_BUFFER_SIZE+4; cli->max_xmit = cli->bufsize; cli->outbuf = (char *)SMB_MALLOC(cli->bufsize+SAFETY_MARGIN); + cli->seqnum = 0; cli->inbuf = (char *)SMB_MALLOC(cli->bufsize+SAFETY_MARGIN); cli->oplock_handler = cli_oplock_ack; cli->case_sensitive = false; @@ -556,9 +643,12 @@ struct cli_state *cli_initialise_ex(int signing_state) #endif /* initialise signing */ - cli->sign_info.allow_smb_signing = allow_smb_signing; - cli->sign_info.mandatory_signing = mandatory_signing; - cli_null_set_signing(cli); + cli->signing_state = smb_signing_init(cli, + allow_smb_signing, + mandatory_signing); + if (!cli->signing_state) { + goto error; + } cli->initialised = 1; @@ -641,7 +731,6 @@ void cli_shutdown(struct cli_state *cli) SAFE_FREE(cli->outbuf); SAFE_FREE(cli->inbuf); - cli_free_signing_context(cli); data_blob_free(&cli->secblob); data_blob_free(&cli->user_session_key); @@ -740,7 +829,6 @@ static void cli_echo_recv_helper(struct async_req *req) cli_req->data.echo.num_echos -= 1; if (cli_req->data.echo.num_echos == 0) { - client_set_trans_sign_state_off(cli_req->cli, cli_req->mid); async_req_done(req); return; } @@ -782,8 +870,6 @@ struct async_req *cli_echo_send(TALLOC_CTX *mem_ctx, struct event_context *ev, } req = talloc_get_type_abort(result->private_data, struct cli_request); - client_set_trans_sign_state_on(cli, req->mid); - req->data.echo.num_echos = num_echos; req->data.echo.data.data = talloc_move(req, &data_copy); req->data.echo.data.length = data.length; diff --git a/source3/libsmb/clisigning.c b/source3/libsmb/clisigning.c new file mode 100644 index 0000000000..0d0e926e6c --- /dev/null +++ b/source3/libsmb/clisigning.c @@ -0,0 +1,87 @@ +/* + Unix SMB/CIFS implementation. + SMB Signing Code + Copyright (C) Jeremy Allison 2003. + Copyright (C) Andrew Bartlett <abartlet@samba.org> 2002-2003 + Copyright (C) Stefan Metzmacher 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" + +bool cli_simple_set_signing(struct cli_state *cli, + const DATA_BLOB user_session_key, + const DATA_BLOB response) +{ + bool ok; + + ok = smb_signing_activate(cli->signing_state, + user_session_key, + response); + if (!ok) { + return false; + } + + cli->readbraw_supported = false; + cli->writebraw_supported = false; + + return true; +} + +bool cli_temp_set_signing(struct cli_state *cli) +{ + return smb_signing_set_bsrspyl(cli->signing_state); +} + +void cli_calculate_sign_mac(struct cli_state *cli, char *buf, uint32_t *seqnum) +{ + *seqnum = smb_signing_next_seqnum(cli->signing_state, false); + smb_signing_sign_pdu(cli->signing_state, (uint8_t *)buf, *seqnum); +} + +bool cli_check_sign_mac(struct cli_state *cli, const char *buf, uint32_t seqnum) +{ + bool ok; + + ok = smb_signing_check_pdu(cli->signing_state, + (const uint8_t *)buf, + seqnum); + + if (!ok) { + return false; + } + + return true; +} + +void cli_set_signing_negotiated(struct cli_state *cli) +{ + smb_signing_set_negotiated(cli->signing_state); +} + +bool client_is_signing_on(struct cli_state *cli) +{ + return smb_signing_is_active(cli->signing_state); +} + +bool client_is_signing_allowed(struct cli_state *cli) +{ + return smb_signing_is_allowed(cli->signing_state); +} + +bool client_is_signing_mandatory(struct cli_state *cli) +{ + return smb_signing_is_mandatory(cli->signing_state); +} diff --git a/source3/libsmb/clitrans.c b/source3/libsmb/clitrans.c index 0266c0307e..c566972b21 100644 --- a/source3/libsmb/clitrans.c +++ b/source3/libsmb/clitrans.c @@ -94,14 +94,12 @@ bool cli_send_trans(struct cli_state *cli, int trans, return False; } - /* Note we're in a trans state. Save the sequence - * numbers for replies. */ - client_set_trans_sign_state_on(cli, mid); + cli_state_seqnum_persistent(cli, mid); if (this_ldata < ldata || this_lparam < lparam) { /* receive interim response */ if (!cli_receive_smb(cli) || cli_is_error(cli)) { - client_set_trans_sign_state_off(cli, mid); + cli_state_seqnum_remove(cli, mid); return(False); } @@ -137,12 +135,11 @@ bool cli_send_trans(struct cli_state *cli, int trans, show_msg(cli->outbuf); - client_set_trans_sign_state_off(cli, mid); cli->mid = mid; if (!cli_send_smb(cli)) { + cli_state_seqnum_remove(cli, mid); return False; } - client_set_trans_sign_state_on(cli, mid); tot_data += this_ldata; tot_param += this_lparam; @@ -165,10 +162,14 @@ bool cli_receive_trans(struct cli_state *cli,int trans, unsigned int this_data,this_param; NTSTATUS status; bool ret = False; + uint16_t mid; *data_len = *param_len = 0; + mid = SVAL(cli->inbuf,smb_mid); + if (!cli_receive_smb(cli)) { + cli_state_seqnum_remove(cli, mid); return False; } @@ -179,6 +180,7 @@ bool cli_receive_trans(struct cli_state *cli,int trans, DEBUG(0,("Expected %s response, got command 0x%02x\n", trans==SMBtrans?"SMBtrans":"SMBtrans2", CVAL(cli->inbuf,smb_com))); + cli_state_seqnum_remove(cli, mid); return False; } @@ -331,6 +333,8 @@ bool cli_receive_trans(struct cli_state *cli,int trans, out: + cli_state_seqnum_remove(cli, mid); + if (ret) { /* Ensure the last 2 bytes of param and data are 2 null * bytes. These are malloc'ed, but not included in any @@ -344,7 +348,6 @@ bool cli_receive_trans(struct cli_state *cli,int trans, } } - client_set_trans_sign_state_off(cli, SVAL(cli->inbuf,smb_mid)); return ret; } @@ -412,14 +415,12 @@ bool cli_send_nt_trans(struct cli_state *cli, return False; } - /* Note we're in a trans state. Save the sequence - * numbers for replies. */ - client_set_trans_sign_state_on(cli, mid); + cli_state_seqnum_persistent(cli, mid); if (this_ldata < ldata || this_lparam < lparam) { /* receive interim response */ if (!cli_receive_smb(cli) || cli_is_error(cli)) { - client_set_trans_sign_state_off(cli, mid); + cli_state_seqnum_remove(cli, mid); return(False); } @@ -454,12 +455,11 @@ bool cli_send_nt_trans(struct cli_state *cli, show_msg(cli->outbuf); - client_set_trans_sign_state_off(cli, mid); cli->mid = mid; if (!cli_send_smb(cli)) { + cli_state_seqnum_remove(cli, mid); return False; } - client_set_trans_sign_state_on(cli, mid); tot_data += this_ldata; tot_param += this_lparam; @@ -483,10 +483,14 @@ bool cli_receive_nt_trans(struct cli_state *cli, uint8 eclass; uint32 ecode; bool ret = False; + uint16_t mid; *data_len = *param_len = 0; + mid = SVAL(cli->inbuf,smb_mid); + if (!cli_receive_smb(cli)) { + cli_state_seqnum_remove(cli, mid); return False; } @@ -496,6 +500,7 @@ bool cli_receive_nt_trans(struct cli_state *cli, if (CVAL(cli->inbuf,smb_com) != SMBnttrans) { DEBUG(0,("Expected SMBnttrans response, got command 0x%02x\n", CVAL(cli->inbuf,smb_com))); + cli_state_seqnum_remove(cli, mid); return(False); } @@ -669,6 +674,8 @@ bool cli_receive_nt_trans(struct cli_state *cli, out: + cli_state_seqnum_remove(cli, mid); + if (ret) { /* Ensure the last 2 bytes of param and data are 2 null * bytes. These are malloc'ed, but not included in any @@ -682,7 +689,6 @@ bool cli_receive_nt_trans(struct cli_state *cli, } } - client_set_trans_sign_state_off(cli, SVAL(cli->inbuf,smb_mid)); return ret; } @@ -696,6 +702,7 @@ struct cli_trans_state { struct event_context *ev; uint8_t cmd; uint16_t mid; + uint32_t seqnum; const char *pipe_name; uint16_t fid; uint16_t function; @@ -919,6 +926,7 @@ static struct async_req *cli_ship_trans(TALLOC_CTX *mem_ctx, cli_req = talloc_get_type_abort(result->private_data, struct cli_request); state->mid = cli_req->mid; + state->seqnum = cli_req->seqnum; } else { uint16_t num_bytes = talloc_get_size(bytes); /* @@ -939,12 +947,10 @@ static struct async_req *cli_ship_trans(TALLOC_CTX *mem_ctx, cli_req->recv_helper.fn = cli_trans_recv_helper; cli_req->recv_helper.priv = state; cli_req->mid = state->mid; - client_set_trans_sign_state_off(state->cli, state->mid); cli_chain_uncork(state->cli); + state->seqnum = cli_req->seqnum; } - client_set_trans_sign_state_on(state->cli, state->mid); - fail: TALLOC_FREE(frame); return result; @@ -953,6 +959,8 @@ static struct async_req *cli_ship_trans(TALLOC_CTX *mem_ctx, static void cli_trans_ship_rest(struct async_req *req, struct cli_trans_state *state) { + struct cli_request *cli_req; + state->secondary_request_ctx = talloc_new(state); if (state->secondary_request_ctx == NULL) { async_req_nterror(req, NT_STATUS_NO_MEMORY); @@ -961,14 +969,19 @@ static void cli_trans_ship_rest(struct async_req *req, while ((state->param_sent < state->num_param) || (state->data_sent < state->num_data)) { - struct async_req *cli_req; + struct async_req *subreq; - cli_req = cli_ship_trans(state->secondary_request_ctx, state); - if (cli_req == NULL) { + subreq = cli_ship_trans(state->secondary_request_ctx, state); + if (subreq == NULL) { async_req_nterror(req, NT_STATUS_NO_MEMORY); return; } } + + cli_req = talloc_get_type_abort(req->private_data, + struct cli_request); + + cli_req->seqnum = state->seqnum; } static NTSTATUS cli_pull_trans(struct async_req *req, @@ -1174,7 +1187,6 @@ static void cli_trans_recv_helper(struct async_req *req) if ((state->rparam.total == state->rparam.received) && (state->rdata.total == state->rdata.received)) { - client_set_trans_sign_state_off(state->cli, state->mid); async_req_done(req); } } diff --git a/source3/libsmb/dsgetdcname.c b/source3/libsmb/dsgetdcname.c index 3491544175..1064a63d97 100644 --- a/source3/libsmb/dsgetdcname.c +++ b/source3/libsmb/dsgetdcname.c @@ -311,7 +311,7 @@ static uint32_t get_cldap_reply_server_flags(struct netlogon_samlogon_response * /**************************************************************** ****************************************************************/ -#define RETURN_ON_FALSE(x) if (!x) return false; +#define RETURN_ON_FALSE(x) if (!(x)) return false; static bool check_cldap_reply_required_flags(uint32_t ret_flags, uint32_t req_flags) diff --git a/source3/libsmb/smb_seal.c b/source3/libsmb/smb_seal.c index 795c8bc14c..2f7305c5b6 100644 --- a/source3/libsmb/smb_seal.c +++ b/source3/libsmb/smb_seal.c @@ -136,7 +136,7 @@ NTSTATUS common_ntlm_encrypt_buffer(NTLMSSP_STATE *ntlmssp_state, smb_set_enclen(buf_out, smb_len(buf) + NTLMSSP_SIG_SIZE, enc_ctx_num); - sig = data_blob(NULL, NTLMSSP_SIG_SIZE); + ZERO_STRUCT(sig); status = ntlmssp_seal_packet(ntlmssp_state, (unsigned char *)buf_out + 8 + NTLMSSP_SIG_SIZE, /* 4 byte len + 0xFF 'S' <enc> <ctx> */ @@ -153,6 +153,7 @@ NTSTATUS common_ntlm_encrypt_buffer(NTLMSSP_STATE *ntlmssp_state, /* First 16 data bytes are signature for SSPI compatibility. */ memcpy(buf_out + 8, sig.data, NTLMSSP_SIG_SIZE); + data_blob_free(&sig); *ppbuf_out = buf_out; return NT_STATUS_OK; } diff --git a/source3/libsmb/smb_signing.c b/source3/libsmb/smb_signing.c index a3ed0e7572..32d2883965 100644 --- a/source3/libsmb/smb_signing.c +++ b/source3/libsmb/smb_signing.c @@ -1,8 +1,9 @@ -/* +/* Unix SMB/CIFS implementation. SMB Signing Code Copyright (C) Jeremy Allison 2003. Copyright (C) Andrew Bartlett <abartlet@samba.org> 2002-2003 + Copyright (C) Stefan Metzmacher 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 @@ -20,260 +21,89 @@ #include "includes.h" -/* Lookup a packet's MID (multiplex id) and figure out it's sequence number */ -struct outstanding_packet_lookup { - struct outstanding_packet_lookup *prev, *next; - uint16 mid; - uint32 reply_seq_num; - bool can_delete; /* Set to False in trans state. */ -}; +/* Used by the SMB signing functions. */ -struct smb_basic_signing_context { - DATA_BLOB mac_key; - uint32 send_seq_num; - struct outstanding_packet_lookup *outstanding_packet_list; -}; - -static bool store_sequence_for_reply(struct outstanding_packet_lookup **list, - uint16 mid, uint32 reply_seq_num) -{ - struct outstanding_packet_lookup *t; +struct smb_signing_state { + /* is signing localy allowed */ + bool allowed; - /* Ensure we only add a mid once. */ - for (t = *list; t; t = t->next) { - if (t->mid == mid) { - return False; - } - } + /* is signing localy mandatory */ + bool mandatory; - t = SMB_XMALLOC_P(struct outstanding_packet_lookup); - ZERO_STRUCTP(t); + /* is signing negotiated by the peer */ + bool negotiated; - t->mid = mid; - t->reply_seq_num = reply_seq_num; - t->can_delete = True; + /* send BSRSPYL signatures */ + bool bsrspyl; - /* - * Add to the *start* of the list not the end of the list. - * This ensures that the *last* send sequence with this mid - * is returned by preference. - * This can happen if the mid wraps and one of the early - * mid numbers didn't get a reply and is still lurking on - * the list. JRA. Found by Fran Fabrizio <fran@cis.uab.edu>. - */ + bool active; /* Have I ever seen a validly signed packet? */ - DLIST_ADD(*list, t); - DEBUG(10,("store_sequence_for_reply: stored seq = %u mid = %u\n", - (unsigned int)reply_seq_num, (unsigned int)mid )); - return True; -} + /* mac_key.length > 0 means signing is started */ + DATA_BLOB mac_key; -static bool get_sequence_for_reply(struct outstanding_packet_lookup **list, - uint16 mid, uint32 *reply_seq_num) -{ - struct outstanding_packet_lookup *t; - - for (t = *list; t; t = t->next) { - if (t->mid == mid) { - *reply_seq_num = t->reply_seq_num; - DEBUG(10,("get_sequence_for_reply: found seq = %u mid = %u\n", - (unsigned int)t->reply_seq_num, (unsigned int)t->mid )); - if (t->can_delete) { - DLIST_REMOVE(*list, t); - SAFE_FREE(t); - } - return True; - } - } - return False; -} + /* the next expected seqnum */ + uint32_t seqnum; +}; -static bool set_sequence_can_delete_flag(struct outstanding_packet_lookup **list, uint16 mid, bool can_delete_entry) +static void smb_signing_reset_info(struct smb_signing_state *si) { - struct outstanding_packet_lookup *t; - - for (t = *list; t; t = t->next) { - if (t->mid == mid) { - t->can_delete = can_delete_entry; - return True; - } - } - return False; + si->active = false; + si->bsrspyl = false; + data_blob_free(&si->mac_key); + si->seqnum = 0; } -/*********************************************************** - SMB signing - Common code before we set a new signing implementation -************************************************************/ - -static bool cli_set_smb_signing_common(struct cli_state *cli) +struct smb_signing_state *smb_signing_init(TALLOC_CTX *mem_ctx, + bool allowed, + bool mandatory) { - if (!cli->sign_info.allow_smb_signing) { - return False; - } + struct smb_signing_state *si; - if (!cli->sign_info.negotiated_smb_signing - && !cli->sign_info.mandatory_signing) { - return False; + si = talloc_zero(mem_ctx, struct smb_signing_state); + if (si == NULL) { + return NULL; } - if (cli->sign_info.doing_signing) { - return False; + if (mandatory) { + allowed = true; } - if (cli->sign_info.free_signing_context) - cli->sign_info.free_signing_context(&cli->sign_info); - - /* These calls are INCOMPATIBLE with SMB signing */ - cli->readbraw_supported = False; - cli->writebraw_supported = False; - - return True; -} - -/*********************************************************** - SMB signing - Common code for 'real' implementations -************************************************************/ - -static bool set_smb_signing_real_common(struct smb_sign_info *si) -{ - if (si->mandatory_signing) { - DEBUG(5, ("Mandatory SMB signing enabled!\n")); - } - - si->doing_signing = True; - DEBUG(5, ("SMB signing enabled!\n")); - - return True; -} - -static void mark_packet_signed(char *outbuf) -{ - uint16 flags2; - flags2 = SVAL(outbuf,smb_flg2); - flags2 |= FLAGS2_SMB_SECURITY_SIGNATURES; - SSVAL(outbuf,smb_flg2, flags2); -} - -/*********************************************************** - SMB signing - NULL implementation - calculate a MAC to send. -************************************************************/ - -static void null_sign_outgoing_message(char *outbuf, struct smb_sign_info *si) -{ - /* we can't zero out the sig, as we might be trying to send a - session request - which is NBT-level, not SMB level and doesn't - have the field */ - return; -} - -/*********************************************************** - SMB signing - NULL implementation - check a MAC sent by server. -************************************************************/ - -static bool null_check_incoming_message(const char *inbuf, - struct smb_sign_info *si, - bool must_be_ok) -{ - return True; -} - -/*********************************************************** - SMB signing - NULL implementation - free signing context -************************************************************/ - -static void null_free_signing_context(struct smb_sign_info *si) -{ - return; -} - -/** - SMB signing - NULL implementation - setup the MAC key. - - @note Used as an initialisation only - it will not correctly - shut down a real signing mechanism -*/ - -static bool null_set_signing(struct smb_sign_info *si) -{ - si->signing_context = NULL; - - si->sign_outgoing_message = null_sign_outgoing_message; - si->check_incoming_message = null_check_incoming_message; - si->free_signing_context = null_free_signing_context; - - return True; -} - -/** - * Free the signing context - */ - -static void free_signing_context(struct smb_sign_info *si) -{ - if (si->free_signing_context) { - si->free_signing_context(si); - si->signing_context = NULL; - } + si->allowed = allowed; + si->mandatory = mandatory; - null_set_signing(si); + return si; } - -static bool signing_good(const char *inbuf, struct smb_sign_info *si, - bool good, uint32 seq, bool must_be_ok) +static bool smb_signing_good(struct smb_signing_state *si, + bool good, uint32_t seq) { if (good) { - - if (!si->doing_signing) { - si->doing_signing = True; + if (!si->active) { + si->active = true; } + return true; + } - if (!si->seen_valid) { - si->seen_valid = True; - } - - } else { - if (!si->mandatory_signing && !si->seen_valid) { - - if (!must_be_ok) { - return True; - } - /* Non-mandatory signing - just turn off if this is the first bad packet.. */ - DEBUG(5, ("srv_check_incoming_message: signing negotiated but not required and peer\n" - "isn't sending correct signatures. Turning off.\n")); - si->negotiated_smb_signing = False; - si->allow_smb_signing = False; - si->doing_signing = False; - free_signing_context(si); - return True; - } else if (!must_be_ok) { - /* This packet is known to be unsigned */ - return True; - } else { - /* Mandatory signing or bad packet after signing started - fail and disconnect. */ - if (seq) - DEBUG(0, ("signing_good: BAD SIG: seq %u\n", (unsigned int)seq)); - return False; - } + if (!si->mandatory && !si->active) { + /* Non-mandatory signing - just turn off if this is the first bad packet.. */ + DEBUG(5, ("smb_signing_good: signing negotiated but not required and peer\n" + "isn't sending correct signatures. Turning off.\n")); + smb_signing_reset_info(si); + return true; } - return True; -} -/*********************************************************** - SMB signing - Simple implementation - calculate a MAC on the packet -************************************************************/ + /* Mandatory signing or bad packet after signing started - fail and disconnect. */ + DEBUG(0, ("smb_signing_good: BAD SIG: seq %u\n", (unsigned int)seq)); + return false; +} -static void simple_packet_signature(struct smb_basic_signing_context *data, - const uchar *buf, uint32 seq_number, - unsigned char calc_md5_mac[16]) +static void smb_signing_md5(const DATA_BLOB *mac_key, + const uint8_t *buf, uint32_t seq_number, + uint8_t calc_md5_mac[16]) { const size_t offset_end_of_sig = (smb_ss_field + 8); - unsigned char sequence_buf[8]; + uint8_t sequence_buf[8]; struct MD5Context md5_ctx; -#if 0 - /* JRA - apparently this is incorrect. */ - unsigned char key_buf[16]; -#endif /* * Firstly put the sequence number into the first 4 bytes. @@ -282,7 +112,7 @@ static void simple_packet_signature(struct smb_basic_signing_context *data, * We do this here, to avoid modifying the packet. */ - DEBUG(10,("simple_packet_signature: sequence number %u\n", seq_number )); + DEBUG(10,("smb_signing_md5: sequence number %u\n", seq_number )); SIVAL(sequence_buf, 0, seq_number); SIVAL(sequence_buf, 4, 0); @@ -295,17 +125,7 @@ static void simple_packet_signature(struct smb_basic_signing_context *data, MD5Init(&md5_ctx); /* intialise with the key */ - MD5Update(&md5_ctx, data->mac_key.data, data->mac_key.length); -#if 0 - /* JRA - apparently this is incorrect. */ - /* NB. When making and verifying SMB signatures, Windows apparently - zero-pads the key to 128 bits if it isn't long enough. - From Nalin Dahyabhai <nalin@redhat.com> */ - if (data->mac_key.length < sizeof(key_buf)) { - memset(key_buf, 0, sizeof(key_buf)); - MD5Update(&md5_ctx, key_buf, sizeof(key_buf) - data->mac_key.length); - } -#endif + MD5Update(&md5_ctx, mac_key->data, mac_key->length); /* copy in the first bit of the SMB header */ MD5Update(&md5_ctx, buf + 4, smb_ss_field - 4); @@ -317,690 +137,234 @@ static void simple_packet_signature(struct smb_basic_signing_context *data, MD5Update(&md5_ctx, buf + offset_end_of_sig, smb_len(buf) - (offset_end_of_sig - 4)); - /* calculate the MD5 sig */ + /* calculate the MD5 sig */ MD5Final(calc_md5_mac, &md5_ctx); } - -/*********************************************************** - SMB signing - Client implementation - send the MAC. -************************************************************/ - -static void client_sign_outgoing_message(char *outbuf, struct smb_sign_info *si) -{ - unsigned char calc_md5_mac[16]; - struct smb_basic_signing_context *data = - (struct smb_basic_signing_context *)si->signing_context; - - if (!si->doing_signing) - return; - - /* JRA Paranioa test - we should be able to get rid of this... */ - if (smb_len(outbuf) < (smb_ss_field + 8 - 4)) { - DEBUG(1, ("client_sign_outgoing_message: Logic error. Can't check signature on short packet! smb_len = %u\n", - smb_len(outbuf) )); - abort(); - } - - /* mark the packet as signed - BEFORE we sign it...*/ - mark_packet_signed(outbuf); - - simple_packet_signature(data, (const unsigned char *)outbuf, - data->send_seq_num, calc_md5_mac); - - DEBUG(10, ("client_sign_outgoing_message: sent SMB signature of\n")); - dump_data(10, calc_md5_mac, 8); - - memcpy(&outbuf[smb_ss_field], calc_md5_mac, 8); - -/* cli->outbuf[smb_ss_field+2]=0; - Uncomment this to test if the remote server actually verifies signatures...*/ - - /* Instead of re-introducing the trans_info_conect we - used to have here, we use the fact that during a - SMBtrans/SMBtrans2/SMBnttrans send that the mid stays - constant. This means that calling store_sequence_for_reply() - will return False for all trans secondaries, as the mid is already - on the stored sequence list. As the send_seqence_number must - remain constant for all primary+secondary trans sends, we - only increment the send sequence number when we successfully - add a new entry to the outstanding sequence list. This means - I can isolate the fix here rather than re-adding the trans - signing on/off calls in libsmb/clitrans2.c JRA. - */ - - if (store_sequence_for_reply(&data->outstanding_packet_list, SVAL(outbuf,smb_mid), data->send_seq_num + 1)) { - data->send_seq_num += 2; - } -} - -/*********************************************************** - SMB signing - Client implementation - check a MAC sent by server. -************************************************************/ - -static bool client_check_incoming_message(const char *inbuf, - struct smb_sign_info *si, - bool must_be_ok) +uint32_t smb_signing_next_seqnum(struct smb_signing_state *si, bool oneway) { - bool good; - uint32 reply_seq_number; - unsigned char calc_md5_mac[16]; - unsigned char *server_sent_mac; - - struct smb_basic_signing_context *data = - (struct smb_basic_signing_context *)si->signing_context; + uint32_t seqnum; - if (!si->doing_signing) - return True; - - if (smb_len(inbuf) < (smb_ss_field + 8 - 4)) { - DEBUG(1, ("client_check_incoming_message: Can't check signature on short packet! smb_len = %u\n", smb_len(inbuf))); - return False; + if (si->mac_key.length == 0) { + return 0; } - if (!get_sequence_for_reply(&data->outstanding_packet_list, SVAL(inbuf, smb_mid), &reply_seq_number)) { - DEBUG(1, ("client_check_incoming_message: received message " - "with mid %u with no matching send record.\n", (unsigned int)SVAL(inbuf, smb_mid) )); - return False; - } - - simple_packet_signature(data, (const unsigned char *)inbuf, - reply_seq_number, calc_md5_mac); - - server_sent_mac = (unsigned char *)&inbuf[smb_ss_field]; - good = (memcmp(server_sent_mac, calc_md5_mac, 8) == 0); - - if (!good) { - DEBUG(5, ("client_check_incoming_message: BAD SIG: wanted SMB signature of\n")); - dump_data(5, calc_md5_mac, 8); - - DEBUG(5, ("client_check_incoming_message: BAD SIG: got SMB signature of\n")); - dump_data(5, server_sent_mac, 8); -#if 1 /* JRATEST */ - { - int i; - for (i = -5; i < 5; i++) { - simple_packet_signature(data, (const unsigned char *)inbuf, reply_seq_number+i, calc_md5_mac); - if (memcmp(server_sent_mac, calc_md5_mac, 8) == 0) { - DEBUG(0,("client_check_incoming_message: out of seq. seq num %u matches. \ -We were expecting seq %u\n", reply_seq_number+i, reply_seq_number )); - break; - } - } - } -#endif /* JRATEST */ - + seqnum = si->seqnum; + if (oneway) { + si->seqnum += 1; } else { - DEBUG(10, ("client_check_incoming_message: seq %u: got good SMB signature of\n", (unsigned int)reply_seq_number)); - dump_data(10, server_sent_mac, 8); - } - return signing_good(inbuf, si, good, reply_seq_number, must_be_ok); -} - -/*********************************************************** - SMB signing - Simple implementation - free signing context -************************************************************/ - -static void simple_free_signing_context(struct smb_sign_info *si) -{ - struct smb_basic_signing_context *data = - (struct smb_basic_signing_context *)si->signing_context; - struct outstanding_packet_lookup *list; - struct outstanding_packet_lookup *next; - - for (list = data->outstanding_packet_list; list; list = next) { - next = list->next; - DLIST_REMOVE(data->outstanding_packet_list, list); - SAFE_FREE(list); + si->seqnum += 2; } - data_blob_free(&data->mac_key); - - SAFE_FREE(si->signing_context); - - return; + return seqnum; } -/*********************************************************** - SMB signing - Simple implementation - setup the MAC key. -************************************************************/ - -bool cli_simple_set_signing(struct cli_state *cli, - const DATA_BLOB user_session_key, - const DATA_BLOB response) +void smb_signing_cancel_reply(struct smb_signing_state *si, bool oneway) { - struct smb_basic_signing_context *data; - - if (!user_session_key.length) - return False; - - if (!cli_set_smb_signing_common(cli)) { - return False; - } - - if (!set_smb_signing_real_common(&cli->sign_info)) { - return False; + if (si->mac_key.length == 0) { + return; } - data = SMB_XMALLOC_P(struct smb_basic_signing_context); - memset(data, '\0', sizeof(*data)); - - cli->sign_info.signing_context = data; - - data->mac_key = data_blob(NULL, response.length + user_session_key.length); - - memcpy(&data->mac_key.data[0], user_session_key.data, user_session_key.length); - - DEBUG(10, ("cli_simple_set_signing: user_session_key\n")); - dump_data(10, user_session_key.data, user_session_key.length); - - if (response.length) { - memcpy(&data->mac_key.data[user_session_key.length],response.data, response.length); - DEBUG(10, ("cli_simple_set_signing: response_data\n")); - dump_data(10, response.data, response.length); + if (oneway) { + si->seqnum -= 1; } else { - DEBUG(10, ("cli_simple_set_signing: NULL response_data\n")); + si->seqnum -= 2; } - - dump_data_pw("MAC ssession key is:\n", data->mac_key.data, data->mac_key.length); - - /* Initialise the sequence number */ - data->send_seq_num = 0; - - /* Initialise the list of outstanding packets */ - data->outstanding_packet_list = NULL; - - cli->sign_info.sign_outgoing_message = client_sign_outgoing_message; - cli->sign_info.check_incoming_message = client_check_incoming_message; - cli->sign_info.free_signing_context = simple_free_signing_context; - - return True; } -/*********************************************************** - SMB signing - TEMP implementation - calculate a MAC to send. -************************************************************/ - -static void temp_sign_outgoing_message(char *outbuf, struct smb_sign_info *si) +void smb_signing_sign_pdu(struct smb_signing_state *si, + uint8_t *outbuf, uint32_t seqnum) { - /* mark the packet as signed - BEFORE we sign it...*/ - mark_packet_signed(outbuf); - - /* I wonder what BSRSPYL stands for - but this is what MS - actually sends! */ - memcpy(&outbuf[smb_ss_field], "BSRSPYL ", 8); - return; -} - -/*********************************************************** - SMB signing - TEMP implementation - check a MAC sent by server. -************************************************************/ + uint8_t calc_md5_mac[16]; + uint16_t flags2; -static bool temp_check_incoming_message(const char *inbuf, - struct smb_sign_info *si, bool foo) -{ - return True; -} - -/*********************************************************** - SMB signing - TEMP implementation - free signing context -************************************************************/ - -static void temp_free_signing_context(struct smb_sign_info *si) -{ - return; -} - -/*********************************************************** - SMB signing - NULL implementation - setup the MAC key. -************************************************************/ - -bool cli_null_set_signing(struct cli_state *cli) -{ - return null_set_signing(&cli->sign_info); -} - -/*********************************************************** - SMB signing - temp implementation - setup the MAC key. -************************************************************/ - -bool cli_temp_set_signing(struct cli_state *cli) -{ - if (!cli_set_smb_signing_common(cli)) { - return False; - } - - cli->sign_info.signing_context = NULL; - - cli->sign_info.sign_outgoing_message = temp_sign_outgoing_message; - cli->sign_info.check_incoming_message = temp_check_incoming_message; - cli->sign_info.free_signing_context = temp_free_signing_context; - - return True; -} - -void cli_free_signing_context(struct cli_state *cli) -{ - free_signing_context(&cli->sign_info); -} - -/** - * Sign a packet with the current mechanism - */ - -void cli_calculate_sign_mac(struct cli_state *cli, char *buf) -{ - cli->sign_info.sign_outgoing_message(buf, &cli->sign_info); -} - -/** - * Check a packet with the current mechanism - * @return False if we had an established signing connection - * which had a bad checksum, True otherwise. - */ - -bool cli_check_sign_mac(struct cli_state *cli, char *buf) -{ - if (!cli->sign_info.check_incoming_message(buf, &cli->sign_info, True)) { - free_signing_context(&cli->sign_info); - return False; - } - return True; -} - -/*********************************************************** - Enter trans/trans2/nttrans state. -************************************************************/ - -bool client_set_trans_sign_state_on(struct cli_state *cli, uint16 mid) -{ - struct smb_sign_info *si = &cli->sign_info; - struct smb_basic_signing_context *data = (struct smb_basic_signing_context *)si->signing_context; - - if (!si->doing_signing) { - return True; - } - - if (!data) { - return False; - } - - if (!set_sequence_can_delete_flag(&data->outstanding_packet_list, mid, False)) { - return False; - } - - return True; -} - -/*********************************************************** - Leave trans/trans2/nttrans state. -************************************************************/ - -bool client_set_trans_sign_state_off(struct cli_state *cli, uint16 mid) -{ - uint32 reply_seq_num; - struct smb_sign_info *si = &cli->sign_info; - struct smb_basic_signing_context *data = (struct smb_basic_signing_context *)si->signing_context; - - if (!si->doing_signing) { - return True; - } - - if (!data) { - return False; - } - - if (!set_sequence_can_delete_flag(&data->outstanding_packet_list, mid, True)) { - return False; - } - - /* Now delete the stored mid entry. */ - if (!get_sequence_for_reply(&data->outstanding_packet_list, mid, &reply_seq_num)) { - return False; - } - - return True; -} - -/*********************************************************** - Is client signing on ? -************************************************************/ - -bool client_is_signing_on(struct cli_state *cli) -{ - struct smb_sign_info *si = &cli->sign_info; - return si->doing_signing; -} - -/*********************************************************** - SMB signing - Server implementation - send the MAC. -************************************************************/ - -static void srv_sign_outgoing_message(char *outbuf, struct smb_sign_info *si) -{ - unsigned char calc_md5_mac[16]; - struct smb_basic_signing_context *data = - (struct smb_basic_signing_context *)si->signing_context; - uint32 send_seq_number = data->send_seq_num-1; - uint16 mid; - - if (!si->doing_signing) { - return; + if (si->mac_key.length == 0) { + if (!si->bsrspyl) { + return; + } } /* JRA Paranioa test - we should be able to get rid of this... */ if (smb_len(outbuf) < (smb_ss_field + 8 - 4)) { - DEBUG(1, ("srv_sign_outgoing_message: Logic error. Can't send signature on short packet! smb_len = %u\n", - smb_len(outbuf) )); + DEBUG(1,("smb_signing_sign_pdu: Logic error. " + "Can't check signature on short packet! smb_len = %u\n", + smb_len(outbuf))); abort(); } /* mark the packet as signed - BEFORE we sign it...*/ - mark_packet_signed(outbuf); - - mid = SVAL(outbuf, smb_mid); - - /* See if this is a reply for a deferred packet. */ - get_sequence_for_reply(&data->outstanding_packet_list, mid, &send_seq_number); + flags2 = SVAL(outbuf,smb_flg2); + flags2 |= FLAGS2_SMB_SECURITY_SIGNATURES; + SSVAL(outbuf, smb_flg2, flags2); - simple_packet_signature(data, (const unsigned char *)outbuf, send_seq_number, calc_md5_mac); + if (si->bsrspyl) { + /* I wonder what BSRSPYL stands for - but this is what MS + actually sends! */ + memcpy(calc_md5_mac, "BSRSPYL ", 8); + } else { + smb_signing_md5(&si->mac_key, outbuf, + seqnum, calc_md5_mac); + } - DEBUG(10, ("srv_sign_outgoing_message: seq %u: sent SMB signature of\n", (unsigned int)send_seq_number)); + DEBUG(10, ("smb_signing_sign_pdu: sent SMB signature of\n")); dump_data(10, calc_md5_mac, 8); memcpy(&outbuf[smb_ss_field], calc_md5_mac, 8); -/* cli->outbuf[smb_ss_field+2]=0; - Uncomment this to test if the remote client actually verifies signatures...*/ +/* outbuf[smb_ss_field+2]=0; + Uncomment this to test if the remote server actually verifies signatures...*/ } -/*********************************************************** - SMB signing - Server implementation - check a MAC sent by server. -************************************************************/ - -static bool srv_check_incoming_message(const char *inbuf, - struct smb_sign_info *si, - bool must_be_ok) +bool smb_signing_check_pdu(struct smb_signing_state *si, + const uint8_t *inbuf, uint32_t seqnum) { bool good; - struct smb_basic_signing_context *data = - (struct smb_basic_signing_context *)si->signing_context; - uint32 reply_seq_number = data->send_seq_num; - uint32 saved_seq; - unsigned char calc_md5_mac[16]; - unsigned char *server_sent_mac; + uint8_t calc_md5_mac[16]; + const uint8_t *reply_sent_mac; - if (!si->doing_signing) - return True; + if (si->mac_key.length == 0) { + return true; + } if (smb_len(inbuf) < (smb_ss_field + 8 - 4)) { - DEBUG(1, ("srv_check_incoming_message: Can't check signature on short packet! smb_len = %u\n", smb_len(inbuf))); + DEBUG(1,("smb_signing_check_pdu: Can't check signature " + "on short packet! smb_len = %u\n", + smb_len(inbuf))); return False; } - /* We always increment the sequence number. */ - data->send_seq_num += 2; - - saved_seq = reply_seq_number; - simple_packet_signature(data, (const unsigned char *)inbuf, reply_seq_number, calc_md5_mac); + smb_signing_md5(&si->mac_key, inbuf, + seqnum, calc_md5_mac); - server_sent_mac = (unsigned char *)&inbuf[smb_ss_field]; - good = (memcmp(server_sent_mac, calc_md5_mac, 8) == 0); + reply_sent_mac = &inbuf[smb_ss_field]; + good = (memcmp(reply_sent_mac, calc_md5_mac, 8) == 0); if (!good) { + int i; + const int sign_range = 5; - if (saved_seq) { - DEBUG(0, ("srv_check_incoming_message: BAD SIG: seq %u wanted SMB signature of\n", - (unsigned int)saved_seq)); - dump_data(5, calc_md5_mac, 8); - - DEBUG(0, ("srv_check_incoming_message: BAD SIG: seq %u got SMB signature of\n", - (unsigned int)reply_seq_number)); - dump_data(5, server_sent_mac, 8); - } + DEBUG(5, ("smb_signing_check_pdu: BAD SIG: wanted SMB signature of\n")); + dump_data(5, calc_md5_mac, 8); -#if 1 /* JRATEST */ - { - int i; - reply_seq_number -= 5; - for (i = 0; i < 10; i++, reply_seq_number++) { - simple_packet_signature(data, (const unsigned char *)inbuf, reply_seq_number, calc_md5_mac); - if (memcmp(server_sent_mac, calc_md5_mac, 8) == 0) { - DEBUG(0,("srv_check_incoming_message: out of seq. seq num %u matches. \ -We were expecting seq %u\n", reply_seq_number, saved_seq )); - break; - } + DEBUG(5, ("smb_signing_check_pdu: BAD SIG: got SMB signature of\n")); + dump_data(5, reply_sent_mac, 8); + + for (i = -sign_range; i < sign_range; i++) { + smb_signing_md5(&si->mac_key, inbuf, + seqnum+i, calc_md5_mac); + if (memcmp(reply_sent_mac, calc_md5_mac, 8) == 0) { + DEBUG(0,("smb_signing_check_pdu: " + "out of seq. seq num %u matches. " + "We were expecting seq %u\n", + (unsigned int)seqnum+i, + (unsigned int)seqnum)); + break; } } -#endif /* JRATEST */ - } else { - DEBUG(10, ("srv_check_incoming_message: seq %u: (current is %u) got good SMB signature of\n", (unsigned int)reply_seq_number, (unsigned int)data->send_seq_num)); - dump_data(10, server_sent_mac, 8); + DEBUG(10, ("smb_signing_check_pdu: seq %u: " + "got good SMB signature of\n", + (unsigned int)seqnum)); + dump_data(10, reply_sent_mac, 8); } - return (signing_good(inbuf, si, good, saved_seq, must_be_ok)); + return smb_signing_good(si, good, seqnum); } -/*********************************************************** - SMB signing - server API's. -************************************************************/ - -static struct smb_sign_info srv_sign_info = { - null_sign_outgoing_message, - null_check_incoming_message, - null_free_signing_context, - NULL, - False, - False, - False, - False -}; - -/*********************************************************** - Turn signing off or on for oplock break code. -************************************************************/ - -bool srv_oplock_set_signing(bool onoff) +bool smb_signing_set_bsrspyl(struct smb_signing_state *si) { - bool ret = srv_sign_info.doing_signing; - srv_sign_info.doing_signing = onoff; - return ret; -} - -/*********************************************************** - Called to validate an incoming packet from the client. -************************************************************/ - -bool srv_check_sign_mac(const char *inbuf, bool must_be_ok) -{ - /* Check if it's a non-session message. */ - if(CVAL(inbuf,0)) { - return True; + if (!si->negotiated) { + return false; } - return srv_sign_info.check_incoming_message(inbuf, &srv_sign_info, must_be_ok); -} - -/*********************************************************** - Called to sign an outgoing packet to the client. -************************************************************/ - -void srv_calculate_sign_mac(char *outbuf) -{ - /* Check if it's a non-session message. */ - if(CVAL(outbuf,0)) { - return; + if (si->active) { + return false; } - srv_sign_info.sign_outgoing_message(outbuf, &srv_sign_info); -} + si->bsrspyl = true; -/*********************************************************** - Called by server to defer an outgoing packet. -************************************************************/ + return true; +} -void srv_defer_sign_response(uint16 mid) +bool smb_signing_activate(struct smb_signing_state *si, + const DATA_BLOB user_session_key, + const DATA_BLOB response) { - struct smb_basic_signing_context *data; - - if (!srv_sign_info.doing_signing) - return; + size_t len; + off_t ofs; - data = (struct smb_basic_signing_context *)srv_sign_info.signing_context; + if (!user_session_key.length) { + return false; + } - if (!data) - return; + if (!si->negotiated) { + return false; + } - /* - * Ensure we only store this mid reply once... - */ + if (si->active) { + return false; + } - store_sequence_for_reply(&data->outstanding_packet_list, mid, - data->send_seq_num-1); -} + if (si->mac_key.length > 0) { + return false; + } -/*********************************************************** - Called to remove sequence records when a deferred packet is - cancelled by mid. This should never find one.... -************************************************************/ + smb_signing_reset_info(si); -void srv_cancel_sign_response(uint16 mid, bool cancel) -{ - struct smb_basic_signing_context *data; - uint32 dummy_seq; + len = response.length + user_session_key.length; + si->mac_key = data_blob_talloc(si, NULL, len); - if (!srv_sign_info.doing_signing) - return; + ofs = 0; + memcpy(&si->mac_key.data[ofs], user_session_key.data, user_session_key.length); - data = (struct smb_basic_signing_context *)srv_sign_info.signing_context; + DEBUG(10, ("smb_signing_activate: user_session_key\n")); + dump_data(10, user_session_key.data, user_session_key.length); - if (!data) - return; + if (response.length) { + ofs = user_session_key.length; + memcpy(&si->mac_key.data[ofs], response.data, response.length); + DEBUG(10, ("smb_signing_activate: response_data\n")); + dump_data(10, response.data, response.length); + } else { + DEBUG(10, ("smb_signing_activate: NULL response_data\n")); + } - DEBUG(10,("srv_cancel_sign_response: for mid %u\n", (unsigned int)mid )); + dump_data_pw("smb_signing_activate: mac key is:\n", + si->mac_key.data, si->mac_key.length); - while (get_sequence_for_reply(&data->outstanding_packet_list, mid, &dummy_seq)) - ; + /* Initialise the sequence number */ + si->seqnum = 2; - /* cancel doesn't send a reply so doesn't burn a sequence number. */ - if (cancel) { - data->send_seq_num -= 1; - } + return true; } -/*********************************************************** - Called by server negprot when signing has been negotiated. -************************************************************/ - -void srv_set_signing_negotiated(void) +bool smb_signing_is_active(struct smb_signing_state *si) { - srv_sign_info.allow_smb_signing = True; - srv_sign_info.negotiated_smb_signing = True; - if (lp_server_signing() == Required) - srv_sign_info.mandatory_signing = True; - - srv_sign_info.sign_outgoing_message = temp_sign_outgoing_message; - srv_sign_info.check_incoming_message = temp_check_incoming_message; - srv_sign_info.free_signing_context = temp_free_signing_context; + return si->active; } -/*********************************************************** - Returns whether signing is active. We can't use sendfile or raw - reads/writes if it is. -************************************************************/ - -bool srv_is_signing_active(void) +bool smb_signing_is_allowed(struct smb_signing_state *si) { - return srv_sign_info.doing_signing; + return si->allowed; } - -/*********************************************************** - Returns whether signing is negotiated. We can't use it unless it was - in the negprot. -************************************************************/ - -bool srv_is_signing_negotiated(void) +bool smb_signing_is_mandatory(struct smb_signing_state *si) { - return srv_sign_info.negotiated_smb_signing; + return si->mandatory; } -/*********************************************************** - Returns whether signing is actually happening -************************************************************/ - -bool srv_signing_started(void) +bool smb_signing_set_negotiated(struct smb_signing_state *si) { - struct smb_basic_signing_context *data; - - if (!srv_sign_info.doing_signing) { - return False; + if (!si->allowed) { + return false; } - data = (struct smb_basic_signing_context *)srv_sign_info.signing_context; - if (!data) - return False; + si->negotiated = true; - if (data->send_seq_num == 0) { - return False; - } - - return True; + return true; } -/*********************************************************** - Turn on signing from this packet onwards. -************************************************************/ - -void srv_set_signing(const DATA_BLOB user_session_key, const DATA_BLOB response) +bool smb_signing_is_negotiated(struct smb_signing_state *si) { - struct smb_basic_signing_context *data; - - if (!user_session_key.length) - return; - - if (!srv_sign_info.negotiated_smb_signing && !srv_sign_info.mandatory_signing) { - DEBUG(5,("srv_set_signing: signing negotiated = %u, mandatory_signing = %u. Not allowing smb signing.\n", - (unsigned int)srv_sign_info.negotiated_smb_signing, - (unsigned int)srv_sign_info.mandatory_signing )); - return; - } - - /* Once we've turned on, ignore any more sessionsetups. */ - if (srv_sign_info.doing_signing) { - return; - } - - if (srv_sign_info.free_signing_context) - srv_sign_info.free_signing_context(&srv_sign_info); - - srv_sign_info.doing_signing = True; - - data = SMB_XMALLOC_P(struct smb_basic_signing_context); - memset(data, '\0', sizeof(*data)); - - srv_sign_info.signing_context = data; - - data->mac_key = data_blob(NULL, response.length + user_session_key.length); - - memcpy(&data->mac_key.data[0], user_session_key.data, user_session_key.length); - if (response.length) - memcpy(&data->mac_key.data[user_session_key.length],response.data, response.length); - - dump_data_pw("MAC ssession key is:\n", data->mac_key.data, data->mac_key.length); - - DEBUG(3,("srv_set_signing: turning on SMB signing: signing negotiated = %s, mandatory_signing = %s.\n", - BOOLSTR(srv_sign_info.negotiated_smb_signing), - BOOLSTR(srv_sign_info.mandatory_signing) )); - - /* Initialise the sequence number */ - data->send_seq_num = 0; - - /* Initialise the list of outstanding packets */ - data->outstanding_packet_list = NULL; - - srv_sign_info.sign_outgoing_message = srv_sign_outgoing_message; - srv_sign_info.check_incoming_message = srv_check_incoming_message; - srv_sign_info.free_signing_context = simple_free_signing_context; + return si->negotiated; } diff --git a/source3/libsmb/unexpected.c b/source3/libsmb/unexpected.c index df4d2119e2..d123e24aa8 100644 --- a/source3/libsmb/unexpected.c +++ b/source3/libsmb/unexpected.c @@ -162,6 +162,8 @@ static int traverse_match(TDB_CONTEXT *ttdb, TDB_DATA kbuf, TDB_DATA dbuf, state->match_type, ip, port); + if (!p) + return 0; if ((state->match_type == NMB_PACKET && p->packet.nmb.header.name_trn_id == state->match_id) || diff --git a/source3/locking/locking.c b/source3/locking/locking.c index bafb89522a..70841225a7 100644 --- a/source3/locking/locking.c +++ b/source3/locking/locking.c @@ -887,7 +887,8 @@ struct share_mode_lock *fetch_share_mode_unlocked(TALLOC_CTX *mem_ctx, } if (!fill_share_mode_lock(lck, id, servicepath, fname, data, NULL)) { - DEBUG(3, ("fill_share_mode_lock failed\n")); + DEBUG(10, ("fetch_share_mode_unlocked: no share_mode record " + "around (file not open)\n")); TALLOC_FREE(lck); return NULL; } diff --git a/source3/modules/onefs_acl.c b/source3/modules/onefs_acl.c index 6f23d608d4..8ee31abc88 100644 --- a/source3/modules/onefs_acl.c +++ b/source3/modules/onefs_acl.c @@ -825,7 +825,7 @@ NTSTATUS onefs_samba_sd_to_sd(uint32 security_info_sent, SEC_DESC *psd, /* Setup owner */ if (security_info_sent & OWNER_SECURITY_INFORMATION) { if (!onefs_og_to_identity(psd->owner_sid, &owner, false, snum)) - return NT_STATUS_UNSUCCESSFUL; + return NT_STATUS_ACCESS_DENIED; SMB_ASSERT(owner.id.uid >= 0); @@ -835,7 +835,7 @@ NTSTATUS onefs_samba_sd_to_sd(uint32 security_info_sent, SEC_DESC *psd, /* Setup group */ if (security_info_sent & GROUP_SECURITY_INFORMATION) { if (!onefs_og_to_identity(psd->group_sid, &group, true, snum)) - return NT_STATUS_UNSUCCESSFUL; + return NT_STATUS_ACCESS_DENIED; SMB_ASSERT(group.id.gid >= 0); @@ -846,7 +846,7 @@ NTSTATUS onefs_samba_sd_to_sd(uint32 security_info_sent, SEC_DESC *psd, if ((security_info_sent & DACL_SECURITY_INFORMATION) && (psd->dacl)) { if (!onefs_samba_acl_to_acl(psd->dacl, &daclp, &ignore_aces, snum)) - return NT_STATUS_UNSUCCESSFUL; + return NT_STATUS_ACCESS_DENIED; if (ignore_aces == true) security_info_sent &= ~DACL_SECURITY_INFORMATION; @@ -863,7 +863,7 @@ NTSTATUS onefs_samba_sd_to_sd(uint32 security_info_sent, SEC_DESC *psd, if (psd->sacl) { if (!onefs_samba_acl_to_acl(psd->sacl, &saclp, &ignore_aces, snum)) - return NT_STATUS_UNSUCCESSFUL; + return NT_STATUS_ACCESS_DENIED; if (ignore_aces == true) { security_info_sent &= @@ -877,7 +877,7 @@ NTSTATUS onefs_samba_sd_to_sd(uint32 security_info_sent, SEC_DESC *psd, DEBUG(5,("Setting up SD\n")); if (aclu_initialize_sd(sd, psd->type, ownerp, groupp, (daclp ? &daclp : NULL), (saclp ? &saclp : NULL), false)) - return NT_STATUS_UNSUCCESSFUL; + return NT_STATUS_ACCESS_DENIED; return NT_STATUS_OK; } diff --git a/source3/modules/onefs_open.c b/source3/modules/onefs_open.c index c5030f4ab8..c23c176b79 100644 --- a/source3/modules/onefs_open.c +++ b/source3/modules/onefs_open.c @@ -208,14 +208,14 @@ static NTSTATUS onefs_open_file(files_struct *fsp, if ((oplock_request & ~SAMBA_PRIVATE_OPLOCK_MASK) != NO_OPLOCK) { DEBUG(0,("Oplock(%d) being requested on a stream! " - "Ignoring oplock request: base=%s, stream=%s", + "Ignoring oplock request: base=%s, stream=%s\n", oplock_request & ~SAMBA_PRIVATE_OPLOCK_MASK, base, stream)); /* Recover by requesting NO_OPLOCK instead. */ oplock_request &= SAMBA_PRIVATE_OPLOCK_MASK; } - DEBUG(10,("Opening a stream: base=%s(%d), stream=%s", + DEBUG(10,("Opening a stream: base=%s(%d), stream=%s\n", base, fsp->base_fsp->fh->fd, stream)); base_fd = fsp->base_fsp->fh->fd; @@ -386,15 +386,6 @@ static void defer_open(struct share_mode_lock *lck, exit_server("push_deferred_smb_message failed"); } add_deferred_open(lck, req->mid, request_time, state->id); - - /* - * Push the MID of this packet on the signing queue. - * We only do this once, the first time we push the packet - * onto the deferred open queue, as this has a side effect - * of incrementing the response sequence number. - */ - - srv_defer_sign_response(req->mid); } static void schedule_defer_open(struct share_mode_lock *lck, diff --git a/source3/modules/vfs_dirsort.c b/source3/modules/vfs_dirsort.c new file mode 100644 index 0000000000..53d1820c11 --- /dev/null +++ b/source3/modules/vfs_dirsort.c @@ -0,0 +1,194 @@ +/* + * VFS module to provide a sorted directory list. + * + * Copyright (C) Andy Kelk (andy@mopoke.co.uk), 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" + +static int compare_dirent (const void *a, const void *b) { + const SMB_STRUCT_DIRENT *da = (const SMB_STRUCT_DIRENT *) a; + const SMB_STRUCT_DIRENT *db = (const SMB_STRUCT_DIRENT *) b; + return StrCaseCmp(da->d_name, db->d_name); +} + +struct dirsort_privates { + long pos; + SMB_STRUCT_DIRENT *directory_list; + long number_of_entries; + time_t mtime; + SMB_STRUCT_DIR *source_directory; + int fd; +}; + +static void free_dirsort_privates(void **datap) { + struct dirsort_privates *data = (struct dirsort_privates *) *datap; + SAFE_FREE(data->directory_list); + SAFE_FREE(data); + *datap = NULL; + + return; +} + +static void open_and_sort_dir (vfs_handle_struct *handle) +{ + SMB_STRUCT_DIRENT *dp; + struct stat dir_stat; + long current_pos; + struct dirsort_privates *data = NULL; + + SMB_VFS_HANDLE_GET_DATA(handle, data, struct dirsort_privates, return); + + data->number_of_entries = 0; + + if (fstat(data->fd, &dir_stat) == 0) { + data->mtime = dir_stat.st_mtime; + } + + while (SMB_VFS_NEXT_READDIR(handle, data->source_directory, NULL) + != NULL) { + data->number_of_entries++; + } + + /* Open the underlying directory and count the number of entries + Skip back to the beginning as we'll read it again */ + SMB_VFS_NEXT_REWINDDIR(handle, data->source_directory); + + /* Set up an array and read the directory entries into it */ + SAFE_FREE(data->directory_list); /* destroy previous cache if needed */ + data->directory_list = (SMB_STRUCT_DIRENT *)SMB_MALLOC( + data->number_of_entries * sizeof(SMB_STRUCT_DIRENT)); + current_pos = data->pos; + data->pos = 0; + while ((dp = SMB_VFS_NEXT_READDIR(handle, data->source_directory, + NULL)) != NULL) { + data->directory_list[data->pos++] = *dp; + } + + /* Sort the directory entries by name */ + data->pos = current_pos; + qsort(data->directory_list, data->number_of_entries, + sizeof(SMB_STRUCT_DIRENT), compare_dirent); +} + +static SMB_STRUCT_DIR *dirsort_opendir(vfs_handle_struct *handle, + const char *fname, const char *mask, + uint32 attr) +{ + struct dirsort_privates *data = NULL; + + /* set up our private data about this directory */ + data = (struct dirsort_privates *)SMB_MALLOC( + sizeof(struct dirsort_privates)); + + data->directory_list = NULL; + data->pos = 0; + + /* Open the underlying directory and count the number of entries */ + data->source_directory = SMB_VFS_NEXT_OPENDIR(handle, fname, mask, + attr); + + data->fd = dirfd(data->source_directory); + + SMB_VFS_HANDLE_SET_DATA(handle, data, free_dirsort_privates, + struct dirsort_privates, return NULL); + + open_and_sort_dir(handle); + + return data->source_directory; +} + +static SMB_STRUCT_DIRENT *dirsort_readdir(vfs_handle_struct *handle, + SMB_STRUCT_DIR *dirp) +{ + struct dirsort_privates *data = NULL; + time_t current_mtime; + struct stat dir_stat; + + SMB_VFS_HANDLE_GET_DATA(handle, data, struct dirsort_privates, + return NULL); + + if (fstat(data->fd, &dir_stat) == -1) { + return NULL; + } + + current_mtime = dir_stat.st_mtime; + + /* throw away cache and re-read the directory if we've changed */ + if (current_mtime > data->mtime) { + open_and_sort_dir(handle); + } + + if (data->pos >= data->number_of_entries) { + return NULL; + } + + return &data->directory_list[data->pos++]; +} + +static void dirsort_seekdir(vfs_handle_struct *handle, SMB_STRUCT_DIR *dirp, + long offset) +{ + struct dirsort_privates *data = NULL; + SMB_VFS_HANDLE_GET_DATA(handle, data, struct dirsort_privates, return); + + data->pos = offset; +} + +static long dirsort_telldir(vfs_handle_struct *handle, SMB_STRUCT_DIR *dirp) +{ + struct dirsort_privates *data = NULL; + SMB_VFS_HANDLE_GET_DATA(handle, data, struct dirsort_privates, + return -1); + + return data->pos; +} + +static void dirsort_rewinddir(vfs_handle_struct *handle, SMB_STRUCT_DIR *dirp) +{ + struct dirsort_privates *data = NULL; + SMB_VFS_HANDLE_GET_DATA(handle, data, struct dirsort_privates, return); + + data->pos = 0; +} + +/* VFS operations structure */ + +static vfs_op_tuple dirsort_op_tuples[] = { + + /* Directory operations */ + + {SMB_VFS_OP(dirsort_opendir), SMB_VFS_OP_OPENDIR, + SMB_VFS_LAYER_TRANSPARENT}, + {SMB_VFS_OP(dirsort_readdir), SMB_VFS_OP_READDIR, + SMB_VFS_LAYER_TRANSPARENT}, + {SMB_VFS_OP(dirsort_seekdir), SMB_VFS_OP_SEEKDIR, + SMB_VFS_LAYER_TRANSPARENT}, + {SMB_VFS_OP(dirsort_telldir), SMB_VFS_OP_TELLDIR, + SMB_VFS_LAYER_TRANSPARENT}, + {SMB_VFS_OP(dirsort_rewinddir), SMB_VFS_OP_REWINDDIR, + SMB_VFS_LAYER_TRANSPARENT}, + + {NULL, SMB_VFS_OP_NOOP, + SMB_VFS_LAYER_NOOP} +}; + +NTSTATUS vfs_dirsort_init(void) +{ + return smb_register_vfs(SMB_VFS_INTERFACE_VERSION, "dirsort", + dirsort_op_tuples); +} diff --git a/source3/nmbd/nmbd.c b/source3/nmbd/nmbd.c index 3279466602..daf4c295a6 100644 --- a/source3/nmbd/nmbd.c +++ b/source3/nmbd/nmbd.c @@ -988,6 +988,12 @@ static bool open_sockets(bool isdaemon, int port) exit(1); } + if (!initialize_nmbd_proxy_logon()) { + DEBUG(0,("ERROR: Failed setup nmbd_proxy_logon.\n")); + kill_async_dns_child(); + exit(1); + } + TALLOC_FREE(frame); process(); diff --git a/source3/nmbd/nmbd_processlogon.c b/source3/nmbd/nmbd_processlogon.c index 59a2ca405e..8173337da0 100644 --- a/source3/nmbd/nmbd_processlogon.c +++ b/source3/nmbd/nmbd_processlogon.c @@ -24,6 +24,9 @@ */ #include "includes.h" +#include "../libcli/netlogon.h" +#include "../libcli/cldap/cldap.h" +#include "../lib/tsocket/tsocket.h" struct sam_database_info { uint32 index; @@ -65,6 +68,235 @@ static void delayed_init_logon_handler(struct event_context *event_ctx, TALLOC_FREE(te); } +struct nmbd_proxy_logon_context { + struct cldap_socket *cldap_sock; +}; + +static struct nmbd_proxy_logon_context *global_nmbd_proxy_logon; + +bool initialize_nmbd_proxy_logon(void) +{ + const char *cldap_server = lp_parm_const_string(-1, "nmbd_proxy_logon", + "cldap_server", NULL); + struct nmbd_proxy_logon_context *ctx; + NTSTATUS status; + struct in_addr addr; + char addrstr[INET_ADDRSTRLEN]; + const char *server_str; + int ret; + struct tsocket_address *server_addr; + + if (!cldap_server) { + return true; + } + + addr = interpret_addr2(cldap_server); + server_str = inet_ntop(AF_INET, &addr, + addrstr, sizeof(addrstr)); + if (!server_str || strcmp("0.0.0.0", server_str) == 0) { + DEBUG(0,("Failed to resolve[%s] for nmbd_proxy_logon\n", + cldap_server)); + return false; + } + + ctx = talloc_zero(nmbd_event_context(), + struct nmbd_proxy_logon_context); + if (!ctx) { + return false; + } + + ret = tsocket_address_inet_from_strings(ctx, "ipv4", + server_str, LDAP_PORT, + &server_addr); + if (ret != 0) { + TALLOC_FREE(ctx); + status = map_nt_error_from_unix(errno); + DEBUG(0,("Failed to create cldap tsocket_address for %s - %s\n", + server_str, nt_errstr(status))); + return false; + } + + /* we create a connected udp socket */ + status = cldap_socket_init(ctx, nmbd_event_context(), NULL, + server_addr, &ctx->cldap_sock); + TALLOC_FREE(server_addr); + if (!NT_STATUS_IS_OK(status)) { + TALLOC_FREE(ctx); + DEBUG(0,("failed to create cldap socket for %s: %s\n", + server_str, nt_errstr(status))); + return false; + } + + global_nmbd_proxy_logon = ctx; + return true; +} + +struct nmbd_proxy_logon_state { + struct in_addr local_ip; + struct packet_struct *p; + const char *remote_name; + uint8_t remote_name_type; + const char *remote_mailslot; + struct nbt_netlogon_packet req; + struct nbt_netlogon_response resp; + struct cldap_netlogon io; +}; + +static int nmbd_proxy_logon_state_destructor(struct nmbd_proxy_logon_state *s) +{ + s->p->locked = false; + free_packet(s->p); + return 0; +} + +static void nmbd_proxy_logon_done(struct tevent_req *subreq); + +static void nmbd_proxy_logon(struct nmbd_proxy_logon_context *ctx, + struct in_addr local_ip, + struct packet_struct *p, + uint8_t *buf, + uint32_t len) +{ + struct nmbd_proxy_logon_state *state; + enum ndr_err_code ndr_err; + DATA_BLOB blob = data_blob_const(buf, len); + const char *computer_name = NULL; + const char *mailslot_name = NULL; + const char *user_name = NULL; + const char *domain_sid = NULL; + uint32_t acct_control = 0; + uint32_t nt_version = 0; + struct tevent_req *subreq; + fstring source_name; + struct dgram_packet *dgram = &p->packet.dgram; + + state = TALLOC_ZERO_P(ctx, struct nmbd_proxy_logon_state); + if (!state) { + DEBUG(0,("failed to allocate nmbd_proxy_logon_state\n")); + return; + } + + pull_ascii_nstring(source_name, sizeof(source_name), dgram->source_name.name); + state->remote_name = talloc_strdup(state, source_name); + state->remote_name_type = dgram->source_name.name_type, + state->local_ip = local_ip; + state->p = p; + + ndr_err = ndr_pull_struct_blob( + &blob, state, NULL, &state->req, + (ndr_pull_flags_fn_t)ndr_pull_nbt_netlogon_packet); + if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { + NTSTATUS status = ndr_map_error2ntstatus(ndr_err); + DEBUG(0,("failed parse nbt_letlogon_packet: %s\n", + nt_errstr(status))); + TALLOC_FREE(state); + return; + } + + if (DEBUGLEVEL >= 10) { + DEBUG(10, ("nmbd_proxy_logon:\n")); + NDR_PRINT_DEBUG(nbt_netlogon_packet, &state->req); + } + + switch (state->req.command) { + case LOGON_SAM_LOGON_REQUEST: + computer_name = state->req.req.logon.computer_name; + user_name = state->req.req.logon.user_name; + mailslot_name = state->req.req.logon.mailslot_name; + acct_control = state->req.req.logon.acct_control; + if (state->req.req.logon.sid_size > 0) { + domain_sid = dom_sid_string(state, + &state->req.req.logon.sid); + if (!domain_sid) { + DEBUG(0,("failed to get a string for sid\n")); + TALLOC_FREE(state); + return; + } + } + nt_version = state->req.req.logon.nt_version; + break; + + default: + /* this can't happen as the caller already checks the command */ + break; + } + + state->remote_mailslot = mailslot_name; + + if (user_name && strlen(user_name) == 0) { + user_name = NULL; + } + + if (computer_name && strlen(computer_name) == 0) { + computer_name = NULL; + } + + /* + * as the socket is connected, + * we don't need to specify the destination + */ + state->io.in.dest_address = NULL; + state->io.in.dest_port = 0; + state->io.in.realm = NULL; + state->io.in.host = computer_name; + state->io.in.user = user_name; + state->io.in.domain_guid = NULL; + state->io.in.domain_sid = domain_sid; + state->io.in.acct_control = acct_control; + state->io.in.version = nt_version; + state->io.in.map_response = false; + + subreq = cldap_netlogon_send(state, + ctx->cldap_sock, + &state->io); + if (!subreq) { + DEBUG(0,("failed to send cldap netlogon call\n")); + TALLOC_FREE(state); + return; + } + tevent_req_set_callback(subreq, nmbd_proxy_logon_done, state); + + /* we reply async */ + state->p->locked = true; + talloc_set_destructor(state, nmbd_proxy_logon_state_destructor); +} + +static void nmbd_proxy_logon_done(struct tevent_req *subreq) +{ + struct nmbd_proxy_logon_state *state = + tevent_req_callback_data(subreq, + struct nmbd_proxy_logon_state); + NTSTATUS status; + DATA_BLOB response; + + status = cldap_netlogon_recv(subreq, NULL, state, &state->io); + if (!NT_STATUS_IS_OK(status)) { + DEBUG(0,("failed to recv cldap netlogon call: %s\n", + nt_errstr(status))); + TALLOC_FREE(state); + return; + } + + status = push_netlogon_samlogon_response(&response, state, NULL, + &state->io.out.netlogon); + if (!NT_STATUS_IS_OK(status)) { + DEBUG(0,("failed to push netlogon_samlogon_response: %s\n", + nt_errstr(status))); + TALLOC_FREE(state); + return; + } + + send_mailslot(true, state->remote_mailslot, + (char *)response.data, response.length, + global_myname(), 0x0, + state->remote_name, + state->remote_name_type, + state->p->ip, + state->local_ip, + state->p->port); + TALLOC_FREE(state); +} + /**************************************************************************** Process a domain logon packet **************************************************************************/ @@ -318,6 +550,12 @@ reporting %s domain %s 0x%x ntversion=%x lm_nt token=%x lm_20 token=%x\n", char *q = buf + 2; fstring asccomp; + if (global_nmbd_proxy_logon) { + nmbd_proxy_logon(global_nmbd_proxy_logon, + ip, p, (uint8_t *)buf, len); + return; + } + q += 2; if (PTR_DIFF(q, buf) >= len) { diff --git a/source3/param/loadparm.c b/source3/param/loadparm.c index f49a1bc4c9..66fb8bf1bc 100644 --- a/source3/param/loadparm.c +++ b/source3/param/loadparm.c @@ -9542,10 +9542,6 @@ const char *lp_printcapname(void) return PRINTCAP_NAME; } -/******************************************************************* - Ensure we don't use sendfile if server smb signing is active. -********************************************************************/ - static uint32 spoolss_state; bool lp_disable_spoolss( void ) @@ -9572,15 +9568,20 @@ uint32 lp_get_spoolss_state( void ) Ensure we don't use sendfile if server smb signing is active. ********************************************************************/ -bool lp_use_sendfile(int snum) +bool lp_use_sendfile(int snum, struct smb_signing_state *signing_state) { + bool sign_active = false; + /* Using sendfile blows the brains out of any DOS or Win9x TCP stack... JRA. */ if (Protocol < PROTOCOL_NT1) { - return False; + return false; + } + if (signing_state) { + sign_active = smb_signing_is_active(signing_state); } return (_lp_use_sendfile(snum) && (get_remote_arch() != RA_WIN95) && - !srv_is_signing_active()); + !sign_active); } /******************************************************************* diff --git a/source3/passdb/lookup_sid.c b/source3/passdb/lookup_sid.c index 9c20042a62..a5c2d50366 100644 --- a/source3/passdb/lookup_sid.c +++ b/source3/passdb/lookup_sid.c @@ -804,7 +804,7 @@ NTSTATUS lookup_sids(TALLOC_CTX *mem_ctx, int num_sids, } else { /* This is a normal SID with rid component */ if (!sid_split_rid(&sid, &rid)) { - result = NT_STATUS_INVALID_PARAMETER; + result = NT_STATUS_INVALID_SID; goto fail; } } diff --git a/source3/printing/nt_printing.c b/source3/printing/nt_printing.c index 8e6fe1f364..a99485d381 100644 --- a/source3/printing/nt_printing.c +++ b/source3/printing/nt_printing.c @@ -2275,7 +2275,9 @@ static WERROR get_a_printer_driver_3_default(NT_PRINTER_DRIVER_INFO_LEVEL_3 **in /**************************************************************************** ****************************************************************************/ -static WERROR get_a_printer_driver_3(NT_PRINTER_DRIVER_INFO_LEVEL_3 **info_ptr, fstring drivername, const char *arch, uint32 version) +static WERROR get_a_printer_driver_3(NT_PRINTER_DRIVER_INFO_LEVEL_3 **info_ptr, + const char *drivername, const char *arch, + uint32_t version) { NT_PRINTER_DRIVER_INFO_LEVEL_3 driver; TDB_DATA dbuf; @@ -4448,7 +4450,7 @@ bool set_driver_init(NT_PRINTER_INFO_LEVEL *printer, uint32 level) Delete driver init data stored for a specified driver ****************************************************************************/ -bool del_driver_init(char *drivername) +bool del_driver_init(const char *drivername) { char *key; bool ret; @@ -4837,8 +4839,9 @@ uint32 add_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL driver, uint32 level) /**************************************************************************** ****************************************************************************/ -WERROR get_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL *driver, uint32 level, - fstring drivername, const char *architecture, uint32 version) +WERROR get_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL *driver, uint32_t level, + const char *drivername, const char *architecture, + uint32_t version) { WERROR result; diff --git a/source3/registry/regfio.c b/source3/registry/regfio.c index d002bd72e7..e1c04c4777 100644 --- a/source3/registry/regfio.c +++ b/source3/registry/regfio.c @@ -712,8 +712,30 @@ static bool hbin_prs_sk_rec( const char *desc, REGF_HBIN *hbin, int depth, REGF_ if ( !prs_uint32( "size", ps, depth, &sk->size)) return False; - if ( !sec_io_desc( "sec_desc", &sk->sec_desc, ps, depth )) - return False; + { + NTSTATUS status; + TALLOC_CTX *mem_ctx = prs_get_mem_context(&hbin->ps); + DATA_BLOB blob; + + if (MARSHALLING(&hbin->ps)) { + status = marshall_sec_desc(mem_ctx, + sk->sec_desc, + &blob.data, &blob.length); + if (!NT_STATUS_IS_OK(status)) + return False; + if (!prs_copy_data_in(&hbin->ps, (const char *)blob.data, blob.length)) + return False; + } else { + blob = data_blob_const(prs_data_p(&hbin->ps), + prs_data_size(&hbin->ps)); + status = unmarshall_sec_desc(mem_ctx, + blob.data, blob.length, + &sk->sec_desc); + if (!NT_STATUS_IS_OK(status)) + return False; + prs_set_offset(&hbin->ps, blob.length); + } + } end_off = prs_offset( &hbin->ps ); diff --git a/source3/rpc_client/cli_pipe.c b/source3/rpc_client/cli_pipe.c index 57f49fb83a..6b83c170f5 100644 --- a/source3/rpc_client/cli_pipe.c +++ b/source3/rpc_client/cli_pipe.c @@ -207,18 +207,18 @@ struct rpc_read_state { size_t num_read; }; -static void rpc_read_done(struct async_req *subreq); +static void rpc_read_done(struct tevent_req *subreq); -static struct async_req *rpc_read_send(TALLOC_CTX *mem_ctx, - struct event_context *ev, - struct rpc_cli_transport *transport, - uint8_t *data, size_t size) +static struct tevent_req *rpc_read_send(TALLOC_CTX *mem_ctx, + struct event_context *ev, + struct rpc_cli_transport *transport, + uint8_t *data, size_t size) { - struct async_req *result, *subreq; + struct tevent_req *req, *subreq; struct rpc_read_state *state; - if (!async_req_setup(mem_ctx, &result, &state, - struct rpc_read_state)) { + req = tevent_req_create(mem_ctx, &state, struct rpc_read_state); + if (req == NULL) { return NULL; } state->ev = ev; @@ -234,34 +234,33 @@ static struct async_req *rpc_read_send(TALLOC_CTX *mem_ctx, if (subreq == NULL) { goto fail; } - subreq->async.fn = rpc_read_done; - subreq->async.priv = result; - return result; + tevent_req_set_callback(subreq, rpc_read_done, req); + return req; fail: - TALLOC_FREE(result); + TALLOC_FREE(req); return NULL; } -static void rpc_read_done(struct async_req *subreq) +static void rpc_read_done(struct tevent_req *subreq) { - struct async_req *req = talloc_get_type_abort( - subreq->async.priv, struct async_req); - struct rpc_read_state *state = talloc_get_type_abort( - req->private_data, struct rpc_read_state); + struct tevent_req *req = tevent_req_callback_data( + subreq, struct tevent_req); + struct rpc_read_state *state = tevent_req_data( + req, struct rpc_read_state); NTSTATUS status; ssize_t received; status = state->transport->read_recv(subreq, &received); TALLOC_FREE(subreq); if (!NT_STATUS_IS_OK(status)) { - async_req_nterror(req, status); + tevent_req_nterror(req, status); return; } state->num_read += received; if (state->num_read == state->size) { - async_req_done(req); + tevent_req_done(req); return; } @@ -269,16 +268,15 @@ static void rpc_read_done(struct async_req *subreq) state->data + state->num_read, state->size - state->num_read, state->transport->priv); - if (async_req_nomem(subreq, req)) { + if (tevent_req_nomem(subreq, req)) { return; } - subreq->async.fn = rpc_read_done; - subreq->async.priv = req; + tevent_req_set_callback(subreq, rpc_read_done, req); } -static NTSTATUS rpc_read_recv(struct async_req *req) +static NTSTATUS rpc_read_recv(struct tevent_req *req) { - return async_req_simple_recv_ntstatus(req); + return tevent_req_simple_recv_ntstatus(req); } struct rpc_write_state { @@ -289,18 +287,18 @@ struct rpc_write_state { size_t num_written; }; -static void rpc_write_done(struct async_req *subreq); +static void rpc_write_done(struct tevent_req *subreq); -static struct async_req *rpc_write_send(TALLOC_CTX *mem_ctx, - struct event_context *ev, - struct rpc_cli_transport *transport, - const uint8_t *data, size_t size) +static struct tevent_req *rpc_write_send(TALLOC_CTX *mem_ctx, + struct event_context *ev, + struct rpc_cli_transport *transport, + const uint8_t *data, size_t size) { - struct async_req *result, *subreq; + struct tevent_req *req, *subreq; struct rpc_write_state *state; - if (!async_req_setup(mem_ctx, &result, &state, - struct rpc_write_state)) { + req = tevent_req_create(mem_ctx, &state, struct rpc_write_state); + if (req == NULL) { return NULL; } state->ev = ev; @@ -315,34 +313,33 @@ static struct async_req *rpc_write_send(TALLOC_CTX *mem_ctx, if (subreq == NULL) { goto fail; } - subreq->async.fn = rpc_write_done; - subreq->async.priv = result; - return result; + tevent_req_set_callback(subreq, rpc_write_done, req); + return req; fail: - TALLOC_FREE(result); + TALLOC_FREE(req); return NULL; } -static void rpc_write_done(struct async_req *subreq) +static void rpc_write_done(struct tevent_req *subreq) { - struct async_req *req = talloc_get_type_abort( - subreq->async.priv, struct async_req); - struct rpc_write_state *state = talloc_get_type_abort( - req->private_data, struct rpc_write_state); + struct tevent_req *req = tevent_req_callback_data( + subreq, struct tevent_req); + struct rpc_write_state *state = tevent_req_data( + req, struct rpc_write_state); NTSTATUS status; ssize_t written; status = state->transport->write_recv(subreq, &written); TALLOC_FREE(subreq); if (!NT_STATUS_IS_OK(status)) { - async_req_nterror(req, status); + tevent_req_nterror(req, status); return; } state->num_written += written; if (state->num_written == state->size) { - async_req_done(req); + tevent_req_done(req); return; } @@ -350,16 +347,15 @@ static void rpc_write_done(struct async_req *subreq) state->data + state->num_written, state->size - state->num_written, state->transport->priv); - if (async_req_nomem(subreq, req)) { + if (tevent_req_nomem(subreq, req)) { return; } - subreq->async.fn = rpc_write_done; - subreq->async.priv = req; + tevent_req_set_callback(subreq, rpc_write_done, req); } -static NTSTATUS rpc_write_recv(struct async_req *req) +static NTSTATUS rpc_write_recv(struct tevent_req *req) { - return async_req_simple_recv_ntstatus(req); + return tevent_req_simple_recv_ntstatus(req); } @@ -399,22 +395,23 @@ struct get_complete_frag_state { prs_struct *pdu; }; -static void get_complete_frag_got_header(struct async_req *subreq); -static void get_complete_frag_got_rest(struct async_req *subreq); +static void get_complete_frag_got_header(struct tevent_req *subreq); +static void get_complete_frag_got_rest(struct tevent_req *subreq); -static struct async_req *get_complete_frag_send(TALLOC_CTX *mem_ctx, - struct event_context *ev, - struct rpc_pipe_client *cli, - struct rpc_hdr_info *prhdr, - prs_struct *pdu) +static struct tevent_req *get_complete_frag_send(TALLOC_CTX *mem_ctx, + struct event_context *ev, + struct rpc_pipe_client *cli, + struct rpc_hdr_info *prhdr, + prs_struct *pdu) { - struct async_req *result, *subreq; + struct tevent_req *req, *subreq; struct get_complete_frag_state *state; uint32_t pdu_len; NTSTATUS status; - if (!async_req_setup(mem_ctx, &result, &state, - struct get_complete_frag_state)) { + req = tevent_req_create(mem_ctx, &state, + struct get_complete_frag_state); + if (req == NULL) { return NULL; } state->ev = ev; @@ -437,9 +434,9 @@ static struct async_req *get_complete_frag_send(TALLOC_CTX *mem_ctx, status = NT_STATUS_NO_MEMORY; goto post_status; } - subreq->async.fn = get_complete_frag_got_header; - subreq->async.priv = result; - return result; + tevent_req_set_callback(subreq, get_complete_frag_got_header, + req); + return req; } status = parse_rpc_header(cli, prhdr, pdu); @@ -463,43 +460,44 @@ static struct async_req *get_complete_frag_send(TALLOC_CTX *mem_ctx, status = NT_STATUS_NO_MEMORY; goto post_status; } - subreq->async.fn = get_complete_frag_got_rest; - subreq->async.priv = result; - return result; + tevent_req_set_callback(subreq, get_complete_frag_got_rest, + req); + return req; } status = NT_STATUS_OK; post_status: - if (async_post_ntstatus(result, ev, status)) { - return result; + if (NT_STATUS_IS_OK(status)) { + tevent_req_done(req); + } else { + tevent_req_nterror(req, status); } - TALLOC_FREE(result); - return NULL; + return tevent_req_post(req, ev); } -static void get_complete_frag_got_header(struct async_req *subreq) +static void get_complete_frag_got_header(struct tevent_req *subreq) { - struct async_req *req = talloc_get_type_abort( - subreq->async.priv, struct async_req); - struct get_complete_frag_state *state = talloc_get_type_abort( - req->private_data, struct get_complete_frag_state); + struct tevent_req *req = tevent_req_callback_data( + subreq, struct tevent_req); + struct get_complete_frag_state *state = tevent_req_data( + req, struct get_complete_frag_state); NTSTATUS status; status = rpc_read_recv(subreq); TALLOC_FREE(subreq); if (!NT_STATUS_IS_OK(status)) { - async_req_nterror(req, status); + tevent_req_nterror(req, status); return; } status = parse_rpc_header(state->cli, state->prhdr, state->pdu); if (!NT_STATUS_IS_OK(status)) { - async_req_nterror(req, status); + tevent_req_nterror(req, status); return; } if (!rpc_grow_buffer(state->pdu, state->prhdr->frag_len)) { - async_req_nterror(req, NT_STATUS_NO_MEMORY); + tevent_req_nterror(req, NT_STATUS_NO_MEMORY); return; } @@ -512,31 +510,30 @@ static void get_complete_frag_got_header(struct async_req *subreq) state, state->ev, state->cli->transport, (uint8_t *)(prs_data_p(state->pdu) + RPC_HEADER_LEN), state->prhdr->frag_len - RPC_HEADER_LEN); - if (async_req_nomem(subreq, req)) { + if (tevent_req_nomem(subreq, req)) { return; } - subreq->async.fn = get_complete_frag_got_rest; - subreq->async.priv = req; + tevent_req_set_callback(subreq, get_complete_frag_got_rest, req); } -static void get_complete_frag_got_rest(struct async_req *subreq) +static void get_complete_frag_got_rest(struct tevent_req *subreq) { - struct async_req *req = talloc_get_type_abort( - subreq->async.priv, struct async_req); + struct tevent_req *req = tevent_req_callback_data( + subreq, struct tevent_req); NTSTATUS status; status = rpc_read_recv(subreq); TALLOC_FREE(subreq); if (!NT_STATUS_IS_OK(status)) { - async_req_nterror(req, status); + tevent_req_nterror(req, status); return; } - async_req_done(req); + tevent_req_done(req); } -static NTSTATUS get_complete_frag_recv(struct async_req *req) +static NTSTATUS get_complete_frag_recv(struct tevent_req *req) { - return async_req_simple_recv_ntstatus(req); + return tevent_req_simple_recv_ntstatus(req); } /**************************************************************************** @@ -1037,22 +1034,22 @@ struct cli_api_pipe_state { uint32_t rdata_len; }; -static void cli_api_pipe_trans_done(struct async_req *subreq); -static void cli_api_pipe_write_done(struct async_req *subreq); -static void cli_api_pipe_read_done(struct async_req *subreq); +static void cli_api_pipe_trans_done(struct tevent_req *subreq); +static void cli_api_pipe_write_done(struct tevent_req *subreq); +static void cli_api_pipe_read_done(struct tevent_req *subreq); -static struct async_req *cli_api_pipe_send(TALLOC_CTX *mem_ctx, - struct event_context *ev, - struct rpc_cli_transport *transport, - uint8_t *data, size_t data_len, - uint32_t max_rdata_len) +static struct tevent_req *cli_api_pipe_send(TALLOC_CTX *mem_ctx, + struct event_context *ev, + struct rpc_cli_transport *transport, + uint8_t *data, size_t data_len, + uint32_t max_rdata_len) { - struct async_req *result, *subreq; + struct tevent_req *req, *subreq; struct cli_api_pipe_state *state; NTSTATUS status; - if (!async_req_setup(mem_ctx, &result, &state, - struct cli_api_pipe_state)) { + req = tevent_req_create(mem_ctx, &state, struct cli_api_pipe_state); + if (req == NULL) { return NULL; } state->ev = ev; @@ -1072,12 +1069,10 @@ static struct async_req *cli_api_pipe_send(TALLOC_CTX *mem_ctx, subreq = transport->trans_send(state, ev, data, data_len, max_rdata_len, transport->priv); if (subreq == NULL) { - status = NT_STATUS_NO_MEMORY; - goto post_status; + goto fail; } - subreq->async.fn = cli_api_pipe_trans_done; - subreq->async.priv = result; - return result; + tevent_req_set_callback(subreq, cli_api_pipe_trans_done, req); + return req; } /* @@ -1089,56 +1084,54 @@ static struct async_req *cli_api_pipe_send(TALLOC_CTX *mem_ctx, if (subreq == NULL) { goto fail; } - subreq->async.fn = cli_api_pipe_write_done; - subreq->async.priv = result; - return result; + tevent_req_set_callback(subreq, cli_api_pipe_write_done, req); + return req; status = NT_STATUS_INVALID_PARAMETER; post_status: - if (async_post_ntstatus(result, ev, status)) { - return result; - } + tevent_req_nterror(req, status); + return tevent_req_post(req, ev); fail: - TALLOC_FREE(result); + TALLOC_FREE(req); return NULL; } -static void cli_api_pipe_trans_done(struct async_req *subreq) +static void cli_api_pipe_trans_done(struct tevent_req *subreq) { - struct async_req *req = talloc_get_type_abort( - subreq->async.priv, struct async_req); - struct cli_api_pipe_state *state = talloc_get_type_abort( - req->private_data, struct cli_api_pipe_state); + struct tevent_req *req = tevent_req_callback_data( + subreq, struct tevent_req); + struct cli_api_pipe_state *state = tevent_req_data( + req, struct cli_api_pipe_state); NTSTATUS status; status = state->transport->trans_recv(subreq, state, &state->rdata, &state->rdata_len); TALLOC_FREE(subreq); if (!NT_STATUS_IS_OK(status)) { - async_req_nterror(req, status); + tevent_req_nterror(req, status); return; } - async_req_done(req); + tevent_req_done(req); } -static void cli_api_pipe_write_done(struct async_req *subreq) +static void cli_api_pipe_write_done(struct tevent_req *subreq) { - struct async_req *req = talloc_get_type_abort( - subreq->async.priv, struct async_req); - struct cli_api_pipe_state *state = talloc_get_type_abort( - req->private_data, struct cli_api_pipe_state); + struct tevent_req *req = tevent_req_callback_data( + subreq, struct tevent_req); + struct cli_api_pipe_state *state = tevent_req_data( + req, struct cli_api_pipe_state); NTSTATUS status; status = rpc_write_recv(subreq); TALLOC_FREE(subreq); if (!NT_STATUS_IS_OK(status)) { - async_req_nterror(req, status); + tevent_req_nterror(req, status); return; } state->rdata = TALLOC_ARRAY(state, uint8_t, RPC_HEADER_LEN); - if (async_req_nomem(state->rdata, req)) { + if (tevent_req_nomem(state->rdata, req)) { return; } @@ -1150,40 +1143,39 @@ static void cli_api_pipe_write_done(struct async_req *subreq) subreq = state->transport->read_send(state, state->ev, state->rdata, RPC_HEADER_LEN, state->transport->priv); - if (async_req_nomem(subreq, req)) { + if (tevent_req_nomem(subreq, req)) { return; } - subreq->async.fn = cli_api_pipe_read_done; - subreq->async.priv = req; + tevent_req_set_callback(subreq, cli_api_pipe_read_done, req); } -static void cli_api_pipe_read_done(struct async_req *subreq) +static void cli_api_pipe_read_done(struct tevent_req *subreq) { - struct async_req *req = talloc_get_type_abort( - subreq->async.priv, struct async_req); - struct cli_api_pipe_state *state = talloc_get_type_abort( - req->private_data, struct cli_api_pipe_state); + struct tevent_req *req = tevent_req_callback_data( + subreq, struct tevent_req); + struct cli_api_pipe_state *state = tevent_req_data( + req, struct cli_api_pipe_state); NTSTATUS status; ssize_t received; status = state->transport->read_recv(subreq, &received); TALLOC_FREE(subreq); if (!NT_STATUS_IS_OK(status)) { - async_req_nterror(req, status); + tevent_req_nterror(req, status); return; } state->rdata_len = received; - async_req_done(req); + tevent_req_done(req); } -static NTSTATUS cli_api_pipe_recv(struct async_req *req, TALLOC_CTX *mem_ctx, +static NTSTATUS cli_api_pipe_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx, uint8_t **prdata, uint32_t *prdata_len) { - struct cli_api_pipe_state *state = talloc_get_type_abort( - req->private_data, struct cli_api_pipe_state); + struct cli_api_pipe_state *state = tevent_req_data( + req, struct cli_api_pipe_state); NTSTATUS status; - if (async_req_is_nterror(req, &status)) { + if (tevent_req_is_nterror(req, &status)) { return status; } @@ -1237,22 +1229,22 @@ static int rpc_api_pipe_state_destructor(struct rpc_api_pipe_state *state) return 0; } -static void rpc_api_pipe_trans_done(struct async_req *subreq); -static void rpc_api_pipe_got_pdu(struct async_req *subreq); +static void rpc_api_pipe_trans_done(struct tevent_req *subreq); +static void rpc_api_pipe_got_pdu(struct tevent_req *subreq); -static struct async_req *rpc_api_pipe_send(TALLOC_CTX *mem_ctx, - struct event_context *ev, - struct rpc_pipe_client *cli, - prs_struct *data, /* Outgoing PDU */ - uint8_t expected_pkt_type) +static struct tevent_req *rpc_api_pipe_send(TALLOC_CTX *mem_ctx, + struct event_context *ev, + struct rpc_pipe_client *cli, + prs_struct *data, /* Outgoing PDU */ + uint8_t expected_pkt_type) { - struct async_req *result, *subreq; + struct tevent_req *req, *subreq; struct rpc_api_pipe_state *state; uint16_t max_recv_frag; NTSTATUS status; - if (!async_req_setup(mem_ctx, &result, &state, - struct rpc_api_pipe_state)) { + req = tevent_req_create(mem_ctx, &state, struct rpc_api_pipe_state); + if (req == NULL) { return NULL; } state->ev = ev; @@ -1288,27 +1280,25 @@ static struct async_req *rpc_api_pipe_send(TALLOC_CTX *mem_ctx, (uint8_t *)prs_data_p(data), prs_offset(data), max_recv_frag); if (subreq == NULL) { - status = NT_STATUS_NO_MEMORY; - goto post_status; + goto fail; } - subreq->async.fn = rpc_api_pipe_trans_done; - subreq->async.priv = result; - return result; + tevent_req_set_callback(subreq, rpc_api_pipe_trans_done, req); + return req; post_status: - if (async_post_ntstatus(result, ev, status)) { - return result; - } - TALLOC_FREE(result); + tevent_req_nterror(req, status); + return tevent_req_post(req, ev); + fail: + TALLOC_FREE(req); return NULL; } -static void rpc_api_pipe_trans_done(struct async_req *subreq) +static void rpc_api_pipe_trans_done(struct tevent_req *subreq) { - struct async_req *req = talloc_get_type_abort( - subreq->async.priv, struct async_req); - struct rpc_api_pipe_state *state = talloc_get_type_abort( - req->private_data, struct rpc_api_pipe_state); + struct tevent_req *req = tevent_req_callback_data( + subreq, struct tevent_req); + struct rpc_api_pipe_state *state = tevent_req_data( + req, struct rpc_api_pipe_state); NTSTATUS status; uint8_t *rdata = NULL; uint32_t rdata_len = 0; @@ -1318,14 +1308,14 @@ 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_nterror(req, status); + tevent_req_nterror(req, status); return; } if (rdata == NULL) { DEBUG(3,("rpc_api_pipe: %s failed to return data.\n", rpccli_pipe_txt(debug_ctx(), state->cli))); - async_req_done(req); + tevent_req_done(req); return; } @@ -1336,7 +1326,7 @@ static void rpc_api_pipe_trans_done(struct async_req *subreq) */ rdata_copy = (char *)memdup(rdata, rdata_len); TALLOC_FREE(rdata); - if (async_req_nomem(rdata_copy, req)) { + if (tevent_req_nomem(rdata_copy, req)) { return; } prs_give_memory(&state->incoming_frag, rdata_copy, rdata_len, true); @@ -1344,19 +1334,18 @@ static void rpc_api_pipe_trans_done(struct async_req *subreq) /* Ensure we have enough data for a pdu. */ subreq = get_complete_frag_send(state, state->ev, state->cli, &state->rhdr, &state->incoming_frag); - if (async_req_nomem(subreq, req)) { + if (tevent_req_nomem(subreq, req)) { return; } - subreq->async.fn = rpc_api_pipe_got_pdu; - subreq->async.priv = req; + tevent_req_set_callback(subreq, rpc_api_pipe_got_pdu, req); } -static void rpc_api_pipe_got_pdu(struct async_req *subreq) +static void rpc_api_pipe_got_pdu(struct tevent_req *subreq) { - struct async_req *req = talloc_get_type_abort( - subreq->async.priv, struct async_req); - struct rpc_api_pipe_state *state = talloc_get_type_abort( - req->private_data, struct rpc_api_pipe_state); + struct tevent_req *req = tevent_req_callback_data( + subreq, struct tevent_req); + struct rpc_api_pipe_state *state = tevent_req_data( + req, struct rpc_api_pipe_state); NTSTATUS status; char *rdata = NULL; uint32_t rdata_len = 0; @@ -1366,7 +1355,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_nterror(req, status); + tevent_req_nterror(req, status); return; } @@ -1381,7 +1370,7 @@ static void rpc_api_pipe_got_pdu(struct async_req *subreq) nt_errstr(status))); if (!NT_STATUS_IS_OK(status)) { - async_req_nterror(req, status); + tevent_req_nterror(req, status); return; } @@ -1405,13 +1394,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_nterror(req, NT_STATUS_INVALID_PARAMETER); + tevent_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_nterror(req, NT_STATUS_NO_MEMORY); + tevent_req_nterror(req, NT_STATUS_NO_MEMORY); return; } @@ -1422,7 +1411,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_nterror(req, status); + tevent_req_nterror(req, status); return; } @@ -1430,27 +1419,26 @@ static void rpc_api_pipe_got_pdu(struct async_req *subreq) DEBUG(10,("rpc_api_pipe: %s returned %u bytes.\n", rpccli_pipe_txt(debug_ctx(), state->cli), (unsigned)prs_data_size(&state->incoming_pdu))); - async_req_done(req); + tevent_req_done(req); return; } subreq = get_complete_frag_send(state, state->ev, state->cli, &state->rhdr, &state->incoming_frag); - if (async_req_nomem(subreq, req)) { + if (tevent_req_nomem(subreq, req)) { return; } - subreq->async.fn = rpc_api_pipe_got_pdu; - subreq->async.priv = req; + tevent_req_set_callback(subreq, rpc_api_pipe_got_pdu, req); } -static NTSTATUS rpc_api_pipe_recv(struct async_req *req, TALLOC_CTX *mem_ctx, +static NTSTATUS rpc_api_pipe_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx, prs_struct *reply_pdu) { - struct rpc_api_pipe_state *state = talloc_get_type_abort( - req->private_data, struct rpc_api_pipe_state); + struct rpc_api_pipe_state *state = tevent_req_data( + req, struct rpc_api_pipe_state); NTSTATUS status; - if (async_req_is_nterror(req, &status)) { + if (tevent_req_is_nterror(req, &status)) { return status; } @@ -2043,24 +2031,25 @@ static int rpc_api_pipe_req_state_destructor(struct rpc_api_pipe_req_state *s) return 0; } -static void rpc_api_pipe_req_write_done(struct async_req *subreq); -static void rpc_api_pipe_req_done(struct async_req *subreq); +static void rpc_api_pipe_req_write_done(struct tevent_req *subreq); +static void rpc_api_pipe_req_done(struct tevent_req *subreq); static NTSTATUS prepare_next_frag(struct rpc_api_pipe_req_state *state, bool *is_last_frag); -struct async_req *rpc_api_pipe_req_send(TALLOC_CTX *mem_ctx, - struct event_context *ev, - struct rpc_pipe_client *cli, - uint8_t op_num, - prs_struct *req_data) +struct tevent_req *rpc_api_pipe_req_send(TALLOC_CTX *mem_ctx, + struct event_context *ev, + struct rpc_pipe_client *cli, + uint8_t op_num, + prs_struct *req_data) { - struct async_req *result, *subreq; + struct tevent_req *req, *subreq; struct rpc_api_pipe_req_state *state; NTSTATUS status; bool is_last_frag; - if (!async_req_setup(mem_ctx, &result, &state, - struct rpc_api_pipe_req_state)) { + req = tevent_req_create(mem_ctx, &state, + struct rpc_api_pipe_req_state); + if (req == NULL) { return NULL; } state->ev = ev; @@ -2081,8 +2070,7 @@ struct async_req *rpc_api_pipe_req_send(TALLOC_CTX *mem_ctx, if (!prs_init(&state->outgoing_frag, cli->max_xmit_frag, state, MARSHALL)) { - status = NT_STATUS_NO_MEMORY; - goto post_status; + goto fail; } talloc_set_destructor(state, rpc_api_pipe_req_state_destructor); @@ -2097,30 +2085,27 @@ struct async_req *rpc_api_pipe_req_send(TALLOC_CTX *mem_ctx, &state->outgoing_frag, RPC_RESPONSE); if (subreq == NULL) { - status = NT_STATUS_NO_MEMORY; - goto post_status; + goto fail; } - subreq->async.fn = rpc_api_pipe_req_done; - subreq->async.priv = result; + tevent_req_set_callback(subreq, rpc_api_pipe_req_done, req); } else { subreq = rpc_write_send( state, ev, cli->transport, (uint8_t *)prs_data_p(&state->outgoing_frag), prs_offset(&state->outgoing_frag)); if (subreq == NULL) { - status = NT_STATUS_NO_MEMORY; - goto post_status; + goto fail; } - subreq->async.fn = rpc_api_pipe_req_write_done; - subreq->async.priv = result; + tevent_req_set_callback(subreq, rpc_api_pipe_req_write_done, + req); } - return result; + return req; post_status: - if (async_post_ntstatus(result, ev, status)) { - return result; - } - TALLOC_FREE(result); + tevent_req_nterror(req, status); + return tevent_req_post(req, ev); + fail: + TALLOC_FREE(req); return NULL; } @@ -2209,25 +2194,25 @@ static NTSTATUS prepare_next_frag(struct rpc_api_pipe_req_state *state, return status; } -static void rpc_api_pipe_req_write_done(struct async_req *subreq) +static void rpc_api_pipe_req_write_done(struct tevent_req *subreq) { - struct async_req *req = talloc_get_type_abort( - subreq->async.priv, struct async_req); - struct rpc_api_pipe_req_state *state = talloc_get_type_abort( - req->private_data, struct rpc_api_pipe_req_state); + struct tevent_req *req = tevent_req_callback_data( + subreq, struct tevent_req); + struct rpc_api_pipe_req_state *state = tevent_req_data( + req, struct rpc_api_pipe_req_state); NTSTATUS status; bool is_last_frag; status = rpc_write_recv(subreq); TALLOC_FREE(subreq); if (!NT_STATUS_IS_OK(status)) { - async_req_nterror(req, status); + tevent_req_nterror(req, status); return; } status = prepare_next_frag(state, &is_last_frag); if (!NT_STATUS_IS_OK(status)) { - async_req_nterror(req, status); + tevent_req_nterror(req, status); return; } @@ -2235,50 +2220,49 @@ static void rpc_api_pipe_req_write_done(struct async_req *subreq) subreq = rpc_api_pipe_send(state, state->ev, state->cli, &state->outgoing_frag, RPC_RESPONSE); - if (async_req_nomem(subreq, req)) { + if (tevent_req_nomem(subreq, req)) { return; } - subreq->async.fn = rpc_api_pipe_req_done; - subreq->async.priv = req; + tevent_req_set_callback(subreq, rpc_api_pipe_req_done, req); } else { subreq = rpc_write_send( state, state->ev, state->cli->transport, (uint8_t *)prs_data_p(&state->outgoing_frag), prs_offset(&state->outgoing_frag)); - if (async_req_nomem(subreq, req)) { + if (tevent_req_nomem(subreq, req)) { return; } - subreq->async.fn = rpc_api_pipe_req_write_done; - subreq->async.priv = req; + tevent_req_set_callback(subreq, rpc_api_pipe_req_write_done, + req); } } -static void rpc_api_pipe_req_done(struct async_req *subreq) +static void rpc_api_pipe_req_done(struct tevent_req *subreq) { - struct async_req *req = talloc_get_type_abort( - subreq->async.priv, struct async_req); - struct rpc_api_pipe_req_state *state = talloc_get_type_abort( - req->private_data, struct rpc_api_pipe_req_state); + struct tevent_req *req = tevent_req_callback_data( + subreq, struct tevent_req); + struct rpc_api_pipe_req_state *state = tevent_req_data( + req, struct rpc_api_pipe_req_state); NTSTATUS status; status = rpc_api_pipe_recv(subreq, state, &state->reply_pdu); TALLOC_FREE(subreq); if (!NT_STATUS_IS_OK(status)) { - async_req_nterror(req, status); + tevent_req_nterror(req, status); return; } - async_req_done(req); + tevent_req_done(req); } -NTSTATUS rpc_api_pipe_req_recv(struct async_req *req, TALLOC_CTX *mem_ctx, +NTSTATUS rpc_api_pipe_req_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx, prs_struct *reply_pdu) { - struct rpc_api_pipe_req_state *state = talloc_get_type_abort( - req->private_data, struct rpc_api_pipe_req_state); + struct rpc_api_pipe_req_state *state = tevent_req_data( + req, struct rpc_api_pipe_req_state); NTSTATUS status; - if (async_req_is_nterror(req, &status)) { + if (tevent_req_is_nterror(req, &status)) { /* * We always have to initialize to reply pdu, even if there is * none. The rpccli_* caller routines expect this. @@ -2306,7 +2290,7 @@ NTSTATUS rpc_api_pipe_req(TALLOC_CTX *mem_ctx, struct rpc_pipe_client *cli, { TALLOC_CTX *frame = talloc_stackframe(); struct event_context *ev; - struct async_req *req; + struct tevent_req *req; NTSTATUS status = NT_STATUS_NO_MEMORY; ev = event_context_init(frame); @@ -2319,9 +2303,7 @@ NTSTATUS rpc_api_pipe_req(TALLOC_CTX *mem_ctx, struct rpc_pipe_client *cli, goto fail; } - while (req->state < ASYNC_REQ_DONE) { - event_loop_once(ev); - } + tevent_req_poll(req, ev); status = rpc_api_pipe_req_recv(req, mem_ctx, out_data); fail: @@ -2522,29 +2504,29 @@ static int rpc_pipe_bind_state_destructor(struct rpc_pipe_bind_state *state) return 0; } -static void rpc_pipe_bind_step_one_done(struct async_req *subreq); -static NTSTATUS rpc_finish_auth3_bind_send(struct async_req *req, +static void rpc_pipe_bind_step_one_done(struct tevent_req *subreq); +static NTSTATUS rpc_finish_auth3_bind_send(struct tevent_req *req, struct rpc_pipe_bind_state *state, struct rpc_hdr_info *phdr, prs_struct *reply_pdu); -static void rpc_bind_auth3_write_done(struct async_req *subreq); -static NTSTATUS rpc_finish_spnego_ntlmssp_bind_send(struct async_req *req, +static void rpc_bind_auth3_write_done(struct tevent_req *subreq); +static NTSTATUS rpc_finish_spnego_ntlmssp_bind_send(struct tevent_req *req, struct rpc_pipe_bind_state *state, struct rpc_hdr_info *phdr, prs_struct *reply_pdu); -static void rpc_bind_ntlmssp_api_done(struct async_req *subreq); +static void rpc_bind_ntlmssp_api_done(struct tevent_req *subreq); -struct async_req *rpc_pipe_bind_send(TALLOC_CTX *mem_ctx, - struct event_context *ev, - struct rpc_pipe_client *cli, - struct cli_pipe_auth_data *auth) +struct tevent_req *rpc_pipe_bind_send(TALLOC_CTX *mem_ctx, + struct event_context *ev, + struct rpc_pipe_client *cli, + struct cli_pipe_auth_data *auth) { - struct async_req *result, *subreq; + struct tevent_req *req, *subreq; struct rpc_pipe_bind_state *state; NTSTATUS status; - if (!async_req_setup(mem_ctx, &result, &state, - struct rpc_pipe_bind_state)) { + req = tevent_req_create(mem_ctx, &state, struct rpc_pipe_bind_state); + if (req == NULL) { return NULL; } @@ -2577,27 +2559,25 @@ struct async_req *rpc_pipe_bind_send(TALLOC_CTX *mem_ctx, subreq = rpc_api_pipe_send(state, ev, cli, &state->rpc_out, RPC_BINDACK); if (subreq == NULL) { - status = NT_STATUS_NO_MEMORY; - goto post_status; + goto fail; } - subreq->async.fn = rpc_pipe_bind_step_one_done; - subreq->async.priv = result; - return result; + tevent_req_set_callback(subreq, rpc_pipe_bind_step_one_done, req); + return req; post_status: - if (async_post_ntstatus(result, ev, status)) { - return result; - } - TALLOC_FREE(result); + tevent_req_nterror(req, status); + return tevent_req_post(req, ev); + fail: + TALLOC_FREE(req); return NULL; } -static void rpc_pipe_bind_step_one_done(struct async_req *subreq) +static void rpc_pipe_bind_step_one_done(struct tevent_req *subreq) { - struct async_req *req = talloc_get_type_abort( - subreq->async.priv, struct async_req); - struct rpc_pipe_bind_state *state = talloc_get_type_abort( - req->private_data, struct rpc_pipe_bind_state); + struct tevent_req *req = tevent_req_callback_data( + subreq, struct tevent_req); + struct rpc_pipe_bind_state *state = tevent_req_data( + req, struct rpc_pipe_bind_state); prs_struct reply_pdu; struct rpc_hdr_info hdr; struct rpc_hdr_ba_info hdr_ba; @@ -2609,7 +2589,7 @@ 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_nterror(req, status); + tevent_req_nterror(req, status); return; } @@ -2617,7 +2597,7 @@ static void rpc_pipe_bind_step_one_done(struct async_req *subreq) if (!smb_io_rpc_hdr("hdr", &hdr, &reply_pdu, 0)) { DEBUG(0, ("rpc_pipe_bind: failed to unmarshall RPC_HDR.\n")); prs_mem_free(&reply_pdu); - async_req_nterror(req, NT_STATUS_BUFFER_TOO_SMALL); + tevent_req_nterror(req, NT_STATUS_BUFFER_TOO_SMALL); return; } @@ -2625,14 +2605,14 @@ static void rpc_pipe_bind_step_one_done(struct async_req *subreq) DEBUG(0, ("rpc_pipe_bind: Failed to unmarshall " "RPC_HDR_BA.\n")); prs_mem_free(&reply_pdu); - async_req_nterror(req, NT_STATUS_BUFFER_TOO_SMALL); + tevent_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")); prs_mem_free(&reply_pdu); - async_req_nterror(req, NT_STATUS_BUFFER_TOO_SMALL); + tevent_req_nterror(req, NT_STATUS_BUFFER_TOO_SMALL); return; } @@ -2649,7 +2629,7 @@ static void rpc_pipe_bind_step_one_done(struct async_req *subreq) case PIPE_AUTH_TYPE_SCHANNEL: /* Bind complete. */ prs_mem_free(&reply_pdu); - async_req_done(req); + tevent_req_done(req); break; case PIPE_AUTH_TYPE_NTLMSSP: @@ -2658,7 +2638,7 @@ static void rpc_pipe_bind_step_one_done(struct async_req *subreq) &reply_pdu); prs_mem_free(&reply_pdu); if (!NT_STATUS_IS_OK(status)) { - async_req_nterror(req, status); + tevent_req_nterror(req, status); } break; @@ -2668,7 +2648,7 @@ static void rpc_pipe_bind_step_one_done(struct async_req *subreq) &reply_pdu); prs_mem_free(&reply_pdu); if (!NT_STATUS_IS_OK(status)) { - async_req_nterror(req, status); + tevent_req_nterror(req, status); } break; @@ -2679,11 +2659,11 @@ static void rpc_pipe_bind_step_one_done(struct async_req *subreq) DEBUG(0,("cli_finish_bind_auth: unknown auth type %u\n", (unsigned int)state->cli->auth->auth_type)); prs_mem_free(&reply_pdu); - async_req_nterror(req, NT_STATUS_INTERNAL_ERROR); + tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR); } } -static NTSTATUS rpc_finish_auth3_bind_send(struct async_req *req, +static NTSTATUS rpc_finish_auth3_bind_send(struct tevent_req *req, struct rpc_pipe_bind_state *state, struct rpc_hdr_info *phdr, prs_struct *reply_pdu) @@ -2691,7 +2671,7 @@ static NTSTATUS rpc_finish_auth3_bind_send(struct async_req *req, DATA_BLOB server_response = data_blob_null; DATA_BLOB client_reply = data_blob_null; struct rpc_hdr_auth_info hdr_auth; - struct async_req *subreq; + struct tevent_req *subreq; NTSTATUS status; if ((phdr->auth_len == 0) @@ -2742,27 +2722,26 @@ static NTSTATUS rpc_finish_auth3_bind_send(struct async_req *req, if (subreq == NULL) { return NT_STATUS_NO_MEMORY; } - subreq->async.fn = rpc_bind_auth3_write_done; - subreq->async.priv = req; + tevent_req_set_callback(subreq, rpc_bind_auth3_write_done, req); return NT_STATUS_OK; } -static void rpc_bind_auth3_write_done(struct async_req *subreq) +static void rpc_bind_auth3_write_done(struct tevent_req *subreq) { - struct async_req *req = talloc_get_type_abort( - subreq->async.priv, struct async_req); + struct tevent_req *req = tevent_req_callback_data( + subreq, struct tevent_req); NTSTATUS status; status = rpc_write_recv(subreq); TALLOC_FREE(subreq); if (!NT_STATUS_IS_OK(status)) { - async_req_nterror(req, status); + tevent_req_nterror(req, status); return; } - async_req_done(req); + tevent_req_done(req); } -static NTSTATUS rpc_finish_spnego_ntlmssp_bind_send(struct async_req *req, +static NTSTATUS rpc_finish_spnego_ntlmssp_bind_send(struct tevent_req *req, struct rpc_pipe_bind_state *state, struct rpc_hdr_info *phdr, prs_struct *reply_pdu) @@ -2772,7 +2751,7 @@ static NTSTATUS rpc_finish_spnego_ntlmssp_bind_send(struct async_req *req, DATA_BLOB client_reply = data_blob_null; DATA_BLOB tmp_blob = data_blob_null; RPC_HDR_AUTH hdr_auth; - struct async_req *subreq; + struct tevent_req *subreq; NTSTATUS status; if ((phdr->auth_len == 0) @@ -2850,17 +2829,16 @@ static NTSTATUS rpc_finish_spnego_ntlmssp_bind_send(struct async_req *req, if (subreq == NULL) { return NT_STATUS_NO_MEMORY; } - subreq->async.fn = rpc_bind_ntlmssp_api_done; - subreq->async.priv = req; + tevent_req_set_callback(subreq, rpc_bind_ntlmssp_api_done, req); return NT_STATUS_OK; } -static void rpc_bind_ntlmssp_api_done(struct async_req *subreq) +static void rpc_bind_ntlmssp_api_done(struct tevent_req *subreq) { - struct async_req *req = talloc_get_type_abort( - subreq->async.priv, struct async_req); - struct rpc_pipe_bind_state *state = talloc_get_type_abort( - req->private_data, struct rpc_pipe_bind_state); + struct tevent_req *req = tevent_req_callback_data( + subreq, struct tevent_req); + struct rpc_pipe_bind_state *state = tevent_req_data( + req, struct rpc_pipe_bind_state); DATA_BLOB server_spnego_response = data_blob_null; DATA_BLOB tmp_blob = data_blob_null; prs_struct reply_pdu; @@ -2871,7 +2849,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_nterror(req, status); + tevent_req_nterror(req, status); return; } @@ -2879,19 +2857,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_nterror(req, NT_STATUS_BUFFER_TOO_SMALL); + tevent_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_nterror(req, NT_STATUS_INVALID_PARAMETER); + tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER); return; } if (!smb_io_rpc_hdr_auth("hdr_auth", &hdr_auth, &reply_pdu, 0)) { - async_req_nterror(req, NT_STATUS_INVALID_PARAMETER); + tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER); return; } @@ -2904,7 +2882,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_nterror(req, NT_STATUS_INVALID_PARAMETER); + tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER); return; } @@ -2913,12 +2891,12 @@ static void rpc_bind_ntlmssp_api_done(struct async_req *subreq) DEBUG(5,("rpc_finish_spnego_ntlmssp_bind: alter context request to " "%s.\n", rpccli_pipe_txt(debug_ctx(), state->cli))); - async_req_done(req); + tevent_req_done(req); } -NTSTATUS rpc_pipe_bind_recv(struct async_req *req) +NTSTATUS rpc_pipe_bind_recv(struct tevent_req *req) { - return async_req_simple_recv_ntstatus(req); + return tevent_req_simple_recv_ntstatus(req); } NTSTATUS rpc_pipe_bind(struct rpc_pipe_client *cli, @@ -2926,7 +2904,7 @@ NTSTATUS rpc_pipe_bind(struct rpc_pipe_client *cli, { TALLOC_CTX *frame = talloc_stackframe(); struct event_context *ev; - struct async_req *req; + struct tevent_req *req; NTSTATUS status = NT_STATUS_NO_MEMORY; ev = event_context_init(frame); @@ -2939,9 +2917,7 @@ NTSTATUS rpc_pipe_bind(struct rpc_pipe_client *cli, goto fail; } - while (req->state < ASYNC_REQ_DONE) { - event_loop_once(ev); - } + tevent_req_poll(req, ev); status = rpc_pipe_bind_recv(req); fail: diff --git a/source3/rpc_client/rpc_transport_np.c b/source3/rpc_client/rpc_transport_np.c index 80ff384046..8b45cb4e9c 100644 --- a/source3/rpc_client/rpc_transport_np.c +++ b/source3/rpc_client/rpc_transport_np.c @@ -51,18 +51,19 @@ struct rpc_np_write_state { static void rpc_np_write_done(struct async_req *subreq); -static struct async_req *rpc_np_write_send(TALLOC_CTX *mem_ctx, - struct event_context *ev, - const uint8_t *data, size_t size, - void *priv) +static struct tevent_req *rpc_np_write_send(TALLOC_CTX *mem_ctx, + struct event_context *ev, + const uint8_t *data, size_t size, + void *priv) { struct rpc_transport_np_state *np_transport = talloc_get_type_abort( priv, struct rpc_transport_np_state); - struct async_req *result, *subreq; + struct tevent_req *req; + struct async_req *subreq; struct rpc_np_write_state *state; - if (!async_req_setup(mem_ctx, &result, &state, - struct rpc_np_write_state)) { + req = tevent_req_create(mem_ctx, &state, struct rpc_np_write_state); + if (req == NULL) { return NULL; } state->size = size; @@ -75,37 +76,37 @@ static struct async_req *rpc_np_write_send(TALLOC_CTX *mem_ctx, goto fail; } subreq->async.fn = rpc_np_write_done; - subreq->async.priv = result; - return result; + subreq->async.priv = req; + return req; fail: - TALLOC_FREE(result); + TALLOC_FREE(req); return NULL; } static void rpc_np_write_done(struct async_req *subreq) { - struct async_req *req = talloc_get_type_abort( - subreq->async.priv, struct async_req); - struct rpc_np_write_state *state = talloc_get_type_abort( - req->private_data, struct rpc_np_write_state); + struct tevent_req *req = talloc_get_type_abort( + subreq->async.priv, struct tevent_req); + struct rpc_np_write_state *state = tevent_req_data( + req, struct rpc_np_write_state); NTSTATUS status; status = cli_write_andx_recv(subreq, &state->written); TALLOC_FREE(subreq); if (!NT_STATUS_IS_OK(status)) { - async_req_nterror(req, status); + tevent_req_nterror(req, status); return; } - async_req_done(req); + tevent_req_done(req); } -static NTSTATUS rpc_np_write_recv(struct async_req *req, ssize_t *pwritten) +static NTSTATUS rpc_np_write_recv(struct tevent_req *req, ssize_t *pwritten) { - struct rpc_np_write_state *state = talloc_get_type_abort( - req->private_data, struct rpc_np_write_state); + struct rpc_np_write_state *state = tevent_req_data( + req, struct rpc_np_write_state); NTSTATUS status; - if (async_req_is_nterror(req, &status)) { + if (tevent_req_is_nterror(req, &status)) { return status; } *pwritten = state->written; @@ -120,18 +121,19 @@ struct rpc_np_read_state { static void rpc_np_read_done(struct async_req *subreq); -static struct async_req *rpc_np_read_send(TALLOC_CTX *mem_ctx, - struct event_context *ev, - uint8_t *data, size_t size, - void *priv) +static struct tevent_req *rpc_np_read_send(TALLOC_CTX *mem_ctx, + struct event_context *ev, + uint8_t *data, size_t size, + void *priv) { struct rpc_transport_np_state *np_transport = talloc_get_type_abort( priv, struct rpc_transport_np_state); - struct async_req *result, *subreq; + struct tevent_req *req; + struct async_req *subreq; struct rpc_np_read_state *state; - if (!async_req_setup(mem_ctx, &result, &state, - struct rpc_np_read_state)) { + req = tevent_req_create(mem_ctx, &state, struct rpc_np_read_state); + if (req == NULL) { return NULL; } state->data = data; @@ -143,19 +145,19 @@ static struct async_req *rpc_np_read_send(TALLOC_CTX *mem_ctx, goto fail; } subreq->async.fn = rpc_np_read_done; - subreq->async.priv = result; - return result; + subreq->async.priv = req; + return req; fail: - TALLOC_FREE(result); + TALLOC_FREE(req); return NULL; } static void rpc_np_read_done(struct async_req *subreq) { - struct async_req *req = talloc_get_type_abort( - subreq->async.priv, struct async_req); - struct rpc_np_read_state *state = talloc_get_type_abort( - req->private_data, struct rpc_np_read_state); + struct tevent_req *req = talloc_get_type_abort( + subreq->async.priv, struct tevent_req); + struct rpc_np_read_state *state = tevent_req_data( + req, struct rpc_np_read_state); NTSTATUS status; uint8_t *rcvbuf; @@ -169,27 +171,27 @@ static void rpc_np_read_done(struct async_req *subreq) } if (!NT_STATUS_IS_OK(status)) { TALLOC_FREE(subreq); - async_req_nterror(req, status); + tevent_req_nterror(req, status); return; } if (state->received > state->size) { TALLOC_FREE(subreq); - async_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE); + tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE); return; } memcpy(state->data, rcvbuf, state->received); - async_req_done(req); + tevent_req_done(req); } -static NTSTATUS rpc_np_read_recv(struct async_req *req, ssize_t *preceived) +static NTSTATUS rpc_np_read_recv(struct tevent_req *req, ssize_t *preceived) { - struct rpc_np_read_state *state = talloc_get_type_abort( - req->private_data, struct rpc_np_read_state); + struct rpc_np_read_state *state = tevent_req_data( + req, struct rpc_np_read_state); NTSTATUS status; - if (async_req_is_nterror(req, &status)) { + if (tevent_req_is_nterror(req, &status)) { return status; } *preceived = state->received; @@ -204,19 +206,20 @@ struct rpc_np_trans_state { static void rpc_np_trans_done(struct async_req *subreq); -static struct async_req *rpc_np_trans_send(TALLOC_CTX *mem_ctx, - struct event_context *ev, - uint8_t *data, size_t data_len, - uint32_t max_rdata_len, - void *priv) +static struct tevent_req *rpc_np_trans_send(TALLOC_CTX *mem_ctx, + struct event_context *ev, + uint8_t *data, size_t data_len, + uint32_t max_rdata_len, + void *priv) { struct rpc_transport_np_state *np_transport = talloc_get_type_abort( priv, struct rpc_transport_np_state); - struct async_req *result, *subreq; + struct tevent_req *req; + struct async_req *subreq; struct rpc_np_trans_state *state; - if (!async_req_setup(mem_ctx, &result, &state, - struct rpc_np_trans_state)) { + req = tevent_req_create(mem_ctx, &state, struct rpc_np_trans_state); + if (req == NULL) { return NULL; } @@ -231,40 +234,40 @@ static struct async_req *rpc_np_trans_send(TALLOC_CTX *mem_ctx, goto fail; } subreq->async.fn = rpc_np_trans_done; - subreq->async.priv = result; - return result; + subreq->async.priv = req; + return req; fail: - TALLOC_FREE(result); + TALLOC_FREE(req); return NULL; } static void rpc_np_trans_done(struct async_req *subreq) { - struct async_req *req = talloc_get_type_abort( - subreq->async.priv, struct async_req); - struct rpc_np_trans_state *state = talloc_get_type_abort( - req->private_data, struct rpc_np_trans_state); + struct tevent_req *req = talloc_get_type_abort( + subreq->async.priv, struct tevent_req); + struct rpc_np_trans_state *state = tevent_req_data( + req, struct rpc_np_trans_state); NTSTATUS status; status = cli_trans_recv(subreq, state, NULL, NULL, NULL, NULL, &state->rdata, &state->rdata_len); TALLOC_FREE(subreq); if (!NT_STATUS_IS_OK(status)) { - async_req_nterror(req, status); + tevent_req_nterror(req, status); return; } - async_req_done(req); + tevent_req_done(req); } -static NTSTATUS rpc_np_trans_recv(struct async_req *req, TALLOC_CTX *mem_ctx, +static NTSTATUS rpc_np_trans_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx, uint8_t **prdata, uint32_t *prdata_len) { - struct rpc_np_trans_state *state = talloc_get_type_abort( - req->private_data, struct rpc_np_trans_state); + struct rpc_np_trans_state *state = tevent_req_data( + req, struct rpc_np_trans_state); NTSTATUS status; - if (async_req_is_nterror(req, &status)) { + if (tevent_req_is_nterror(req, &status)) { return status; } *prdata = talloc_move(mem_ctx, &state->rdata); diff --git a/source3/rpc_client/rpc_transport_smbd.c b/source3/rpc_client/rpc_transport_smbd.c index bf4aa65dae..bde8d04208 100644 --- a/source3/rpc_client/rpc_transport_smbd.c +++ b/source3/rpc_client/rpc_transport_smbd.c @@ -432,20 +432,20 @@ struct rpc_smbd_write_state { ssize_t written; }; -static void rpc_smbd_write_done(struct async_req *subreq); +static void rpc_smbd_write_done(struct tevent_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) +static struct tevent_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 tevent_req *req, *subreq; struct rpc_smbd_write_state *state; - if (!async_req_setup(mem_ctx, &result, &state, - struct rpc_smbd_write_state)) { + req = tevent_req_create(mem_ctx, &state, struct rpc_smbd_write_state); + if (req == NULL) { return NULL; } state->sub_transp = transp->sub_transp; @@ -460,40 +460,38 @@ static struct async_req *rpc_smbd_write_send(TALLOC_CTX *mem_ctx, rpc_cli_smbd_stdout_reader, transp->conn) == NULL) { goto fail; } - - subreq->async.fn = rpc_smbd_write_done; - subreq->async.priv = result; - return result; + tevent_req_set_callback(subreq, rpc_smbd_write_done, req); + return req; fail: - TALLOC_FREE(result); + TALLOC_FREE(req); return NULL; } -static void rpc_smbd_write_done(struct async_req *subreq) +static void rpc_smbd_write_done(struct tevent_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); + struct tevent_req *req = tevent_req_callback_data( + subreq, struct tevent_req); + struct rpc_smbd_write_state *state = tevent_req_data( + req, 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); + tevent_req_nterror(req, status); return; } - async_req_done(req); + tevent_req_done(req); } -static NTSTATUS rpc_smbd_write_recv(struct async_req *req, ssize_t *pwritten) +static NTSTATUS rpc_smbd_write_recv(struct tevent_req *req, ssize_t *pwritten) { - struct rpc_smbd_write_state *state = talloc_get_type_abort( - req->private_data, struct rpc_smbd_write_state); + struct rpc_smbd_write_state *state = tevent_req_data( + req, struct rpc_smbd_write_state); NTSTATUS status; - if (async_req_is_nterror(req, &status)) { + if (tevent_req_is_nterror(req, &status)) { return status; } *pwritten = state->written; @@ -505,20 +503,20 @@ struct rpc_smbd_read_state { ssize_t received; }; -static void rpc_smbd_read_done(struct async_req *subreq); +static void rpc_smbd_read_done(struct tevent_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) +static struct tevent_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 tevent_req *req, *subreq; struct rpc_smbd_read_state *state; - if (!async_req_setup(mem_ctx, &result, &state, - struct rpc_smbd_read_state)) { + req = tevent_req_create(mem_ctx, &state, struct rpc_smbd_read_state); + if (req == NULL) { return NULL; } state->sub_transp = transp->sub_transp; @@ -533,40 +531,37 @@ static struct async_req *rpc_smbd_read_send(TALLOC_CTX *mem_ctx, rpc_cli_smbd_stdout_reader, transp->conn) == NULL) { goto fail; } - - subreq->async.fn = rpc_smbd_read_done; - subreq->async.priv = result; - return result; - + tevent_req_set_callback(subreq, rpc_smbd_read_done, req); + return req; fail: - TALLOC_FREE(result); + TALLOC_FREE(req); return NULL; } -static void rpc_smbd_read_done(struct async_req *subreq) +static void rpc_smbd_read_done(struct tevent_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); + struct tevent_req *req = tevent_req_callback_data( + subreq, struct tevent_req); + struct rpc_smbd_read_state *state = tevent_req_data( + req, 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); + tevent_req_nterror(req, status); return; } - async_req_done(req); + tevent_req_done(req); } -static NTSTATUS rpc_smbd_read_recv(struct async_req *req, ssize_t *preceived) +static NTSTATUS rpc_smbd_read_recv(struct tevent_req *req, ssize_t *preceived) { - struct rpc_smbd_read_state *state = talloc_get_type_abort( - req->private_data, struct rpc_smbd_read_state); + struct rpc_smbd_read_state *state = tevent_req_data( + req, struct rpc_smbd_read_state); NTSTATUS status; - if (async_req_is_nterror(req, &status)) { + if (tevent_req_is_nterror(req, &status)) { return status; } *preceived = state->received; diff --git a/source3/rpc_client/rpc_transport_sock.c b/source3/rpc_client/rpc_transport_sock.c index b1d9d8fbe1..570d792c9c 100644 --- a/source3/rpc_client/rpc_transport_sock.c +++ b/source3/rpc_client/rpc_transport_sock.c @@ -41,19 +41,18 @@ struct rpc_sock_read_state { static void rpc_sock_read_done(struct tevent_req *subreq); -static struct async_req *rpc_sock_read_send(TALLOC_CTX *mem_ctx, - struct event_context *ev, - uint8_t *data, size_t size, - void *priv) +static struct tevent_req *rpc_sock_read_send(TALLOC_CTX *mem_ctx, + struct event_context *ev, + uint8_t *data, size_t size, + void *priv) { struct rpc_transport_sock_state *sock_transp = talloc_get_type_abort( priv, struct rpc_transport_sock_state); - struct async_req *result; - struct tevent_req *subreq; + struct tevent_req *req, *subreq; struct rpc_sock_read_state *state; - if (!async_req_setup(mem_ctx, &result, &state, - struct rpc_sock_read_state)) { + req = tevent_req_create(mem_ctx, &state, struct rpc_sock_read_state); + if (req == NULL) { return NULL; } @@ -61,36 +60,36 @@ static struct async_req *rpc_sock_read_send(TALLOC_CTX *mem_ctx, if (subreq == NULL) { goto fail; } - tevent_req_set_callback(subreq, rpc_sock_read_done, result); - return result; + tevent_req_set_callback(subreq, rpc_sock_read_done, req); + return req; fail: - TALLOC_FREE(result); + TALLOC_FREE(req); return NULL; } static void rpc_sock_read_done(struct tevent_req *subreq) { - struct async_req *req = - tevent_req_callback_data(subreq, struct async_req); - struct rpc_sock_read_state *state = talloc_get_type_abort( - req->private_data, struct rpc_sock_read_state); + struct tevent_req *req = tevent_req_callback_data( + subreq, struct tevent_req); + struct rpc_sock_read_state *state = tevent_req_data( + req, struct rpc_sock_read_state); int err; state->received = async_recv_recv(subreq, &err); if (state->received == -1) { - async_req_nterror(req, map_nt_error_from_unix(err)); + tevent_req_nterror(req, map_nt_error_from_unix(err)); return; } - async_req_done(req); + tevent_req_done(req); } -static NTSTATUS rpc_sock_read_recv(struct async_req *req, ssize_t *preceived) +static NTSTATUS rpc_sock_read_recv(struct tevent_req *req, ssize_t *preceived) { - struct rpc_sock_read_state *state = talloc_get_type_abort( - req->private_data, struct rpc_sock_read_state); + struct rpc_sock_read_state *state = tevent_req_data( + req, struct rpc_sock_read_state); NTSTATUS status; - if (async_req_is_nterror(req, &status)) { + if (tevent_req_is_nterror(req, &status)) { return status; } *preceived = state->received; @@ -103,55 +102,54 @@ struct rpc_sock_write_state { static void rpc_sock_write_done(struct tevent_req *subreq); -static struct async_req *rpc_sock_write_send(TALLOC_CTX *mem_ctx, - struct event_context *ev, - const uint8_t *data, size_t size, - void *priv) +static struct tevent_req *rpc_sock_write_send(TALLOC_CTX *mem_ctx, + struct event_context *ev, + const uint8_t *data, size_t size, + void *priv) { struct rpc_transport_sock_state *sock_transp = talloc_get_type_abort( priv, struct rpc_transport_sock_state); - struct async_req *result; - struct tevent_req *subreq; + struct tevent_req *req, *subreq; struct rpc_sock_write_state *state; - if (!async_req_setup(mem_ctx, &result, &state, - struct rpc_sock_write_state)) { + req = tevent_req_create(mem_ctx, &state, struct rpc_sock_write_state); + if (req == NULL) { return NULL; } subreq = async_send_send(state, ev, sock_transp->fd, data, size, 0); if (subreq == NULL) { goto fail; } - tevent_req_set_callback(subreq, rpc_sock_write_done, result); - return result; + tevent_req_set_callback(subreq, rpc_sock_write_done, req); + return req; fail: - TALLOC_FREE(result); + TALLOC_FREE(req); return NULL; } static void rpc_sock_write_done(struct tevent_req *subreq) { - struct async_req *req = - tevent_req_callback_data(subreq, struct async_req); - struct rpc_sock_write_state *state = talloc_get_type_abort( - req->private_data, struct rpc_sock_write_state); + struct tevent_req *req = tevent_req_callback_data( + subreq, struct tevent_req); + struct rpc_sock_write_state *state = tevent_req_data( + req, struct rpc_sock_write_state); int err; state->sent = async_send_recv(subreq, &err); if (state->sent == -1) { - async_req_nterror(req, map_nt_error_from_unix(err)); + tevent_req_nterror(req, map_nt_error_from_unix(err)); return; } - async_req_done(req); + tevent_req_done(req); } -static NTSTATUS rpc_sock_write_recv(struct async_req *req, ssize_t *psent) +static NTSTATUS rpc_sock_write_recv(struct tevent_req *req, ssize_t *psent) { - struct rpc_sock_write_state *state = talloc_get_type_abort( - req->private_data, struct rpc_sock_write_state); + struct rpc_sock_write_state *state = tevent_req_data( + req, struct rpc_sock_write_state); NTSTATUS status; - if (async_req_is_nterror(req, &status)) { + if (tevent_req_is_nterror(req, &status)) { return status; } *psent = state->sent; diff --git a/source3/rpc_parse/parse_misc.c b/source3/rpc_parse/parse_misc.c index 8b4135a1e8..1ea4ecf46f 100644 --- a/source3/rpc_parse/parse_misc.c +++ b/source3/rpc_parse/parse_misc.c @@ -101,44 +101,6 @@ bool make_systemtime(SYSTEMTIME *systime, struct tm *unixtime) } /******************************************************************* - Reads or writes a DOM_SID structure. -********************************************************************/ - -bool smb_io_dom_sid(const char *desc, DOM_SID *sid, prs_struct *ps, int depth) -{ - int i; - - if (sid == NULL) - return False; - - prs_debug(ps, depth, desc, "smb_io_dom_sid"); - depth++; - - if(!prs_uint8 ("sid_rev_num", ps, depth, &sid->sid_rev_num)) - return False; - - if(!prs_uint8 ("num_auths ", ps, depth, (uint8 *)&sid->num_auths)) - return False; - - for (i = 0; i < 6; i++) - { - fstring tmp; - slprintf(tmp, sizeof(tmp) - 1, "id_auth[%d] ", i); - if(!prs_uint8 (tmp, ps, depth, &sid->id_auth[i])) - return False; - } - - /* oops! XXXX should really issue a warning here... */ - if (sid->num_auths > MAXSUBAUTHS) - sid->num_auths = MAXSUBAUTHS; - - if(!prs_uint32s(False, "sub_auths ", ps, depth, sid->sub_auths, sid->num_auths)) - return False; - - return True; -} - -/******************************************************************* Reads or writes a struct GUID ********************************************************************/ @@ -167,25 +129,6 @@ bool smb_io_uuid(const char *desc, struct GUID *uuid, } /******************************************************************* - Inits a UNISTR structure. -********************************************************************/ - -void init_unistr(UNISTR *str, const char *buf) -{ - size_t len; - - if (buf == NULL) { - str->buffer = NULL; - return; - } - - len = rpcstr_push_talloc(talloc_tos(), &str->buffer, buf); - if (len == (size_t)-1) { - str->buffer = NULL; - } -} - -/******************************************************************* Inits a UNISTR2 structure. ********************************************************************/ diff --git a/source3/rpc_parse/parse_sec.c b/source3/rpc_parse/parse_sec.c deleted file mode 100644 index 91d8591a05..0000000000 --- a/source3/rpc_parse/parse_sec.c +++ /dev/null @@ -1,436 +0,0 @@ -/* - * Unix SMB/Netbios implementation. - * Version 1.9. - * RPC Pipe client / server routines - * Copyright (C) Andrew Tridgell 1992-1998, - * Copyright (C) Jeremy R. Allison 1995-2005. - * Copyright (C) Luke Kenneth Casson Leighton 1996-1998, - * Copyright (C) Paul Ashton 1997-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/>. - */ - -#include "includes.h" - -#undef DBGC_CLASS -#define DBGC_CLASS DBGC_RPC_PARSE - -/******************************************************************* - Reads or writes a SEC_ACE structure. -********************************************************************/ - -static bool sec_io_ace(const char *desc, SEC_ACE *psa, prs_struct *ps, - int depth) -{ - uint32 old_offset; - uint32 offset_ace_size; - uint8 type; - - if (psa == NULL) - return False; - - prs_debug(ps, depth, desc, "sec_io_ace"); - depth++; - - old_offset = prs_offset(ps); - - if (MARSHALLING(ps)) { - type = (uint8)psa->type; - } - - if(!prs_uint8("type ", ps, depth, &type)) - return False; - - if (UNMARSHALLING(ps)) { - psa->type = (enum security_ace_type)type; - } - - if(!prs_uint8("flags", ps, depth, &psa->flags)) - return False; - - if(!prs_uint16_pre("size ", ps, depth, &psa->size, &offset_ace_size)) - return False; - - if(!prs_uint32("access_mask", ps, depth, &psa->access_mask)) - return False; - - /* check whether object access is present */ - if (!sec_ace_object(psa->type)) { - if (!smb_io_dom_sid("trustee ", &psa->trustee , ps, depth)) - return False; - } else { - if (!prs_uint32("obj_flags", ps, depth, &psa->object.object.flags)) - return False; - - if (psa->object.object.flags & SEC_ACE_OBJECT_TYPE_PRESENT) - if (!smb_io_uuid("obj_guid", &psa->object.object.type.type, ps,depth)) - return False; - - if (psa->object.object.flags & SEC_ACE_INHERITED_OBJECT_TYPE_PRESENT) - if (!smb_io_uuid("inh_guid", &psa->object.object.inherited_type.inherited_type, ps,depth)) - return False; - - if(!smb_io_dom_sid("trustee ", &psa->trustee , ps, depth)) - return False; - } - - /* Theorectically an ACE can have a size greater than the - sum of its components. When marshalling, pad with extra null bytes up to the - correct size. */ - - if (MARSHALLING(ps) && (psa->size > prs_offset(ps) - old_offset)) { - uint32 extra_len = psa->size - (prs_offset(ps) - old_offset); - uint32 i; - uint8 c = 0; - - for (i = 0; i < extra_len; i++) { - if (!prs_uint8("ace extra space", ps, depth, &c)) - return False; - } - } - - if(!prs_uint16_post("size ", ps, depth, &psa->size, offset_ace_size, old_offset)) - return False; - - return True; -} - -/******************************************************************* - Reads or writes a SEC_ACL structure. - - First of the xx_io_xx functions that allocates its data structures - for you as it reads them. -********************************************************************/ - -static bool sec_io_acl(const char *desc, SEC_ACL **ppsa, prs_struct *ps, - int depth) -{ - unsigned int i; - uint32 old_offset; - uint32 offset_acl_size; - SEC_ACL *psa; - uint16 revision; - - /* - * Note that the size is always a multiple of 4 bytes due to the - * nature of the data structure. Therefore the prs_align() calls - * have been removed as they through us off when doing two-layer - * marshalling such as in the printing code (RPC_BUFFER). --jerry - */ - - if (ppsa == NULL) - return False; - - psa = *ppsa; - - if(UNMARSHALLING(ps) && psa == NULL) { - /* - * This is a read and we must allocate the stuct to read into. - */ - if((psa = PRS_ALLOC_MEM(ps, SEC_ACL, 1)) == NULL) - return False; - *ppsa = psa; - } - - prs_debug(ps, depth, desc, "sec_io_acl"); - depth++; - - old_offset = prs_offset(ps); - - if (MARSHALLING(ps)) { - revision = (uint16)psa->revision; - } - - if(!prs_uint16("revision", ps, depth, &revision)) - return False; - - if (UNMARSHALLING(ps)) { - psa->revision = (enum security_acl_revision)revision; - } - - if(!prs_uint16_pre("size ", ps, depth, &psa->size, &offset_acl_size)) - return False; - - if(!prs_uint32("num_aces ", ps, depth, &psa->num_aces)) - return False; - - if (UNMARSHALLING(ps)) { - if (psa->num_aces) { - if((psa->aces = PRS_ALLOC_MEM(ps, SEC_ACE, psa->num_aces)) == NULL) - return False; - } else { - psa->aces = NULL; - } - } - - for (i = 0; i < psa->num_aces; i++) { - fstring tmp; - slprintf(tmp, sizeof(tmp)-1, "ace_list[%02d]: ", i); - if(!sec_io_ace(tmp, &psa->aces[i], ps, depth)) - return False; - } - - /* Theorectically an ACL can have a size greater than the - sum of its components. When marshalling, pad with extra null bytes up to the - correct size. */ - - if (MARSHALLING(ps) && (psa->size > prs_offset(ps) - old_offset)) { - uint32 extra_len = psa->size - (prs_offset(ps) - old_offset); - uint8 c = 0; - - for (i = 0; i < extra_len; i++) { - if (!prs_uint8("acl extra space", ps, depth, &c)) - return False; - } - } - - if(!prs_uint16_post("size ", ps, depth, &psa->size, offset_acl_size, old_offset)) - return False; - - return True; -} - -/******************************************************************* - Reads or writes a SEC_DESC structure. - If reading and the *ppsd = NULL, allocates the structure. -********************************************************************/ - -bool sec_io_desc(const char *desc, SEC_DESC **ppsd, prs_struct *ps, int depth) -{ - uint32 old_offset; - uint32 max_offset = 0; /* after we're done, move offset to end */ - uint32 tmp_offset = 0; - uint32 off_sacl, off_dacl, off_owner_sid, off_grp_sid; - uint16 revision; - - SEC_DESC *psd; - - if (ppsd == NULL) - return False; - - psd = *ppsd; - - if (psd == NULL) { - if(UNMARSHALLING(ps)) { - if((psd = PRS_ALLOC_MEM(ps,SEC_DESC,1)) == NULL) - return False; - *ppsd = psd; - } else { - /* Marshalling - just ignore. */ - return True; - } - } - - prs_debug(ps, depth, desc, "sec_io_desc"); - depth++; - - /* start of security descriptor stored for back-calc offset purposes */ - old_offset = prs_offset(ps); - - if (MARSHALLING(ps)) { - revision = (uint16)psd->revision; - } - - if(!prs_uint16("revision", ps, depth, &revision)) - return False; - - if (UNMARSHALLING(ps)) { - psd->revision = (enum security_descriptor_revision)revision; - } - - if(!prs_uint16("type ", ps, depth, &psd->type)) - return False; - - if (MARSHALLING(ps)) { - uint32 offset = SEC_DESC_HEADER_SIZE; - - /* - * Work out the offsets here, as we write it out. - */ - - if (psd->sacl != NULL) { - off_sacl = offset; - offset += psd->sacl->size; - } else { - off_sacl = 0; - } - - if (psd->dacl != NULL) { - off_dacl = offset; - offset += psd->dacl->size; - } else { - off_dacl = 0; - } - - if (psd->owner_sid != NULL) { - off_owner_sid = offset; - offset += ndr_size_dom_sid(psd->owner_sid, NULL, 0); - } else { - off_owner_sid = 0; - } - - if (psd->group_sid != NULL) { - off_grp_sid = offset; - offset += ndr_size_dom_sid(psd->group_sid, NULL, 0); - } else { - off_grp_sid = 0; - } - } - - if(!prs_uint32("off_owner_sid", ps, depth, &off_owner_sid)) - return False; - - if(!prs_uint32("off_grp_sid ", ps, depth, &off_grp_sid)) - return False; - - if(!prs_uint32("off_sacl ", ps, depth, &off_sacl)) - return False; - - if(!prs_uint32("off_dacl ", ps, depth, &off_dacl)) - return False; - - max_offset = MAX(max_offset, prs_offset(ps)); - - if (off_owner_sid != 0) { - - tmp_offset = prs_offset(ps); - if(!prs_set_offset(ps, old_offset + off_owner_sid)) - return False; - - if (UNMARSHALLING(ps)) { - /* reading */ - if((psd->owner_sid = PRS_ALLOC_MEM(ps,DOM_SID,1)) == NULL) - return False; - } - - if(!smb_io_dom_sid("owner_sid ", psd->owner_sid , ps, depth)) - return False; - - max_offset = MAX(max_offset, prs_offset(ps)); - - if (!prs_set_offset(ps,tmp_offset)) - return False; - } - - if (psd->group_sid != 0) { - - tmp_offset = prs_offset(ps); - if(!prs_set_offset(ps, old_offset + off_grp_sid)) - return False; - - if (UNMARSHALLING(ps)) { - /* reading */ - if((psd->group_sid = PRS_ALLOC_MEM(ps,DOM_SID,1)) == NULL) - return False; - } - - if(!smb_io_dom_sid("grp_sid", psd->group_sid, ps, depth)) - return False; - - max_offset = MAX(max_offset, prs_offset(ps)); - - if (!prs_set_offset(ps,tmp_offset)) - return False; - } - - if ((psd->type & SEC_DESC_SACL_PRESENT) && off_sacl) { - tmp_offset = prs_offset(ps); - if(!prs_set_offset(ps, old_offset + off_sacl)) - return False; - if(!sec_io_acl("sacl", &psd->sacl, ps, depth)) - return False; - max_offset = MAX(max_offset, prs_offset(ps)); - if (!prs_set_offset(ps,tmp_offset)) - return False; - } - - if ((psd->type & SEC_DESC_DACL_PRESENT) && off_dacl != 0) { - tmp_offset = prs_offset(ps); - if(!prs_set_offset(ps, old_offset + off_dacl)) - return False; - if(!sec_io_acl("dacl", &psd->dacl, ps, depth)) - return False; - max_offset = MAX(max_offset, prs_offset(ps)); - if (!prs_set_offset(ps,tmp_offset)) - return False; - } - - if(!prs_set_offset(ps, max_offset)) - return False; - - return True; -} - -/******************************************************************* - Reads or writes a SEC_DESC_BUF structure. -********************************************************************/ - -bool sec_io_desc_buf(const char *desc, SEC_DESC_BUF **ppsdb, prs_struct *ps, int depth) -{ - uint32 off_len; - uint32 off_max_len; - uint32 old_offset; - uint32 size; - uint32 len; - SEC_DESC_BUF *psdb; - uint32 ptr; - - if (ppsdb == NULL) - return False; - - psdb = *ppsdb; - - if (UNMARSHALLING(ps) && psdb == NULL) { - if((psdb = PRS_ALLOC_MEM(ps,SEC_DESC_BUF,1)) == NULL) - return False; - *ppsdb = psdb; - } - - prs_debug(ps, depth, desc, "sec_io_desc_buf"); - depth++; - - if(!prs_align(ps)) - return False; - - if(!prs_uint32_pre("max_len", ps, depth, &psdb->sd_size, &off_max_len)) - return False; - - ptr = 1; - if(!prs_uint32 ("ptr ", ps, depth, &ptr)) - return False; - - len = ndr_size_security_descriptor(psdb->sd, NULL, 0); - if(!prs_uint32_pre("len ", ps, depth, &len, &off_len)) - return False; - - old_offset = prs_offset(ps); - - /* reading, length is non-zero; writing, descriptor is non-NULL */ - if ((UNMARSHALLING(ps) && psdb->sd_size != 0) || (MARSHALLING(ps) && psdb->sd != NULL)) { - if(!sec_io_desc("sec ", &psdb->sd, ps, depth)) - return False; - } - - if(!prs_align(ps)) - return False; - - size = prs_offset(ps) - old_offset; - if(!prs_uint32_post("max_len", ps, depth, &psdb->sd_size, off_max_len, size == 0 ? psdb->sd_size : size)) - return False; - - if(!prs_uint32_post("len ", ps, depth, &len, off_len, size)) - return False; - - return True; -} diff --git a/source3/rpc_server/srv_lsa_nt.c b/source3/rpc_server/srv_lsa_nt.c index ed54c3a86e..5fdcaf2d4a 100644 --- a/source3/rpc_server/srv_lsa_nt.c +++ b/source3/rpc_server/srv_lsa_nt.c @@ -827,6 +827,10 @@ NTSTATUS _lsa_LookupSids(pipes_struct *p, &names, &mapped_count); + if (NT_STATUS_IS_ERR(status)) { + return status; + } + /* Convert from lsa_TranslatedName2 to lsa_TranslatedName */ names_out = TALLOC_ARRAY(p->mem_ctx, struct lsa_TranslatedName, num_sids); diff --git a/source3/rpc_server/srv_spoolss_nt.c b/source3/rpc_server/srv_spoolss_nt.c index b66f48aa29..15c137a88c 100644 --- a/source3/rpc_server/srv_spoolss_nt.c +++ b/source3/rpc_server/srv_spoolss_nt.c @@ -393,7 +393,7 @@ static bool get_printer_snum(pipes_struct *p, struct policy_handle *hnd, Check if it's \\server or \\server\printer ****************************************************************************/ -static bool set_printer_hnd_printertype(Printer_entry *Printer, char *handlename) +static bool set_printer_hnd_printertype(Printer_entry *Printer, const char *handlename) { DEBUG(3,("Setting printer type=%s\n", handlename)); @@ -423,7 +423,7 @@ static bool set_printer_hnd_printertype(Printer_entry *Printer, char *handlename XcvDataPort() interface. ****************************************************************************/ -static bool set_printer_hnd_name(Printer_entry *Printer, char *handlename) +static bool set_printer_hnd_name(Printer_entry *Printer, const char *handlename) { int snum; int n_services=lp_numservices(); @@ -434,9 +434,10 @@ static bool set_printer_hnd_name(Printer_entry *Printer, char *handlename) NT_PRINTER_INFO_LEVEL *printer = NULL; WERROR result; - DEBUG(4,("Setting printer name=%s (len=%lu)\n", handlename, (unsigned long)strlen(handlename))); + DEBUG(4,("Setting printer name=%s (len=%lu)\n", handlename, + (unsigned long)strlen(handlename))); - aprinter = handlename; + aprinter = CONST_DISCARD(char *, handlename); if ( *handlename == '\\' ) { servername = canon_servername(handlename); if ( (aprinter = strchr_m( servername, '\\' )) != NULL ) { @@ -556,7 +557,7 @@ static bool set_printer_hnd_name(Printer_entry *Printer, char *handlename) ****************************************************************************/ static bool open_printer_hnd(pipes_struct *p, struct policy_handle *hnd, - char *name, uint32_t access_granted) + const char *name, uint32_t access_granted) { Printer_entry *new_printer; @@ -1247,7 +1248,7 @@ static void receive_notify2_message_list(struct messaging_context *msg, driver ********************************************************************/ -static bool srv_spoolss_drv_upgrade_printer(char* drivername) +static bool srv_spoolss_drv_upgrade_printer(const char *drivername) { int len = strlen(drivername); @@ -1545,20 +1546,19 @@ bool convert_devicemode(const char *printername, WERROR _spoolss_OpenPrinterEx(pipes_struct *p, struct spoolss_OpenPrinterEx *r) { - char *name = CONST_DISCARD(char *, r->in.printername); int snum; Printer_entry *Printer=NULL; - if (!name) { + if (!r->in.printername) { return WERR_INVALID_PARAM; } /* some sanity check because you can open a printer or a print server */ /* aka: \\server\printer or \\server */ - DEBUGADD(3,("checking name: %s\n",name)); + DEBUGADD(3,("checking name: %s\n", r->in.printername)); - if (!open_printer_hnd(p, r->out.handle, name, 0)) { + if (!open_printer_hnd(p, r->out.handle, r->in.printername, 0)) { ZERO_STRUCTP(r->out.handle); return WERR_INVALID_PARAM; } @@ -1566,7 +1566,7 @@ WERROR _spoolss_OpenPrinterEx(pipes_struct *p, Printer = find_printer_index_by_hnd(p, r->out.handle); if ( !Printer ) { DEBUG(0,("_spoolss_OpenPrinterEx: logic error. Can't find printer " - "handle we created for printer %s\n", name )); + "handle we created for printer %s\n", r->in.printername)); close_printer_handle(p, r->out.handle); ZERO_STRUCTP(r->out.handle); return WERR_INVALID_PARAM; @@ -2075,7 +2075,7 @@ WERROR _spoolss_DeletePrinter(pipes_struct *p, * long architecture string ******************************************************************/ -static int get_version_id (char * arch) +static int get_version_id(const char *arch) { int i; struct table_node archi_table[]= { @@ -2106,8 +2106,6 @@ static int get_version_id (char * arch) WERROR _spoolss_DeletePrinterDriver(pipes_struct *p, struct spoolss_DeletePrinterDriver *r) { - char *driver; - char *arch; NT_PRINTER_DRIVER_INFO_LEVEL info; NT_PRINTER_DRIVER_INFO_LEVEL info_win2k; int version; @@ -2128,24 +2126,26 @@ WERROR _spoolss_DeletePrinterDriver(pipes_struct *p, return WERR_ACCESS_DENIED; } - driver = CONST_DISCARD(char *, r->in.driver); - arch = CONST_DISCARD(char *, r->in.architecture); - /* check that we have a valid driver name first */ - if ((version=get_version_id(arch)) == -1) + if ((version = get_version_id(r->in.architecture)) == -1) return WERR_INVALID_ENVIRONMENT; ZERO_STRUCT(info); ZERO_STRUCT(info_win2k); - if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version))) + if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, r->in.driver, + r->in.architecture, + version))) { /* try for Win2k driver if "Windows NT x86" */ if ( version == 2 ) { version = 3; - if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version))) { + if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, + r->in.driver, + r->in.architecture, + version))) { status = WERR_UNKNOWN_PRINTER_DRIVER; goto done; } @@ -2165,7 +2165,9 @@ WERROR _spoolss_DeletePrinterDriver(pipes_struct *p, if ( version == 2 ) { - if (W_ERROR_IS_OK(get_a_printer_driver(&info_win2k, 3, driver, arch, 3))) + if (W_ERROR_IS_OK(get_a_printer_driver(&info_win2k, 3, + r->in.driver, + r->in.architecture, 3))) { /* if we get to here, we now have 2 driver info structures to remove */ /* remove the Win2k driver first*/ @@ -2203,8 +2205,6 @@ done: WERROR _spoolss_DeletePrinterDriverEx(pipes_struct *p, struct spoolss_DeletePrinterDriverEx *r) { - char *driver; - char *arch; NT_PRINTER_DRIVER_INFO_LEVEL info; NT_PRINTER_DRIVER_INFO_LEVEL info_win2k; int version; @@ -2225,11 +2225,8 @@ WERROR _spoolss_DeletePrinterDriverEx(pipes_struct *p, return WERR_ACCESS_DENIED; } - driver = CONST_DISCARD(char *, r->in.driver); - arch = CONST_DISCARD(char *, r->in.architecture); - /* check that we have a valid driver name first */ - if ((version=get_version_id(arch)) == -1) { + if ((version = get_version_id(r->in.architecture)) == -1) { /* this is what NT returns */ return WERR_INVALID_ENVIRONMENT; } @@ -2240,7 +2237,8 @@ WERROR _spoolss_DeletePrinterDriverEx(pipes_struct *p, ZERO_STRUCT(info); ZERO_STRUCT(info_win2k); - status = get_a_printer_driver(&info, 3, driver, arch, version); + status = get_a_printer_driver(&info, 3, r->in.driver, + r->in.architecture, version); if ( !W_ERROR_IS_OK(status) ) { @@ -2256,7 +2254,9 @@ WERROR _spoolss_DeletePrinterDriverEx(pipes_struct *p, /* try for Win2k driver if "Windows NT x86" */ version = 3; - if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version))) { + if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, r->in.driver, + r->in.architecture, + version))) { status = WERR_UNKNOWN_PRINTER_DRIVER; goto done; } @@ -2293,7 +2293,9 @@ WERROR _spoolss_DeletePrinterDriverEx(pipes_struct *p, /* also check for W32X86/3 if necessary; maybe we already have? */ if ( (version == 2) && ((r->in.delete_flags & DPD_DELETE_SPECIFIC_VERSION) != DPD_DELETE_SPECIFIC_VERSION) ) { - if (W_ERROR_IS_OK(get_a_printer_driver(&info_win2k, 3, driver, arch, 3))) + if (W_ERROR_IS_OK(get_a_printer_driver(&info_win2k, 3, + r->in.driver, + r->in.architecture, 3))) { if ( delete_files && printer_driver_files_in_use(info_win2k.info_3) & (r->in.delete_flags & DPD_DELETE_ALL_FILES) ) { @@ -4202,61 +4204,88 @@ static bool snum_is_shared_printer(int snum) Spoolss_enumprinters. ********************************************************************/ -static WERROR enum_all_printers_info_1(TALLOC_CTX *mem_ctx, - uint32_t flags, - union spoolss_PrinterInfo **info_p, - uint32_t *count) +static WERROR enum_all_printers_info_level(TALLOC_CTX *mem_ctx, + uint32_t level, + uint32_t flags, + union spoolss_PrinterInfo **info_p, + uint32_t *count_p) { int snum; int n_services = lp_numservices(); union spoolss_PrinterInfo *info = NULL; + uint32_t count = 0; WERROR result = WERR_OK; - DEBUG(4,("enum_all_printers_info_1\n")); - - *count = 0; + *count_p = 0; + *info_p = NULL; - for (snum=0; snum<n_services; snum++) { + for (snum = 0; snum < n_services; snum++) { NT_PRINTER_INFO_LEVEL *ntprinter = NULL; - struct spoolss_PrinterInfo1 info1; if (!snum_is_shared_printer(snum)) { continue; } - DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum)); + DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", + lp_servicename(snum), snum)); - result = get_a_printer(NULL, &ntprinter, 2, lp_const_servicename(snum)); - if (!W_ERROR_IS_OK(result)) { - continue; + info = TALLOC_REALLOC_ARRAY(mem_ctx, info, + union spoolss_PrinterInfo, + count + 1); + if (!info) { + result = WERR_NOMEM; + goto out; } - result = construct_printer_info1(info, ntprinter, flags, &info1, snum); - free_a_printer(&ntprinter,2); + result = get_a_printer(NULL, &ntprinter, 2, + lp_const_servicename(snum)); if (!W_ERROR_IS_OK(result)) { - continue; + goto out; } - info = TALLOC_REALLOC_ARRAY(mem_ctx, info, - union spoolss_PrinterInfo, - *count + 1); - if (!info) { - DEBUG(2,("enum_all_printers_info_1: failed to enlarge printers buffer!\n")); - result = WERR_NOMEM; + switch (level) { + case 0: + result = construct_printer_info0(info, ntprinter, + &info[count].info0, snum); + break; + case 1: + result = construct_printer_info1(info, ntprinter, flags, + &info[count].info1, snum); + break; + case 2: + result = construct_printer_info2(info, ntprinter, + &info[count].info2, snum); + break; + case 4: + result = construct_printer_info4(info, ntprinter, + &info[count].info4, snum); + break; + case 5: + result = construct_printer_info5(info, ntprinter, + &info[count].info5, snum); + break; + + default: + result = WERR_UNKNOWN_LEVEL; + free_a_printer(&ntprinter, 2); goto out; } - DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_1\n", *count)); + free_a_printer(&ntprinter, 2); + if (!W_ERROR_IS_OK(result)) { + goto out; + } - info[*count].info1 = info1; - (*count)++; + count++; } + *count_p = count; + *info_p = info; + out: if (!W_ERROR_IS_OK(result)) { TALLOC_FREE(info); - *count = 0; return result; } @@ -4266,6 +4295,35 @@ static WERROR enum_all_printers_info_1(TALLOC_CTX *mem_ctx, } /******************************************************************** + * handle enumeration of printers at level 0 + ********************************************************************/ + +static WERROR enumprinters_level0(TALLOC_CTX *mem_ctx, + uint32_t flags, + const char *servername, + union spoolss_PrinterInfo **info, + uint32_t *count) +{ + DEBUG(4,("enum_all_printers_info_0\n")); + + return enum_all_printers_info_level(mem_ctx, 0, flags, info, count); +} + + +/******************************************************************** +********************************************************************/ + +static WERROR enum_all_printers_info_1(TALLOC_CTX *mem_ctx, + uint32_t flags, + union spoolss_PrinterInfo **info, + uint32_t *count) +{ + DEBUG(4,("enum_all_printers_info_1\n")); + + return enum_all_printers_info_level(mem_ctx, 1, flags, info, count); +} + +/******************************************************************** enum_all_printers_info_1_local. *********************************************************************/ @@ -4341,64 +4399,12 @@ static WERROR enum_all_printers_info_1_network(TALLOC_CTX *mem_ctx, ********************************************************************/ static WERROR enum_all_printers_info_2(TALLOC_CTX *mem_ctx, - union spoolss_PrinterInfo **info_p, + union spoolss_PrinterInfo **info, uint32_t *count) { - int snum; - int n_services = lp_numservices(); - union spoolss_PrinterInfo *info = NULL; - WERROR result = WERR_OK; + DEBUG(4,("enum_all_printers_info_2\n")); - *count = 0; - - for (snum=0; snum<n_services; snum++) { - - struct spoolss_PrinterInfo2 info2; - NT_PRINTER_INFO_LEVEL *ntprinter = NULL; - - if (!snum_is_shared_printer(snum)) { - continue; - } - - DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum)); - - result = get_a_printer(NULL, &ntprinter, 2, lp_const_servicename(snum)); - if (!W_ERROR_IS_OK(result)) { - continue; - } - - result = construct_printer_info2(info, ntprinter, &info2, snum); - free_a_printer(&ntprinter, 2); - if (!W_ERROR_IS_OK(result)) { - continue; - } - - info = TALLOC_REALLOC_ARRAY(mem_ctx, info, - union spoolss_PrinterInfo, - *count + 1); - if (!info) { - DEBUG(2,("enum_all_printers_info_2: failed to enlarge printers buffer!\n")); - result = WERR_NOMEM; - goto out; - } - - DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_2\n", *count + 1)); - - info[*count].info2 = info2; - - (*count)++; - } - - out: - if (!W_ERROR_IS_OK(result)) { - TALLOC_FREE(info); - *count = 0; - return result; - } - - *info_p = info; - - return WERR_OK; + return enum_all_printers_info_level(mem_ctx, 2, 0, info, count); } /******************************************************************** @@ -4458,6 +4464,22 @@ static WERROR enumprinters_level2(TALLOC_CTX *mem_ctx, } /******************************************************************** + * handle enumeration of printers at level 4 + ********************************************************************/ + +static WERROR enumprinters_level4(TALLOC_CTX *mem_ctx, + uint32_t flags, + const char *servername, + union spoolss_PrinterInfo **info, + uint32_t *count) +{ + DEBUG(4,("enum_all_printers_info_4\n")); + + return enum_all_printers_info_level(mem_ctx, 4, flags, info, count); +} + + +/******************************************************************** * handle enumeration of printers at level 5 ********************************************************************/ @@ -4467,8 +4489,9 @@ static WERROR enumprinters_level5(TALLOC_CTX *mem_ctx, union spoolss_PrinterInfo **info, uint32_t *count) { -/* return enum_all_printers_info_5(mem_ctx, info, offered, needed, count);*/ - return WERR_OK; + DEBUG(4,("enum_all_printers_info_5\n")); + + return enum_all_printers_info_level(mem_ctx, 5, flags, info, count); } /**************************************************************** @@ -4510,6 +4533,10 @@ WERROR _spoolss_EnumPrinters(pipes_struct *p, W_ERROR_HAVE_NO_MEMORY(name); switch (r->in.level) { + case 0: + result = enumprinters_level0(p->mem_ctx, r->in.flags, name, + r->out.info, r->out.count); + break; case 1: result = enumprinters_level1(p->mem_ctx, r->in.flags, name, r->out.info, r->out.count); @@ -4518,14 +4545,14 @@ WERROR _spoolss_EnumPrinters(pipes_struct *p, result = enumprinters_level2(p->mem_ctx, r->in.flags, name, r->out.info, r->out.count); break; + case 4: + result = enumprinters_level4(p->mem_ctx, r->in.flags, name, + r->out.info, r->out.count); + break; case 5: result = enumprinters_level5(p->mem_ctx, r->in.flags, name, r->out.info, r->out.count); break; - case 3: - case 4: - result = WERR_OK; /* ??? */ - break; default: return WERR_UNKNOWN_LEVEL; } @@ -7247,7 +7274,7 @@ WERROR _spoolss_AddPrinterDriver(pipes_struct *p, struct spoolss_AddDriverInfoCtr *info = r->in.info_ctr; WERROR err = WERR_OK; NT_PRINTER_DRIVER_INFO_LEVEL driver; - fstring driver_name; + const char *driver_name = NULL; uint32_t version; const char *fn; @@ -7297,12 +7324,10 @@ WERROR _spoolss_AddPrinterDriver(pipes_struct *p, switch(level) { case 3: - fstrcpy(driver_name, - driver.info_3->name ? driver.info_3->name : ""); + driver_name = driver.info_3->name ? driver.info_3->name : ""; break; case 6: - fstrcpy(driver_name, - driver.info_6->name ? driver.info_6->name : ""); + driver_name = driver.info_6->name ? driver.info_6->name : ""; break; } diff --git a/source3/rpcclient/cmd_spoolss.c b/source3/rpcclient/cmd_spoolss.c index 18c0790569..c9c457b364 100644 --- a/source3/rpcclient/cmd_spoolss.c +++ b/source3/rpcclient/cmd_spoolss.c @@ -257,9 +257,10 @@ static WERROR cmd_spoolss_enum_printers(struct rpc_pipe_client *cli, union spoolss_PrinterInfo *info; uint32_t i, count; const char *name; + uint32_t flags = PRINTER_ENUM_LOCAL; - if (argc > 3) { - printf("Usage: %s [level] [name]\n", argv[0]); + if (argc > 4) { + printf("Usage: %s [level] [name] [flags]\n", argv[0]); return WERR_OK; } @@ -267,14 +268,18 @@ static WERROR cmd_spoolss_enum_printers(struct rpc_pipe_client *cli, level = atoi(argv[1]); } - if (argc == 3) { + if (argc >= 3) { name = argv[2]; } else { name = cli->srv_name_slash; } + if (argc == 4) { + flags = atoi(argv[3]); + } + result = rpccli_spoolss_enumprinters(cli, mem_ctx, - PRINTER_ENUM_LOCAL, + flags, name, level, 0, diff --git a/source3/samba4.mk b/source3/samba4.mk index 7e7690aadf..3f661bdd14 100644 --- a/source3/samba4.mk +++ b/source3/samba4.mk @@ -225,32 +225,32 @@ test4-%:: valgrindtest4:: valgrindtest-all valgrindtest4-quick:: all - SMBD_VALGRIND="xterm -n server -e $(selftestdir)/valgrind_run $(LD_LIBPATH_OVERRIDE)" \ + SAMBA_VALGRIND="xterm -n server -e $(selftestdir)/valgrind_run $(LD_LIBPATH_OVERRIDE)" \ VALGRIND="valgrind -q --num-callers=30 --log-file=${selftest_prefix}/valgrind.log" \ $(SELFTEST4) $(SELFTEST4_QUICK_OPTS) --immediate --socket-wrapper $(TESTS) valgrindtest4-all:: everything - SMBD_VALGRIND="xterm -n server -e $(selftestdir)/valgrind_run $(LD_LIBPATH_OVERRIDE)" \ + SAMBA_VALGRIND="xterm -n server -e $(selftestdir)/valgrind_run $(LD_LIBPATH_OVERRIDE)" \ VALGRIND="valgrind -q --num-callers=30 --log-file=${selftest_prefix}/valgrind.log" \ $(SELFTEST4) $(SELFTEST4_NOSLOW_OPTS) --immediate --socket-wrapper $(TESTS) valgrindtest4-env:: everything - SMBD_VALGRIND="xterm -n server -e $(selftestdir)/valgrind_run $(LD_LIBPATH_OVERRIDE)" \ + SAMBA_VALGRIND="xterm -n server -e $(selftestdir)/valgrind_run $(LD_LIBPATH_OVERRIDE)" \ VALGRIND="valgrind -q --num-callers=30 --log-file=${selftest_prefix}/valgrind.log" \ $(SELFTEST4) $(SELFTEST4_NOSLOW_OPTS) --socket-wrapper --testenv gdbtest4:: gdbtest4-all gdbtest4-quick:: all - SMBD_VALGRIND="xterm -n server -e $(selftestdir)/gdb_run $(LD_LIBPATH_OVERRIDE)" \ + SAMBA_VALGRIND="xterm -n server -e $(selftestdir)/gdb_run $(LD_LIBPATH_OVERRIDE)" \ $(SELFTEST4) $(SELFTEST4_QUICK_OPTS) --immediate --socket-wrapper $(TESTS) gdbtest4-all:: everything - SMBD_VALGRIND="xterm -n server -e $(selftestdir)/gdb_run $(LD_LIBPATH_OVERRIDE)" \ + SAMBA_VALGRIND="xterm -n server -e $(selftestdir)/gdb_run $(LD_LIBPATH_OVERRIDE)" \ $(SELFTEST4) $(SELFTEST4_NOSLOW_OPTS) --immediate --socket-wrapper $(TESTS) gdbtest4-env:: everything - SMBD_VALGRIND="xterm -n server -e $(selftestdir)/gdb_run $(LD_LIBPATH_OVERRIDE)" \ + SAMBA_VALGRIND="xterm -n server -e $(selftestdir)/gdb_run $(LD_LIBPATH_OVERRIDE)" \ $(SELFTEST4) $(SELFTEST4_NOSLOW_OPTS) --socket-wrapper --testenv plugins: $(PLUGINS) diff --git a/source3/selftest/tests.sh b/source3/selftest/tests.sh index f88dab0337..ea59f0ee8e 100755 --- a/source3/selftest/tests.sh +++ b/source3/selftest/tests.sh @@ -120,6 +120,10 @@ plantest "blackbox.smbclient_s3.plain" dc BINDIR="$BINDIR" script/tests/test_smb 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 +# sign, only the member server allows signing +plantest "blackbox.smbclient_s3.sign member creds" member BINDIR="$BINDIR" script/tests/test_smbclient_s3.sh \$SERVER \$SERVER_IP \$SERVER\\\\\$USERNAME \$PASSWORD "--signing=required" +plantest "blackbox.smbclient_s3.sign domain creds" member BINDIR="$BINDIR" script/tests/test_smbclient_s3.sh \$SERVER \$SERVER_IP \$DOMAIN\\\\\$DC_USERNAME \$DC_PASSWORD "--signing=required" + # encrypted plantest "blackbox.smbclient_s3.crypt" dc BINDIR="$BINDIR" script/tests/test_smbclient_s3.sh \$SERVER \$SERVER_IP \$USERNAME \$PASSWORD "-e" diff --git a/source3/smbd/aio.c b/source3/smbd/aio.c index cfa4b430eb..77616be48c 100644 --- a/source3/smbd/aio.c +++ b/source3/smbd/aio.c @@ -197,7 +197,6 @@ bool schedule_aio_read_and_X(connection_struct *conn, fsp->fsp_name, (double)startpos, (unsigned int)smb_maxcnt, (unsigned int)aio_ex->req->mid )); - srv_defer_sign_response(aio_ex->req->mid); outstanding_aio_calls++; return True; } @@ -303,6 +302,7 @@ bool schedule_aio_write_and_X(connection_struct *conn, SSVAL(aio_ex->outbuf,smb_vwv4,(numtowrite>>16)&1); show_msg(aio_ex->outbuf); if (!srv_send_smb(smbd_server_fd(),aio_ex->outbuf, + true, aio_ex->req->seqnum+1, IS_CONN_ENCRYPTED(fsp->conn), &req->pcd)) { exit_server_cleanly("handle_aio_write: srv_send_smb " @@ -310,8 +310,6 @@ bool schedule_aio_write_and_X(connection_struct *conn, } DEBUG(10,("schedule_aio_write_and_X: scheduled aio_write " "behind for file %s\n", fsp->fsp_name )); - } else { - srv_defer_sign_response(aio_ex->req->mid); } outstanding_aio_calls++; @@ -347,7 +345,6 @@ static int handle_aio_read_complete(struct aio_extra *aio_ex) /* If errno is ECANCELED then don't return anything to the * client. */ if (errno == ECANCELED) { - srv_cancel_sign_response(aio_ex->req->mid, false); return 0; } @@ -378,6 +375,7 @@ static int handle_aio_read_complete(struct aio_extra *aio_ex) smb_setlen(outbuf,outsize - 4); show_msg(outbuf); if (!srv_send_smb(smbd_server_fd(),outbuf, + true, aio_ex->req->seqnum+1, IS_CONN_ENCRYPTED(aio_ex->fsp->conn), NULL)) { exit_server_cleanly("handle_aio_read_complete: srv_send_smb " "failed."); @@ -441,7 +439,6 @@ static int handle_aio_write_complete(struct aio_extra *aio_ex) /* If errno is ECANCELED then don't return anything to the * client. */ if (errno == ECANCELED) { - srv_cancel_sign_response(aio_ex->req->mid, false); return 0; } @@ -475,7 +472,9 @@ static int handle_aio_write_complete(struct aio_extra *aio_ex) } show_msg(outbuf); - if (!srv_send_smb(smbd_server_fd(),outbuf,IS_CONN_ENCRYPTED(fsp->conn), + if (!srv_send_smb(smbd_server_fd(),outbuf, + true, aio_ex->req->seqnum+1, + IS_CONN_ENCRYPTED(fsp->conn), NULL)) { exit_server_cleanly("handle_aio_write: srv_send_smb failed."); } @@ -534,7 +533,6 @@ void smbd_aio_complete_mid(unsigned int mid) if (!aio_ex) { DEBUG(3,("smbd_aio_complete_mid: Can't find record to " "match mid %u.\n", mid)); - srv_cancel_sign_response(mid, false); return; } @@ -544,7 +542,6 @@ void smbd_aio_complete_mid(unsigned int mid) * ignore. */ DEBUG( 3,( "smbd_aio_complete_mid: file closed whilst " "aio outstanding (mid[%u]).\n", mid)); - srv_cancel_sign_response(mid, false); return; } diff --git a/source3/smbd/avahi_register.c b/source3/smbd/avahi_register.c new file mode 100644 index 0000000000..1903b0ef96 --- /dev/null +++ b/source3/smbd/avahi_register.c @@ -0,0 +1,170 @@ +/* + * Unix SMB/CIFS implementation. + * Register _smb._tcp with avahi + * + * 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" + +#include <avahi-client/client.h> +#include <avahi-client/publish.h> +#include <avahi-common/error.h> + +struct avahi_state_struct { + struct AvahiPoll *poll; + AvahiClient *client; + AvahiEntryGroup *entry_group; + uint16_t port; +}; + +static void avahi_entry_group_callback(AvahiEntryGroup *g, + AvahiEntryGroupState status, + void *userdata) +{ + struct avahi_state_struct *state = talloc_get_type_abort( + userdata, struct avahi_state_struct); + int error; + + switch (status) { + case AVAHI_ENTRY_GROUP_ESTABLISHED: + DEBUG(10, ("avahi_entry_group_callback: " + "AVAHI_ENTRY_GROUP_ESTABLISHED\n")); + break; + case AVAHI_ENTRY_GROUP_FAILURE: + error = avahi_client_errno(state->client); + + DEBUG(10, ("avahi_entry_group_callback: " + "AVAHI_ENTRY_GROUP_FAILURE: %s\n", + avahi_strerror(error))); + break; + case AVAHI_ENTRY_GROUP_COLLISION: + DEBUG(10, ("avahi_entry_group_callback: " + "AVAHI_ENTRY_GROUP_COLLISION\n")); + break; + case AVAHI_ENTRY_GROUP_UNCOMMITED: + DEBUG(10, ("avahi_entry_group_callback: " + "AVAHI_ENTRY_GROUP_UNCOMMITED\n")); + break; + case AVAHI_ENTRY_GROUP_REGISTERING: + DEBUG(10, ("avahi_entry_group_callback: " + "AVAHI_ENTRY_GROUP_REGISTERING\n")); + break; + } +} + +static void avahi_client_callback(AvahiClient *c, AvahiClientState status, + void *userdata) +{ + struct avahi_state_struct *state = talloc_get_type_abort( + userdata, struct avahi_state_struct); + int error; + + switch (status) { + case AVAHI_CLIENT_S_RUNNING: + DEBUG(10, ("avahi_client_callback: AVAHI_CLIENT_S_RUNNING\n")); + + state->entry_group = avahi_entry_group_new( + c, avahi_entry_group_callback, state); + if (state->entry_group == NULL) { + error = avahi_client_errno(c); + DEBUG(10, ("avahi_entry_group_new failed: %s\n", + avahi_strerror(error))); + break; + } + if (avahi_entry_group_add_service( + state->entry_group, AVAHI_IF_UNSPEC, + AVAHI_PROTO_UNSPEC, 0, global_myname(), + "_smb._tcp", NULL, NULL, state->port, NULL) < 0) { + error = avahi_client_errno(c); + DEBUG(10, ("avahi_entry_group_add_service failed: " + "%s\n", avahi_strerror(error))); + avahi_entry_group_free(state->entry_group); + state->entry_group = NULL; + break; + } + if (avahi_entry_group_commit(state->entry_group) < 0) { + error = avahi_client_errno(c); + DEBUG(10, ("avahi_entry_group_commit failed: " + "%s\n", avahi_strerror(error))); + avahi_entry_group_free(state->entry_group); + state->entry_group = NULL; + break; + } + break; + case AVAHI_CLIENT_FAILURE: + error = avahi_client_errno(c); + + DEBUG(10, ("avahi_client_callback: AVAHI_CLIENT_FAILURE: %s\n", + avahi_strerror(error))); + + if (error != AVAHI_ERR_DISCONNECTED) { + break; + } + avahi_client_free(c); + state->client = avahi_client_new(state->poll, AVAHI_CLIENT_NO_FAIL, + avahi_client_callback, state, + &error); + if (state->client == NULL) { + DEBUG(10, ("avahi_client_new failed: %s\n", + avahi_strerror(error))); + break; + } + break; + case AVAHI_CLIENT_S_COLLISION: + DEBUG(10, ("avahi_client_callback: " + "AVAHI_CLIENT_S_COLLISION\n")); + break; + case AVAHI_CLIENT_S_REGISTERING: + DEBUG(10, ("avahi_client_callback: " + "AVAHI_CLIENT_S_REGISTERING\n")); + break; + case AVAHI_CLIENT_CONNECTING: + DEBUG(10, ("avahi_client_callback: " + "AVAHI_CLIENT_CONNECTING\n")); + break; + } +} + +void *avahi_start_register(TALLOC_CTX *mem_ctx, struct tevent_context *ev, + uint16_t port) +{ + struct avahi_state_struct *state; + int error; + + state = talloc(mem_ctx, struct avahi_state_struct); + if (state == NULL) { + return state; + } + state->port = port; + state->poll = tevent_avahi_poll(state, ev); + if (state->poll == NULL) { + goto fail; + } + state->client = avahi_client_new(state->poll, AVAHI_CLIENT_NO_FAIL, + avahi_client_callback, state, + &error); + if (state->client == NULL) { + DEBUG(10, ("avahi_client_new failed: %s\n", + avahi_strerror(error))); + goto fail; + } + return state; + + fail: + TALLOC_FREE(state); + return NULL; +} diff --git a/source3/smbd/blocking.c b/source3/smbd/blocking.c index 42849931f3..4c61428692 100644 --- a/source3/smbd/blocking.c +++ b/source3/smbd/blocking.c @@ -204,9 +204,6 @@ bool push_blocking_lock_request( struct byte_range_lock *br_lck, (unsigned int)blr->expire_time.tv_usec, lock_timeout, blr->fsp->fnum, blr->fsp->fsp_name )); - /* Push the MID of this packet on the signing queue. */ - srv_defer_sign_response(blr->req->mid); - return True; } @@ -260,6 +257,7 @@ static void generic_blocking_lock_error(struct blocking_lock_record *blr, NTSTAT reply_nterror(blr->req, status); if (!srv_send_smb(smbd_server_fd(), (char *)blr->req->outbuf, + true, blr->req->seqnum+1, blr->req->encrypted, NULL)) { exit_server_cleanly("generic_blocking_lock_error: srv_send_smb failed."); } @@ -343,6 +341,7 @@ static void blocking_lock_reply_error(struct blocking_lock_record *blr, NTSTATUS if (!srv_send_smb(smbd_server_fd(), (char *)blr->req->outbuf, + true, blr->req->seqnum+1, IS_CONN_ENCRYPTED(blr->fsp->conn), NULL)) { exit_server_cleanly("blocking_lock_reply_error: " diff --git a/source3/smbd/globals.h b/source3/smbd/globals.h index 6ac92ed3dd..b646bc30fd 100644 --- a/source3/smbd/globals.h +++ b/source3/smbd/globals.h @@ -202,6 +202,7 @@ extern int num_children; struct smbd_server_connection { struct fd_event *fde; uint64_t num_requests; + struct smb_signing_state *signing_state; }; extern struct smbd_server_connection *smbd_server_conn; diff --git a/source3/smbd/ipc.c b/source3/smbd/ipc.c index f20c851297..d39aab4f47 100644 --- a/source3/smbd/ipc.c +++ b/source3/smbd/ipc.c @@ -134,6 +134,7 @@ void send_trans_reply(connection_struct *conn, show_msg((char *)req->outbuf); if (!srv_send_smb(smbd_server_fd(), (char *)req->outbuf, + true, req->seqnum+1, IS_CONN_ENCRYPTED(conn), &req->pcd)) { exit_server_cleanly("send_trans_reply: srv_send_smb failed."); } @@ -190,6 +191,7 @@ void send_trans_reply(connection_struct *conn, show_msg((char *)req->outbuf); if (!srv_send_smb(smbd_server_fd(), (char *)req->outbuf, + true, req->seqnum+1, IS_CONN_ENCRYPTED(conn), &req->pcd)) exit_server_cleanly("send_trans_reply: srv_send_smb " "failed."); @@ -296,6 +298,7 @@ static void api_dcerpc_cmd_write_done(struct tevent_req *subreq) send: if (!srv_send_smb( smbd_server_fd(), (char *)req->outbuf, + true, req->seqnum+1, IS_CONN_ENCRYPTED(req->conn) || req->encrypted, &req->pcd)) { exit_server_cleanly("construct_reply: srv_send_smb failed."); @@ -322,6 +325,7 @@ static void api_dcerpc_cmd_read_done(struct tevent_req *subreq) reply_nterror(req, status); if (!srv_send_smb(smbd_server_fd(), (char *)req->outbuf, + true, req->seqnum+1, IS_CONN_ENCRYPTED(req->conn) ||req->encrypted, &req->pcd)) { exit_server_cleanly("construct_reply: srv_send_smb " diff --git a/source3/smbd/negprot.c b/source3/smbd/negprot.c index a921954c49..e548c587c1 100644 --- a/source3/smbd/negprot.c +++ b/source3/smbd/negprot.c @@ -316,7 +316,7 @@ static void reply_nt1(struct smb_request *req, uint16 choice) capabilities &= ~CAP_RAW_MODE; if (lp_server_signing() == Required) secword |=NEGOTIATE_SECURITY_SIGNATURES_REQUIRED; - srv_set_signing_negotiated(); + srv_set_signing_negotiated(smbd_server_conn); } else { DEBUG(0,("reply_nt1: smb signing is incompatible with share level security !\n")); if (lp_server_signing() == Required) { diff --git a/source3/smbd/notify.c b/source3/smbd/notify.c index 8ceeaf5f55..fdab2ca848 100644 --- a/source3/smbd/notify.c +++ b/source3/smbd/notify.c @@ -143,7 +143,9 @@ static void change_notify_reply_packet(connection_struct *conn, } show_msg((char *)req->outbuf); - if (!srv_send_smb(smbd_server_fd(), (char *)req->outbuf, + if (!srv_send_smb(smbd_server_fd(), + (char *)req->outbuf, + true, req->seqnum+1, req->encrypted, &req->pcd)) { exit_server_cleanly("change_notify_reply_packet: srv_send_smb " "failed."); @@ -260,9 +262,6 @@ NTSTATUS change_notify_add_request(struct smb_request *req, map->mid = request->req->mid; DLIST_ADD(notify_changes_by_mid, map); - /* Push the MID of this packet on the signing queue. */ - srv_defer_sign_response(request->req->mid); - return NT_STATUS_OK; } diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index 9c7fb1914e..7e75eea6b4 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -230,6 +230,7 @@ void send_nt_replies(connection_struct *conn, show_msg((char *)req->outbuf); if (!srv_send_smb(smbd_server_fd(), (char *)req->outbuf, + true, req->seqnum+1, IS_CONN_ENCRYPTED(conn), &req->pcd)) { exit_server_cleanly("send_nt_replies: srv_send_smb failed."); @@ -440,6 +441,8 @@ void reply_ntcreate_and_X(struct smb_request *req) START_PROFILE(SMBntcreateX); + SET_STAT_INVALID(sbuf); + if (req->wct < 24) { reply_nterror(req, NT_STATUS_INVALID_PARAMETER); return; @@ -864,6 +867,8 @@ static void call_nt_transact_create(connection_struct *conn, uint8_t oplock_granted; TALLOC_CTX *ctx = talloc_tos(); + SET_STAT_INVALID(sbuf); + DEBUG(5,("call_nt_transact_create\n")); /* @@ -1129,9 +1134,9 @@ void reply_ntcancel(struct smb_request *req) */ START_PROFILE(SMBntcancel); + srv_cancel_sign_response(smbd_server_conn); remove_pending_change_notify_requests_by_mid(req->mid); remove_pending_lock_requests_by_mid(req->mid); - srv_cancel_sign_response(req->mid, true); DEBUG(3,("reply_ntcancel: cancel called on mid = %d.\n", req->mid)); diff --git a/source3/smbd/open.c b/source3/smbd/open.c index d529b009d5..52df4fa143 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -1033,15 +1033,6 @@ static void defer_open(struct share_mode_lock *lck, exit_server("push_deferred_smb_message failed"); } add_deferred_open(lck, req->mid, request_time, state->id); - - /* - * Push the MID of this packet on the signing queue. - * We only do this once, the first time we push the packet - * onto the deferred open queue, as this has a side effect - * of incrementing the response sequence number. - */ - - srv_defer_sign_response(req->mid); } diff --git a/source3/smbd/oplock.c b/source3/smbd/oplock.c index 22870283fa..ce00397bbd 100644 --- a/source3/smbd/oplock.c +++ b/source3/smbd/oplock.c @@ -361,7 +361,6 @@ void process_oplock_async_level2_break_message(struct messaging_context *msg_ctx struct share_mode_entry msg; files_struct *fsp; char *break_msg; - bool sign_state; if (data->data == NULL) { DEBUG(0, ("Got NULL buffer\n")); @@ -423,20 +422,14 @@ void process_oplock_async_level2_break_message(struct messaging_context *msg_ctx wait_before_sending_break(); } - /* Save the server smb signing state. */ - sign_state = srv_oplock_set_signing(False); - show_msg(break_msg); if (!srv_send_smb(smbd_server_fd(), - break_msg, + break_msg, false, 0, IS_CONN_ENCRYPTED(fsp->conn), NULL)) { exit_server_cleanly("oplock_break: srv_send_smb failed."); } - /* Restore the sign state to what it was. */ - srv_oplock_set_signing(sign_state); - TALLOC_FREE(break_msg); /* Async level2 request, don't send a reply, just remove the oplock. */ @@ -457,7 +450,6 @@ static void process_oplock_break_message(struct messaging_context *msg_ctx, files_struct *fsp; char *break_msg; bool break_to_level2 = False; - bool sign_state; if (data->data == NULL) { DEBUG(0, ("Got NULL buffer\n")); @@ -530,20 +522,14 @@ static void process_oplock_break_message(struct messaging_context *msg_ctx, wait_before_sending_break(); } - /* Save the server smb signing state. */ - sign_state = srv_oplock_set_signing(False); - show_msg(break_msg); if (!srv_send_smb(smbd_server_fd(), - break_msg, + break_msg, false, 0, IS_CONN_ENCRYPTED(fsp->conn), NULL)) { exit_server_cleanly("oplock_break: srv_send_smb failed."); } - /* Restore the sign state to what it was. */ - srv_oplock_set_signing(sign_state); - TALLOC_FREE(break_msg); fsp->sent_oplock_break = break_to_level2 ? LEVEL_II_BREAK_SENT:BREAK_TO_NONE_SENT; @@ -570,7 +556,6 @@ static void process_kernel_oplock_break(struct messaging_context *msg_ctx, unsigned long file_id; files_struct *fsp; char *break_msg; - bool sign_state; if (data->data == NULL) { DEBUG(0, ("Got NULL buffer\n")); @@ -610,20 +595,14 @@ static void process_kernel_oplock_break(struct messaging_context *msg_ctx, exit_server("Could not talloc break_msg\n"); } - /* Save the server smb signing state. */ - sign_state = srv_oplock_set_signing(False); - show_msg(break_msg); if (!srv_send_smb(smbd_server_fd(), - break_msg, + break_msg, false, 0, IS_CONN_ENCRYPTED(fsp->conn), NULL)) { exit_server_cleanly("oplock_break: srv_send_smb failed."); } - /* Restore the sign state to what it was. */ - srv_oplock_set_signing(sign_state); - TALLOC_FREE(break_msg); fsp->sent_oplock_break = BREAK_TO_NONE_SENT; diff --git a/source3/smbd/password.c b/source3/smbd/password.c index 15d120a79c..076965e783 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -298,11 +298,13 @@ int register_existing_vuid(uint16 vuid, vuser->server_info->unix_name); } - if (srv_is_signing_negotiated() && !vuser->server_info->guest && - !srv_signing_started()) { + if (srv_is_signing_negotiated(smbd_server_conn) && + !vuser->server_info->guest) { /* Try and turn on server signing on the first non-guest * sessionsetup. */ - srv_set_signing(vuser->server_info->user_session_key, response_blob); + srv_set_signing(smbd_server_conn, + vuser->server_info->user_session_key, + response_blob); } /* fill in the current_user_info struct */ diff --git a/source3/smbd/pipes.c b/source3/smbd/pipes.c index 2686cf41d9..7ae7435646 100644 --- a/source3/smbd/pipes.c +++ b/source3/smbd/pipes.c @@ -216,6 +216,7 @@ static void pipe_write_done(struct tevent_req *subreq) send: if (!srv_send_smb(smbd_server_fd(), (char *)req->outbuf, + true, req->seqnum+1, IS_CONN_ENCRYPTED(req->conn)||req->encrypted, &req->pcd)) { exit_server_cleanly("construct_reply: srv_send_smb failed."); diff --git a/source3/smbd/process.c b/source3/smbd/process.c index 18fbdd7939..65778ab0fc 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -32,16 +32,20 @@ static void construct_reply_common(struct smb_request *req, const char *inbuf, Send an smb to a fd. ****************************************************************************/ -bool srv_send_smb(int fd, char *buffer, bool do_encrypt, - struct smb_perfcount_data *pcd) +bool srv_send_smb(int fd, char *buffer, + bool do_signing, uint32_t seqnum, + bool do_encrypt, + struct smb_perfcount_data *pcd) { size_t len = 0; size_t nwritten=0; ssize_t ret; char *buf_out = buffer; - /* Sign the outgoing packet if required. */ - srv_calculate_sign_mac(buf_out); + if (do_signing) { + /* Sign the outgoing packet if required. */ + srv_calculate_sign_mac(smbd_server_conn, buf_out, seqnum); + } if (do_encrypt) { NTSTATUS status = srv_encrypt_buffer(buffer, &buf_out); @@ -275,7 +279,7 @@ static NTSTATUS receive_smb_raw_talloc(TALLOC_CTX *mem_ctx, int fd, if (CVAL(lenbuf,0) == 0 && min_recv_size && (smb_len_large(lenbuf) > /* Could be a UNIX large writeX. */ (min_recv_size + STANDARD_WRITE_AND_X_HEADER_SIZE)) && - !srv_is_signing_active()) { + !srv_is_signing_active(smbd_server_conn)) { return receive_smb_raw_talloc_partial_read( mem_ctx, lenbuf, fd, buffer, timeout, p_unread, plen); @@ -311,7 +315,8 @@ static NTSTATUS receive_smb_raw_talloc(TALLOC_CTX *mem_ctx, int fd, static NTSTATUS receive_smb_talloc(TALLOC_CTX *mem_ctx, int fd, char **buffer, unsigned int timeout, size_t *p_unread, bool *p_encrypted, - size_t *p_len) + size_t *p_len, + uint32_t *seqnum) { size_t len = 0; NTSTATUS status; @@ -336,7 +341,7 @@ static NTSTATUS receive_smb_talloc(TALLOC_CTX *mem_ctx, int fd, } /* Check the incoming SMB signature. */ - if (!srv_check_sign_mac(*buffer, true)) { + if (!srv_check_sign_mac(smbd_server_conn, *buffer, seqnum)) { DEBUG(0, ("receive_smb: SMB Signature verification failed on " "incoming packet!\n")); return NT_STATUS_INVALID_NETWORK_RESPONSE; @@ -366,6 +371,7 @@ void init_smb_request(struct smb_request *req, req->flags2 = SVAL(inbuf, smb_flg2); req->smbpid = SVAL(inbuf, smb_pid); req->mid = SVAL(inbuf, smb_mid); + req->seqnum = 0; req->vuid = SVAL(inbuf, smb_uid); req->tid = SVAL(inbuf, smb_tid); req->wct = CVAL(inbuf, smb_wct); @@ -401,7 +407,8 @@ void init_smb_request(struct smb_request *req, static void process_smb(struct smbd_server_connection *conn, uint8_t *inbuf, size_t nread, size_t unread_bytes, - bool encrypted, struct smb_perfcount_data *deferred_pcd); + uint32_t seqnum, bool encrypted, + struct smb_perfcount_data *deferred_pcd); static void smbd_deferred_open_timer(struct event_context *ev, struct timed_event *te, @@ -427,7 +434,7 @@ static void smbd_deferred_open_timer(struct event_context *ev, process_smb(smbd_server_conn, inbuf, msg->buf.length, 0, - msg->encrypted, &msg->pcd); + msg->seqnum, msg->encrypted, &msg->pcd); } /**************************************************************************** @@ -458,6 +465,7 @@ static bool push_queued_message(struct smb_request *req, } msg->request_time = request_time; + msg->seqnum = req->seqnum; msg->encrypted = req->encrypted; SMB_PERFCOUNT_DEFER_OP(&req->pcd, &msg->pcd); @@ -913,7 +921,7 @@ static const struct smb_message_struct { /* 0x30 */ { NULL, NULL, 0 }, /* 0x31 */ { NULL, NULL, 0 }, /* 0x32 */ { "SMBtrans2",reply_trans2, AS_USER | CAN_IPC }, -/* 0x33 */ { "SMBtranss2",reply_transs2, AS_USER}, +/* 0x33 */ { "SMBtranss2",reply_transs2, AS_USER | CAN_IPC }, /* 0x34 */ { "SMBfindclose",reply_findclose,AS_USER}, /* 0x35 */ { "SMBfindnclose",reply_findnclose,AS_USER}, /* 0x36 */ { NULL, NULL, 0 }, @@ -1362,7 +1370,7 @@ static connection_struct *switch_message(uint8 type, struct smb_request *req, in ****************************************************************************/ static void construct_reply(char *inbuf, int size, size_t unread_bytes, - bool encrypted, + uint32_t seqnum, bool encrypted, struct smb_perfcount_data *deferred_pcd) { connection_struct *conn; @@ -1374,6 +1382,7 @@ static void construct_reply(char *inbuf, int size, size_t unread_bytes, init_smb_request(req, (uint8 *)inbuf, unread_bytes, encrypted); req->inbuf = (uint8_t *)talloc_move(req, &inbuf); + req->seqnum = seqnum; /* we popped this message off the queue - keep original perf data */ if (deferred_pcd) @@ -1405,6 +1414,7 @@ static void construct_reply(char *inbuf, int size, size_t unread_bytes, if (!srv_send_smb(smbd_server_fd(), (char *)req->outbuf, + true, req->seqnum+1, IS_CONN_ENCRYPTED(conn)||req->encrypted, &req->pcd)) { exit_server_cleanly("construct_reply: srv_send_smb failed."); @@ -1420,7 +1430,8 @@ static void construct_reply(char *inbuf, int size, size_t unread_bytes, ****************************************************************************/ static void process_smb(struct smbd_server_connection *conn, uint8_t *inbuf, size_t nread, size_t unread_bytes, - bool encrypted, struct smb_perfcount_data *deferred_pcd) + uint32_t seqnum, bool encrypted, + struct smb_perfcount_data *deferred_pcd) { int msg_type = CVAL(inbuf,0); @@ -1442,7 +1453,7 @@ static void process_smb(struct smbd_server_connection *conn, show_msg((char *)inbuf); - construct_reply((char *)inbuf,nread,unread_bytes,encrypted,deferred_pcd); + construct_reply((char *)inbuf,nread,unread_bytes,seqnum,encrypted,deferred_pcd); trans_num++; done: @@ -1637,6 +1648,7 @@ void chain_reply(struct smb_request *req) talloc_get_size(req->chain_outbuf) - 4); if (!srv_send_smb(smbd_server_fd(), (char *)req->chain_outbuf, + true, req->seqnum+1, IS_CONN_ENCRYPTED(req->conn) ||req->encrypted, &req->pcd)) { @@ -1761,6 +1773,7 @@ void chain_reply(struct smb_request *req) show_msg((char *)(req->chain_outbuf)); if (!srv_send_smb(smbd_server_fd(), (char *)req->chain_outbuf, + true, req->seqnum+1, IS_CONN_ENCRYPTED(req->conn)||req->encrypted, &req->pcd)) { exit_server_cleanly("construct_reply: srv_send_smb failed."); @@ -1830,6 +1843,7 @@ static void smbd_server_connection_read_handler(struct smbd_server_connection *c bool encrypted = false; TALLOC_CTX *mem_ctx = talloc_tos(); NTSTATUS status; + uint32_t seqnum; /* TODO: make this completely nonblocking */ @@ -1838,7 +1852,7 @@ static void smbd_server_connection_read_handler(struct smbd_server_connection *c 0, /* timeout */ &unread_bytes, &encrypted, - &inbuf_len); + &inbuf_len, &seqnum); if (NT_STATUS_EQUAL(status, NT_STATUS_RETRY)) { goto process; } @@ -1850,7 +1864,8 @@ static void smbd_server_connection_read_handler(struct smbd_server_connection *c } process: - process_smb(conn, inbuf, inbuf_len, unread_bytes, encrypted, NULL); + process_smb(conn, inbuf, inbuf_len, unread_bytes, + seqnum, encrypted, NULL); } static void smbd_server_connection_handler(struct event_context *ev, @@ -2015,7 +2030,8 @@ void smbd_process(void) unsigned char buf[5] = {0x83, 0, 0, 1, 0x81}; DEBUG( 1, ("Connection denied from %s\n", client_addr(get_client_fd(),addr,sizeof(addr)) ) ); - (void)srv_send_smb(smbd_server_fd(),(char *)buf,false, NULL); + (void)srv_send_smb(smbd_server_fd(),(char *)buf, false, + 0, false, NULL); exit_server_cleanly("connection denied"); } @@ -2041,6 +2057,10 @@ void smbd_process(void) DEBUG(0,("Changed root to %s\n", lp_rootdir())); } + if (!srv_init_signing(smbd_server_conn)) { + exit_server("Failed to init smb_signing"); + } + /* Setup oplocks */ if (!init_oplocks(smbd_messaging_context())) exit_server("Failed to init oplocks"); diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 8b560bd8ca..16eb4a7fd7 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -497,7 +497,7 @@ void reply_special(char *inbuf) DEBUG(5,("init msg_type=0x%x msg_flags=0x%x\n", msg_type, msg_flags)); - srv_send_smb(smbd_server_fd(), outbuf, false, NULL); + srv_send_smb(smbd_server_fd(), outbuf, false, 0, false, NULL); return; } @@ -1606,6 +1606,8 @@ void reply_open(struct smb_request *req) START_PROFILE(SMBopen); + SET_STAT_INVALID(sbuf); + if (req->wct < 2) { reply_nterror(req, NT_STATUS_INVALID_PARAMETER); END_PROFILE(SMBopen); @@ -1741,6 +1743,8 @@ void reply_open_and_X(struct smb_request *req) return; } + SET_STAT_INVALID(sbuf); + open_flags = SVAL(req->vwv+2, 0); deny_mode = SVAL(req->vwv+3, 0); smb_attr = SVAL(req->vwv+5, 0); @@ -1945,6 +1949,7 @@ void reply_mknew(struct smb_request *req) START_PROFILE(SMBcreate); ZERO_STRUCT(ft); + SET_STAT_INVALID(sbuf); if (req->wct < 3) { reply_nterror(req, NT_STATUS_INVALID_PARAMETER); @@ -2123,6 +2128,7 @@ void reply_ctemp(struct smb_request *req) return; } + SET_STAT_INVALID(sbuf); SMB_VFS_STAT(conn,fname,&sbuf); /* We should fail if file does not exist. */ @@ -2766,7 +2772,8 @@ static void send_file_readbraw(connection_struct *conn, */ if ( !req_is_in_chain(req) && (nread > 0) && (fsp->base_fsp == NULL) && - (fsp->wcp == NULL) && lp_use_sendfile(SNUM(conn)) ) { + (fsp->wcp == NULL) && + lp_use_sendfile(SNUM(conn), smbd_server_conn->signing_state) ) { ssize_t sendfile_read = -1; char header[4]; DATA_BLOB header_blob; @@ -2870,7 +2877,8 @@ void reply_readbraw(struct smb_request *req) START_PROFILE(SMBreadbraw); - if (srv_is_signing_active() || is_encrypted_packet(req->inbuf)) { + if (srv_is_signing_active(smbd_server_conn) || + is_encrypted_packet(req->inbuf)) { exit_server_cleanly("reply_readbraw: SMB signing/sealing is active - " "raw reads/writes are disallowed."); } @@ -3274,7 +3282,8 @@ static void send_file_readX(connection_struct *conn, struct smb_request *req, if (!req_is_in_chain(req) && !is_encrypted_packet(req->inbuf) && (fsp->base_fsp == NULL) && - lp_use_sendfile(SNUM(conn)) && (fsp->wcp == NULL) ) { + (fsp->wcp == NULL) && + lp_use_sendfile(SNUM(conn), smbd_server_conn->signing_state) ) { uint8 headerbuf[smb_size + 12 * 2]; DATA_BLOB header; @@ -3450,7 +3459,8 @@ void reply_read_and_X(struct smb_request *req) return; } /* We currently don't do this on signed or sealed data. */ - if (srv_is_signing_active() || is_encrypted_packet(req->inbuf)) { + if (srv_is_signing_active(smbd_server_conn) || + is_encrypted_packet(req->inbuf)) { reply_nterror(req, NT_STATUS_NOT_SUPPORTED); END_PROFILE(SMBreadX); return; @@ -3558,7 +3568,7 @@ void reply_writebraw(struct smb_request *req) */ SCVAL(req->inbuf,smb_com,SMBwritec); - if (srv_is_signing_active()) { + if (srv_is_signing_active(smbd_server_conn)) { END_PROFILE(SMBwritebraw); exit_server_cleanly("reply_writebraw: SMB signing is active - " "raw reads/writes are disallowed."); @@ -3653,9 +3663,10 @@ void reply_writebraw(struct smb_request *req) SSVALS(buf,smb_vwv0,0xFFFF); show_msg(buf); if (!srv_send_smb(smbd_server_fd(), - buf, - IS_CONN_ENCRYPTED(conn), - &req->pcd)) { + buf, + false, 0, /* no signing */ + IS_CONN_ENCRYPTED(conn), + &req->pcd)) { exit_server_cleanly("reply_writebraw: srv_send_smb " "failed."); } @@ -4757,6 +4768,7 @@ void reply_echo(struct smb_request *req) show_msg((char *)req->outbuf); if (!srv_send_smb(smbd_server_fd(), (char *)req->outbuf, + true, req->seqnum+1, IS_CONN_ENCRYPTED(conn)||req->encrypted, cur_pcd)) exit_server_cleanly("reply_echo: srv_send_smb failed."); diff --git a/source3/smbd/server.c b/source3/smbd/server.c index d27f98281b..67836f785b 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -643,8 +643,19 @@ static bool open_sockets_smbd(struct smbd_parent_context *parent, #endif if (dns_port != 0) { +#ifdef WITH_DNSSD_SUPPORT smbd_setup_mdns_registration(smbd_event_context(), parent, dns_port); +#endif +#ifdef WITH_AVAHI_SUPPORT + void *avahi_conn; + + avahi_conn = avahi_start_register( + smbd_event_context(), smbd_event_context(), dns_port); + if (avahi_conn == NULL) { + DEBUG(10, ("avahi_start_register failed\n")); + } +#endif } return true; diff --git a/source3/smbd/service.c b/source3/smbd/service.c index eb16a2601e..e33f04d971 100644 --- a/source3/smbd/service.c +++ b/source3/smbd/service.c @@ -1110,7 +1110,7 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser, if( DEBUGLVL( IS_IPC(conn) ? 3 : 1 ) ) { dbgtext( "%s (%s) ", get_remote_machine_name(), conn->client_address ); - dbgtext( "%s", srv_is_signing_active() ? "signed " : ""); + dbgtext( "%s", srv_is_signing_active(smbd_server_conn) ? "signed " : ""); dbgtext( "connect to service %s ", lp_servicename(snum) ); dbgtext( "initially as user %s ", conn->server_info->unix_name ); diff --git a/source3/smbd/sesssetup.c b/source3/smbd/sesssetup.c index 2c29192220..e8878a29ab 100644 --- a/source3/smbd/sesssetup.c +++ b/source3/smbd/sesssetup.c @@ -91,25 +91,6 @@ static int push_signature(uint8 **outbuf) } /**************************************************************************** - Start the signing engine if needed. Don't fail signing here. -****************************************************************************/ - -static void sessionsetup_start_signing_engine( - const auth_serversupplied_info *server_info, - const uint8 *inbuf) -{ - if (!server_info->guest && !srv_signing_started()) { - /* We need to start the signing engine - * here but a W2K client sends the old - * "BSRSPYL " signature instead of the - * correct one. Subsequent packets will - * be correct. - */ - srv_check_sign_mac((char *)inbuf, False); - } -} - -/**************************************************************************** Send a security blob via a session setup reply. ****************************************************************************/ @@ -579,7 +560,6 @@ static void reply_spnego_kerberos(struct smb_request *req, SSVAL(req->outbuf, smb_uid, sess_vuid); - sessionsetup_start_signing_engine(server_info, req->inbuf); /* Successful logon. Keep this vuid. */ *p_invalidate_vuid = False; } @@ -668,9 +648,6 @@ static void reply_spnego_ntlmssp(struct smb_request *req, if (server_info->guest) { SSVAL(req->outbuf,smb_vwv2,1); } - - sessionsetup_start_signing_engine(server_info, - (uint8 *)req->inbuf); } out: @@ -1804,8 +1781,6 @@ void reply_sesssetup_and_X(struct smb_request *req) /* current_user_info is changed on new vuid */ reload_services( True ); - - sessionsetup_start_signing_engine(server_info, req->inbuf); } data_blob_free(&nt_resp); diff --git a/source3/smbd/signing.c b/source3/smbd/signing.c new file mode 100644 index 0000000000..b56eb71f45 --- /dev/null +++ b/source3/smbd/signing.c @@ -0,0 +1,158 @@ +/* + Unix SMB/CIFS implementation. + SMB Signing Code + Copyright (C) Jeremy Allison 2003. + Copyright (C) Andrew Bartlett <abartlet@samba.org> 2002-2003 + Copyright (C) Stefan Metzmacher 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 "smbd/globals.h" + + +/*********************************************************** + Called to validate an incoming packet from the client. +************************************************************/ + +bool srv_check_sign_mac(struct smbd_server_connection *conn, + const char *inbuf, uint32_t *seqnum) +{ + /* Check if it's a non-session message. */ + if(CVAL(inbuf,0)) { + return true; + } + + *seqnum = smb_signing_next_seqnum(conn->signing_state, false); + return smb_signing_check_pdu(conn->signing_state, + (const uint8_t *)inbuf, + *seqnum); +} + +/*********************************************************** + Called to sign an outgoing packet to the client. +************************************************************/ + +void srv_calculate_sign_mac(struct smbd_server_connection *conn, + char *outbuf, uint32_t seqnum) +{ + /* Check if it's a non-session message. */ + if(CVAL(outbuf,0)) { + return; + } + + smb_signing_sign_pdu(conn->signing_state, (uint8_t *)outbuf, seqnum); +} + + +/*********************************************************** + Called to indicate a oneway request +************************************************************/ +void srv_cancel_sign_response(struct smbd_server_connection *conn) +{ + smb_signing_cancel_reply(conn->signing_state, true); +} + +/*********************************************************** + Called by server negprot when signing has been negotiated. +************************************************************/ + +bool srv_init_signing(struct smbd_server_connection *conn) +{ + bool allowed = true; + bool mandatory = false; + + switch (lp_server_signing()) { + case Required: + mandatory = true; + break; + case Auto: + break; + case True: + break; + case False: + allowed = false; + break; + } + + conn->signing_state = smb_signing_init(smbd_event_context(), + allowed, mandatory); + if (!conn->signing_state) { + return false; + } + + return true; +} + +void srv_set_signing_negotiated(struct smbd_server_connection *conn) +{ + smb_signing_set_negotiated(conn->signing_state); +} + +/*********************************************************** + Returns whether signing is active. We can't use sendfile or raw + reads/writes if it is. +************************************************************/ + +bool srv_is_signing_active(struct smbd_server_connection *conn) +{ + return smb_signing_is_active(conn->signing_state); +} + + +/*********************************************************** + Returns whether signing is negotiated. We can't use it unless it was + in the negprot. +************************************************************/ + +bool srv_is_signing_negotiated(struct smbd_server_connection *conn) +{ + return smb_signing_is_negotiated(conn->signing_state); +} + +/*********************************************************** + Turn on signing from this packet onwards. +************************************************************/ + +void srv_set_signing(struct smbd_server_connection *conn, + const DATA_BLOB user_session_key, + const DATA_BLOB response) +{ + bool negotiated; + bool mandatory; + + if (!user_session_key.length) + return; + + negotiated = smb_signing_is_negotiated(conn->signing_state); + mandatory = smb_signing_is_mandatory(conn->signing_state); + + if (!negotiated && !mandatory) { + DEBUG(5,("srv_set_signing: signing negotiated = %u, " + "mandatory_signing = %u. Not allowing smb signing.\n", + negotiated, mandatory)); + return; + } + + if (!smb_signing_activate(conn->signing_state, + user_session_key, response)) { + return; + } + + DEBUG(3,("srv_set_signing: turning on SMB signing: " + "signing negotiated = %u, mandatory_signing = %u.\n", + negotiated, mandatory)); +} + diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index ee1dda98b2..04b1145e58 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -832,6 +832,7 @@ void send_trans2_replies(connection_struct *conn, show_msg((char *)req->outbuf); if (!srv_send_smb(smbd_server_fd(), (char *)req->outbuf, + true, req->seqnum+1, IS_CONN_ENCRYPTED(conn), &req->pcd)) exit_server_cleanly("send_trans2_replies: srv_send_smb failed."); @@ -894,6 +895,8 @@ static void call_trans2open(connection_struct *conn, uint32 create_options = 0; TALLOC_CTX *ctx = talloc_tos(); + SET_STAT_INVALID(sbuf); + /* * Ensure we have enough parameters to perform the operation. */ @@ -2892,8 +2895,8 @@ cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned case SMB_QUERY_CIFS_UNIX_INFO: { bool large_write = lp_min_receive_file_size() && - !srv_is_signing_active(); - bool large_read = !srv_is_signing_active(); + !srv_is_signing_active(smbd_server_conn); + bool large_read = !srv_is_signing_active(smbd_server_conn); int encrypt_caps = 0; if (!lp_unix_extensions()) { diff --git a/source3/utils/net_rpc_printer.c b/source3/utils/net_rpc_printer.c index 1d0e9a38be..9721628f02 100644 --- a/source3/utils/net_rpc_printer.c +++ b/source3/utils/net_rpc_printer.c @@ -2260,14 +2260,13 @@ NTSTATUS rpc_printer_migrate_settings_internals(struct net_context *c, info_dst.info2.secdesc = NULL; #if 0 - if (asprintf(&devicename, "\\\\%s\\%s", longname, - printername) < 0) { + info_dst.info2.devmode.devicename = + talloc_asprintf(mem_ctx, "\\\\%s\\%s", + longname, printername); + if (!info_dst.info2.devmode.devicename) { nt_status = NT_STATUS_NO_MEMORY; goto done; } - - init_unistr(&ctr_dst.printers_2->devmode->devicename, - devicename); #endif if (!net_spoolss_setprinter(pipe_hnd_dst, mem_ctx, &hnd_dst, level, &info_dst)) diff --git a/source3/winbindd/winbindd_pam.c b/source3/winbindd/winbindd_pam.c index 15d1b7e2bf..54bcac2b04 100644 --- a/source3/winbindd/winbindd_pam.c +++ b/source3/winbindd/winbindd_pam.c @@ -1854,7 +1854,7 @@ enum winbindd_result winbindd_dual_pam_auth_crap(struct winbindd_domain *domain, if (state->request.data.auth_crap.lm_resp_len > sizeof(state->request.data.auth_crap.lm_resp) || state->request.data.auth_crap.nt_resp_len > sizeof(state->request.data.auth_crap.nt_resp)) { - if (!state->request.flags & WBFLAG_BIG_NTLMV2_BLOB || + if (!(state->request.flags & WBFLAG_BIG_NTLMV2_BLOB) || state->request.extra_len != state->request.data.auth_crap.nt_resp_len) { DEBUG(0, ("winbindd_pam_auth_crap: invalid password length %u/%u\n", state->request.data.auth_crap.lm_resp_len, |