s3:rpc_client: make use of the new netlogon_creds_cli_context
[samba.git] / source3 / rpc_client / cli_netlogon.c
1 /*
2    Unix SMB/CIFS implementation.
3    NT Domain Authentication SMB / MSRPC client
4    Copyright (C) Andrew Tridgell 1992-2000
5    Copyright (C) Jeremy Allison                    1998.
6    Largely re-written by Jeremy Allison (C)        2005.
7    Copyright (C) Guenther Deschner                 2008.
8
9    This program is free software; you can redistribute it and/or modify
10    it under the terms of the GNU General Public License as published by
11    the Free Software Foundation; either version 3 of the License, or
12    (at your option) any later version.
13
14    This program is distributed in the hope that it will be useful,
15    but WITHOUT ANY WARRANTY; without even the implied warranty of
16    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17    GNU General Public License for more details.
18
19    You should have received a copy of the GNU General Public License
20    along with this program.  If not, see <http://www.gnu.org/licenses/>.
21 */
22
23 #include "includes.h"
24 #include "rpc_client/rpc_client.h"
25 #include "../libcli/auth/libcli_auth.h"
26 #include "../libcli/auth/netlogon_creds_cli.h"
27 #include "../librpc/gen_ndr/ndr_netlogon_c.h"
28 #include "rpc_client/cli_netlogon.h"
29 #include "rpc_client/init_netlogon.h"
30 #include "rpc_client/util_netlogon.h"
31 #include "../libcli/security/security.h"
32 #include "lib/param/param.h"
33
34 /****************************************************************************
35  Wrapper function that uses the auth and auth2 calls to set up a NETLOGON
36  credentials chain. Stores the credentials in the struct dcinfo in the
37  netlogon pipe struct.
38 ****************************************************************************/
39
40 NTSTATUS rpccli_netlogon_setup_creds(struct rpc_pipe_client *cli,
41                                      const char *server_name,
42                                      const char *domain,
43                                      const char *clnt_name,
44                                      const char *machine_account,
45                                      const unsigned char machine_pwd[16],
46                                      enum netr_SchannelType sec_chan_type,
47                                      uint32_t *neg_flags_inout)
48 {
49         TALLOC_CTX *frame = talloc_stackframe();
50         struct loadparm_context *lp_ctx;
51         NTSTATUS status;
52         struct samr_Password password;
53         fstring mach_acct;
54         struct dcerpc_binding_handle *b = cli->binding_handle;
55         struct netlogon_creds_CredentialState *creds = NULL;
56
57         if (!ndr_syntax_id_equal(&cli->abstract_syntax,
58                                  &ndr_table_netlogon.syntax_id)) {
59                 TALLOC_FREE(frame);
60                 return NT_STATUS_INVALID_PARAMETER;
61         }
62
63         if (!strequal(lp_netbios_name(), clnt_name)) {
64                 TALLOC_FREE(frame);
65                 return NT_STATUS_INVALID_PARAMETER;
66         }
67
68         TALLOC_FREE(cli->netlogon_creds);
69
70         fstr_sprintf( mach_acct, "%s$", machine_account);
71
72         lp_ctx = loadparm_init_s3(frame, loadparm_s3_helpers());
73         if (lp_ctx == NULL) {
74                 TALLOC_FREE(frame);
75                 return NT_STATUS_NO_MEMORY;
76         }
77         status = netlogon_creds_cli_context_global(lp_ctx,
78                                                    NULL, /* msg_ctx */
79                                                    mach_acct,
80                                                    sec_chan_type,
81                                                    server_name,
82                                                    domain,
83                                                    cli, &cli->netlogon_creds);
84         talloc_unlink(frame, lp_ctx);
85         if (!NT_STATUS_IS_OK(status)) {
86                 TALLOC_FREE(frame);
87                 return status;
88         }
89
90         status = netlogon_creds_cli_get(cli->netlogon_creds,
91                                         frame, &creds);
92         if (NT_STATUS_IS_OK(status)) {
93                 DEBUG(5,("rpccli_netlogon_setup_creds: server %s using "
94                          "cached credential\n",
95                          cli->desthost));
96                 *neg_flags_inout = creds->negotiate_flags;
97                 TALLOC_FREE(frame);
98                 return NT_STATUS_OK;
99         }
100
101         /* Store the machine account password we're going to use. */
102         memcpy(password.hash, machine_pwd, 16);
103
104         DEBUG(5,("rpccli_netlogon_setup_creds: server %s credential "
105                 "chain established.\n",
106                 cli->desthost ));
107
108         status = netlogon_creds_cli_auth(cli->netlogon_creds, b,
109                                          password, NULL);
110         if (!NT_STATUS_IS_OK(status)) {
111                 TALLOC_FREE(frame);
112                 return status;
113         }
114
115         status = netlogon_creds_cli_get(cli->netlogon_creds,
116                                         frame, &creds);
117         if (!NT_STATUS_IS_OK(status)) {
118                 TALLOC_FREE(frame);
119                 return NT_STATUS_INTERNAL_ERROR;
120         }
121
122         *neg_flags_inout = creds->negotiate_flags;
123         TALLOC_FREE(frame);
124         return NT_STATUS_OK;
125 }
126
127 /* Logon domain user */
128
129 NTSTATUS rpccli_netlogon_sam_logon(struct rpc_pipe_client *cli,
130                                    TALLOC_CTX *mem_ctx,
131                                    uint32 logon_parameters,
132                                    const char *domain,
133                                    const char *username,
134                                    const char *password,
135                                    const char *workstation,
136                                    uint16_t _ignored_validation_level,
137                                    int logon_type)
138 {
139         NTSTATUS status;
140         union netr_LogonLevel *logon;
141         uint16_t validation_level = 0;
142         union netr_Validation *validation = NULL;
143         uint8_t authoritative = 0;
144         uint32_t flags = 0;
145         fstring clnt_name_slash;
146
147         logon = talloc_zero(mem_ctx, union netr_LogonLevel);
148         if (!logon) {
149                 return NT_STATUS_NO_MEMORY;
150         }
151
152         if (workstation) {
153                 fstr_sprintf( clnt_name_slash, "\\\\%s", workstation );
154         } else {
155                 fstr_sprintf( clnt_name_slash, "\\\\%s", lp_netbios_name() );
156         }
157
158         /* Initialise input parameters */
159
160         switch (logon_type) {
161         case NetlogonInteractiveInformation: {
162
163                 struct netr_PasswordInfo *password_info;
164
165                 struct samr_Password lmpassword;
166                 struct samr_Password ntpassword;
167
168                 password_info = talloc_zero(mem_ctx, struct netr_PasswordInfo);
169                 if (!password_info) {
170                         return NT_STATUS_NO_MEMORY;
171                 }
172
173                 nt_lm_owf_gen(password, ntpassword.hash, lmpassword.hash);
174
175                 password_info->identity_info.domain_name.string         = domain;
176                 password_info->identity_info.parameter_control          = logon_parameters;
177                 password_info->identity_info.logon_id_low               = 0xdead;
178                 password_info->identity_info.logon_id_high              = 0xbeef;
179                 password_info->identity_info.account_name.string        = username;
180                 password_info->identity_info.workstation.string         = clnt_name_slash;
181
182                 password_info->lmpassword = lmpassword;
183                 password_info->ntpassword = ntpassword;
184
185                 logon->password = password_info;
186
187                 break;
188         }
189         case NetlogonNetworkInformation: {
190                 struct netr_NetworkInfo *network_info;
191                 uint8 chal[8];
192                 unsigned char local_lm_response[24];
193                 unsigned char local_nt_response[24];
194                 struct netr_ChallengeResponse lm;
195                 struct netr_ChallengeResponse nt;
196
197                 ZERO_STRUCT(lm);
198                 ZERO_STRUCT(nt);
199
200                 network_info = talloc_zero(mem_ctx, struct netr_NetworkInfo);
201                 if (!network_info) {
202                         return NT_STATUS_NO_MEMORY;
203                 }
204
205                 generate_random_buffer(chal, 8);
206
207                 SMBencrypt(password, chal, local_lm_response);
208                 SMBNTencrypt(password, chal, local_nt_response);
209
210                 lm.length = 24;
211                 lm.data = local_lm_response;
212
213                 nt.length = 24;
214                 nt.data = local_nt_response;
215
216                 network_info->identity_info.domain_name.string          = domain;
217                 network_info->identity_info.parameter_control           = logon_parameters;
218                 network_info->identity_info.logon_id_low                = 0xdead;
219                 network_info->identity_info.logon_id_high               = 0xbeef;
220                 network_info->identity_info.account_name.string         = username;
221                 network_info->identity_info.workstation.string          = clnt_name_slash;
222
223                 memcpy(network_info->challenge, chal, 8);
224                 network_info->nt = nt;
225                 network_info->lm = lm;
226
227                 logon->network = network_info;
228
229                 break;
230         }
231         default:
232                 DEBUG(0, ("switch value %d not supported\n",
233                         logon_type));
234                 return NT_STATUS_INVALID_INFO_CLASS;
235         }
236
237         status = netlogon_creds_cli_LogonSamLogon(cli->netlogon_creds,
238                                                   cli->binding_handle,
239                                                   logon_type,
240                                                   logon,
241                                                   mem_ctx,
242                                                   &validation_level,
243                                                   &validation,
244                                                   &authoritative,
245                                                   &flags);
246         if (!NT_STATUS_IS_OK(status)) {
247                 return status;
248         }
249
250         return NT_STATUS_OK;
251 }
252
253 static NTSTATUS map_validation_to_info3(TALLOC_CTX *mem_ctx,
254                                         uint16_t validation_level,
255                                         union netr_Validation *validation,
256                                         struct netr_SamInfo3 **info3_p)
257 {
258         struct netr_SamInfo3 *info3;
259         NTSTATUS status;
260
261         if (validation == NULL) {
262                 return NT_STATUS_INVALID_PARAMETER;
263         }
264
265         switch (validation_level) {
266         case 3:
267                 if (validation->sam3 == NULL) {
268                         return NT_STATUS_INVALID_PARAMETER;
269                 }
270
271                 info3 = talloc_move(mem_ctx, &validation->sam3);
272                 break;
273         case 6:
274                 if (validation->sam6 == NULL) {
275                         return NT_STATUS_INVALID_PARAMETER;
276                 }
277
278                 info3 = talloc_zero(mem_ctx, struct netr_SamInfo3);
279                 if (info3 == NULL) {
280                         return NT_STATUS_NO_MEMORY;
281                 }
282                 status = copy_netr_SamBaseInfo(info3, &validation->sam6->base, &info3->base);
283                 if (!NT_STATUS_IS_OK(status)) {
284                         TALLOC_FREE(info3);
285                         return status;
286                 }
287
288                 info3->sidcount = validation->sam6->sidcount;
289                 info3->sids = talloc_move(info3, &validation->sam6->sids);
290                 break;
291         default:
292                 return NT_STATUS_BAD_VALIDATION_CLASS;
293         }
294
295         *info3_p = info3;
296
297         return NT_STATUS_OK;
298 }
299
300 /**
301  * Logon domain user with an 'network' SAM logon
302  *
303  * @param info3 Pointer to a NET_USER_INFO_3 already allocated by the caller.
304  **/
305
306 NTSTATUS rpccli_netlogon_sam_network_logon(struct rpc_pipe_client *cli,
307                                            TALLOC_CTX *mem_ctx,
308                                            uint32 logon_parameters,
309                                            const char *server,
310                                            const char *username,
311                                            const char *domain,
312                                            const char *workstation,
313                                            const uint8 chal[8],
314                                            uint16_t _ignored_validation_level,
315                                            DATA_BLOB lm_response,
316                                            DATA_BLOB nt_response,
317                                            struct netr_SamInfo3 **info3)
318 {
319         NTSTATUS status;
320         const char *workstation_name_slash;
321         union netr_LogonLevel *logon = NULL;
322         struct netr_NetworkInfo *network_info;
323         uint16_t validation_level = 0;
324         union netr_Validation *validation = NULL;
325         uint8_t authoritative = 0;
326         uint32_t flags = 0;
327         struct netr_ChallengeResponse lm;
328         struct netr_ChallengeResponse nt;
329
330         *info3 = NULL;
331
332         ZERO_STRUCT(lm);
333         ZERO_STRUCT(nt);
334
335         logon = talloc_zero(mem_ctx, union netr_LogonLevel);
336         if (!logon) {
337                 return NT_STATUS_NO_MEMORY;
338         }
339
340         network_info = talloc_zero(mem_ctx, struct netr_NetworkInfo);
341         if (!network_info) {
342                 return NT_STATUS_NO_MEMORY;
343         }
344
345         if (workstation[0] != '\\' && workstation[1] != '\\') {
346                 workstation_name_slash = talloc_asprintf(mem_ctx, "\\\\%s", workstation);
347         } else {
348                 workstation_name_slash = workstation;
349         }
350
351         if (!workstation_name_slash) {
352                 DEBUG(0, ("talloc_asprintf failed!\n"));
353                 return NT_STATUS_NO_MEMORY;
354         }
355
356         /* Initialise input parameters */
357
358         lm.data = lm_response.data;
359         lm.length = lm_response.length;
360         nt.data = nt_response.data;
361         nt.length = nt_response.length;
362
363         network_info->identity_info.domain_name.string          = domain;
364         network_info->identity_info.parameter_control           = logon_parameters;
365         network_info->identity_info.logon_id_low                = 0xdead;
366         network_info->identity_info.logon_id_high               = 0xbeef;
367         network_info->identity_info.account_name.string         = username;
368         network_info->identity_info.workstation.string          = workstation_name_slash;
369
370         memcpy(network_info->challenge, chal, 8);
371         network_info->nt = nt;
372         network_info->lm = lm;
373
374         logon->network = network_info;
375
376         /* Marshall data and send request */
377
378         status = netlogon_creds_cli_LogonSamLogon(cli->netlogon_creds,
379                                                   cli->binding_handle,
380                                                   NetlogonNetworkInformation,
381                                                   logon,
382                                                   mem_ctx,
383                                                   &validation_level,
384                                                   &validation,
385                                                   &authoritative,
386                                                   &flags);
387         if (!NT_STATUS_IS_OK(status)) {
388                 return status;
389         }
390
391         status = map_validation_to_info3(mem_ctx,
392                                          validation_level, validation,
393                                          info3);
394         if (!NT_STATUS_IS_OK(status)) {
395                 return status;
396         }
397
398         return NT_STATUS_OK;
399 }
400
401 NTSTATUS rpccli_netlogon_sam_network_logon_ex(struct rpc_pipe_client *cli,
402                                               TALLOC_CTX *mem_ctx,
403                                               uint32 logon_parameters,
404                                               const char *server,
405                                               const char *username,
406                                               const char *domain,
407                                               const char *workstation,
408                                               const uint8 chal[8],
409                                               uint16_t validation_level,
410                                               DATA_BLOB lm_response,
411                                               DATA_BLOB nt_response,
412                                               struct netr_SamInfo3 **info3)
413 {
414         return rpccli_netlogon_sam_network_logon(cli,
415                                                  mem_ctx,
416                                                  logon_parameters,
417                                                  server,
418                                                  username,
419                                                  domain,
420                                                  workstation,
421                                                  chal,
422                                                  validation_level,
423                                                  lm_response,
424                                                  nt_response,
425                                                  info3);
426 }
427
428 /*********************************************************
429  Change the domain password on the PDC.
430
431  Just changes the password betwen the two values specified.
432
433  Caller must have the cli connected to the netlogon pipe
434  already.
435 **********************************************************/
436
437 NTSTATUS rpccli_netlogon_set_trust_password(struct rpc_pipe_client *cli,
438                                             TALLOC_CTX *mem_ctx,
439                                             const char *account_name,
440                                             const unsigned char orig_trust_passwd_hash[16],
441                                             const char *new_trust_pwd_cleartext,
442                                             const unsigned char new_trust_passwd_hash[16],
443                                             enum netr_SchannelType sec_channel_type)
444 {
445         NTSTATUS result;
446
447         if (cli->netlogon_creds == NULL) {
448                 uint32_t neg_flags = NETLOGON_NEG_AUTH2_ADS_FLAGS |
449                                         NETLOGON_NEG_SUPPORTS_AES;
450                 result = rpccli_netlogon_setup_creds(cli,
451                                                      cli->desthost, /* server name */
452                                                      lp_workgroup(), /* domain */
453                                                      lp_netbios_name(), /* client name */
454                                                      account_name, /* machine account name */
455                                                      orig_trust_passwd_hash,
456                                                      sec_channel_type,
457                                                      &neg_flags);
458                 if (!NT_STATUS_IS_OK(result)) {
459                         DEBUG(3,("rpccli_netlogon_set_trust_password: unable to setup creds (%s)!\n",
460                                  nt_errstr(result)));
461                         return result;
462                 }
463         }
464
465         result = netlogon_creds_cli_ServerPasswordSet(cli->netlogon_creds,
466                                                       cli->binding_handle,
467                                                       new_trust_pwd_cleartext,
468                                                       NULL); /* new_version */
469         if (!NT_STATUS_IS_OK(result)) {
470                 DEBUG(0,("netlogon_creds_cli_ServerPasswordSet failed: %s\n",
471                         nt_errstr(result)));
472                 return result;
473         }
474
475         return NT_STATUS_OK;
476 }
477