2 * Unix SMB/CIFS implementation.
3 * RPC Pipe client / server routines
4 * Largely rewritten by Jeremy Allison 2005.
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 3 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, see <http://www.gnu.org/licenses/>.
21 #include "../librpc/gen_ndr/ndr_schannel.h"
22 #include "../librpc/gen_ndr/ndr_netlogon.h"
23 #include "../libcli/auth/schannel.h"
24 #include "rpc_client/cli_netlogon.h"
25 #include "rpc_client/cli_pipe.h"
26 #include "librpc/gen_ndr/ndr_dcerpc.h"
27 #include "librpc/rpc/dcerpc.h"
31 #define DBGC_CLASS DBGC_RPC_CLI
34 /****************************************************************************
35 Get a the schannel session key out of an already opened netlogon pipe.
36 ****************************************************************************/
37 static NTSTATUS get_schannel_session_key_common(struct rpc_pipe_client *netlogon_pipe,
38 struct cli_state *cli,
42 enum netr_SchannelType sec_chan_type = 0;
43 unsigned char machine_pwd[16];
44 const char *machine_account;
47 /* Get the machine account credentials from secrets.tdb. */
48 if (!get_trust_pw_hash(domain, machine_pwd, &machine_account,
51 DEBUG(0, ("get_schannel_session_key: could not fetch "
52 "trust account password for domain '%s'\n",
54 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
57 status = rpccli_netlogon_setup_creds(netlogon_pipe,
58 cli->desthost, /* server name */
60 global_myname(), /* client name */
61 machine_account, /* machine account name */
66 if (!NT_STATUS_IS_OK(status)) {
67 DEBUG(3, ("get_schannel_session_key_common: "
68 "rpccli_netlogon_setup_creds failed with result %s "
69 "to server %s, domain %s, machine account %s.\n",
70 nt_errstr(status), cli->desthost, domain,
75 if (((*pneg_flags) & NETLOGON_NEG_SCHANNEL) == 0) {
76 DEBUG(3, ("get_schannel_session_key: Server %s did not offer schannel\n",
78 return NT_STATUS_INVALID_NETWORK_RESPONSE;
84 /****************************************************************************
85 Open a named pipe to an SMB server and bind using schannel (bind type 68).
86 Fetch the session key ourselves using a temporary netlogon pipe. This
87 version uses an ntlmssp auth bound netlogon pipe to get the key.
88 ****************************************************************************/
90 static NTSTATUS get_schannel_session_key_auth_ntlmssp(struct cli_state *cli,
95 struct rpc_pipe_client **presult)
97 struct rpc_pipe_client *netlogon_pipe = NULL;
100 status = cli_rpc_pipe_open_spnego_ntlmssp(
101 cli, &ndr_table_netlogon.syntax_id, NCACN_NP,
102 DCERPC_AUTH_LEVEL_PRIVACY,
103 domain, username, password, &netlogon_pipe);
104 if (!NT_STATUS_IS_OK(status)) {
108 status = get_schannel_session_key_common(netlogon_pipe, cli, domain,
110 if (!NT_STATUS_IS_OK(status)) {
111 TALLOC_FREE(netlogon_pipe);
115 *presult = netlogon_pipe;
119 /****************************************************************************
120 Open a named pipe to an SMB server and bind using schannel (bind type 68).
121 Fetch the session key ourselves using a temporary netlogon pipe. This version
122 uses an ntlmssp bind to get the session key.
123 ****************************************************************************/
125 NTSTATUS cli_rpc_pipe_open_ntlmssp_auth_schannel(struct cli_state *cli,
126 const struct ndr_syntax_id *interface,
127 enum dcerpc_transport_t transport,
128 enum dcerpc_AuthLevel auth_level,
130 const char *username,
131 const char *password,
132 struct rpc_pipe_client **presult)
134 uint32_t neg_flags = NETLOGON_NEG_AUTH2_ADS_FLAGS;
135 struct rpc_pipe_client *netlogon_pipe = NULL;
136 struct rpc_pipe_client *result = NULL;
139 status = get_schannel_session_key_auth_ntlmssp(
140 cli, domain, username, password, &neg_flags, &netlogon_pipe);
141 if (!NT_STATUS_IS_OK(status)) {
142 DEBUG(0,("cli_rpc_pipe_open_ntlmssp_auth_schannel: failed to get schannel session "
143 "key from server %s for domain %s.\n",
144 cli->desthost, domain ));
148 status = cli_rpc_pipe_open_schannel_with_key(
149 cli, interface, transport, auth_level, domain, &netlogon_pipe->dc,
152 /* Now we've bound using the session key we can close the netlog pipe. */
153 TALLOC_FREE(netlogon_pipe);
155 if (NT_STATUS_IS_OK(status)) {
161 /****************************************************************************
162 Open a named pipe to an SMB server and bind using schannel (bind type 68).
163 Fetch the session key ourselves using a temporary netlogon pipe.
164 ****************************************************************************/
166 NTSTATUS cli_rpc_pipe_open_schannel(struct cli_state *cli,
167 const struct ndr_syntax_id *interface,
168 enum dcerpc_transport_t transport,
169 enum dcerpc_AuthLevel auth_level,
171 struct rpc_pipe_client **presult)
173 uint32_t neg_flags = NETLOGON_NEG_AUTH2_ADS_FLAGS;
174 struct rpc_pipe_client *netlogon_pipe = NULL;
175 struct rpc_pipe_client *result = NULL;
178 status = get_schannel_session_key(cli, domain, &neg_flags,
180 if (!NT_STATUS_IS_OK(status)) {
181 DEBUG(0,("cli_rpc_pipe_open_schannel: failed to get schannel session "
182 "key from server %s for domain %s.\n",
183 cli->desthost, domain ));
187 status = cli_rpc_pipe_open_schannel_with_key(
188 cli, interface, transport, auth_level, domain, &netlogon_pipe->dc,
191 /* Now we've bound using the session key we can close the netlog pipe. */
192 TALLOC_FREE(netlogon_pipe);
194 if (NT_STATUS_IS_OK(status)) {
201 /****************************************************************************
202 Open a netlogon pipe and get the schannel session key.
203 Now exposed to external callers.
204 ****************************************************************************/
207 NTSTATUS get_schannel_session_key(struct cli_state *cli,
210 struct rpc_pipe_client **presult)
212 struct rpc_pipe_client *netlogon_pipe = NULL;
215 status = cli_rpc_pipe_open_noauth(cli, &ndr_table_netlogon.syntax_id,
217 if (!NT_STATUS_IS_OK(status)) {
221 status = get_schannel_session_key_common(netlogon_pipe, cli, domain,
223 if (!NT_STATUS_IS_OK(status)) {
224 TALLOC_FREE(netlogon_pipe);
228 *presult = netlogon_pipe;