From 0ed16e94c374efb06650f741827bcbed85f1af59 Mon Sep 17 00:00:00 2001 From: Günther Deschner Date: Tue, 17 Aug 2010 00:46:25 +0200 Subject: s3: separate out cli schannel functions that depend on cli_netlogon. Guenther --- source3/Makefile.in | 14 +- source3/rpc_client/cli_pipe.c | 200 ----------------------------- source3/rpc_client/cli_pipe_schannel.c | 228 +++++++++++++++++++++++++++++++++ source3/wscript_build | 3 + 4 files changed, 241 insertions(+), 204 deletions(-) create mode 100644 source3/rpc_client/cli_pipe_schannel.c diff --git a/source3/Makefile.in b/source3/Makefile.in index 82f0541bfc..eabf35105f 100644 --- a/source3/Makefile.in +++ b/source3/Makefile.in @@ -717,7 +717,8 @@ RPC_SERVER_OBJ = @RPC_STATIC@ $(RPC_PIPE_OBJ) $(NPA_TSTREAM_OBJ) \ $(LIBCLI_WINREG_OBJ) \ $(LIBCLI_SRVSVC_OBJ) \ $(LIBCLI_LSA_OBJ) \ - $(LIBCLI_SAMR_OBJ) + $(LIBCLI_SAMR_OBJ) \ + $(RPC_CLIENT_SCHANNEL_OBJ) RPC_CLIENT_OBJ = rpc_client/cli_pipe.o \ librpc/rpc/dcerpc_gssapi.o \ @@ -726,6 +727,8 @@ RPC_CLIENT_OBJ = rpc_client/cli_pipe.o \ rpc_client/rpc_transport_np.o \ rpc_client/rpc_transport_sock.o +RPC_CLIENT_SCHANNEL_OBJ = rpc_client/cli_pipe_schannel.o + LOCKING_OBJ = locking/locking.o locking/brlock.o locking/posix.o PRIVILEGES_BASIC_OBJ = lib/privileges_basic.o @@ -1017,7 +1020,8 @@ RPCCLIENT_OBJ = $(RPCCLIENT_OBJ1) \ $(LIBCLI_WKSSVC_OBJ) \ $(LIBCLI_SRVSVC_OBJ) \ $(LIBCLI_LSA_OBJ) \ - $(LIBCLI_SAMR_OBJ) + $(LIBCLI_SAMR_OBJ) \ + $(RPC_CLIENT_SCHANNEL_OBJ) PAM_WINBIND_OBJ = ../nsswitch/pam_winbind.o $(WBCOMMON_OBJ) \ $(LIBREPLACE_OBJ) @BUILD_INIPARSER@ @@ -1129,7 +1133,8 @@ NET_OBJ1 = utils/net.o utils/net_ads.o utils/net_help.o \ $(LIBCLI_WKSSVC_OBJ) \ $(LIBCLI_SRVSVC_OBJ) \ $(LIBCLI_LSA_OBJ) \ - $(LIBCLI_SAMR_OBJ) + $(LIBCLI_SAMR_OBJ) \ + $(RPC_CLIENT_SCHANNEL_OBJ) # these are not processed by make proto NET_OBJ2 = utils/net_registry_util.o utils/net_help_common.o @@ -2298,7 +2303,8 @@ LIBNETAPI_OBJ = $(LIBNETAPI_OBJ0) $(LIBNET_OBJ) \ $(LIBCLI_WKSSVC_OBJ) \ $(LIBCLI_SRVSVC_OBJ) \ $(LIBCLI_LSA_OBJ) \ - $(LIBCLI_SAMR_OBJ) + $(LIBCLI_SAMR_OBJ) \ + $(RPC_CLIENT_SCHANNEL_OBJ) LIBNETAPI_SHARED_TARGET=@LIBNETAPI_SHARED_TARGET@ LIBNETAPI_SOVER=@LIBNETAPI_SOVER@ diff --git a/source3/rpc_client/cli_pipe.c b/source3/rpc_client/cli_pipe.c index d57bc0af60..16bd649b46 100644 --- a/source3/rpc_client/cli_pipe.c +++ b/source3/rpc_client/cli_pipe.c @@ -22,13 +22,11 @@ #include "librpc/gen_ndr/cli_epmapper.h" #include "../librpc/gen_ndr/ndr_schannel.h" #include "../librpc/gen_ndr/ndr_dssetup.h" -#include "../librpc/gen_ndr/ndr_netlogon.h" #include "../libcli/auth/schannel.h" #include "../libcli/auth/spnego.h" #include "smb_krb5.h" #include "../libcli/auth/ntlmssp.h" #include "ntlmssp_wrap.h" -#include "rpc_client/cli_netlogon.h" #include "librpc/gen_ndr/ndr_dcerpc.h" #include "librpc/rpc/dcerpc.h" #include "librpc/rpc/dcerpc_gssapi.h" @@ -2922,87 +2920,6 @@ NTSTATUS cli_rpc_pipe_open_ntlmssp(struct cli_state *cli, return status; } -/**************************************************************************** - Get a the schannel session key out of an already opened netlogon pipe. - ****************************************************************************/ -static NTSTATUS get_schannel_session_key_common(struct rpc_pipe_client *netlogon_pipe, - struct cli_state *cli, - const char *domain, - uint32 *pneg_flags) -{ - enum netr_SchannelType sec_chan_type = 0; - unsigned char machine_pwd[16]; - const char *machine_account; - NTSTATUS status; - - /* Get the machine account credentials from secrets.tdb. */ - if (!get_trust_pw_hash(domain, machine_pwd, &machine_account, - &sec_chan_type)) - { - DEBUG(0, ("get_schannel_session_key: could not fetch " - "trust account password for domain '%s'\n", - domain)); - return NT_STATUS_CANT_ACCESS_DOMAIN_INFO; - } - - status = rpccli_netlogon_setup_creds(netlogon_pipe, - cli->desthost, /* server name */ - domain, /* domain */ - global_myname(), /* client name */ - machine_account, /* machine account name */ - machine_pwd, - sec_chan_type, - pneg_flags); - - if (!NT_STATUS_IS_OK(status)) { - DEBUG(3, ("get_schannel_session_key_common: " - "rpccli_netlogon_setup_creds failed with result %s " - "to server %s, domain %s, machine account %s.\n", - nt_errstr(status), cli->desthost, domain, - machine_account )); - return status; - } - - if (((*pneg_flags) & NETLOGON_NEG_SCHANNEL) == 0) { - DEBUG(3, ("get_schannel_session_key: Server %s did not offer schannel\n", - cli->desthost)); - return NT_STATUS_INVALID_NETWORK_RESPONSE; - } - - return NT_STATUS_OK;; -} - -/**************************************************************************** - Open a netlogon pipe and get the schannel session key. - Now exposed to external callers. - ****************************************************************************/ - - -NTSTATUS get_schannel_session_key(struct cli_state *cli, - const char *domain, - uint32 *pneg_flags, - struct rpc_pipe_client **presult) -{ - struct rpc_pipe_client *netlogon_pipe = NULL; - NTSTATUS status; - - status = cli_rpc_pipe_open_noauth(cli, &ndr_table_netlogon.syntax_id, - &netlogon_pipe); - if (!NT_STATUS_IS_OK(status)) { - return status; - } - - status = get_schannel_session_key_common(netlogon_pipe, cli, domain, - pneg_flags); - if (!NT_STATUS_IS_OK(status)) { - TALLOC_FREE(netlogon_pipe); - return status; - } - - *presult = netlogon_pipe; - return NT_STATUS_OK; -} - /**************************************************************************** External interface. Open a named pipe to an SMB server and bind using schannel (bind type 68) @@ -3065,123 +2982,6 @@ NTSTATUS cli_rpc_pipe_open_schannel_with_key(struct cli_state *cli, return NT_STATUS_OK; } -/**************************************************************************** - Open a named pipe to an SMB server and bind using schannel (bind type 68). - Fetch the session key ourselves using a temporary netlogon pipe. This - version uses an ntlmssp auth bound netlogon pipe to get the key. - ****************************************************************************/ - -static NTSTATUS get_schannel_session_key_auth_ntlmssp(struct cli_state *cli, - const char *domain, - const char *username, - const char *password, - uint32 *pneg_flags, - struct rpc_pipe_client **presult) -{ - struct rpc_pipe_client *netlogon_pipe = NULL; - NTSTATUS status; - - status = cli_rpc_pipe_open_spnego_ntlmssp( - cli, &ndr_table_netlogon.syntax_id, NCACN_NP, - DCERPC_AUTH_LEVEL_PRIVACY, - domain, username, password, &netlogon_pipe); - if (!NT_STATUS_IS_OK(status)) { - return status; - } - - status = get_schannel_session_key_common(netlogon_pipe, cli, domain, - pneg_flags); - if (!NT_STATUS_IS_OK(status)) { - TALLOC_FREE(netlogon_pipe); - return status; - } - - *presult = netlogon_pipe; - return NT_STATUS_OK; -} - -/**************************************************************************** - Open a named pipe to an SMB server and bind using schannel (bind type 68). - Fetch the session key ourselves using a temporary netlogon pipe. This version - uses an ntlmssp bind to get the session key. - ****************************************************************************/ - -NTSTATUS cli_rpc_pipe_open_ntlmssp_auth_schannel(struct cli_state *cli, - const struct ndr_syntax_id *interface, - enum dcerpc_transport_t transport, - enum dcerpc_AuthLevel auth_level, - const char *domain, - const char *username, - const char *password, - struct rpc_pipe_client **presult) -{ - uint32_t neg_flags = NETLOGON_NEG_AUTH2_ADS_FLAGS; - struct rpc_pipe_client *netlogon_pipe = NULL; - struct rpc_pipe_client *result = NULL; - NTSTATUS status; - - status = get_schannel_session_key_auth_ntlmssp( - cli, domain, username, password, &neg_flags, &netlogon_pipe); - if (!NT_STATUS_IS_OK(status)) { - DEBUG(0,("cli_rpc_pipe_open_ntlmssp_auth_schannel: failed to get schannel session " - "key from server %s for domain %s.\n", - cli->desthost, domain )); - return status; - } - - status = cli_rpc_pipe_open_schannel_with_key( - cli, interface, transport, auth_level, domain, &netlogon_pipe->dc, - &result); - - /* Now we've bound using the session key we can close the netlog pipe. */ - TALLOC_FREE(netlogon_pipe); - - if (NT_STATUS_IS_OK(status)) { - *presult = result; - } - return status; -} - -/**************************************************************************** - Open a named pipe to an SMB server and bind using schannel (bind type 68). - Fetch the session key ourselves using a temporary netlogon pipe. - ****************************************************************************/ - -NTSTATUS cli_rpc_pipe_open_schannel(struct cli_state *cli, - const struct ndr_syntax_id *interface, - enum dcerpc_transport_t transport, - enum dcerpc_AuthLevel auth_level, - const char *domain, - struct rpc_pipe_client **presult) -{ - uint32_t neg_flags = NETLOGON_NEG_AUTH2_ADS_FLAGS; - struct rpc_pipe_client *netlogon_pipe = NULL; - struct rpc_pipe_client *result = NULL; - NTSTATUS status; - - status = get_schannel_session_key(cli, domain, &neg_flags, - &netlogon_pipe); - if (!NT_STATUS_IS_OK(status)) { - DEBUG(0,("cli_rpc_pipe_open_schannel: failed to get schannel session " - "key from server %s for domain %s.\n", - cli->desthost, domain )); - return status; - } - - status = cli_rpc_pipe_open_schannel_with_key( - cli, interface, transport, auth_level, domain, &netlogon_pipe->dc, - &result); - - /* Now we've bound using the session key we can close the netlog pipe. */ - TALLOC_FREE(netlogon_pipe); - - if (NT_STATUS_IS_OK(status)) { - *presult = result; - } - - return status; -} - /**************************************************************************** Open a named pipe to an SMB server and bind using krb5 (bind type 16). The idea is this can be called with service_princ, username and password all diff --git a/source3/rpc_client/cli_pipe_schannel.c b/source3/rpc_client/cli_pipe_schannel.c new file mode 100644 index 0000000000..7bc8d80ec9 --- /dev/null +++ b/source3/rpc_client/cli_pipe_schannel.c @@ -0,0 +1,228 @@ +/* + * 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 . + */ + +#include "includes.h" +#include "../librpc/gen_ndr/ndr_schannel.h" +#include "../librpc/gen_ndr/ndr_netlogon.h" +#include "../libcli/auth/schannel.h" +#include "rpc_client/cli_netlogon.h" +#include "librpc/gen_ndr/ndr_dcerpc.h" +#include "librpc/rpc/dcerpc.h" + +#undef DBGC_CLASS +#define DBGC_CLASS DBGC_RPC_CLI + + +/**************************************************************************** + Get a the schannel session key out of an already opened netlogon pipe. + ****************************************************************************/ +static NTSTATUS get_schannel_session_key_common(struct rpc_pipe_client *netlogon_pipe, + struct cli_state *cli, + const char *domain, + uint32 *pneg_flags) +{ + enum netr_SchannelType sec_chan_type = 0; + unsigned char machine_pwd[16]; + const char *machine_account; + NTSTATUS status; + + /* Get the machine account credentials from secrets.tdb. */ + if (!get_trust_pw_hash(domain, machine_pwd, &machine_account, + &sec_chan_type)) + { + DEBUG(0, ("get_schannel_session_key: could not fetch " + "trust account password for domain '%s'\n", + domain)); + return NT_STATUS_CANT_ACCESS_DOMAIN_INFO; + } + + status = rpccli_netlogon_setup_creds(netlogon_pipe, + cli->desthost, /* server name */ + domain, /* domain */ + global_myname(), /* client name */ + machine_account, /* machine account name */ + machine_pwd, + sec_chan_type, + pneg_flags); + + if (!NT_STATUS_IS_OK(status)) { + DEBUG(3, ("get_schannel_session_key_common: " + "rpccli_netlogon_setup_creds failed with result %s " + "to server %s, domain %s, machine account %s.\n", + nt_errstr(status), cli->desthost, domain, + machine_account )); + return status; + } + + if (((*pneg_flags) & NETLOGON_NEG_SCHANNEL) == 0) { + DEBUG(3, ("get_schannel_session_key: Server %s did not offer schannel\n", + cli->desthost)); + return NT_STATUS_INVALID_NETWORK_RESPONSE; + } + + return NT_STATUS_OK;; +} + +/**************************************************************************** + Open a named pipe to an SMB server and bind using schannel (bind type 68). + Fetch the session key ourselves using a temporary netlogon pipe. This + version uses an ntlmssp auth bound netlogon pipe to get the key. + ****************************************************************************/ + +static NTSTATUS get_schannel_session_key_auth_ntlmssp(struct cli_state *cli, + const char *domain, + const char *username, + const char *password, + uint32 *pneg_flags, + struct rpc_pipe_client **presult) +{ + struct rpc_pipe_client *netlogon_pipe = NULL; + NTSTATUS status; + + status = cli_rpc_pipe_open_spnego_ntlmssp( + cli, &ndr_table_netlogon.syntax_id, NCACN_NP, + DCERPC_AUTH_LEVEL_PRIVACY, + domain, username, password, &netlogon_pipe); + if (!NT_STATUS_IS_OK(status)) { + return status; + } + + status = get_schannel_session_key_common(netlogon_pipe, cli, domain, + pneg_flags); + if (!NT_STATUS_IS_OK(status)) { + TALLOC_FREE(netlogon_pipe); + return status; + } + + *presult = netlogon_pipe; + return NT_STATUS_OK; +} + +/**************************************************************************** + Open a named pipe to an SMB server and bind using schannel (bind type 68). + Fetch the session key ourselves using a temporary netlogon pipe. This version + uses an ntlmssp bind to get the session key. + ****************************************************************************/ + +NTSTATUS cli_rpc_pipe_open_ntlmssp_auth_schannel(struct cli_state *cli, + const struct ndr_syntax_id *interface, + enum dcerpc_transport_t transport, + enum dcerpc_AuthLevel auth_level, + const char *domain, + const char *username, + const char *password, + struct rpc_pipe_client **presult) +{ + uint32_t neg_flags = NETLOGON_NEG_AUTH2_ADS_FLAGS; + struct rpc_pipe_client *netlogon_pipe = NULL; + struct rpc_pipe_client *result = NULL; + NTSTATUS status; + + status = get_schannel_session_key_auth_ntlmssp( + cli, domain, username, password, &neg_flags, &netlogon_pipe); + if (!NT_STATUS_IS_OK(status)) { + DEBUG(0,("cli_rpc_pipe_open_ntlmssp_auth_schannel: failed to get schannel session " + "key from server %s for domain %s.\n", + cli->desthost, domain )); + return status; + } + + status = cli_rpc_pipe_open_schannel_with_key( + cli, interface, transport, auth_level, domain, &netlogon_pipe->dc, + &result); + + /* Now we've bound using the session key we can close the netlog pipe. */ + TALLOC_FREE(netlogon_pipe); + + if (NT_STATUS_IS_OK(status)) { + *presult = result; + } + return status; +} + +/**************************************************************************** + Open a named pipe to an SMB server and bind using schannel (bind type 68). + Fetch the session key ourselves using a temporary netlogon pipe. + ****************************************************************************/ + +NTSTATUS cli_rpc_pipe_open_schannel(struct cli_state *cli, + const struct ndr_syntax_id *interface, + enum dcerpc_transport_t transport, + enum dcerpc_AuthLevel auth_level, + const char *domain, + struct rpc_pipe_client **presult) +{ + uint32_t neg_flags = NETLOGON_NEG_AUTH2_ADS_FLAGS; + struct rpc_pipe_client *netlogon_pipe = NULL; + struct rpc_pipe_client *result = NULL; + NTSTATUS status; + + status = get_schannel_session_key(cli, domain, &neg_flags, + &netlogon_pipe); + if (!NT_STATUS_IS_OK(status)) { + DEBUG(0,("cli_rpc_pipe_open_schannel: failed to get schannel session " + "key from server %s for domain %s.\n", + cli->desthost, domain )); + return status; + } + + status = cli_rpc_pipe_open_schannel_with_key( + cli, interface, transport, auth_level, domain, &netlogon_pipe->dc, + &result); + + /* Now we've bound using the session key we can close the netlog pipe. */ + TALLOC_FREE(netlogon_pipe); + + if (NT_STATUS_IS_OK(status)) { + *presult = result; + } + + return status; +} + +/**************************************************************************** + Open a netlogon pipe and get the schannel session key. + Now exposed to external callers. + ****************************************************************************/ + + +NTSTATUS get_schannel_session_key(struct cli_state *cli, + const char *domain, + uint32 *pneg_flags, + struct rpc_pipe_client **presult) +{ + struct rpc_pipe_client *netlogon_pipe = NULL; + NTSTATUS status; + + status = cli_rpc_pipe_open_noauth(cli, &ndr_table_netlogon.syntax_id, + &netlogon_pipe); + if (!NT_STATUS_IS_OK(status)) { + return status; + } + + status = get_schannel_session_key_common(netlogon_pipe, cli, domain, + pneg_flags); + if (!NT_STATUS_IS_OK(status)) { + TALLOC_FREE(netlogon_pipe); + return status; + } + + *presult = netlogon_pipe; + return NT_STATUS_OK; +} diff --git a/source3/wscript_build b/source3/wscript_build index 0c7f5aa86b..ed47f3642e 100644 --- a/source3/wscript_build +++ b/source3/wscript_build @@ -477,6 +477,8 @@ RPC_CLIENT_SRC = '''rpc_client/cli_pipe.c rpc_client/rpc_transport_np.c rpc_client/rpc_transport_sock.c''' +RPC_CLIENT_SCHANNEL_SRC = '''rpc_client/cli_pipe_schannel.c''' + LOCKING_SRC = '''locking/locking.c locking/brlock.c locking/posix.c''' PRIVILEGES_BASIC_SRC = '''lib/privileges_basic.c''' @@ -805,6 +807,7 @@ SMBD_SRC_BASE = '''${SMBD_SRC_SRV} ${LIBCLI_SRVSVC_SRC} ${LIBCLI_LSA_SRC} ${LIBCLI_SAMR_SRC} + ${RPC_CLIENT_SCHANNEL_SRC} ${AUTH_SRC} ${PRIVILEGES_BASIC_SRC}''' -- cgit