s3:net factor out net_idmap_dbfile
[Samba.git] / source3 / rpc_client / cli_pipe_schannel.c
blob2c605c6c40f305699ded14e6d1281f26bb111920
1 /*
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/>.
20 #include "includes.h"
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 "librpc/gen_ndr/ndr_dcerpc.h"
26 #include "librpc/rpc/dcerpc.h"
28 #undef DBGC_CLASS
29 #define DBGC_CLASS DBGC_RPC_CLI
32 /****************************************************************************
33 Get a the schannel session key out of an already opened netlogon pipe.
34 ****************************************************************************/
35 static NTSTATUS get_schannel_session_key_common(struct rpc_pipe_client *netlogon_pipe,
36 struct cli_state *cli,
37 const char *domain,
38 uint32 *pneg_flags)
40 enum netr_SchannelType sec_chan_type = 0;
41 unsigned char machine_pwd[16];
42 const char *machine_account;
43 NTSTATUS status;
45 /* Get the machine account credentials from secrets.tdb. */
46 if (!get_trust_pw_hash(domain, machine_pwd, &machine_account,
47 &sec_chan_type))
49 DEBUG(0, ("get_schannel_session_key: could not fetch "
50 "trust account password for domain '%s'\n",
51 domain));
52 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
55 status = rpccli_netlogon_setup_creds(netlogon_pipe,
56 cli->desthost, /* server name */
57 domain, /* domain */
58 global_myname(), /* client name */
59 machine_account, /* machine account name */
60 machine_pwd,
61 sec_chan_type,
62 pneg_flags);
64 if (!NT_STATUS_IS_OK(status)) {
65 DEBUG(3, ("get_schannel_session_key_common: "
66 "rpccli_netlogon_setup_creds failed with result %s "
67 "to server %s, domain %s, machine account %s.\n",
68 nt_errstr(status), cli->desthost, domain,
69 machine_account ));
70 return status;
73 if (((*pneg_flags) & NETLOGON_NEG_SCHANNEL) == 0) {
74 DEBUG(3, ("get_schannel_session_key: Server %s did not offer schannel\n",
75 cli->desthost));
76 return NT_STATUS_INVALID_NETWORK_RESPONSE;
79 return NT_STATUS_OK;
82 /****************************************************************************
83 Open a named pipe to an SMB server and bind using schannel (bind type 68).
84 Fetch the session key ourselves using a temporary netlogon pipe. This
85 version uses an ntlmssp auth bound netlogon pipe to get the key.
86 ****************************************************************************/
88 static NTSTATUS get_schannel_session_key_auth_ntlmssp(struct cli_state *cli,
89 const char *domain,
90 const char *username,
91 const char *password,
92 uint32 *pneg_flags,
93 struct rpc_pipe_client **presult)
95 struct rpc_pipe_client *netlogon_pipe = NULL;
96 NTSTATUS status;
98 status = cli_rpc_pipe_open_spnego_ntlmssp(
99 cli, &ndr_table_netlogon.syntax_id, NCACN_NP,
100 DCERPC_AUTH_LEVEL_PRIVACY,
101 domain, username, password, &netlogon_pipe);
102 if (!NT_STATUS_IS_OK(status)) {
103 return status;
106 status = get_schannel_session_key_common(netlogon_pipe, cli, domain,
107 pneg_flags);
108 if (!NT_STATUS_IS_OK(status)) {
109 TALLOC_FREE(netlogon_pipe);
110 return status;
113 *presult = netlogon_pipe;
114 return NT_STATUS_OK;
117 /****************************************************************************
118 Open a named pipe to an SMB server and bind using schannel (bind type 68).
119 Fetch the session key ourselves using a temporary netlogon pipe. This version
120 uses an ntlmssp bind to get the session key.
121 ****************************************************************************/
123 NTSTATUS cli_rpc_pipe_open_ntlmssp_auth_schannel(struct cli_state *cli,
124 const struct ndr_syntax_id *interface,
125 enum dcerpc_transport_t transport,
126 enum dcerpc_AuthLevel auth_level,
127 const char *domain,
128 const char *username,
129 const char *password,
130 struct rpc_pipe_client **presult)
132 uint32_t neg_flags = NETLOGON_NEG_AUTH2_ADS_FLAGS;
133 struct rpc_pipe_client *netlogon_pipe = NULL;
134 struct rpc_pipe_client *result = NULL;
135 NTSTATUS status;
137 status = get_schannel_session_key_auth_ntlmssp(
138 cli, domain, username, password, &neg_flags, &netlogon_pipe);
139 if (!NT_STATUS_IS_OK(status)) {
140 DEBUG(0,("cli_rpc_pipe_open_ntlmssp_auth_schannel: failed to get schannel session "
141 "key from server %s for domain %s.\n",
142 cli->desthost, domain ));
143 return status;
146 status = cli_rpc_pipe_open_schannel_with_key(
147 cli, interface, transport, auth_level, domain, &netlogon_pipe->dc,
148 &result);
150 /* Now we've bound using the session key we can close the netlog pipe. */
151 TALLOC_FREE(netlogon_pipe);
153 if (NT_STATUS_IS_OK(status)) {
154 *presult = result;
156 return status;
159 /****************************************************************************
160 Open a named pipe to an SMB server and bind using schannel (bind type 68).
161 Fetch the session key ourselves using a temporary netlogon pipe.
162 ****************************************************************************/
164 NTSTATUS cli_rpc_pipe_open_schannel(struct cli_state *cli,
165 const struct ndr_syntax_id *interface,
166 enum dcerpc_transport_t transport,
167 enum dcerpc_AuthLevel auth_level,
168 const char *domain,
169 struct rpc_pipe_client **presult)
171 uint32_t neg_flags = NETLOGON_NEG_AUTH2_ADS_FLAGS;
172 struct rpc_pipe_client *netlogon_pipe = NULL;
173 struct rpc_pipe_client *result = NULL;
174 NTSTATUS status;
176 status = get_schannel_session_key(cli, domain, &neg_flags,
177 &netlogon_pipe);
178 if (!NT_STATUS_IS_OK(status)) {
179 DEBUG(0,("cli_rpc_pipe_open_schannel: failed to get schannel session "
180 "key from server %s for domain %s.\n",
181 cli->desthost, domain ));
182 return status;
185 status = cli_rpc_pipe_open_schannel_with_key(
186 cli, interface, transport, auth_level, domain, &netlogon_pipe->dc,
187 &result);
189 /* Now we've bound using the session key we can close the netlog pipe. */
190 TALLOC_FREE(netlogon_pipe);
192 if (NT_STATUS_IS_OK(status)) {
193 *presult = result;
196 return status;
199 /****************************************************************************
200 Open a netlogon pipe and get the schannel session key.
201 Now exposed to external callers.
202 ****************************************************************************/
205 NTSTATUS get_schannel_session_key(struct cli_state *cli,
206 const char *domain,
207 uint32 *pneg_flags,
208 struct rpc_pipe_client **presult)
210 struct rpc_pipe_client *netlogon_pipe = NULL;
211 NTSTATUS status;
213 status = cli_rpc_pipe_open_noauth(cli, &ndr_table_netlogon.syntax_id,
214 &netlogon_pipe);
215 if (!NT_STATUS_IS_OK(status)) {
216 return status;
219 status = get_schannel_session_key_common(netlogon_pipe, cli, domain,
220 pneg_flags);
221 if (!NT_STATUS_IS_OK(status)) {
222 TALLOC_FREE(netlogon_pipe);
223 return status;
226 *presult = netlogon_pipe;
227 return NT_STATUS_OK;