diff options
Diffstat (limited to 'source3')
58 files changed, 2415 insertions, 1724 deletions
diff --git a/source3/Makefile.in b/source3/Makefile.in index cf74182f27..ec52d85508 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 @@ -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) @@ -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) \ @@ -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 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..3b4b1cf3f1 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, @@ -6720,7 +6735,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 +7234,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..ac9867a1fc --- /dev/null +++ b/source3/lib/avahi.c @@ -0,0 +1,268 @@ +/* + 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); + + 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/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/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/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_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..628fc1bd32 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."); @@ -1129,9 +1130,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..6f19a58178 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; } @@ -2766,7 +2766,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 +2871,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 +3276,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 +3453,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 +3562,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 +3657,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 +4762,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..df01a39893 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."); @@ -2892,8 +2893,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/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, |