BUG 9474: Downgrade v4 printer driver requests to v3.
[Samba.git] / source3 / rpc_client / cli_pipe_schannel.c
blobc27572047c073aa5945b521e613e3baa6c34349f
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 "rpc_client/cli_pipe.h"
26 #include "librpc/gen_ndr/ndr_dcerpc.h"
27 #include "librpc/rpc/dcerpc.h"
28 #include "passdb.h"
29 #include "libsmb/libsmb.h"
30 #include "auth/gensec/gensec.h"
31 #include "../libcli/smb/smbXcli_base.h"
33 #undef DBGC_CLASS
34 #define DBGC_CLASS DBGC_RPC_CLI
37 /****************************************************************************
38 Get a the schannel session key out of an already opened netlogon pipe.
39 ****************************************************************************/
40 static NTSTATUS get_schannel_session_key_common(struct rpc_pipe_client *netlogon_pipe,
41 struct cli_state *cli,
42 const char *domain,
43 uint32 *pneg_flags)
45 enum netr_SchannelType sec_chan_type = 0;
46 unsigned char machine_pwd[16];
47 const char *machine_account;
48 NTSTATUS status;
50 /* Get the machine account credentials from secrets.tdb. */
51 if (!get_trust_pw_hash(domain, machine_pwd, &machine_account,
52 &sec_chan_type))
54 DEBUG(0, ("get_schannel_session_key: could not fetch "
55 "trust account password for domain '%s'\n",
56 domain));
57 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
60 status = rpccli_netlogon_setup_creds(netlogon_pipe,
61 smbXcli_conn_remote_name(cli->conn), /* server name */
62 domain, /* domain */
63 lp_netbios_name(), /* client name */
64 machine_account, /* machine account name */
65 machine_pwd,
66 sec_chan_type,
67 pneg_flags);
69 if (!NT_STATUS_IS_OK(status)) {
70 DEBUG(3, ("get_schannel_session_key_common: "
71 "rpccli_netlogon_setup_creds failed with result %s "
72 "to server %s, domain %s, machine account %s.\n",
73 nt_errstr(status), smbXcli_conn_remote_name(cli->conn), domain,
74 machine_account ));
75 return status;
78 if (((*pneg_flags) & NETLOGON_NEG_SCHANNEL) == 0) {
79 DEBUG(3, ("get_schannel_session_key: Server %s did not offer schannel\n",
80 smbXcli_conn_remote_name(cli->conn)));
81 return NT_STATUS_INVALID_NETWORK_RESPONSE;
84 return NT_STATUS_OK;
87 /****************************************************************************
88 Open a named pipe to an SMB server and bind using schannel (bind type 68).
89 Fetch the session key ourselves using a temporary netlogon pipe. This
90 version uses an ntlmssp auth bound netlogon pipe to get the key.
91 ****************************************************************************/
93 static NTSTATUS get_schannel_session_key_auth_ntlmssp(struct cli_state *cli,
94 const char *domain,
95 const char *username,
96 const char *password,
97 uint32 *pneg_flags,
98 struct rpc_pipe_client **presult)
100 struct rpc_pipe_client *netlogon_pipe = NULL;
101 NTSTATUS status;
103 status = cli_rpc_pipe_open_spnego(
104 cli, &ndr_table_netlogon, NCACN_NP,
105 GENSEC_OID_NTLMSSP,
106 DCERPC_AUTH_LEVEL_PRIVACY,
107 smbXcli_conn_remote_name(cli->conn),
108 domain, username, password, &netlogon_pipe);
109 if (!NT_STATUS_IS_OK(status)) {
110 return status;
113 status = get_schannel_session_key_common(netlogon_pipe, cli, domain,
114 pneg_flags);
115 if (!NT_STATUS_IS_OK(status)) {
116 TALLOC_FREE(netlogon_pipe);
117 return status;
120 *presult = netlogon_pipe;
121 return NT_STATUS_OK;
124 /****************************************************************************
125 Open a named pipe to an SMB server and bind using schannel (bind type 68).
126 Fetch the session key ourselves using a temporary netlogon pipe. This version
127 uses an ntlmssp bind to get the session key.
128 ****************************************************************************/
130 NTSTATUS cli_rpc_pipe_open_ntlmssp_auth_schannel(struct cli_state *cli,
131 const struct ndr_syntax_id *interface,
132 enum dcerpc_transport_t transport,
133 enum dcerpc_AuthLevel auth_level,
134 const char *domain,
135 const char *username,
136 const char *password,
137 struct rpc_pipe_client **presult)
139 uint32_t neg_flags = NETLOGON_NEG_AUTH2_ADS_FLAGS;
140 struct rpc_pipe_client *netlogon_pipe = NULL;
141 struct rpc_pipe_client *result = NULL;
142 NTSTATUS status;
144 status = get_schannel_session_key_auth_ntlmssp(
145 cli, domain, username, password, &neg_flags, &netlogon_pipe);
146 if (!NT_STATUS_IS_OK(status)) {
147 DEBUG(0,("cli_rpc_pipe_open_ntlmssp_auth_schannel: failed to get schannel session "
148 "key from server %s for domain %s.\n",
149 smbXcli_conn_remote_name(cli->conn), domain ));
150 return status;
153 status = cli_rpc_pipe_open_schannel_with_key(
154 cli, interface, transport, auth_level, domain, &netlogon_pipe->dc,
155 &result);
157 /* Now we've bound using the session key we can close the netlog pipe. */
158 TALLOC_FREE(netlogon_pipe);
160 if (NT_STATUS_IS_OK(status)) {
161 *presult = result;
163 return status;
166 /****************************************************************************
167 Open a named pipe to an SMB server and bind using schannel (bind type 68).
168 Fetch the session key ourselves using a temporary netlogon pipe.
169 ****************************************************************************/
171 NTSTATUS cli_rpc_pipe_open_schannel(struct cli_state *cli,
172 const struct ndr_syntax_id *interface,
173 enum dcerpc_transport_t transport,
174 enum dcerpc_AuthLevel auth_level,
175 const char *domain,
176 struct rpc_pipe_client **presult)
178 uint32_t neg_flags = NETLOGON_NEG_AUTH2_ADS_FLAGS;
179 struct rpc_pipe_client *netlogon_pipe = NULL;
180 struct rpc_pipe_client *result = NULL;
181 NTSTATUS status;
183 status = get_schannel_session_key(cli, domain, &neg_flags,
184 &netlogon_pipe);
185 if (!NT_STATUS_IS_OK(status)) {
186 DEBUG(0,("cli_rpc_pipe_open_schannel: failed to get schannel session "
187 "key from server %s for domain %s.\n",
188 smbXcli_conn_remote_name(cli->conn), domain ));
189 return status;
192 status = cli_rpc_pipe_open_schannel_with_key(
193 cli, interface, transport, auth_level, domain, &netlogon_pipe->dc,
194 &result);
196 /* Now we've bound using the session key we can close the netlog pipe. */
197 TALLOC_FREE(netlogon_pipe);
199 if (NT_STATUS_IS_OK(status)) {
200 *presult = result;
203 return status;
206 /****************************************************************************
207 Open a netlogon pipe and get the schannel session key.
208 Now exposed to external callers.
209 ****************************************************************************/
212 NTSTATUS get_schannel_session_key(struct cli_state *cli,
213 const char *domain,
214 uint32 *pneg_flags,
215 struct rpc_pipe_client **presult)
217 struct rpc_pipe_client *netlogon_pipe = NULL;
218 NTSTATUS status;
220 status = cli_rpc_pipe_open_noauth(cli, &ndr_table_netlogon.syntax_id,
221 &netlogon_pipe);
222 if (!NT_STATUS_IS_OK(status)) {
223 return status;
226 status = get_schannel_session_key_common(netlogon_pipe, cli, domain,
227 pneg_flags);
228 if (!NT_STATUS_IS_OK(status)) {
229 TALLOC_FREE(netlogon_pipe);
230 return status;
233 *presult = netlogon_pipe;
234 return NT_STATUS_OK;