build: make make tests SCREEN=1 work on freebsd
[Samba/gbeck.git] / source3 / rpc_client / cli_netlogon.c
blob28972c96fa8bd5a904675b32756baad63aafbac8
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.
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.
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.
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/>.
23 #include "includes.h"
24 #include "../libcli/auth/libcli_auth.h"
25 #include "../librpc/gen_ndr/cli_netlogon.h"
26 #include "rpc_client/cli_netlogon.h"
27 #include "rpc_client/init_netlogon.h"
29 /****************************************************************************
30 Wrapper function that uses the auth and auth2 calls to set up a NETLOGON
31 credentials chain. Stores the credentials in the struct dcinfo in the
32 netlogon pipe struct.
33 ****************************************************************************/
35 NTSTATUS rpccli_netlogon_setup_creds(struct rpc_pipe_client *cli,
36 const char *server_name,
37 const char *domain,
38 const char *clnt_name,
39 const char *machine_account,
40 const unsigned char machine_pwd[16],
41 enum netr_SchannelType sec_chan_type,
42 uint32_t *neg_flags_inout)
44 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
45 struct netr_Credential clnt_chal_send;
46 struct netr_Credential srv_chal_recv;
47 struct samr_Password password;
48 bool retried = false;
49 fstring mach_acct;
50 uint32_t neg_flags = *neg_flags_inout;
52 if (!ndr_syntax_id_equal(&cli->abstract_syntax,
53 &ndr_table_netlogon.syntax_id)) {
54 return NT_STATUS_INVALID_PARAMETER;
57 TALLOC_FREE(cli->dc);
59 /* Store the machine account password we're going to use. */
60 memcpy(password.hash, machine_pwd, 16);
62 fstr_sprintf( mach_acct, "%s$", machine_account);
64 again:
65 /* Create the client challenge. */
66 generate_random_buffer(clnt_chal_send.data, 8);
68 /* Get the server challenge. */
69 result = rpccli_netr_ServerReqChallenge(cli, talloc_tos(),
70 cli->srv_name_slash,
71 clnt_name,
72 &clnt_chal_send,
73 &srv_chal_recv);
74 if (!NT_STATUS_IS_OK(result)) {
75 return result;
78 /* Calculate the session key and client credentials */
80 cli->dc = netlogon_creds_client_init(cli,
81 mach_acct,
82 clnt_name,
83 &clnt_chal_send,
84 &srv_chal_recv,
85 &password,
86 &clnt_chal_send,
87 neg_flags);
89 if (!cli->dc) {
90 return NT_STATUS_NO_MEMORY;
94 * Send client auth-2 challenge and receive server repy.
97 result = rpccli_netr_ServerAuthenticate2(cli, talloc_tos(),
98 cli->srv_name_slash,
99 cli->dc->account_name,
100 sec_chan_type,
101 cli->dc->computer_name,
102 &clnt_chal_send, /* input. */
103 &srv_chal_recv, /* output. */
104 &neg_flags);
106 /* we might be talking to NT4, so let's downgrade in that case and retry
107 * with the returned neg_flags - gd */
109 if (NT_STATUS_EQUAL(result, NT_STATUS_ACCESS_DENIED) && !retried) {
110 retried = true;
111 TALLOC_FREE(cli->dc);
112 goto again;
115 if (!NT_STATUS_IS_OK(result)) {
116 return result;
120 * Check the returned value using the initial
121 * server received challenge.
124 if (!netlogon_creds_client_check(cli->dc, &srv_chal_recv)) {
126 * Server replied with bad credential. Fail.
128 DEBUG(0,("rpccli_netlogon_setup_creds: server %s "
129 "replied with bad credential\n",
130 cli->desthost ));
131 return NT_STATUS_ACCESS_DENIED;
134 DEBUG(5,("rpccli_netlogon_setup_creds: server %s credential "
135 "chain established.\n",
136 cli->desthost ));
138 cli->dc->negotiate_flags = neg_flags;
139 *neg_flags_inout = neg_flags;
141 return NT_STATUS_OK;
144 /* Logon domain user */
146 NTSTATUS rpccli_netlogon_sam_logon(struct rpc_pipe_client *cli,
147 TALLOC_CTX *mem_ctx,
148 uint32 logon_parameters,
149 const char *domain,
150 const char *username,
151 const char *password,
152 const char *workstation,
153 int logon_type)
155 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
156 struct netr_Authenticator clnt_creds;
157 struct netr_Authenticator ret_creds;
158 union netr_LogonLevel *logon;
159 union netr_Validation validation;
160 uint8_t authoritative;
161 int validation_level = 3;
162 fstring clnt_name_slash;
164 ZERO_STRUCT(ret_creds);
166 logon = TALLOC_ZERO_P(mem_ctx, union netr_LogonLevel);
167 if (!logon) {
168 return NT_STATUS_NO_MEMORY;
171 if (workstation) {
172 fstr_sprintf( clnt_name_slash, "\\\\%s", workstation );
173 } else {
174 fstr_sprintf( clnt_name_slash, "\\\\%s", global_myname() );
177 /* Initialise input parameters */
179 netlogon_creds_client_authenticator(cli->dc, &clnt_creds);
181 switch (logon_type) {
182 case NetlogonInteractiveInformation: {
184 struct netr_PasswordInfo *password_info;
186 struct samr_Password lmpassword;
187 struct samr_Password ntpassword;
189 password_info = TALLOC_ZERO_P(mem_ctx, struct netr_PasswordInfo);
190 if (!password_info) {
191 return NT_STATUS_NO_MEMORY;
194 nt_lm_owf_gen(password, ntpassword.hash, lmpassword.hash);
196 if (cli->dc->negotiate_flags & NETLOGON_NEG_ARCFOUR) {
197 netlogon_creds_arcfour_crypt(cli->dc, lmpassword.hash, 16);
198 netlogon_creds_arcfour_crypt(cli->dc, ntpassword.hash, 16);
199 } else {
200 netlogon_creds_des_encrypt(cli->dc, &lmpassword);
201 netlogon_creds_des_encrypt(cli->dc, &ntpassword);
204 password_info->identity_info.domain_name.string = domain;
205 password_info->identity_info.parameter_control = logon_parameters;
206 password_info->identity_info.logon_id_low = 0xdead;
207 password_info->identity_info.logon_id_high = 0xbeef;
208 password_info->identity_info.account_name.string = username;
209 password_info->identity_info.workstation.string = clnt_name_slash;
211 password_info->lmpassword = lmpassword;
212 password_info->ntpassword = ntpassword;
214 logon->password = password_info;
216 break;
218 case NetlogonNetworkInformation: {
219 struct netr_NetworkInfo *network_info;
220 uint8 chal[8];
221 unsigned char local_lm_response[24];
222 unsigned char local_nt_response[24];
223 struct netr_ChallengeResponse lm;
224 struct netr_ChallengeResponse nt;
226 ZERO_STRUCT(lm);
227 ZERO_STRUCT(nt);
229 network_info = TALLOC_ZERO_P(mem_ctx, struct netr_NetworkInfo);
230 if (!network_info) {
231 return NT_STATUS_NO_MEMORY;
234 generate_random_buffer(chal, 8);
236 SMBencrypt(password, chal, local_lm_response);
237 SMBNTencrypt(password, chal, local_nt_response);
239 lm.length = 24;
240 lm.data = local_lm_response;
242 nt.length = 24;
243 nt.data = local_nt_response;
245 network_info->identity_info.domain_name.string = domain;
246 network_info->identity_info.parameter_control = logon_parameters;
247 network_info->identity_info.logon_id_low = 0xdead;
248 network_info->identity_info.logon_id_high = 0xbeef;
249 network_info->identity_info.account_name.string = username;
250 network_info->identity_info.workstation.string = clnt_name_slash;
252 memcpy(network_info->challenge, chal, 8);
253 network_info->nt = nt;
254 network_info->lm = lm;
256 logon->network = network_info;
258 break;
260 default:
261 DEBUG(0, ("switch value %d not supported\n",
262 logon_type));
263 return NT_STATUS_INVALID_INFO_CLASS;
266 result = rpccli_netr_LogonSamLogon(cli, mem_ctx,
267 cli->srv_name_slash,
268 global_myname(),
269 &clnt_creds,
270 &ret_creds,
271 logon_type,
272 logon,
273 validation_level,
274 &validation,
275 &authoritative);
277 /* Always check returned credentials */
278 if (!netlogon_creds_client_check(cli->dc, &ret_creds.cred)) {
279 DEBUG(0,("rpccli_netlogon_sam_logon: credentials chain check failed\n"));
280 return NT_STATUS_ACCESS_DENIED;
283 return result;
288 * Logon domain user with an 'network' SAM logon
290 * @param info3 Pointer to a NET_USER_INFO_3 already allocated by the caller.
293 NTSTATUS rpccli_netlogon_sam_network_logon(struct rpc_pipe_client *cli,
294 TALLOC_CTX *mem_ctx,
295 uint32 logon_parameters,
296 const char *server,
297 const char *username,
298 const char *domain,
299 const char *workstation,
300 const uint8 chal[8],
301 DATA_BLOB lm_response,
302 DATA_BLOB nt_response,
303 struct netr_SamInfo3 **info3)
305 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
306 int validation_level = 3;
307 const char *workstation_name_slash;
308 const char *server_name_slash;
309 struct netr_Authenticator clnt_creds;
310 struct netr_Authenticator ret_creds;
311 union netr_LogonLevel *logon = NULL;
312 struct netr_NetworkInfo *network_info;
313 uint8_t authoritative;
314 union netr_Validation validation;
315 struct netr_ChallengeResponse lm;
316 struct netr_ChallengeResponse nt;
318 *info3 = NULL;
320 ZERO_STRUCT(ret_creds);
322 ZERO_STRUCT(lm);
323 ZERO_STRUCT(nt);
325 logon = TALLOC_ZERO_P(mem_ctx, union netr_LogonLevel);
326 if (!logon) {
327 return NT_STATUS_NO_MEMORY;
330 network_info = TALLOC_ZERO_P(mem_ctx, struct netr_NetworkInfo);
331 if (!network_info) {
332 return NT_STATUS_NO_MEMORY;
335 netlogon_creds_client_authenticator(cli->dc, &clnt_creds);
337 if (server[0] != '\\' && server[1] != '\\') {
338 server_name_slash = talloc_asprintf(mem_ctx, "\\\\%s", server);
339 } else {
340 server_name_slash = server;
343 if (workstation[0] != '\\' && workstation[1] != '\\') {
344 workstation_name_slash = talloc_asprintf(mem_ctx, "\\\\%s", workstation);
345 } else {
346 workstation_name_slash = workstation;
349 if (!workstation_name_slash || !server_name_slash) {
350 DEBUG(0, ("talloc_asprintf failed!\n"));
351 return NT_STATUS_NO_MEMORY;
354 /* Initialise input parameters */
356 lm.data = lm_response.data;
357 lm.length = lm_response.length;
358 nt.data = nt_response.data;
359 nt.length = nt_response.length;
361 network_info->identity_info.domain_name.string = domain;
362 network_info->identity_info.parameter_control = logon_parameters;
363 network_info->identity_info.logon_id_low = 0xdead;
364 network_info->identity_info.logon_id_high = 0xbeef;
365 network_info->identity_info.account_name.string = username;
366 network_info->identity_info.workstation.string = workstation_name_slash;
368 memcpy(network_info->challenge, chal, 8);
369 network_info->nt = nt;
370 network_info->lm = lm;
372 logon->network = network_info;
374 /* Marshall data and send request */
376 result = rpccli_netr_LogonSamLogon(cli, mem_ctx,
377 server_name_slash,
378 global_myname(),
379 &clnt_creds,
380 &ret_creds,
381 NetlogonNetworkInformation,
382 logon,
383 validation_level,
384 &validation,
385 &authoritative);
386 if (!NT_STATUS_IS_OK(result)) {
387 return result;
390 /* Always check returned credentials. */
391 if (!netlogon_creds_client_check(cli->dc, &ret_creds.cred)) {
392 DEBUG(0,("rpccli_netlogon_sam_network_logon: credentials chain check failed\n"));
393 return NT_STATUS_ACCESS_DENIED;
396 netlogon_creds_decrypt_samlogon(cli->dc, validation_level, &validation);
398 *info3 = validation.sam3;
400 return result;
403 NTSTATUS rpccli_netlogon_sam_network_logon_ex(struct rpc_pipe_client *cli,
404 TALLOC_CTX *mem_ctx,
405 uint32 logon_parameters,
406 const char *server,
407 const char *username,
408 const char *domain,
409 const char *workstation,
410 const uint8 chal[8],
411 DATA_BLOB lm_response,
412 DATA_BLOB nt_response,
413 struct netr_SamInfo3 **info3)
415 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
416 int validation_level = 3;
417 const char *workstation_name_slash;
418 const char *server_name_slash;
419 union netr_LogonLevel *logon = NULL;
420 struct netr_NetworkInfo *network_info;
421 uint8_t authoritative;
422 union netr_Validation validation;
423 struct netr_ChallengeResponse lm;
424 struct netr_ChallengeResponse nt;
425 uint32_t flags = 0;
427 *info3 = NULL;
429 ZERO_STRUCT(lm);
430 ZERO_STRUCT(nt);
432 logon = TALLOC_ZERO_P(mem_ctx, union netr_LogonLevel);
433 if (!logon) {
434 return NT_STATUS_NO_MEMORY;
437 network_info = TALLOC_ZERO_P(mem_ctx, struct netr_NetworkInfo);
438 if (!network_info) {
439 return NT_STATUS_NO_MEMORY;
442 if (server[0] != '\\' && server[1] != '\\') {
443 server_name_slash = talloc_asprintf(mem_ctx, "\\\\%s", server);
444 } else {
445 server_name_slash = server;
448 if (workstation[0] != '\\' && workstation[1] != '\\') {
449 workstation_name_slash = talloc_asprintf(mem_ctx, "\\\\%s", workstation);
450 } else {
451 workstation_name_slash = workstation;
454 if (!workstation_name_slash || !server_name_slash) {
455 DEBUG(0, ("talloc_asprintf failed!\n"));
456 return NT_STATUS_NO_MEMORY;
459 /* Initialise input parameters */
461 lm.data = lm_response.data;
462 lm.length = lm_response.length;
463 nt.data = nt_response.data;
464 nt.length = nt_response.length;
466 network_info->identity_info.domain_name.string = domain;
467 network_info->identity_info.parameter_control = logon_parameters;
468 network_info->identity_info.logon_id_low = 0xdead;
469 network_info->identity_info.logon_id_high = 0xbeef;
470 network_info->identity_info.account_name.string = username;
471 network_info->identity_info.workstation.string = workstation_name_slash;
473 memcpy(network_info->challenge, chal, 8);
474 network_info->nt = nt;
475 network_info->lm = lm;
477 logon->network = network_info;
479 /* Marshall data and send request */
481 result = rpccli_netr_LogonSamLogonEx(cli, mem_ctx,
482 server_name_slash,
483 global_myname(),
484 NetlogonNetworkInformation,
485 logon,
486 validation_level,
487 &validation,
488 &authoritative,
489 &flags);
490 if (!NT_STATUS_IS_OK(result)) {
491 return result;
494 netlogon_creds_decrypt_samlogon(cli->dc, validation_level, &validation);
496 *info3 = validation.sam3;
498 return result;
501 /*********************************************************
502 Change the domain password on the PDC.
504 Just changes the password betwen the two values specified.
506 Caller must have the cli connected to the netlogon pipe
507 already.
508 **********************************************************/
510 NTSTATUS rpccli_netlogon_set_trust_password(struct rpc_pipe_client *cli,
511 TALLOC_CTX *mem_ctx,
512 const char *account_name,
513 const unsigned char orig_trust_passwd_hash[16],
514 const char *new_trust_pwd_cleartext,
515 const unsigned char new_trust_passwd_hash[16],
516 enum netr_SchannelType sec_channel_type)
518 NTSTATUS result;
519 struct netr_Authenticator clnt_creds, srv_cred;
521 if (!cli->dc) {
522 uint32_t neg_flags = NETLOGON_NEG_AUTH2_ADS_FLAGS;
523 result = rpccli_netlogon_setup_creds(cli,
524 cli->desthost, /* server name */
525 lp_workgroup(), /* domain */
526 global_myname(), /* client name */
527 account_name, /* machine account name */
528 orig_trust_passwd_hash,
529 sec_channel_type,
530 &neg_flags);
531 if (!NT_STATUS_IS_OK(result)) {
532 DEBUG(3,("rpccli_netlogon_set_trust_password: unable to setup creds (%s)!\n",
533 nt_errstr(result)));
534 return result;
538 netlogon_creds_client_authenticator(cli->dc, &clnt_creds);
540 if (cli->dc->negotiate_flags & NETLOGON_NEG_PASSWORD_SET2) {
542 struct netr_CryptPassword new_password;
544 init_netr_CryptPassword(new_trust_pwd_cleartext,
545 cli->dc->session_key,
546 &new_password);
548 result = rpccli_netr_ServerPasswordSet2(cli, mem_ctx,
549 cli->srv_name_slash,
550 cli->dc->account_name,
551 sec_channel_type,
552 cli->dc->computer_name,
553 &clnt_creds,
554 &srv_cred,
555 &new_password);
556 if (!NT_STATUS_IS_OK(result)) {
557 DEBUG(0,("rpccli_netr_ServerPasswordSet2 failed: %s\n",
558 nt_errstr(result)));
559 return result;
561 } else {
563 struct samr_Password new_password;
564 memcpy(new_password.hash, new_trust_passwd_hash, sizeof(new_password.hash));
565 netlogon_creds_des_encrypt(cli->dc, &new_password);
567 result = rpccli_netr_ServerPasswordSet(cli, mem_ctx,
568 cli->srv_name_slash,
569 cli->dc->account_name,
570 sec_channel_type,
571 cli->dc->computer_name,
572 &clnt_creds,
573 &srv_cred,
574 &new_password);
575 if (!NT_STATUS_IS_OK(result)) {
576 DEBUG(0,("rpccli_netr_ServerPasswordSet failed: %s\n",
577 nt_errstr(result)));
578 return result;
582 /* Always check returned credentials. */
583 if (!netlogon_creds_client_check(cli->dc, &srv_cred.cred)) {
584 DEBUG(0,("credentials chain check failed\n"));
585 return NT_STATUS_ACCESS_DENIED;
588 return result;