summaryrefslogtreecommitdiff
path: root/source3/rpc_client/cli_pipe_schannel.c
diff options
context:
space:
mode:
authorGünther Deschner <gd@samba.org>2010-08-17 00:46:25 +0200
committerGünther Deschner <gd@samba.org>2010-08-26 00:16:57 +0200
commit0ed16e94c374efb06650f741827bcbed85f1af59 (patch)
treedf3af3e75ae19def36763a4d562cfbc8a5a2887d /source3/rpc_client/cli_pipe_schannel.c
parent064826c4d17f71e30386ff775935f86dd426f124 (diff)
downloadsamba-0ed16e94c374efb06650f741827bcbed85f1af59.tar.gz
samba-0ed16e94c374efb06650f741827bcbed85f1af59.tar.bz2
samba-0ed16e94c374efb06650f741827bcbed85f1af59.zip
s3: separate out cli schannel functions that depend on cli_netlogon.
Guenther
Diffstat (limited to 'source3/rpc_client/cli_pipe_schannel.c')
-rw-r--r--source3/rpc_client/cli_pipe_schannel.c228
1 files changed, 228 insertions, 0 deletions
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 <http://www.gnu.org/licenses/>.
+ */
+
+#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;
+}