s3-rpc_cli: pass down ndr_interface_table to cli_rpc_pipe_open_schannel_with_key().
[vlendec/samba-autobuild/.git] / source3 / rpc_client / cli_pipe_schannel.c
1 /*
2  *  Unix SMB/CIFS implementation.
3  *  RPC Pipe client / server routines
4  *  Largely rewritten by Jeremy Allison             2005.
5  *
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.
10  *
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.
15  *
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/>.
18  */
19
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"
32
33 #undef DBGC_CLASS
34 #define DBGC_CLASS DBGC_RPC_CLI
35
36
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)
44 {
45         enum netr_SchannelType sec_chan_type = 0;
46         unsigned char machine_pwd[16];
47         const char *machine_account;
48         NTSTATUS status;
49
50         /* Get the machine account credentials from secrets.tdb. */
51         if (!get_trust_pw_hash(domain, machine_pwd, &machine_account,
52                                &sec_chan_type))
53         {
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;
58         }
59
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);
68
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;
76         }
77
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;
82         }
83
84         return NT_STATUS_OK;
85 }
86
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  ****************************************************************************/
92
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)
99 {
100         struct rpc_pipe_client *netlogon_pipe = NULL;
101         NTSTATUS status;
102
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;
111         }
112
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;
118         }
119
120         *presult = netlogon_pipe;
121         return NT_STATUS_OK;
122 }
123
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  ****************************************************************************/
129
130 NTSTATUS cli_rpc_pipe_open_ntlmssp_auth_schannel(struct cli_state *cli,
131                                                  const struct ndr_interface_table *table,
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)
138 {
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;
143
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;
151         }
152
153         status = cli_rpc_pipe_open_schannel_with_key(
154                 cli, table, transport, auth_level, domain, &netlogon_pipe->dc,
155                 &result);
156
157         /* Now we've bound using the session key we can close the netlog pipe. */
158         TALLOC_FREE(netlogon_pipe);
159
160         if (NT_STATUS_IS_OK(status)) {
161                 *presult = result;
162         }
163         return status;
164 }
165
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  ****************************************************************************/
170
171 NTSTATUS cli_rpc_pipe_open_schannel(struct cli_state *cli,
172                                     const struct ndr_interface_table *table,
173                                     enum dcerpc_transport_t transport,
174                                     enum dcerpc_AuthLevel auth_level,
175                                     const char *domain,
176                                     struct rpc_pipe_client **presult)
177 {
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;
182
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;
190         }
191
192         status = cli_rpc_pipe_open_schannel_with_key(
193                 cli, table, transport, auth_level, domain, &netlogon_pipe->dc,
194                 &result);
195
196         /* Now we've bound using the session key we can close the netlog pipe. */
197         TALLOC_FREE(netlogon_pipe);
198
199         if (NT_STATUS_IS_OK(status)) {
200                 *presult = result;
201         }
202
203         return status;
204 }
205
206 /****************************************************************************
207  Open a netlogon pipe and get the schannel session key.
208  Now exposed to external callers.
209  ****************************************************************************/
210
211
212 NTSTATUS get_schannel_session_key(struct cli_state *cli,
213                                   const char *domain,
214                                   uint32 *pneg_flags,
215                                   struct rpc_pipe_client **presult)
216 {
217         struct rpc_pipe_client *netlogon_pipe = NULL;
218         NTSTATUS status;
219
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;
224         }
225
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;
231         }
232
233         *presult = netlogon_pipe;
234         return NT_STATUS_OK;
235 }