diff options
35 files changed, 1157 insertions, 801 deletions
diff --git a/docs-xml/smbdotconf/protocol/smb2maxread.xml b/docs-xml/smbdotconf/protocol/smb2maxread.xml new file mode 100644 index 0000000000..f4bcb4bbf0 --- /dev/null +++ b/docs-xml/smbdotconf/protocol/smb2maxread.xml @@ -0,0 +1,17 @@ +<samba:parameter name="smb2 max read" + type="integer" + context="G" + advanced="1" developer="1" + xmlns:samba="http://www.samba.org/samba/DTD/samba-doc"> +<description> +<para>This option specifies the protocol value that <citerefentry><refentrytitle>smbd</refentrytitle> +<manvolnum>8</manvolnum></citerefentry> will return to a client, informing the client of the largest +size that may be returned by a single SMB2 read call. +</para> +<para>The default is 1048576 bytes (1MB), which is the same as a Windows7 SMB2 server.</para> +</description> + +<related>smb2 max write</related> +<related>smb2 max trans</related> +<value type="default">1048576</value> +</samba:parameter> diff --git a/docs-xml/smbdotconf/protocol/smb2maxtrans.xml b/docs-xml/smbdotconf/protocol/smb2maxtrans.xml new file mode 100644 index 0000000000..dd654f46d1 --- /dev/null +++ b/docs-xml/smbdotconf/protocol/smb2maxtrans.xml @@ -0,0 +1,17 @@ +<samba:parameter name="smb2 max trans" + type="integer" + context="G" + advanced="1" developer="1" + xmlns:samba="http://www.samba.org/samba/DTD/samba-doc"> +<description> +<para>This option specifies the protocol value that <citerefentry><refentrytitle>smbd</refentrytitle> +<manvolnum>8</manvolnum></citerefentry> will return to a client, informing the client of the largest +size of buffer that may be used in querying file meta-data via QUERY_INFO and related SMB2 calls. +</para> +<para>The default is 1048576 bytes (1MB), which is the same as a Windows7 SMB2 server.</para> +</description> + +<related>smb2 max read</related> +<related>smb2 max write</related> +<value type="default">1048576</value> +</samba:parameter> diff --git a/docs-xml/smbdotconf/protocol/smb2maxwrite.xml b/docs-xml/smbdotconf/protocol/smb2maxwrite.xml new file mode 100644 index 0000000000..cdbc47af47 --- /dev/null +++ b/docs-xml/smbdotconf/protocol/smb2maxwrite.xml @@ -0,0 +1,17 @@ +<samba:parameter name="smb2 max write" + type="integer" + context="G" + advanced="1" developer="1" + xmlns:samba="http://www.samba.org/samba/DTD/samba-doc"> +<description> +<para>This option specifies the protocol value that <citerefentry><refentrytitle>smbd</refentrytitle> +<manvolnum>8</manvolnum></citerefentry> will return to a client, informing the client of the largest +size that may be sent to the server by a single SMB2 write call. +</para> +<para>The default is 1048576 bytes (1MB), which is the same as a Windows7 SMB2 server.</para> +</description> + +<related>smb2 max read</related> +<related>smb2 max trans</related> +<value type="default">1048576</value> +</samba:parameter> diff --git a/examples/perfcounter/perf.h b/examples/perfcounter/perf.h index 7f06b05027..b2968a08cf 100644 --- a/examples/perfcounter/perf.h +++ b/examples/perfcounter/perf.h @@ -21,6 +21,21 @@ #ifndef __PERF_H__ #define __PERF_H__ +#define _PUBLIC_ + +#ifdef HAVE_STDBOOL_H +#include <stdbool.h> +#endif + +#if !defined(HAVE_BOOL) +#ifdef HAVE__Bool +#define bool _Bool +#else +typedef int bool; +#endif +#endif + + #include <stdlib.h> #include <time.h> #include <math.h> diff --git a/lib/iniparser/src/wscript_build b/lib/iniparser/src/wscript_build new file mode 100644 index 0000000000..aa15c9f66e --- /dev/null +++ b/lib/iniparser/src/wscript_build @@ -0,0 +1,7 @@ +#!/usr/bin/env python + +bld.SAMBA_SUBSYSTEM('LIBINIPARSER', + source='../../iniparser_build/iniparser.c ../../iniparser_build/dictionary.c ../../iniparser_build/strlib.c', + deps='replace', + cflags='' + ) diff --git a/librpc/idl/schannel.idl b/librpc/idl/schannel.idl index a30e2928e0..b597a4395d 100644 --- a/librpc/idl/schannel.idl +++ b/librpc/idl/schannel.idl @@ -90,6 +90,8 @@ interface schannel uint8 Confounder[8]; } NL_AUTH_SIGNATURE; + const int NL_AUTH_SIGNATURE_SIZE = 0x20; + /* MS-NRPC 2.2.1.3.3 NL_AUTH_SHA2_SIGNATURE */ typedef [public,flag(NDR_PAHEX)] struct { diff --git a/librpc/rpc/dcerpc_util.c b/librpc/rpc/dcerpc_util.c index a4bc096ddd..c79cfd506a 100644 --- a/librpc/rpc/dcerpc_util.c +++ b/librpc/rpc/dcerpc_util.c @@ -52,6 +52,11 @@ void dcerpc_set_auth_length(DATA_BLOB *blob, uint16_t v) } } +uint8_t dcerpc_get_endian_flag(DATA_BLOB *blob) +{ + return blob->data[DCERPC_DREP_OFFSET]; +} + /* pull an dcerpc_auth structure, taking account of any auth padding in the blob at the end of the structure diff --git a/nsswitch/pam_winbind.c b/nsswitch/pam_winbind.c index b2d74dec4b..e651ce0e49 100644 --- a/nsswitch/pam_winbind.c +++ b/nsswitch/pam_winbind.c @@ -1432,12 +1432,12 @@ static void _pam_warn_krb5_failure(struct pwb_context *ctx, static bool _pam_check_remark_auth_err(struct pwb_context *ctx, const struct wbcAuthErrorInfo *e, const char *nt_status_string, - int *pam_error) + int *pam_err) { const char *ntstatus = NULL; const char *error_string = NULL; - if (!e || !pam_error) { + if (!e || !pam_err) { return false; } @@ -1451,18 +1451,18 @@ static bool _pam_check_remark_auth_err(struct pwb_context *ctx, error_string = _get_ntstatus_error_string(nt_status_string); if (error_string) { _make_remark(ctx, PAM_ERROR_MSG, error_string); - *pam_error = e->pam_error; + *pam_err = e->pam_error; return true; } if (e->display_string) { _make_remark(ctx, PAM_ERROR_MSG, _(e->display_string)); - *pam_error = e->pam_error; + *pam_err = e->pam_error; return true; } _make_remark(ctx, PAM_ERROR_MSG, nt_status_string); - *pam_error = e->pam_error; + *pam_err = e->pam_error; return true; } diff --git a/nsswitch/wscript_build b/nsswitch/wscript_build index 80f11871c9..d708662801 100644 --- a/nsswitch/wscript_build +++ b/nsswitch/wscript_build @@ -18,3 +18,16 @@ bld.SAMBA_BINARY('wbinfo', deps='LIBSAMBA-UTIL LIBCLI_AUTH popt POPT_SAMBA LIBWINBIND-CLIENT LIBWBCLIENT tevent UTIL_TEVENT LIBASYNC_REQ UID_WRAPPER' ) +bld.SAMBA_LIBRARY('nsswinbind', + source='../nsswitch/winbind_nss_linux.c', + deps='LIBWINBIND-CLIENT', + realname='libnss_winbind.so', + vnum='2') + +if bld.CONFIG_SET('HAVE_PAM_START'): + bld.SAMBA_LIBRARY('pamwinbind', + source='../nsswitch/pam_winbind.c', + deps='talloc LIBWBCLIENT LIBWINBIND-CLIENT LIBINIPARSER pam', + cflags='-DLOCALEDIR=\"%s/locale\"' % bld.env.DATADIR, + realname='pam_winbind.so', + ) diff --git a/release-scripts/create-tarball b/release-scripts/create-tarball index 94525e0821..213e35e36e 100755 --- a/release-scripts/create-tarball +++ b/release-scripts/create-tarball @@ -100,7 +100,7 @@ function parseOptions } ## -## Build the dopcumentation (may be a no-op) +## Build the documentation (may be a no-op) ## function buildDocs diff --git a/source3/Makefile.in b/source3/Makefile.in index 9676b37927..26879c4412 100644 --- a/source3/Makefile.in +++ b/source3/Makefile.in @@ -334,6 +334,9 @@ LIBNDR_NTPRINTING_OBJ = librpc/gen_ndr/ndr_ntprinting.o \ LIBNDR_PREG_OBJ = librpc/gen_ndr/ndr_preg.o \ librpc/ndr/ndr_preg.o +LIBNDR_XATTR_OBJ = librpc/gen_ndr/ndr_xattr.o \ + ../librpc/ndr/ndr_xattr.o + LIBNDR_GEN_OBJ = librpc/gen_ndr/ndr_wkssvc.o \ $(LIBNDR_GEN_OBJ0) \ librpc/gen_ndr/ndr_dfs.o \ @@ -345,8 +348,7 @@ LIBNDR_GEN_OBJ = librpc/gen_ndr/ndr_wkssvc.o \ $(LIBNDR_NETLOGON_OBJ) \ librpc/gen_ndr/ndr_dssetup.o \ librpc/gen_ndr/ndr_notify.o \ - librpc/gen_ndr/ndr_xattr.o \ - ../librpc/ndr/ndr_xattr.o \ + $(LIBNDR_XATTR_OBJ) \ librpc/gen_ndr/ndr_epmapper.o \ librpc/gen_ndr/ndr_named_pipe_auth.o \ librpc/gen_ndr/ndr_ntsvcs.o \ @@ -673,8 +675,10 @@ RPC_SERVER_OBJ = @RPC_STATIC@ $(RPC_PIPE_OBJ) $(NPA_TSTREAM_OBJ) RPC_PARSE_OBJ = $(RPC_PARSE_OBJ2) -RPC_CLIENT_OBJ = rpc_client/cli_pipe.o rpc_client/rpc_transport_np.o \ - rpc_client/rpc_transport_sock.o rpc_client/rpc_transport_smbd.o +RPC_CLIENT_OBJ = rpc_client/cli_pipe.o librpc/rpc/rpc_common.o \ + rpc_client/rpc_transport_np.o \ + rpc_client/rpc_transport_sock.o \ + rpc_client/rpc_transport_smbd.o LOCKING_OBJ = locking/locking.o locking/brlock.o locking/posix.o @@ -1341,6 +1345,7 @@ RPC_OPEN_TCP_OBJ = torture/rpc_open_tcp.o \ $(KRBCLIENT_OBJ) \ $(RPC_PARSE_OBJ2) \ $(RPC_CLIENT_OBJ1) \ + librpc/rpc/rpc_common.o \ rpc_client/cli_pipe.o \ ../librpc/rpc/binding.o \ $(LIBMSRPC_GEN_OBJ) diff --git a/source3/configure.in b/source3/configure.in index 4c17e4c928..43119fb246 100644 --- a/source3/configure.in +++ b/source3/configure.in @@ -1799,39 +1799,6 @@ fi AC_MSG_RESULT($BLDSHARED) -saved_before_as_needed_ldflags="$LDFLAGS" -for flags in "-Wl,--as-needed" "-Wl,-z,ignore" "-z ignore" ; do - saved_ldflags="$LDFLAGS" - AC_MSG_CHECKING([if $flags works]) - LDFLAGS="$flags $saved_ldflags" - AC_TRY_LINK([],[], - [AC_MSG_RESULT([yes]) - LD_AS_NEEDED_FLAG=$flags - ld_as_needed_flag_found=yes], - AC_MSG_RESULT([no])) - LDFLAGS="$LD_AS_NEEDED_FLAG $saved_ldflags" - test x"$ld_as_needed_flag_found" = xyes && break -done - -# check if we have to disable LD_AS_NEEDED_FLAG: -# On some systems for a veriety of reasons linking with -# -Wl,--as-needed -lreadline -lncurses fails -# we have to retest, if these combination is detected before. -# Bugzilla #7209 - -if test x$ac_cv_lib_readline_rl_callback_handler_install = xyes ; then - if test x$ld_as_needed_flag_found = xyes ; then - AC_MSG_CHECKING([if $LD_AS_NEEDED_FLAG works with readline]) - # try if check no fails - save_LIBS=$LIBS - LIBS="$LIBS $TERMLIBS" - AC_TRY_LINK([], [rl_callback_handler_install();], [AC_MSG_RESULT([yes])],[ AC_MSG_RESULT([no]); LDFLAGS="$saved_before_as_needed_ldflags"]) - LIBS="$save_LIBS" - fi -fi - - - # for historical reasons almost all linkers don't complain about unresolved # symbols in shared libs. Except for the internal samba modules we want to get # errors when we produce a shared lib with unresolved symbols. On some @@ -6855,17 +6822,7 @@ if test -f Makefile-noincludes -a ! -f Makefile -a ! -h Makefile ; then fi ]) -AC_SUBST(MAKEFILE) -if test x$samba_cv_gnu_make = xyes; then - MAKEFILE=Makefile -else - # When we don't have GNU Make, generate a copy of Makefile.in - # that doesn't have the "include " statements but just includes - # the files verbatim. - MAKEFILE=Makefile-noincludes - $PERL ./script/expand-includes.pl Makefile.in > $MAKEFILE.in -fi -AC_OUTPUT($MAKEFILE +AC_OUTPUT(Makefile script/findsmb smbadduser script/gen-8bit-gap.sh script/installbin.sh script/uninstallbin.sh lib/netapi/examples/Makefile lib/netapi/tests/Makefile diff --git a/source3/include/proto.h b/source3/include/proto.h index ad16e7e52f..9471f63195 100644 --- a/source3/include/proto.h +++ b/source3/include/proto.h @@ -2937,6 +2937,7 @@ NTSTATUS dcerpc_fault_to_nt_status(uint32_t fault_code); void dcerpc_set_frag_length(DATA_BLOB *blob, uint16_t v); uint16_t dcerpc_get_frag_length(const DATA_BLOB *blob); void dcerpc_set_auth_length(DATA_BLOB *blob, uint16_t v); +uint8_t dcerpc_get_endian_flag(DATA_BLOB *blob); NTSTATUS dcerpc_pull_auth_trailer(struct ncacn_packet *pkt, TALLOC_CTX *mem_ctx, DATA_BLOB *pkt_auth_blob, @@ -6166,6 +6167,10 @@ int sessionid_traverse_read(int (*fn)(const char *key, /* The following definitions come from smbd/sesssetup.c */ +NTSTATUS do_map_to_guest(NTSTATUS status, + struct auth_serversupplied_info **server_info, + const char *user, const char *domain); + NTSTATUS parse_spnego_mechanisms(DATA_BLOB blob_in, DATA_BLOB *pblob_out, char **kerb_mechOID); diff --git a/source3/include/rpc_dce.h b/source3/include/rpc_dce.h index 7be8a8a6f7..2cc770e11c 100644 --- a/source3/include/rpc_dce.h +++ b/source3/include/rpc_dce.h @@ -22,8 +22,6 @@ #ifndef _DCE_RPC_H /* _DCE_RPC_H */ #define _DCE_RPC_H -#define SCHANNEL_SIG_SIZE 0x20 - /* Maximum size of the signing data in a fragment. */ #define RPC_MAX_SIGN_SIZE 0x38 /* 56 */ diff --git a/source3/librpc/rpc/dcerpc.h b/source3/librpc/rpc/dcerpc.h index d18920ca0d..bb7bd34de8 100644 --- a/source3/librpc/rpc/dcerpc.h +++ b/source3/librpc/rpc/dcerpc.h @@ -123,7 +123,8 @@ NTSTATUS dcerpc_push_ncacn_packet(TALLOC_CTX *mem_ctx, DATA_BLOB *blob); NTSTATUS dcerpc_pull_ncacn_packet(TALLOC_CTX *mem_ctx, const DATA_BLOB *blob, - struct ncacn_packet *r); + struct ncacn_packet *r, + bool bigendian); NTSTATUS dcerpc_push_schannel_bind(TALLOC_CTX *mem_ctx, struct NL_AUTH_MESSAGE *r, DATA_BLOB *blob); @@ -136,6 +137,7 @@ NTSTATUS dcerpc_push_dcerpc_auth(TALLOC_CTX *mem_ctx, DATA_BLOB *blob); NTSTATUS dcerpc_pull_dcerpc_auth(TALLOC_CTX *mem_ctx, const DATA_BLOB *blob, - struct dcerpc_auth *r); + struct dcerpc_auth *r, + bool bigendian); #endif /* __DCERPC_H__ */ diff --git a/source3/librpc/rpc/dcerpc_helpers.c b/source3/librpc/rpc/dcerpc_helpers.c index ce48a691ac..5c92a792e9 100644 --- a/source3/librpc/rpc/dcerpc_helpers.c +++ b/source3/librpc/rpc/dcerpc_helpers.c @@ -92,15 +92,27 @@ NTSTATUS dcerpc_push_ncacn_packet(TALLOC_CTX *mem_ctx, */ NTSTATUS dcerpc_pull_ncacn_packet(TALLOC_CTX *mem_ctx, const DATA_BLOB *blob, - struct ncacn_packet *r) + struct ncacn_packet *r, + bool bigendian) { enum ndr_err_code ndr_err; + struct ndr_pull *ndr; + + ndr = ndr_pull_init_blob(blob, mem_ctx); + if (!ndr) { + return NT_STATUS_NO_MEMORY; + } + if (bigendian) { + ndr->flags |= LIBNDR_FLAG_BIGENDIAN; + } + + ndr_err = ndr_pull_ncacn_packet(ndr, NDR_SCALARS|NDR_BUFFERS, r); - ndr_err = ndr_pull_struct_blob(blob, mem_ctx, r, - (ndr_pull_flags_fn_t)ndr_pull_ncacn_packet); if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { + talloc_free(ndr); return ndr_map_error2ntstatus(ndr_err); } + talloc_free(ndr); if (DEBUGLEVEL >= 10) { NDR_PRINT_DEBUG(ncacn_packet, r); @@ -194,15 +206,27 @@ NTSTATUS dcerpc_push_dcerpc_auth(TALLOC_CTX *mem_ctx, */ NTSTATUS dcerpc_pull_dcerpc_auth(TALLOC_CTX *mem_ctx, const DATA_BLOB *blob, - struct dcerpc_auth *r) + struct dcerpc_auth *r, + bool bigendian) { enum ndr_err_code ndr_err; + struct ndr_pull *ndr; + + ndr = ndr_pull_init_blob(blob, mem_ctx); + if (!ndr) { + return NT_STATUS_NO_MEMORY; + } + if (bigendian) { + ndr->flags |= LIBNDR_FLAG_BIGENDIAN; + } + + ndr_err = ndr_pull_dcerpc_auth(ndr, NDR_SCALARS|NDR_BUFFERS, r); - ndr_err = ndr_pull_struct_blob(blob, mem_ctx, r, - (ndr_pull_flags_fn_t)ndr_pull_dcerpc_auth); if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { + talloc_free(ndr); return ndr_map_error2ntstatus(ndr_err); } + talloc_free(ndr); if (DEBUGLEVEL >= 10) { NDR_PRINT_DEBUG(dcerpc_auth, r); diff --git a/source3/librpc/rpc/rpc_common.c b/source3/librpc/rpc/rpc_common.c new file mode 100644 index 0000000000..78b88f7e33 --- /dev/null +++ b/source3/librpc/rpc/rpc_common.c @@ -0,0 +1,238 @@ +/* + * Unix SMB/CIFS implementation. + * RPC Pipe client / server routines + * Largely rewritten by Jeremy Allison 2005. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <http://www.gnu.org/licenses/>. + */ + +#include "includes.h" +#include "../librpc/gen_ndr/ndr_schannel.h" +#include "../librpc/gen_ndr/ndr_lsa.h" +#include "../librpc/gen_ndr/ndr_dssetup.h" +#include "../librpc/gen_ndr/ndr_samr.h" +#include "../librpc/gen_ndr/ndr_netlogon.h" +#include "../librpc/gen_ndr/ndr_srvsvc.h" +#include "../librpc/gen_ndr/ndr_wkssvc.h" +#include "../librpc/gen_ndr/ndr_winreg.h" +#include "../librpc/gen_ndr/ndr_spoolss.h" +#include "../librpc/gen_ndr/ndr_dfs.h" +#include "../librpc/gen_ndr/ndr_echo.h" +#include "../librpc/gen_ndr/ndr_initshutdown.h" +#include "../librpc/gen_ndr/ndr_svcctl.h" +#include "../librpc/gen_ndr/ndr_eventlog.h" +#include "../librpc/gen_ndr/ndr_ntsvcs.h" +#include "../librpc/gen_ndr/ndr_epmapper.h" +#include "../librpc/gen_ndr/ndr_drsuapi.h" + +static const char *get_pipe_name_from_iface( + TALLOC_CTX *mem_ctx, const struct ndr_interface_table *interface) +{ + int i; + const struct ndr_interface_string_array *ep = interface->endpoints; + char *p; + + for (i=0; i<ep->count; i++) { + if (strncmp(ep->names[i], "ncacn_np:[\\pipe\\", 16) == 0) { + break; + } + } + if (i == ep->count) { + return NULL; + } + + /* + * extract the pipe name without \\pipe from for example + * ncacn_np:[\\pipe\\epmapper] + */ + p = strchr(ep->names[i]+15, ']'); + if (p == NULL) { + return "PIPE"; + } + return talloc_strndup(mem_ctx, ep->names[i]+15, p - ep->names[i] - 15); +} + +static const struct ndr_interface_table **interfaces; + +bool smb_register_ndr_interface(const struct ndr_interface_table *interface) +{ + int num_interfaces = talloc_array_length(interfaces); + const struct ndr_interface_table **tmp; + int i; + + for (i=0; i<num_interfaces; i++) { + if (ndr_syntax_id_equal(&interfaces[i]->syntax_id, + &interface->syntax_id)) { + return true; + } + } + + tmp = talloc_realloc(NULL, interfaces, + const struct ndr_interface_table *, + num_interfaces + 1); + if (tmp == NULL) { + DEBUG(1, ("smb_register_ndr_interface: talloc failed\n")); + return false; + } + interfaces = tmp; + interfaces[num_interfaces] = interface; + return true; +} + +static bool initialize_interfaces(void) +{ + if (!smb_register_ndr_interface(&ndr_table_lsarpc)) { + return false; + } + if (!smb_register_ndr_interface(&ndr_table_dssetup)) { + return false; + } + if (!smb_register_ndr_interface(&ndr_table_samr)) { + return false; + } + if (!smb_register_ndr_interface(&ndr_table_netlogon)) { + return false; + } + if (!smb_register_ndr_interface(&ndr_table_srvsvc)) { + return false; + } + if (!smb_register_ndr_interface(&ndr_table_wkssvc)) { + return false; + } + if (!smb_register_ndr_interface(&ndr_table_winreg)) { + return false; + } + if (!smb_register_ndr_interface(&ndr_table_spoolss)) { + return false; + } + if (!smb_register_ndr_interface(&ndr_table_netdfs)) { + return false; + } + if (!smb_register_ndr_interface(&ndr_table_rpcecho)) { + return false; + } + if (!smb_register_ndr_interface(&ndr_table_initshutdown)) { + return false; + } + if (!smb_register_ndr_interface(&ndr_table_svcctl)) { + return false; + } + if (!smb_register_ndr_interface(&ndr_table_eventlog)) { + return false; + } + if (!smb_register_ndr_interface(&ndr_table_ntsvcs)) { + return false; + } + if (!smb_register_ndr_interface(&ndr_table_epmapper)) { + return false; + } + if (!smb_register_ndr_interface(&ndr_table_drsuapi)) { + return false; + } + return true; +} + +const struct ndr_interface_table *get_iface_from_syntax( + const struct ndr_syntax_id *syntax) +{ + int num_interfaces; + int i; + + if (interfaces == NULL) { + if (!initialize_interfaces()) { + return NULL; + } + } + num_interfaces = talloc_array_length(interfaces); + + for (i=0; i<num_interfaces; i++) { + if (ndr_syntax_id_equal(&interfaces[i]->syntax_id, syntax)) { + return interfaces[i]; + } + } + + return NULL; +} + +/**************************************************************************** + Return the pipe name from the interface. + ****************************************************************************/ + +const char *get_pipe_name_from_syntax(TALLOC_CTX *mem_ctx, + const struct ndr_syntax_id *syntax) +{ + const struct ndr_interface_table *interface; + char *guid_str; + const char *result; + + interface = get_iface_from_syntax(syntax); + if (interface != NULL) { + result = get_pipe_name_from_iface(mem_ctx, interface); + if (result != NULL) { + return result; + } + } + + /* + * Here we should ask \\epmapper, but for now our code is only + * interested in the known pipes mentioned in pipe_names[] + */ + + guid_str = GUID_string(talloc_tos(), &syntax->uuid); + if (guid_str == NULL) { + return NULL; + } + result = talloc_asprintf(mem_ctx, "Interface %s.%d", guid_str, + (int)syntax->if_version); + TALLOC_FREE(guid_str); + + if (result == NULL) { + return "PIPE"; + } + return result; +} + +/******************************************************************** + Map internal value to wire value. + ********************************************************************/ + +enum dcerpc_AuthType map_pipe_auth_type_to_rpc_auth_type(enum pipe_auth_type auth_type) +{ + switch (auth_type) { + + case PIPE_AUTH_TYPE_NONE: + return DCERPC_AUTH_TYPE_NONE; + + case PIPE_AUTH_TYPE_NTLMSSP: + return DCERPC_AUTH_TYPE_NTLMSSP; + + case PIPE_AUTH_TYPE_SPNEGO_NTLMSSP: + case PIPE_AUTH_TYPE_SPNEGO_KRB5: + return DCERPC_AUTH_TYPE_SPNEGO; + + case PIPE_AUTH_TYPE_SCHANNEL: + return DCERPC_AUTH_TYPE_SCHANNEL; + + case PIPE_AUTH_TYPE_KRB5: + return DCERPC_AUTH_TYPE_KRB5; + + default: + DEBUG(0,("map_pipe_auth_type_to_rpc_type: unknown pipe " + "auth type %u\n", + (unsigned int)auth_type )); + break; + } + return -1; +} + diff --git a/source3/modules/vfs_aio_fork.c b/source3/modules/vfs_aio_fork.c index b43aad2df4..02b1394216 100644 --- a/source3/modules/vfs_aio_fork.c +++ b/source3/modules/vfs_aio_fork.c @@ -765,10 +765,11 @@ static int aio_fork_suspend(struct vfs_handle_struct *handle, } if (timeout) { - struct timeval tv; + struct timeval tv = convert_timespec_to_timeval(*timeout); struct tevent_timer *te = tevent_add_timer(ev, frame, - timeval_current_ofs(tv.tv_sec,0), + timeval_current_ofs(tv.tv_sec, + tv.tv_usec), aio_fork_suspend_timed_out, &timed_out); if (!te) { diff --git a/source3/rpc_client/cli_pipe.c b/source3/rpc_client/cli_pipe.c index c90e06095c..a61200a104 100644 --- a/source3/rpc_client/cli_pipe.c +++ b/source3/rpc_client/cli_pipe.c @@ -20,22 +20,8 @@ #include "includes.h" #include "librpc/gen_ndr/cli_epmapper.h" #include "../librpc/gen_ndr/ndr_schannel.h" -#include "../librpc/gen_ndr/ndr_lsa.h" #include "../librpc/gen_ndr/ndr_dssetup.h" -#include "../librpc/gen_ndr/ndr_samr.h" #include "../librpc/gen_ndr/ndr_netlogon.h" -#include "../librpc/gen_ndr/ndr_srvsvc.h" -#include "../librpc/gen_ndr/ndr_wkssvc.h" -#include "../librpc/gen_ndr/ndr_winreg.h" -#include "../librpc/gen_ndr/ndr_spoolss.h" -#include "../librpc/gen_ndr/ndr_dfs.h" -#include "../librpc/gen_ndr/ndr_echo.h" -#include "../librpc/gen_ndr/ndr_initshutdown.h" -#include "../librpc/gen_ndr/ndr_svcctl.h" -#include "../librpc/gen_ndr/ndr_eventlog.h" -#include "../librpc/gen_ndr/ndr_ntsvcs.h" -#include "../librpc/gen_ndr/ndr_epmapper.h" -#include "../librpc/gen_ndr/ndr_drsuapi.h" #include "../libcli/auth/schannel.h" #include "../libcli/auth/spnego.h" #include "smb_krb5.h" @@ -47,206 +33,6 @@ #undef DBGC_CLASS #define DBGC_CLASS DBGC_RPC_CLI -static const char *get_pipe_name_from_iface( - TALLOC_CTX *mem_ctx, const struct ndr_interface_table *interface) -{ - int i; - const struct ndr_interface_string_array *ep = interface->endpoints; - char *p; - - for (i=0; i<ep->count; i++) { - if (strncmp(ep->names[i], "ncacn_np:[\\pipe\\", 16) == 0) { - break; - } - } - if (i == ep->count) { - return NULL; - } - - /* - * extract the pipe name without \\pipe from for example - * ncacn_np:[\\pipe\\epmapper] - */ - p = strchr(ep->names[i]+15, ']'); - if (p == NULL) { - return "PIPE"; - } - return talloc_strndup(mem_ctx, ep->names[i]+15, p - ep->names[i] - 15); -} - -static const struct ndr_interface_table **interfaces; - -bool smb_register_ndr_interface(const struct ndr_interface_table *interface) -{ - int num_interfaces = talloc_array_length(interfaces); - const struct ndr_interface_table **tmp; - int i; - - for (i=0; i<num_interfaces; i++) { - if (ndr_syntax_id_equal(&interfaces[i]->syntax_id, - &interface->syntax_id)) { - return true; - } - } - - tmp = talloc_realloc(NULL, interfaces, - const struct ndr_interface_table *, - num_interfaces + 1); - if (tmp == NULL) { - DEBUG(1, ("smb_register_ndr_interface: talloc failed\n")); - return false; - } - interfaces = tmp; - interfaces[num_interfaces] = interface; - return true; -} - -static bool initialize_interfaces(void) -{ - if (!smb_register_ndr_interface(&ndr_table_lsarpc)) { - return false; - } - if (!smb_register_ndr_interface(&ndr_table_dssetup)) { - return false; - } - if (!smb_register_ndr_interface(&ndr_table_samr)) { - return false; - } - if (!smb_register_ndr_interface(&ndr_table_netlogon)) { - return false; - } - if (!smb_register_ndr_interface(&ndr_table_srvsvc)) { - return false; - } - if (!smb_register_ndr_interface(&ndr_table_wkssvc)) { - return false; - } - if (!smb_register_ndr_interface(&ndr_table_winreg)) { - return false; - } - if (!smb_register_ndr_interface(&ndr_table_spoolss)) { - return false; - } - if (!smb_register_ndr_interface(&ndr_table_netdfs)) { - return false; - } - if (!smb_register_ndr_interface(&ndr_table_rpcecho)) { - return false; - } - if (!smb_register_ndr_interface(&ndr_table_initshutdown)) { - return false; - } - if (!smb_register_ndr_interface(&ndr_table_svcctl)) { - return false; - } - if (!smb_register_ndr_interface(&ndr_table_eventlog)) { - return false; - } - if (!smb_register_ndr_interface(&ndr_table_ntsvcs)) { - return false; - } - if (!smb_register_ndr_interface(&ndr_table_epmapper)) { - return false; - } - if (!smb_register_ndr_interface(&ndr_table_drsuapi)) { - return false; - } - return true; -} - -const struct ndr_interface_table *get_iface_from_syntax( - const struct ndr_syntax_id *syntax) -{ - int num_interfaces; - int i; - - if (interfaces == NULL) { - if (!initialize_interfaces()) { - return NULL; - } - } - num_interfaces = talloc_array_length(interfaces); - - for (i=0; i<num_interfaces; i++) { - if (ndr_syntax_id_equal(&interfaces[i]->syntax_id, syntax)) { - return interfaces[i]; - } - } - - return NULL; -} - -/**************************************************************************** - Return the pipe name from the interface. - ****************************************************************************/ - -const char *get_pipe_name_from_syntax(TALLOC_CTX *mem_ctx, - const struct ndr_syntax_id *syntax) -{ - const struct ndr_interface_table *interface; - char *guid_str; - const char *result; - - interface = get_iface_from_syntax(syntax); - if (interface != NULL) { - result = get_pipe_name_from_iface(mem_ctx, interface); - if (result != NULL) { - return result; - } - } - - /* - * Here we should ask \\epmapper, but for now our code is only - * interested in the known pipes mentioned in pipe_names[] - */ - - guid_str = GUID_string(talloc_tos(), &syntax->uuid); - if (guid_str == NULL) { - return NULL; - } - result = talloc_asprintf(mem_ctx, "Interface %s.%d", guid_str, - (int)syntax->if_version); - TALLOC_FREE(guid_str); - - if (result == NULL) { - return "PIPE"; - } - return result; -} - -/******************************************************************** - Map internal value to wire value. - ********************************************************************/ - -enum dcerpc_AuthType map_pipe_auth_type_to_rpc_auth_type(enum pipe_auth_type auth_type) -{ - switch (auth_type) { - - case PIPE_AUTH_TYPE_NONE: - return DCERPC_AUTH_TYPE_NONE; - - case PIPE_AUTH_TYPE_NTLMSSP: - return DCERPC_AUTH_TYPE_NTLMSSP; - - case PIPE_AUTH_TYPE_SPNEGO_NTLMSSP: - case PIPE_AUTH_TYPE_SPNEGO_KRB5: - return DCERPC_AUTH_TYPE_SPNEGO; - - case PIPE_AUTH_TYPE_SCHANNEL: - return DCERPC_AUTH_TYPE_SCHANNEL; - - case PIPE_AUTH_TYPE_KRB5: - return DCERPC_AUTH_TYPE_KRB5; - - default: - DEBUG(0,("map_pipe_auth_type_to_rpc_type: unknown pipe " - "auth type %u\n", - (unsigned int)auth_type )); - break; - } - return -1; -} - /******************************************************************** Pipe description for a DEBUG ********************************************************************/ @@ -619,7 +405,7 @@ static NTSTATUS cli_pipe_verify_ntlmssp(struct rpc_pipe_client *cli, DCERPC_AUTH_TRAILER_LENGTH + pkt->auth_length); - status = dcerpc_pull_dcerpc_auth(cli, &blob, &auth_info); + status = dcerpc_pull_dcerpc_auth(cli, &blob, &auth_info, false); if (!NT_STATUS_IS_OK(status)) { DEBUG(0,("cli_pipe_verify_ntlmssp: failed to unmarshall dcerpc_auth.\n")); return status; @@ -722,7 +508,7 @@ static NTSTATUS cli_pipe_verify_schannel(struct rpc_pipe_client *cli, return NT_STATUS_OK; } - if (pkt->auth_length < SCHANNEL_SIG_SIZE) { + if (pkt->auth_length < NL_AUTH_SIGNATURE_SIZE) { DEBUG(0, ("auth_len %u.\n", (unsigned int)pkt->auth_length)); return NT_STATUS_INVALID_PARAMETER; } @@ -749,7 +535,7 @@ static NTSTATUS cli_pipe_verify_schannel(struct rpc_pipe_client *cli, + pkt->auth_length); - status = dcerpc_pull_dcerpc_auth(cli, &blob, &auth_info); + status = dcerpc_pull_dcerpc_auth(cli, &blob, &auth_info, false); if (!NT_STATUS_IS_OK(status)) { DEBUG(0,("cli_pipe_verify_ntlmssp: failed to unmarshall dcerpc_auth.\n")); return status; @@ -915,7 +701,7 @@ static NTSTATUS cli_pipe_validate_current_pdu(TALLOC_CTX *mem_ctx, NTSTATUS ret = NT_STATUS_OK; uint8 ss_padding_len = 0; - ret = dcerpc_pull_ncacn_packet(cli, pdu, pkt); + ret = dcerpc_pull_ncacn_packet(cli, pdu, pkt, false); if (!NT_STATUS_IS_OK(ret)) { return ret; } @@ -976,7 +762,9 @@ static NTSTATUS cli_pipe_validate_current_pdu(TALLOC_CTX *mem_ctx, } DEBUG(10, ("Got pdu len %lu, data_len %lu, ss_len %u\n", - pdu->length, rdata->length, ss_padding_len)); + (long unsigned int)pdu->length, + (long unsigned int)rdata->length, + (unsigned int)ss_padding_len)); /* * If this is the first reply, and the allocation hint is @@ -1991,7 +1779,7 @@ static uint32 calculate_data_len_tosend(struct rpc_pipe_client *cli, *p_auth_len = NTLMSSP_SIG_SIZE; break; case PIPE_AUTH_TYPE_SCHANNEL: - *p_auth_len = SCHANNEL_SIG_SIZE; + *p_auth_len = NL_AUTH_SIGNATURE_SIZE; break; default: smb_panic("bad auth type"); @@ -2612,7 +2400,7 @@ static NTSTATUS rpc_finish_auth3_bind_send(struct tevent_req *req, status = dcerpc_pull_dcerpc_auth(talloc_tos(), &r->u.bind_ack.auth_info, - &auth); + &auth, false); if (!NT_STATUS_IS_OK(status)) { DEBUG(0, ("Failed to pull dcerpc auth: %s.\n", nt_errstr(status))); @@ -2694,7 +2482,7 @@ static NTSTATUS rpc_finish_spnego_ntlmssp_bind_send(struct tevent_req *req, DCERPC_AUTH_TRAILER_LENGTH + r->auth_length); - status = dcerpc_pull_dcerpc_auth(state, &auth_blob, &auth_info); + status = dcerpc_pull_dcerpc_auth(state, &auth_blob, &auth_info, false); if (!NT_STATUS_IS_OK(status)) { DEBUG(0, ("Failed to unmarshall dcerpc_auth.\n")); return status; @@ -2778,7 +2566,7 @@ static void rpc_bind_ntlmssp_api_done(struct tevent_req *subreq) status = dcerpc_pull_dcerpc_auth(pkt, &pkt->u.alter_resp.auth_info, - &auth); + &auth, false); if (!NT_STATUS_IS_OK(status)) { tevent_req_nterror(req, status); return; diff --git a/source3/rpc_client/cli_samr.c b/source3/rpc_client/cli_samr.c index 8c92ebb059..8c1011293a 100644 --- a/source3/rpc_client/cli_samr.c +++ b/source3/rpc_client/cli_samr.c @@ -165,10 +165,29 @@ NTSTATUS rpccli_samr_chng_pswd_auth_crap(struct rpc_pipe_client *cli, init_lsa_String(&server, cli->srv_name_slash); init_lsa_String(&account, username); - memcpy(&new_nt_password.data, new_nt_password_blob.data, 516); - memcpy(&new_lm_password.data, new_lm_password_blob.data, 516); - memcpy(&old_nt_hash_enc.hash, old_nt_hash_enc_blob.data, 16); - memcpy(&old_lm_hash_enc.hash, old_lm_hash_enc_blob.data, 16); + if (new_nt_password_blob.length > 0) { + memcpy(&new_nt_password.data, new_nt_password_blob.data, 516); + } else { + ZERO_STRUCT(new_nt_password_blob); + } + + if (new_lm_password_blob.length > 0) { + memcpy(&new_lm_password.data, new_lm_password_blob.data, 516); + } else { + ZERO_STRUCT(new_lm_password); + } + + if (old_nt_hash_enc_blob.length > 0) { + memcpy(&old_nt_hash_enc.hash, old_nt_hash_enc_blob.data, 16); + } else { + ZERO_STRUCT(old_nt_hash_enc); + } + + if (old_lm_hash_enc_blob.length > 0) { + memcpy(&old_lm_hash_enc.hash, old_lm_hash_enc_blob.data, 16); + } else { + ZERO_STRUCT(old_lm_hash_enc); + } result = rpccli_samr_ChangePasswordUser2(cli, mem_ctx, &server, diff --git a/source3/rpc_server/rpc_server.h b/source3/rpc_server/rpc_server.h new file mode 100644 index 0000000000..f212773f4d --- /dev/null +++ b/source3/rpc_server/rpc_server.h @@ -0,0 +1,26 @@ +/* + * RPC Pipe server helper headers + * Almost completely rewritten by (C) Jeremy Allison 2005 - 2010 + * Copyright (C) Simo Sorce <idra@samba.org> - 2010 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef _RPC_SERVER_H_ +#define _RPC_SERVER_H_ + +void set_incoming_fault(pipes_struct *p); +void process_complete_pdu(pipes_struct *p); + +#endif /* _PRC_SERVER_H_ */ diff --git a/source3/rpc_server/srv_pipe.c b/source3/rpc_server/srv_pipe.c index 6d37ec2bc2..a7a5f4d676 100644 --- a/source3/rpc_server/srv_pipe.c +++ b/source3/rpc_server/srv_pipe.c @@ -33,6 +33,7 @@ #include "../libcli/auth/schannel.h" #include "../libcli/auth/spnego.h" #include "../libcli/auth/ntlmssp.h" +#include "rpc_server.h" #undef DBGC_CLASS #define DBGC_CLASS DBGC_RPC_SRV @@ -427,7 +428,7 @@ bool create_next_pdu(pipes_struct *p) case PIPE_AUTH_TYPE_SCHANNEL: if (!create_next_packet(p, auth_type, p->auth.auth_level, - SCHANNEL_SIG_SIZE)) { + NL_AUTH_SIGNATURE_SIZE)) { return false; } return add_schannel_auth(p); @@ -568,7 +569,7 @@ bool api_pipe_bind_auth3(pipes_struct *p, struct ncacn_packet *pkt) status = dcerpc_pull_dcerpc_auth(pkt, &pkt->u.auth3.auth_info, - &auth_info); + &auth_info, p->endian); if (!NT_STATUS_IS_OK(status)) { DEBUG(0, ("Failed to unmarshall dcerpc_auth.\n")); goto err; @@ -1303,7 +1304,7 @@ bool api_pipe_bind_req(pipes_struct *p, struct ncacn_packet *pkt) */ status = dcerpc_pull_dcerpc_auth(pkt, &pkt->u.bind.auth_info, - &auth_info); + &auth_info, p->endian); if (!NT_STATUS_IS_OK(status)) { DEBUG(0, ("Unable to unmarshall dcerpc_auth.\n")); goto err_exit; @@ -1524,7 +1525,7 @@ bool api_pipe_alter_context(pipes_struct *p, struct ncacn_packet *pkt) status = dcerpc_pull_dcerpc_auth(pkt, &pkt->u.bind.auth_info, - &auth_info); + &auth_info, p->endian); if (!NT_STATUS_IS_OK(status)) { DEBUG(0, ("Unable to unmarshall dcerpc_auth.\n")); goto err_exit; @@ -1838,3 +1839,467 @@ static bool api_rpcTNP(pipes_struct *p, struct ncacn_packet *pkt, return True; } + +/**************************************************************************** + Initialise an outgoing packet. +****************************************************************************/ + +static bool pipe_init_outgoing_data(pipes_struct *p) +{ + output_data *o_data = &p->out_data; + + /* Reset the offset counters. */ + o_data->data_sent_length = 0; + o_data->current_pdu_sent = 0; + + data_blob_free(&o_data->frag); + + /* Free any memory in the current return data buffer. */ + data_blob_free(&o_data->rdata); + + return True; +} + +/**************************************************************************** + Sets the fault state on incoming packets. +****************************************************************************/ + +void set_incoming_fault(pipes_struct *p) +{ + data_blob_free(&p->in_data.data); + p->in_data.pdu_needed_len = 0; + p->in_data.pdu.length = 0; + p->fault_state = True; + DEBUG(10, ("set_incoming_fault: Setting fault state on pipe %s\n", + get_pipe_name_from_syntax(talloc_tos(), &p->syntax))); +} + +static bool dcesrv_auth_request(pipes_struct *p, struct ncacn_packet *pkt) +{ + NTSTATUS status; + size_t hdr_size = DCERPC_REQUEST_LENGTH; + struct dcerpc_auth auth; + uint32_t auth_length; + DATA_BLOB data; + DATA_BLOB full_pkt; + + DEBUG(10, ("Checking request auth.\n")); + + if (pkt->pfc_flags & DCERPC_PFC_FLAG_OBJECT_UUID) { + hdr_size += 16; + } + + switch (p->auth.auth_level) { + case DCERPC_AUTH_LEVEL_PRIVACY: + DEBUG(10, ("Requested Privacy.\n")); + break; + + case DCERPC_AUTH_LEVEL_INTEGRITY: + DEBUG(10, ("Requested Integrity.\n")); + break; + + case DCERPC_AUTH_LEVEL_CONNECT: + if (pkt->auth_length != 0) { + break; + } + return true; + case DCERPC_AUTH_LEVEL_NONE: + if (pkt->auth_length != 0) { + return false; + } + return true; + + default: + return false; + } + + status = dcerpc_pull_auth_trailer(pkt, pkt, + &pkt->u.request.stub_and_verifier, + &auth, &auth_length, false); + if (!NT_STATUS_IS_OK(status)) { + return false; + } + + pkt->u.request.stub_and_verifier.length -= auth_length; + + data.data = p->in_data.pdu.data + hdr_size; + data.length = pkt->u.request.stub_and_verifier.length; + full_pkt.data = p->in_data.pdu.data; + full_pkt.length = p->in_data.pdu.length - auth.credentials.length; + + switch (p->auth.auth_type) { + case PIPE_AUTH_TYPE_NONE: + return true; + + case PIPE_AUTH_TYPE_SPNEGO_NTLMSSP: + case PIPE_AUTH_TYPE_NTLMSSP: + + DEBUG(10, ("NTLMSSP auth\n")); + + if (!p->auth.a_u.auth_ntlmssp_state) { + DEBUG(0, ("Invalid auth level, " + "failed to process packet auth.\n")); + return false; + } + + switch (p->auth.auth_level) { + case DCERPC_AUTH_LEVEL_PRIVACY: + status = auth_ntlmssp_unseal_packet( + p->auth.a_u.auth_ntlmssp_state, + data.data, data.length, + full_pkt.data, full_pkt.length, + &auth.credentials); + if (!NT_STATUS_IS_OK(status)) { + return false; + } + memcpy(pkt->u.request.stub_and_verifier.data, + data.data, data.length); + break; + + case DCERPC_AUTH_LEVEL_INTEGRITY: + status = auth_ntlmssp_check_packet( + p->auth.a_u.auth_ntlmssp_state, + data.data, data.length, + full_pkt.data, full_pkt.length, + &auth.credentials); + if (!NT_STATUS_IS_OK(status)) { + return false; + } + break; + + default: + DEBUG(0, ("Invalid auth level, " + "failed to process packet auth.\n")); + return false; + } + break; + + case PIPE_AUTH_TYPE_SCHANNEL: + + DEBUG(10, ("SCHANNEL auth\n")); + + switch (p->auth.auth_level) { + case DCERPC_AUTH_LEVEL_PRIVACY: + status = netsec_incoming_packet( + p->auth.a_u.schannel_auth, + pkt, true, + data.data, data.length, + &auth.credentials); + if (!NT_STATUS_IS_OK(status)) { + return false; + } + memcpy(pkt->u.request.stub_and_verifier.data, + data.data, data.length); + break; + + case DCERPC_AUTH_LEVEL_INTEGRITY: + status = netsec_incoming_packet( + p->auth.a_u.schannel_auth, + pkt, false, + data.data, data.length, + &auth.credentials); + if (!NT_STATUS_IS_OK(status)) { + return false; + } + break; + + default: + DEBUG(0, ("Invalid auth level, " + "failed to process packet auth.\n")); + return false; + } + break; + + default: + DEBUG(0, ("process_request_pdu: " + "unknown auth type %u set.\n", + (unsigned int)p->auth.auth_type)); + set_incoming_fault(p); + return false; + } + + /* remove the indicated amount of padding */ + if (pkt->u.request.stub_and_verifier.length < auth.auth_pad_length) { + return false; + } + pkt->u.request.stub_and_verifier.length -= auth.auth_pad_length; + + return true; +} + +/**************************************************************************** + Processes a request pdu. This will do auth processing if needed, and + appends the data into the complete stream if the LAST flag is not set. +****************************************************************************/ + +static bool process_request_pdu(pipes_struct *p, struct ncacn_packet *pkt) +{ + DATA_BLOB data; + + if (!p->pipe_bound) { + DEBUG(0,("process_request_pdu: rpc request with no bind.\n")); + set_incoming_fault(p); + return False; + } + + /* Store the opnum */ + p->opnum = pkt->u.request.opnum; + + if (!dcesrv_auth_request(p, pkt)) { + DEBUG(0,("Failed to check packet auth.\n")); + set_incoming_fault(p); + return false; + } + + data = pkt->u.request.stub_and_verifier; + + /* + * Check the data length doesn't go over the 15Mb limit. + * increased after observing a bug in the Windows NT 4.0 SP6a + * spoolsv.exe when the response to a GETPRINTERDRIVER2 RPC + * will not fit in the initial buffer of size 0x1068 --jerry 22/01/2002 + */ + + if (p->in_data.data.length + data.length > MAX_RPC_DATA_SIZE) { + DEBUG(0, ("process_request_pdu: " + "rpc data buffer too large (%u) + (%u)\n", + (unsigned int)p->in_data.data.length, + (unsigned int)data.length)); + set_incoming_fault(p); + return False; + } + + /* + * Append the data portion into the buffer and return. + */ + + if (data.length) { + if (!data_blob_append(p->mem_ctx, &p->in_data.data, + data.data, data.length)) { + DEBUG(0, ("Unable to append data size %u " + "to parse buffer of size %u.\n", + (unsigned int)data.length, + (unsigned int)p->in_data.data.length)); + set_incoming_fault(p); + return False; + } + } + + if (pkt->pfc_flags & DCERPC_PFC_FLAG_LAST) { + bool ret = False; + /* + * Ok - we finally have a complete RPC stream. + * Call the rpc command to process it. + */ + + /* + * Process the complete data stream here. + */ + if (pipe_init_outgoing_data(p)) { + ret = api_pipe_request(p, pkt); + } + + return ret; + } + + return True; +} + +/**************************************************************************** + Processes a finished PDU stored in p->in_data.pdu. +****************************************************************************/ + +void process_complete_pdu(pipes_struct *p) +{ + struct ncacn_packet *pkt = NULL; + NTSTATUS status; + bool reply = False; + + if(p->fault_state) { + DEBUG(10,("process_complete_pdu: pipe %s in fault state.\n", + get_pipe_name_from_syntax(talloc_tos(), &p->syntax))); + goto done; + } + + pkt = talloc(p->mem_ctx, struct ncacn_packet); + if (!pkt) { + DEBUG(0, ("Out of memory!\n")); + goto done; + } + + /* + * Ensure we're using the corrent endianness for both the + * RPC header flags and the raw data we will be reading from. + */ + if (dcerpc_get_endian_flag(&p->in_data.pdu) & DCERPC_DREP_LE) { + p->endian = RPC_LITTLE_ENDIAN; + } else { + p->endian = RPC_BIG_ENDIAN; + } + DEBUG(10, ("PDU is in %s Endian format!\n", p->endian?"Big":"Little")); + + status = dcerpc_pull_ncacn_packet(pkt, &p->in_data.pdu, + pkt, p->endian); + if (!NT_STATUS_IS_OK(status)) { + DEBUG(0, ("Failed to unmarshal rpc packet: %s!\n", + nt_errstr(status))); + goto done; + } + + /* Store the call_id */ + p->call_id = pkt->call_id; + + DEBUG(10, ("Processing packet type %d\n", (int)pkt->ptype)); + + switch (pkt->ptype) { + case DCERPC_PKT_REQUEST: + reply = process_request_pdu(p, pkt); + break; + + case DCERPC_PKT_PING: /* CL request - ignore... */ + DEBUG(0, ("process_complete_pdu: Error. " + "Connectionless packet type %d received on " + "pipe %s.\n", (int)pkt->ptype, + get_pipe_name_from_syntax(talloc_tos(), + &p->syntax))); + break; + + case DCERPC_PKT_RESPONSE: /* No responses here. */ + DEBUG(0, ("process_complete_pdu: Error. " + "DCERPC_PKT_RESPONSE received from client " + "on pipe %s.\n", + get_pipe_name_from_syntax(talloc_tos(), + &p->syntax))); + break; + + case DCERPC_PKT_FAULT: + case DCERPC_PKT_WORKING: + /* CL request - reply to a ping when a call in process. */ + case DCERPC_PKT_NOCALL: + /* CL - server reply to a ping call. */ + case DCERPC_PKT_REJECT: + case DCERPC_PKT_ACK: + case DCERPC_PKT_CL_CANCEL: + case DCERPC_PKT_FACK: + case DCERPC_PKT_CANCEL_ACK: + DEBUG(0, ("process_complete_pdu: Error. " + "Connectionless packet type %u received on " + "pipe %s.\n", (unsigned int)pkt->ptype, + get_pipe_name_from_syntax(talloc_tos(), + &p->syntax))); + break; + + case DCERPC_PKT_BIND: + /* + * We assume that a pipe bind is only in one pdu. + */ + if (pipe_init_outgoing_data(p)) { + reply = api_pipe_bind_req(p, pkt); + } + break; + + case DCERPC_PKT_BIND_ACK: + case DCERPC_PKT_BIND_NAK: + DEBUG(0, ("process_complete_pdu: Error. " + "DCERPC_PKT_BINDACK/DCERPC_PKT_BINDNACK " + "packet type %u received on pipe %s.\n", + (unsigned int)pkt->ptype, + get_pipe_name_from_syntax(talloc_tos(), + &p->syntax))); + break; + + + case DCERPC_PKT_ALTER: + /* + * We assume that a pipe bind is only in one pdu. + */ + if (pipe_init_outgoing_data(p)) { + reply = api_pipe_alter_context(p, pkt); + } + break; + + case DCERPC_PKT_ALTER_RESP: + DEBUG(0, ("process_complete_pdu: Error. " + "DCERPC_PKT_ALTER_RESP on pipe %s: " + "Should only be server -> client.\n", + get_pipe_name_from_syntax(talloc_tos(), + &p->syntax))); + break; + + case DCERPC_PKT_AUTH3: + /* + * The third packet in an NTLMSSP auth exchange. + */ + if (pipe_init_outgoing_data(p)) { + reply = api_pipe_bind_auth3(p, pkt); + } + break; + + case DCERPC_PKT_SHUTDOWN: + DEBUG(0, ("process_complete_pdu: Error. " + "DCERPC_PKT_SHUTDOWN on pipe %s: " + "Should only be server -> client.\n", + get_pipe_name_from_syntax(talloc_tos(), + &p->syntax))); + break; + + case DCERPC_PKT_CO_CANCEL: + /* For now just free all client data and continue + * processing. */ + DEBUG(3,("process_complete_pdu: DCERPC_PKT_CO_CANCEL." + " Abandoning rpc call.\n")); + /* As we never do asynchronous RPC serving, we can + * never cancel a call (as far as I know). + * If we ever did we'd have to send a cancel_ack reply. + * For now, just free all client data and continue + * processing. */ + reply = True; + break; + +#if 0 + /* Enable this if we're doing async rpc. */ + /* We must check the outstanding callid matches. */ + if (pipe_init_outgoing_data(p)) { + /* Send a cancel_ack PDU reply. */ + /* We should probably check the auth-verifier here. */ + reply = setup_cancel_ack_reply(p, pkt); + } + break; +#endif + + case DCERPC_PKT_ORPHANED: + /* We should probably check the auth-verifier here. + * For now just free all client data and continue + * processing. */ + DEBUG(3, ("process_complete_pdu: DCERPC_PKT_ORPHANED." + " Abandoning rpc call.\n")); + reply = True; + break; + + default: + DEBUG(0, ("process_complete_pdu: " + "Unknown rpc type = %u received.\n", + (unsigned int)pkt->ptype)); + break; + } + +done: + if (!reply) { + DEBUG(3,("process_complete_pdu: DCE/RPC fault sent on " + "pipe %s\n", get_pipe_name_from_syntax(talloc_tos(), + &p->syntax))); + set_incoming_fault(p); + setup_fault_pdu(p, NT_STATUS(DCERPC_FAULT_OP_RNG_ERROR)); + TALLOC_FREE(pkt); + } else { + /* + * Reset the lengths. We're ready for a new pdu. + */ + TALLOC_FREE(p->in_data.pdu.data); + p->in_data.pdu_needed_len = 0; + p->in_data.pdu.length = 0; + } + + TALLOC_FREE(pkt); +} + diff --git a/source3/rpc_server/srv_pipe_hnd.c b/source3/rpc_server/srv_pipe_hnd.c index 3055e1a29c..7c4895fe7c 100644 --- a/source3/rpc_server/srv_pipe_hnd.c +++ b/source3/rpc_server/srv_pipe_hnd.c @@ -23,48 +23,12 @@ #include "../librpc/gen_ndr/srv_spoolss.h" #include "librpc/gen_ndr/ndr_named_pipe_auth.h" #include "../libcli/named_pipe_auth/npa_tstream.h" -#include "../libcli/auth/schannel.h" -#include "../libcli/auth/spnego.h" -#include "../libcli/auth/ntlmssp.h" +#include "rpc_server.h" #undef DBGC_CLASS #define DBGC_CLASS DBGC_RPC_SRV /**************************************************************************** - Initialise an outgoing packet. -****************************************************************************/ - -static bool pipe_init_outgoing_data(pipes_struct *p) -{ - output_data *o_data = &p->out_data; - - /* Reset the offset counters. */ - o_data->data_sent_length = 0; - o_data->current_pdu_sent = 0; - - data_blob_free(&o_data->frag); - - /* Free any memory in the current return data buffer. */ - data_blob_free(&o_data->rdata); - - return True; -} - -/**************************************************************************** - Sets the fault state on incoming packets. -****************************************************************************/ - -static void set_incoming_fault(pipes_struct *p) -{ - data_blob_free(&p->in_data.data); - p->in_data.pdu_needed_len = 0; - p->in_data.pdu.length = 0; - p->fault_state = True; - DEBUG(10, ("set_incoming_fault: Setting fault state on pipe %s\n", - get_pipe_name_from_syntax(talloc_tos(), &p->syntax))); -} - -/**************************************************************************** Ensures we have at least RPC_HEADER_LEN amount of data in the incoming buffer. ****************************************************************************/ @@ -154,433 +118,6 @@ static void free_pipe_context(pipes_struct *p) } /**************************************************************************** - Processes a request pdu. This will do auth processing if needed, and - appends the data into the complete stream if the LAST flag is not set. -****************************************************************************/ - -static bool dcesrv_auth_request(pipes_struct *p, struct ncacn_packet *pkt) -{ - NTSTATUS status; - size_t hdr_size = DCERPC_REQUEST_LENGTH; - struct dcerpc_auth auth; - uint32_t auth_length; - DATA_BLOB data; - DATA_BLOB full_pkt; - - DEBUG(10, ("Checking request auth.\n")); - - if (pkt->pfc_flags & DCERPC_PFC_FLAG_OBJECT_UUID) { - hdr_size += 16; - } - - switch (p->auth.auth_level) { - case DCERPC_AUTH_LEVEL_PRIVACY: - DEBUG(10, ("Requested Privacy.\n")); - break; - - case DCERPC_AUTH_LEVEL_INTEGRITY: - DEBUG(10, ("Requested Integrity.\n")); - break; - - case DCERPC_AUTH_LEVEL_CONNECT: - if (pkt->auth_length != 0) { - break; - } - return true; - case DCERPC_AUTH_LEVEL_NONE: - if (pkt->auth_length != 0) { - return false; - } - return true; - - default: - return false; - } - - status = dcerpc_pull_auth_trailer(pkt, pkt, - &pkt->u.request.stub_and_verifier, - &auth, &auth_length, false); - if (!NT_STATUS_IS_OK(status)) { - return false; - } - - pkt->u.request.stub_and_verifier.length -= auth_length; - - data.data = p->in_data.pdu.data + hdr_size; - data.length = pkt->u.request.stub_and_verifier.length; - full_pkt.data = p->in_data.pdu.data; - full_pkt.length = p->in_data.pdu.length - auth.credentials.length; - - switch (p->auth.auth_type) { - case PIPE_AUTH_TYPE_NONE: - return true; - - case PIPE_AUTH_TYPE_SPNEGO_NTLMSSP: - case PIPE_AUTH_TYPE_NTLMSSP: - - DEBUG(10, ("NTLMSSP auth\n")); - - if (!p->auth.a_u.auth_ntlmssp_state) { - DEBUG(0, ("Invalid auth level, " - "failed to process packet auth.\n")); - return false; - } - - switch (p->auth.auth_level) { - case DCERPC_AUTH_LEVEL_PRIVACY: - status = auth_ntlmssp_unseal_packet( - p->auth.a_u.auth_ntlmssp_state, - data.data, data.length, - full_pkt.data, full_pkt.length, - &auth.credentials); - if (!NT_STATUS_IS_OK(status)) { - return false; - } - memcpy(pkt->u.request.stub_and_verifier.data, - data.data, data.length); - break; - - case DCERPC_AUTH_LEVEL_INTEGRITY: - status = auth_ntlmssp_check_packet( - p->auth.a_u.auth_ntlmssp_state, - data.data, data.length, - full_pkt.data, full_pkt.length, - &auth.credentials); - if (!NT_STATUS_IS_OK(status)) { - return false; - } - break; - - default: - DEBUG(0, ("Invalid auth level, " - "failed to process packet auth.\n")); - return false; - } - break; - - case PIPE_AUTH_TYPE_SCHANNEL: - - DEBUG(10, ("SCHANNEL auth\n")); - - switch (p->auth.auth_level) { - case DCERPC_AUTH_LEVEL_PRIVACY: - status = netsec_incoming_packet( - p->auth.a_u.schannel_auth, - pkt, true, - data.data, data.length, - &auth.credentials); - if (!NT_STATUS_IS_OK(status)) { - return false; - } - memcpy(pkt->u.request.stub_and_verifier.data, - data.data, data.length); - break; - - case DCERPC_AUTH_LEVEL_INTEGRITY: - status = netsec_incoming_packet( - p->auth.a_u.schannel_auth, - pkt, false, - data.data, data.length, - &auth.credentials); - if (!NT_STATUS_IS_OK(status)) { - return false; - } - break; - - default: - DEBUG(0, ("Invalid auth level, " - "failed to process packet auth.\n")); - return false; - } - break; - - default: - DEBUG(0, ("process_request_pdu: " - "unknown auth type %u set.\n", - (unsigned int)p->auth.auth_type)); - set_incoming_fault(p); - return false; - } - - /* remove the indicated amount of padding */ - if (pkt->u.request.stub_and_verifier.length < auth.auth_pad_length) { - return false; - } - pkt->u.request.stub_and_verifier.length -= auth.auth_pad_length; - - return true; -} - -static bool process_request_pdu(pipes_struct *p, struct ncacn_packet *pkt) -{ - DATA_BLOB data; - - if (!p->pipe_bound) { - DEBUG(0,("process_request_pdu: rpc request with no bind.\n")); - set_incoming_fault(p); - return False; - } - - /* Store the opnum */ - p->opnum = pkt->u.request.opnum; - - if (!dcesrv_auth_request(p, pkt)) { - DEBUG(0,("Failed to check packet auth.\n")); - set_incoming_fault(p); - return false; - } - - data = pkt->u.request.stub_and_verifier; - - /* - * Check the data length doesn't go over the 15Mb limit. - * increased after observing a bug in the Windows NT 4.0 SP6a - * spoolsv.exe when the response to a GETPRINTERDRIVER2 RPC - * will not fit in the initial buffer of size 0x1068 --jerry 22/01/2002 - */ - - if (p->in_data.data.length + data.length > MAX_RPC_DATA_SIZE) { - DEBUG(0, ("process_request_pdu: " - "rpc data buffer too large (%u) + (%u)\n", - (unsigned int)p->in_data.data.length, - (unsigned int)data.length)); - set_incoming_fault(p); - return False; - } - - /* - * Append the data portion into the buffer and return. - */ - - if (data.length) { - if (!data_blob_append(p->mem_ctx, &p->in_data.data, - data.data, data.length)) { - DEBUG(0, ("Unable to append data size %u " - "to parse buffer of size %u.\n", - (unsigned int)data.length, - (unsigned int)p->in_data.data.length)); - set_incoming_fault(p); - return False; - } - } - - if (pkt->pfc_flags & DCERPC_PFC_FLAG_LAST) { - bool ret = False; - /* - * Ok - we finally have a complete RPC stream. - * Call the rpc command to process it. - */ - - /* - * Process the complete data stream here. - */ - if (pipe_init_outgoing_data(p)) { - ret = api_pipe_request(p, pkt); - } - - return ret; - } - - return True; -} - -/**************************************************************************** - Processes a finished PDU stored in p->in_data.pdu. -****************************************************************************/ - -static void process_complete_pdu(pipes_struct *p) -{ - struct ncacn_packet *pkt = NULL; - NTSTATUS status; - bool reply = False; - - if(p->fault_state) { - DEBUG(10,("process_complete_pdu: pipe %s in fault state.\n", - get_pipe_name_from_syntax(talloc_tos(), &p->syntax))); - goto done; - } - - pkt = talloc(p->mem_ctx, struct ncacn_packet); - if (!pkt) { - DEBUG(0, ("Out of memory!\n")); - goto done; - } - - status = dcerpc_pull_ncacn_packet(pkt, &p->in_data.pdu, pkt); - if (!NT_STATUS_IS_OK(status)) { - DEBUG(0, ("Failed to unmarshal rpc packet: %s!\n", - nt_errstr(status))); - goto done; - } - - /* Store the call_id */ - p->call_id = pkt->call_id; - - /* - * Ensure we're using the corrent endianness for both the - * RPC header flags and the raw data we will be reading from. - */ - if (pkt->drep[0] == DCERPC_DREP_LE) { - p->endian = RPC_LITTLE_ENDIAN; - } else { - p->endian = RPC_BIG_ENDIAN; - } - - DEBUG(10, ("Processing packet type %d\n", (int)pkt->ptype)); - - switch (pkt->ptype) { - case DCERPC_PKT_REQUEST: - reply = process_request_pdu(p, pkt); - break; - - case DCERPC_PKT_PING: /* CL request - ignore... */ - DEBUG(0, ("process_complete_pdu: Error. " - "Connectionless packet type %d received on " - "pipe %s.\n", (int)pkt->ptype, - get_pipe_name_from_syntax(talloc_tos(), - &p->syntax))); - break; - - case DCERPC_PKT_RESPONSE: /* No responses here. */ - DEBUG(0, ("process_complete_pdu: Error. " - "DCERPC_PKT_RESPONSE received from client " - "on pipe %s.\n", - get_pipe_name_from_syntax(talloc_tos(), - &p->syntax))); - break; - - case DCERPC_PKT_FAULT: - case DCERPC_PKT_WORKING: - /* CL request - reply to a ping when a call in process. */ - case DCERPC_PKT_NOCALL: - /* CL - server reply to a ping call. */ - case DCERPC_PKT_REJECT: - case DCERPC_PKT_ACK: - case DCERPC_PKT_CL_CANCEL: - case DCERPC_PKT_FACK: - case DCERPC_PKT_CANCEL_ACK: - DEBUG(0, ("process_complete_pdu: Error. " - "Connectionless packet type %u received on " - "pipe %s.\n", (unsigned int)pkt->ptype, - get_pipe_name_from_syntax(talloc_tos(), - &p->syntax))); - break; - - case DCERPC_PKT_BIND: - /* - * We assume that a pipe bind is only in one pdu. - */ - if (pipe_init_outgoing_data(p)) { - reply = api_pipe_bind_req(p, pkt); - } - break; - - case DCERPC_PKT_BIND_ACK: - case DCERPC_PKT_BIND_NAK: - DEBUG(0, ("process_complete_pdu: Error. " - "DCERPC_PKT_BINDACK/DCERPC_PKT_BINDNACK " - "packet type %u received on pipe %s.\n", - (unsigned int)pkt->ptype, - get_pipe_name_from_syntax(talloc_tos(), - &p->syntax))); - break; - - - case DCERPC_PKT_ALTER: - /* - * We assume that a pipe bind is only in one pdu. - */ - if (pipe_init_outgoing_data(p)) { - reply = api_pipe_alter_context(p, pkt); - } - break; - - case DCERPC_PKT_ALTER_RESP: - DEBUG(0, ("process_complete_pdu: Error. " - "DCERPC_PKT_ALTER_RESP on pipe %s: " - "Should only be server -> client.\n", - get_pipe_name_from_syntax(talloc_tos(), - &p->syntax))); - break; - - case DCERPC_PKT_AUTH3: - /* - * The third packet in an NTLMSSP auth exchange. - */ - if (pipe_init_outgoing_data(p)) { - reply = api_pipe_bind_auth3(p, pkt); - } - break; - - case DCERPC_PKT_SHUTDOWN: - DEBUG(0, ("process_complete_pdu: Error. " - "DCERPC_PKT_SHUTDOWN on pipe %s: " - "Should only be server -> client.\n", - get_pipe_name_from_syntax(talloc_tos(), - &p->syntax))); - break; - - case DCERPC_PKT_CO_CANCEL: - /* For now just free all client data and continue - * processing. */ - DEBUG(3,("process_complete_pdu: DCERPC_PKT_CO_CANCEL." - " Abandoning rpc call.\n")); - /* As we never do asynchronous RPC serving, we can - * never cancel a call (as far as I know). - * If we ever did we'd have to send a cancel_ack reply. - * For now, just free all client data and continue - * processing. */ - reply = True; - break; - -#if 0 - /* Enable this if we're doing async rpc. */ - /* We must check the outstanding callid matches. */ - if (pipe_init_outgoing_data(p)) { - /* Send a cancel_ack PDU reply. */ - /* We should probably check the auth-verifier here. */ - reply = setup_cancel_ack_reply(p, pkt); - } - break; -#endif - - case DCERPC_PKT_ORPHANED: - /* We should probably check the auth-verifier here. - * For now just free all client data and continue - * processing. */ - DEBUG(3, ("process_complete_pdu: DCERPC_PKT_ORPHANED." - " Abandoning rpc call.\n")); - reply = True; - break; - - default: - DEBUG(0, ("process_complete_pdu: " - "Unknown rpc type = %u received.\n", - (unsigned int)pkt->ptype)); - break; - } - -done: - if (!reply) { - DEBUG(3,("process_complete_pdu: DCE/RPC fault sent on " - "pipe %s\n", get_pipe_name_from_syntax(talloc_tos(), - &p->syntax))); - set_incoming_fault(p); - setup_fault_pdu(p, NT_STATUS(DCERPC_FAULT_OP_RNG_ERROR)); - TALLOC_FREE(pkt); - } else { - /* - * Reset the lengths. We're ready for a new pdu. - */ - TALLOC_FREE(p->in_data.pdu.data); - p->in_data.pdu_needed_len = 0; - p->in_data.pdu.length = 0; - } - - TALLOC_FREE(pkt); -} - -/**************************************************************************** Accepts incoming data on an rpc pipe. Processes the data in pdu sized units. ****************************************************************************/ diff --git a/source3/smbd/aio.c b/source3/smbd/aio.c index a5a0e44738..dbce120dc6 100644 --- a/source3/smbd/aio.c +++ b/source3/smbd/aio.c @@ -67,11 +67,17 @@ static void smbd_aio_signal_handler(struct tevent_context *ev_ctx, } -static void initialize_async_io_handler(void) +static bool initialize_async_io_handler(void) { + static bool tried_signal_setup = false; + if (aio_signal_event) { - return; + return true; + } + if (tried_signal_setup) { + return false; } + tried_signal_setup = true; aio_signal_event = tevent_add_signal(smbd_event_context(), smbd_event_context(), @@ -79,7 +85,8 @@ static void initialize_async_io_handler(void) smbd_aio_signal_handler, NULL); if (!aio_signal_event) { - exit_server("Failed to setup RT_SIGNAL_AIO handler"); + DEBUG(10, ("Failed to setup RT_SIGNAL_AIO handler\n")); + return false; } /* tevent supports 100 signal with SA_SIGINFO */ @@ -145,7 +152,9 @@ NTSTATUS schedule_aio_read_and_X(connection_struct *conn, int ret; /* Ensure aio is initialized. */ - initialize_async_io_handler(); + if (!initialize_async_io_handler()) { + return NT_STATUS_RETRY; + } if (fsp->base_fsp != NULL) { /* No AIO on streams yet */ @@ -250,7 +259,9 @@ NTSTATUS schedule_aio_write_and_X(connection_struct *conn, int ret; /* Ensure aio is initialized. */ - initialize_async_io_handler(); + if (!initialize_async_io_handler()) { + return NT_STATUS_RETRY; + } if (fsp->base_fsp != NULL) { /* No AIO on streams yet */ @@ -382,7 +393,9 @@ NTSTATUS schedule_smb2_aio_read(connection_struct *conn, int ret; /* Ensure aio is initialized. */ - initialize_async_io_handler(); + if (!initialize_async_io_handler()) { + return NT_STATUS_RETRY; + } if (fsp->base_fsp != NULL) { /* No AIO on streams yet */ @@ -478,7 +491,9 @@ NTSTATUS schedule_aio_smb2_write(connection_struct *conn, int ret; /* Ensure aio is initialized. */ - initialize_async_io_handler(); + if (!initialize_async_io_handler()) { + return NT_STATUS_RETRY; + } if (fsp->base_fsp != NULL) { /* No AIO on streams yet */ diff --git a/source3/smbd/sesssetup.c b/source3/smbd/sesssetup.c index 80a5239de3..52fcd282a6 100644 --- a/source3/smbd/sesssetup.c +++ b/source3/smbd/sesssetup.c @@ -41,10 +41,13 @@ struct pending_auth_data { on a logon error possibly map the error to success if "map to guest" is set approriately */ -static NTSTATUS do_map_to_guest(NTSTATUS status, - struct auth_serversupplied_info **server_info, - const char *user, const char *domain) +NTSTATUS do_map_to_guest(NTSTATUS status, + struct auth_serversupplied_info **server_info, + const char *user, const char *domain) { + user = user ? user : ""; + domain = domain ? domain : ""; + if (NT_STATUS_EQUAL(status, NT_STATUS_NO_SUCH_USER)) { if ((lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_USER) || (lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_PASSWORD)) { diff --git a/source3/smbd/smb2_sesssetup.c b/source3/smbd/smb2_sesssetup.c index 6586a45439..493e74802d 100644 --- a/source3/smbd/smb2_sesssetup.c +++ b/source3/smbd/smb2_sesssetup.c @@ -143,6 +143,26 @@ static int smbd_smb2_session_destructor(struct smbd_smb2_session *session) return 0; } +static NTSTATUS setup_ntlmssp_server_info(struct smbd_smb2_session *session, + NTSTATUS status) +{ + if (NT_STATUS_IS_OK(status)) { + status = auth_ntlmssp_server_info(session, + session->auth_ntlmssp_state, + &session->server_info); + } else { + /* Note that this server_info won't have a session + * key. But for map to guest, that's exactly the right + * thing - we can't reasonably guess the key the + * client wants, as the password was wrong */ + status = do_map_to_guest(status, + &session->server_info, + auth_ntlmssp_get_username(session->auth_ntlmssp_state), + auth_ntlmssp_get_domain(session->auth_ntlmssp_state)); + } + return status; +} + #ifdef HAVE_KRB5 static NTSTATUS smbd_smb2_session_setup_krb5(struct smbd_smb2_session *session, struct smbd_smb2_request *smb2req, @@ -615,13 +635,6 @@ static NTSTATUS smbd_smb2_common_ntlmssp_auth_return(struct smbd_smb2_session *s uint64_t *out_session_id) { fstring tmp; - NTSTATUS status = auth_ntlmssp_server_info(session, session->auth_ntlmssp_state, - &session->server_info); - if (!NT_STATUS_IS_OK(status)) { - auth_ntlmssp_end(&session->auth_ntlmssp_state); - TALLOC_FREE(session); - return status; - } if ((in_security_mode & SMB2_NEGOTIATE_SIGNING_REQUIRED) || lp_server_signing() == Required) { @@ -775,6 +788,11 @@ static NTSTATUS smbd_smb2_spnego_auth(struct smbd_smb2_session *session, &auth_out); if (!NT_STATUS_IS_OK(status) && !NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) { + status = setup_ntlmssp_server_info(session, status); + } + + if (!NT_STATUS_IS_OK(status) && + !NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) { auth_ntlmssp_end(&session->auth_ntlmssp_state); data_blob_free(&auth); TALLOC_FREE(session); @@ -850,6 +868,9 @@ static NTSTATUS smbd_smb2_raw_ntlmssp_auth(struct smbd_smb2_session *session, *out_session_id = session->vuid; return status; } + + status = setup_ntlmssp_server_info(session, status); + if (!NT_STATUS_IS_OK(status)) { auth_ntlmssp_end(&session->auth_ntlmssp_state); TALLOC_FREE(session); diff --git a/source3/utils/net_dns.c b/source3/utils/net_dns.c index f4ad6f7b47..61cb89d0f7 100644 --- a/source3/utils/net_dns.c +++ b/source3/utils/net_dns.c @@ -1,4 +1,3 @@ - /* Samba Unix/Linux Dynamic DNS Update net ads commands @@ -10,12 +9,12 @@ it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. - + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>. */ @@ -55,7 +54,7 @@ DNS_ERROR DoDNSUpdate(char *pszServerName, if (!(mem_ctx = talloc_init("DoDNSUpdate"))) { return ERROR_DNS_NO_MEMORY; } - + err = dns_open_connection( pszServerName, DNS_TCP, mem_ctx, &conn ); if (!ERR_DNS_IS_OK(err)) { goto error; @@ -114,10 +113,9 @@ DNS_ERROR DoDNSUpdate(char *pszServerName, keyname, &gss_context, DNS_SRV_WIN2000 ); } - + if (!ERR_DNS_IS_OK(err)) goto error; - err = dns_sign_update(req, gss_context, keyname, "gss.microsoft.com", time(NULL), 3600); diff --git a/source3/winbindd/winbindd_dual.c b/source3/winbindd/winbindd_dual.c index ed8eb1339f..47348b997f 100644 --- a/source3/winbindd/winbindd_dual.c +++ b/source3/winbindd/winbindd_dual.c @@ -1129,9 +1129,11 @@ bool winbindd_reinit_after_fork(const char *logfilename) struct winbindd_child *cl; NTSTATUS status; - status = reinit_after_fork(winbind_messaging_context(), - winbind_event_context(), - procid_self(), true); + status = reinit_after_fork( + winbind_messaging_context(), + winbind_event_context(), + messaging_server_id(winbind_messaging_context()), + true); if (!NT_STATUS_IS_OK(status)) { DEBUG(0,("reinit_after_fork() failed\n")); return false; diff --git a/source3/wscript_build b/source3/wscript_build index 38d680518f..f5265011f7 100644 --- a/source3/wscript_build +++ b/source3/wscript_build @@ -68,6 +68,9 @@ LIBNDR_SCHANNEL_SRC = '''../librpc/gen_ndr/ndr_schannel.c LIBNDR_SPOOLSS_SRC = '''../librpc/gen_ndr/ndr_spoolss.c ../librpc/ndr/ndr_spoolss_buf.c''' +LIBNDR_XATTR_SRC = '''../librpc/gen_ndr/ndr_xattr.c + ../librpc/ndr/ndr_xattr.c''' + LIBNDR_GEN_SRC = '''../librpc/gen_ndr/ndr_wkssvc.c ${LIBNDR_GEN_SRC0} ../librpc/gen_ndr/ndr_dfs.c @@ -79,8 +82,7 @@ LIBNDR_GEN_SRC = '''../librpc/gen_ndr/ndr_wkssvc.c ${LIBNDR_NETLOGON_SRC} ../librpc/gen_ndr/ndr_dssetup.c librpc/gen_ndr/ndr_notify.c - ../librpc/gen_ndr/ndr_xattr.c - ../librpc/ndr/ndr_xattr.c + ${LIBNDR_XATTR_SRC} ../librpc/gen_ndr/ndr_epmapper.c ../librpc/gen_ndr/ndr_named_pipe_auth.c ../librpc/gen_ndr/ndr_ntsvcs.c @@ -413,8 +415,10 @@ RPC_SERVER_SRC = '''${RPC_PIPE_SRC} ${NPA_TSTREAM_SRC}''' RPC_PARSE_SRC = '''${RPC_PARSE_SRC2}''' -RPC_CLIENT_SRC = '''rpc_client/cli_pipe.c rpc_client/rpc_transport_np.c - rpc_client/rpc_transport_sock.c rpc_client/rpc_transport_smbd.c''' +RPC_CLIENT_SRC = '''rpc_client/cli_pipe.c librpc/rpc/rpc_common.c + rpc_client/rpc_transport_np.c + rpc_client/rpc_transport_sock.c + rpc_client/rpc_transport_smbd.c''' LOCKING_SRC = '''locking/locking.c locking/brlock.c locking/posix.c''' diff --git a/source4/scripting/bin/ktpass.sh b/source4/scripting/bin/ktpass.sh new file mode 100755 index 0000000000..92b1976932 --- /dev/null +++ b/source4/scripting/bin/ktpass.sh @@ -0,0 +1,93 @@ +#!/usr/bin/env bash +# vim: expandtab +# +# Copyright (C) Matthieu Patou <mat@matws.net> 2010 +# +# +# +# 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/>. + +name="ktpass.sh" +TEMP=`getopt -o h --long princ:,pass:,out:,host:,ptype:,enc:,path-to-ldbsearch: \ + -n "$name" -- "$@"` +eval set -- "$TEMP" + +function usage { + echo -ne "$name --out <keytabfile> --princ <principal> --pass <password>|*\n" + echo -ne " [--host hostname] [--enc <encryption>]\n" + echo -ne " [--ptype <type>] [--path-to-ldbsearch <path>]\n" + echo -ne "\nEncoding should be one of:\n" + echo -ne " * des-cbc-crc\n" + echo -ne " * des-cbc-md5\n" + echo -ne " * rc4-hmac (default)\n" + echo -ne " * aes128-cts\n" + echo -ne " * aes256-cts\n" + exit 0 +} +while true ; do + case "$1" in + --out) outfile=$2 ; shift 2 ;; + --princ) princ=$2 ; shift 2 ;; + --pass) pass=$2 ; shift 2 ;; + --host) host=$2 ; shift 2 ;; + --ptype) shift 2 ;; + --enc) enc=$2; shift 2;; + --path-to-ldbsearch) path="$2/"; shift 2;; + -h) usage;; + --) shift ; break ;; + *) echo "Internal error!" ; exit 1 ;; + esac +done +#RC4-HMAC-NT|AES256-SHA1|AES128-SHA +if [ -z "$enc" ]; then + enc="rc4-hmac" +fi +if [ -z "$path" ]; then + path=`dirname $0`/../bin/ +fi +if [ -z "$outfile" -o -z "$princ" -o -z "$pass" ]; then + echo "At least one mandatory parameter (--out, --princ, --pass) was not specified" + usage +fi +if [ -z $host ]; then + host=`hostname` +fi +kvno=`${path}ldbsearch -H ldap://$host "(|(samaccountname=$princ)(serviceprincipalname=$princ))" msds-keyversionnumber -k 1 -N 2>/dev/null| grep -i msds-keyversionnumber` +if [ "$kvno" == "" ]; then + echo -ne "Unable to find kvno for principal $princ\n" + echo -ne " check that you are authentified with kerberos\n" + exit 1 +else + kvno=`echo $kvno | sed 's/^.*: //'` +fi + +if [ "$pass" == "*" ]; then + echo -n "Enter password for $princ: " + stty -echo + read pass + stty echo + echo "" +fi + +ktutil >/dev/null <<EOF +add_entry -password -p $princ -k $kvno -e $enc +$pass +wkt $outfile +EOF + +if [ $? -eq 0 ]; then + echo "Keytab file $outfile created with success" +else + echo "Error while creating the keytab file $outfile" +fi diff --git a/source4/selftest/tests.sh b/source4/selftest/tests.sh index 52d1d3963e..1dd507eaed 100755 --- a/source4/selftest/tests.sh +++ b/source4/selftest/tests.sh @@ -368,6 +368,7 @@ plantestsuite "blackbox.pkinit" dc:local $bbdir/test_pkinit.sh "\$SERVER" "\$USE plantestsuite "blackbox.kinit" dc:local $bbdir/test_kinit.sh "\$SERVER" "\$USERNAME" "\$PASSWORD" "\$REALM" "\$DOMAIN" "$PREFIX" aes256-cts-hmac-sha1-96 $CONFIGURATION plantestsuite "blackbox.kinit" fl2000dc:local $bbdir/test_kinit.sh "\$SERVER" "\$USERNAME" "\$PASSWORD" "\$REALM" "\$DOMAIN" "$PREFIX" arcfour-hmac-md5 $CONFIGURATION plantestsuite "blackbox.kinit" fl2008r2dc:local $bbdir/test_kinit.sh "\$SERVER" "\$USERNAME" "\$PASSWORD" "\$REALM" "\$DOMAIN" "$PREFIX" aes256-cts-hmac-sha1-96 $CONFIGURATION +plantestsuite "blackbox.ktpass" dc $bbdir/test_ktpass.sh $PREFIX plantestsuite "blackbox.passwords" dc:local $bbdir/test_passwords.sh "\$SERVER" "\$USERNAME" "\$PASSWORD" "\$REALM" "\$DOMAIN" "$PREFIX" plantestsuite "blackbox.export.keytab" dc:local $bbdir/test_export_keytab.sh "\$SERVER" "\$USERNAME" "\$REALM" "\$DOMAIN" "$PREFIX" plantestsuite "blackbox.cifsdd" dc $samba4srcdir/client/tests/test_cifsdd.sh "\$SERVER" "\$USERNAME" "\$PASSWORD" "\$DOMAIN" diff --git a/source4/torture/rpc/bind.c b/source4/torture/rpc/bind.c index b36e54cac0..f6470595e3 100644 --- a/source4/torture/rpc/bind.c +++ b/source4/torture/rpc/bind.c @@ -52,6 +52,7 @@ static bool test_bind(struct torture_context *tctx, torture_rpc_binding(tctx, &binding), "failed to parse binding string"); + binding->flags &= ~DCERPC_AUTH_OPTIONS; binding->flags |= *flags; torture_assert_ntstatus_ok(tctx, @@ -86,11 +87,32 @@ static void test_bind_op(struct torture_suite *suite, struct torture_suite *torture_rpc_bind(TALLOC_CTX *mem_ctx) { struct torture_suite *suite = torture_suite_create(mem_ctx, "BIND"); - - test_bind_op(suite, "ntlm,sign", DCERPC_AUTH_NTLM | DCERPC_SIGN); - test_bind_op(suite, "ntlm,sign,seal", DCERPC_AUTH_NTLM | DCERPC_SIGN | DCERPC_SEAL); - test_bind_op(suite, "spnego,sign", DCERPC_AUTH_SPNEGO | DCERPC_SIGN); - test_bind_op(suite, "spnego,sign,seal", DCERPC_AUTH_SPNEGO | DCERPC_SIGN | DCERPC_SEAL); + struct { + const char *test_name; + uint32_t flags; + } tests[] = { + { + .test_name = "ntlm,sign", + .flags = DCERPC_AUTH_NTLM | DCERPC_SIGN + },{ + .test_name = "ntlm,sign,seal", + .flags = DCERPC_AUTH_NTLM | DCERPC_SIGN | DCERPC_SEAL + },{ + .test_name = "spnego,sign", + .flags = DCERPC_AUTH_SPNEGO | DCERPC_SIGN + },{ + .test_name = "spnego,sign,seal", + .flags = DCERPC_AUTH_SPNEGO | DCERPC_SIGN | DCERPC_SEAL + } + }; + int i; + + for (i=0; i < ARRAY_SIZE(tests); i++) { + test_bind_op(suite, tests[i].test_name, tests[i].flags); + } + for (i=0; i < ARRAY_SIZE(tests); i++) { + test_bind_op(suite, talloc_asprintf(suite, "bigendian,%s", tests[i].test_name), tests[i].flags | DCERPC_PUSH_BIGENDIAN); + } return suite; } diff --git a/source4/torture/shell.c b/source4/torture/shell.c index 7c313af178..03c670a902 100644 --- a/source4/torture/shell.c +++ b/source4/torture/shell.c @@ -175,8 +175,6 @@ static void shell_help(const struct shell_command * command, static void shell_set(const struct shell_command *command, struct torture_context *tctx, int argc, const char **argv) { - char * name; - switch (argc) { case 0: lpcfg_dump(tctx->lp_ctx, stdout, @@ -185,9 +183,12 @@ static void shell_set(const struct shell_command *command, break; case 2: - name = talloc_asprintf(NULL, "torture:%s", argv[0]); - lpcfg_set_cmdline(tctx->lp_ctx, name, argv[1]); - talloc_free(name); + /* We want to allow users to set any config option. Top level + * options will get checked against their static definition, but + * parametric options can't be checked and will just get stashed + * as they are provided. + */ + lpcfg_set_cmdline(tctx->lp_ctx, argv[0], argv[1]); break; default: diff --git a/source4/wscript_build b/source4/wscript_build index 6c1eac6905..090c914ae7 100644 --- a/source4/wscript_build +++ b/source4/wscript_build @@ -56,6 +56,7 @@ bld.RECURSE('cluster') bld.RECURSE('smbd') bld.RECURSE('libnet') bld.RECURSE('auth') +bld.RECURSE('../lib/iniparser/src') bld.RECURSE('../nsswitch') bld.RECURSE('../nsswitch/libwbclient') bld.RECURSE('lib/samba3') diff --git a/testprogs/blackbox/test_ktpass.sh b/testprogs/blackbox/test_ktpass.sh new file mode 100755 index 0000000000..b106d50240 --- /dev/null +++ b/testprogs/blackbox/test_ktpass.sh @@ -0,0 +1,37 @@ +#!/bin/sh + +if [ $# -lt 1 ]; then +cat <<EOF +Usage: blackbox_newuser.sh PREFIX +EOF +exit 1; +fi + +PREFIX="$1" +shift 1 + +. `dirname $0`/subunit.sh + + +net="$BUILDDIR/bin/net" +samba4bindir="$BUILDDIR/bin" +samba4kinit="$samba4bindir/samba4kinit$EXEEXT" +CONFIG="--configfile=$PREFIX/dc/etc/smb.conf" + +#two test for creating new user +#newuser account is created with cn=Given Name Initials. Surname +#newuser1 account is created using cn=username +testit "newuser" $net newuser $CONFIG --given-name="User" --surname="Tester" --initials="T" --profile-path="\\\\myserver\\my\\profile" --script-path="\\\\myserver\\my\\script" --home-directory="\\\\myserver\\my\\homedir" --job-title="Tester" --department="Testing" --company="Samba.org" --description="Description" --mail-address="tester@samba.org" --internet-address="http://samba.org" --telephone-number="001122334455" --physical-delivery-office="101" --home-drive="H:" testuser testp@ssw0Rd|| failed=`expr $failed + 1` + +KRB5CCNAME="$PREFIX/tmpccache" +export KRB5CCNAME +echo "testp@ssw0Rd" >$PREFIX/tmppassfile +testit "kinit with passwd" $samba4kinit -e arcfour-hmac-md5 --password-file=$PREFIX/tmppassfile testuser@SAMBA.EXAMPLE.COM || failed=`expr $failed + 1` +testit "ktpass" $BUILDDIR/scripting/bin/ktpass.sh --host LOCALDC --out $PREFIX/testuser.kt --princ testuser --pass "testp@ssw0Rd" --path-to-ldbsearch=$BUILDDIR/bin|| failed=`expr $failed + 1` + +rm -f $KRB5CCNAME + +testit "kinit with keytab" $samba4kinit -e arcfour-hmac-md5 --use-keytab -t $PREFIX/testuser.kt testuser@SAMBA.EXAMPLE.COM || failed=`expr $failed + 1` + +rm -f $PREFIX/tmpccache $PREFIX/testuser.kt +exit $failed |