s4:librpc/rpc: make PyErr_SetDCERPCStatus() static
[Samba/gebeck_regimport.git] / source3 / rpc_client / cli_netlogon.c
blob3c4ddc21a429eee9cfa41a79110dfc343575b3b5
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"
27 /****************************************************************************
28 Wrapper function that uses the auth and auth2 calls to set up a NETLOGON
29 credentials chain. Stores the credentials in the struct dcinfo in the
30 netlogon pipe struct.
31 ****************************************************************************/
33 NTSTATUS rpccli_netlogon_setup_creds(struct rpc_pipe_client *cli,
34 const char *server_name,
35 const char *domain,
36 const char *clnt_name,
37 const char *machine_account,
38 const unsigned char machine_pwd[16],
39 enum netr_SchannelType sec_chan_type,
40 uint32_t *neg_flags_inout)
42 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
43 struct netr_Credential clnt_chal_send;
44 struct netr_Credential srv_chal_recv;
45 struct samr_Password password;
46 bool retried = false;
47 fstring mach_acct;
48 uint32_t neg_flags = *neg_flags_inout;
50 if (!ndr_syntax_id_equal(&cli->abstract_syntax,
51 &ndr_table_netlogon.syntax_id)) {
52 return NT_STATUS_INVALID_PARAMETER;
55 TALLOC_FREE(cli->dc);
57 /* Store the machine account password we're going to use. */
58 memcpy(password.hash, machine_pwd, 16);
60 fstr_sprintf( mach_acct, "%s$", machine_account);
62 again:
63 /* Create the client challenge. */
64 generate_random_buffer(clnt_chal_send.data, 8);
66 /* Get the server challenge. */
67 result = rpccli_netr_ServerReqChallenge(cli, talloc_tos(),
68 cli->srv_name_slash,
69 clnt_name,
70 &clnt_chal_send,
71 &srv_chal_recv);
72 if (!NT_STATUS_IS_OK(result)) {
73 return result;
76 /* Calculate the session key and client credentials */
78 cli->dc = netlogon_creds_client_init(cli,
79 mach_acct,
80 clnt_name,
81 &clnt_chal_send,
82 &srv_chal_recv,
83 &password,
84 &clnt_chal_send,
85 neg_flags);
87 if (!cli->dc) {
88 return NT_STATUS_NO_MEMORY;
92 * Send client auth-2 challenge and receive server repy.
95 result = rpccli_netr_ServerAuthenticate2(cli, talloc_tos(),
96 cli->srv_name_slash,
97 cli->dc->account_name,
98 sec_chan_type,
99 cli->dc->computer_name,
100 &clnt_chal_send, /* input. */
101 &srv_chal_recv, /* output. */
102 &neg_flags);
104 /* we might be talking to NT4, so let's downgrade in that case and retry
105 * with the returned neg_flags - gd */
107 if (NT_STATUS_EQUAL(result, NT_STATUS_ACCESS_DENIED) && !retried) {
108 retried = true;
109 TALLOC_FREE(cli->dc);
110 goto again;
113 if (!NT_STATUS_IS_OK(result)) {
114 return result;
118 * Check the returned value using the initial
119 * server received challenge.
122 if (!netlogon_creds_client_check(cli->dc, &srv_chal_recv)) {
124 * Server replied with bad credential. Fail.
126 DEBUG(0,("rpccli_netlogon_setup_creds: server %s "
127 "replied with bad credential\n",
128 cli->desthost ));
129 return NT_STATUS_ACCESS_DENIED;
132 DEBUG(5,("rpccli_netlogon_setup_creds: server %s credential "
133 "chain established.\n",
134 cli->desthost ));
136 cli->dc->negotiate_flags = neg_flags;
137 *neg_flags_inout = neg_flags;
139 return NT_STATUS_OK;
142 /* Logon domain user */
144 NTSTATUS rpccli_netlogon_sam_logon(struct rpc_pipe_client *cli,
145 TALLOC_CTX *mem_ctx,
146 uint32 logon_parameters,
147 const char *domain,
148 const char *username,
149 const char *password,
150 const char *workstation,
151 int logon_type)
153 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
154 struct netr_Authenticator clnt_creds;
155 struct netr_Authenticator ret_creds;
156 union netr_LogonLevel *logon;
157 union netr_Validation validation;
158 uint8_t authoritative;
159 int validation_level = 3;
160 fstring clnt_name_slash;
162 ZERO_STRUCT(ret_creds);
164 logon = TALLOC_ZERO_P(mem_ctx, union netr_LogonLevel);
165 if (!logon) {
166 return NT_STATUS_NO_MEMORY;
169 if (workstation) {
170 fstr_sprintf( clnt_name_slash, "\\\\%s", workstation );
171 } else {
172 fstr_sprintf( clnt_name_slash, "\\\\%s", global_myname() );
175 /* Initialise input parameters */
177 netlogon_creds_client_authenticator(cli->dc, &clnt_creds);
179 switch (logon_type) {
180 case NetlogonInteractiveInformation: {
182 struct netr_PasswordInfo *password_info;
184 struct samr_Password lmpassword;
185 struct samr_Password ntpassword;
187 password_info = TALLOC_ZERO_P(mem_ctx, struct netr_PasswordInfo);
188 if (!password_info) {
189 return NT_STATUS_NO_MEMORY;
192 nt_lm_owf_gen(password, ntpassword.hash, lmpassword.hash);
194 if (cli->dc->negotiate_flags & NETLOGON_NEG_ARCFOUR) {
195 netlogon_creds_arcfour_crypt(cli->dc, lmpassword.hash, 16);
196 netlogon_creds_arcfour_crypt(cli->dc, ntpassword.hash, 16);
197 } else {
198 netlogon_creds_des_encrypt(cli->dc, &lmpassword);
199 netlogon_creds_des_encrypt(cli->dc, &ntpassword);
202 password_info->identity_info.domain_name.string = domain;
203 password_info->identity_info.parameter_control = logon_parameters;
204 password_info->identity_info.logon_id_low = 0xdead;
205 password_info->identity_info.logon_id_high = 0xbeef;
206 password_info->identity_info.account_name.string = username;
207 password_info->identity_info.workstation.string = clnt_name_slash;
209 password_info->lmpassword = lmpassword;
210 password_info->ntpassword = ntpassword;
212 logon->password = password_info;
214 break;
216 case NetlogonNetworkInformation: {
217 struct netr_NetworkInfo *network_info;
218 uint8 chal[8];
219 unsigned char local_lm_response[24];
220 unsigned char local_nt_response[24];
221 struct netr_ChallengeResponse lm;
222 struct netr_ChallengeResponse nt;
224 ZERO_STRUCT(lm);
225 ZERO_STRUCT(nt);
227 network_info = TALLOC_ZERO_P(mem_ctx, struct netr_NetworkInfo);
228 if (!network_info) {
229 return NT_STATUS_NO_MEMORY;
232 generate_random_buffer(chal, 8);
234 SMBencrypt(password, chal, local_lm_response);
235 SMBNTencrypt(password, chal, local_nt_response);
237 lm.length = 24;
238 lm.data = local_lm_response;
240 nt.length = 24;
241 nt.data = local_nt_response;
243 network_info->identity_info.domain_name.string = domain;
244 network_info->identity_info.parameter_control = logon_parameters;
245 network_info->identity_info.logon_id_low = 0xdead;
246 network_info->identity_info.logon_id_high = 0xbeef;
247 network_info->identity_info.account_name.string = username;
248 network_info->identity_info.workstation.string = clnt_name_slash;
250 memcpy(network_info->challenge, chal, 8);
251 network_info->nt = nt;
252 network_info->lm = lm;
254 logon->network = network_info;
256 break;
258 default:
259 DEBUG(0, ("switch value %d not supported\n",
260 logon_type));
261 return NT_STATUS_INVALID_INFO_CLASS;
264 result = rpccli_netr_LogonSamLogon(cli, mem_ctx,
265 cli->srv_name_slash,
266 global_myname(),
267 &clnt_creds,
268 &ret_creds,
269 logon_type,
270 logon,
271 validation_level,
272 &validation,
273 &authoritative);
275 /* Always check returned credentials */
276 if (!netlogon_creds_client_check(cli->dc, &ret_creds.cred)) {
277 DEBUG(0,("rpccli_netlogon_sam_logon: credentials chain check failed\n"));
278 return NT_STATUS_ACCESS_DENIED;
281 return result;
286 * Logon domain user with an 'network' SAM logon
288 * @param info3 Pointer to a NET_USER_INFO_3 already allocated by the caller.
291 NTSTATUS rpccli_netlogon_sam_network_logon(struct rpc_pipe_client *cli,
292 TALLOC_CTX *mem_ctx,
293 uint32 logon_parameters,
294 const char *server,
295 const char *username,
296 const char *domain,
297 const char *workstation,
298 const uint8 chal[8],
299 DATA_BLOB lm_response,
300 DATA_BLOB nt_response,
301 struct netr_SamInfo3 **info3)
303 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
304 int validation_level = 3;
305 const char *workstation_name_slash;
306 const char *server_name_slash;
307 struct netr_Authenticator clnt_creds;
308 struct netr_Authenticator ret_creds;
309 union netr_LogonLevel *logon = NULL;
310 struct netr_NetworkInfo *network_info;
311 uint8_t authoritative;
312 union netr_Validation validation;
313 struct netr_ChallengeResponse lm;
314 struct netr_ChallengeResponse nt;
316 *info3 = NULL;
318 ZERO_STRUCT(ret_creds);
320 ZERO_STRUCT(lm);
321 ZERO_STRUCT(nt);
323 logon = TALLOC_ZERO_P(mem_ctx, union netr_LogonLevel);
324 if (!logon) {
325 return NT_STATUS_NO_MEMORY;
328 network_info = TALLOC_ZERO_P(mem_ctx, struct netr_NetworkInfo);
329 if (!network_info) {
330 return NT_STATUS_NO_MEMORY;
333 netlogon_creds_client_authenticator(cli->dc, &clnt_creds);
335 if (server[0] != '\\' && server[1] != '\\') {
336 server_name_slash = talloc_asprintf(mem_ctx, "\\\\%s", server);
337 } else {
338 server_name_slash = server;
341 if (workstation[0] != '\\' && workstation[1] != '\\') {
342 workstation_name_slash = talloc_asprintf(mem_ctx, "\\\\%s", workstation);
343 } else {
344 workstation_name_slash = workstation;
347 if (!workstation_name_slash || !server_name_slash) {
348 DEBUG(0, ("talloc_asprintf failed!\n"));
349 return NT_STATUS_NO_MEMORY;
352 /* Initialise input parameters */
354 lm.data = lm_response.data;
355 lm.length = lm_response.length;
356 nt.data = nt_response.data;
357 nt.length = nt_response.length;
359 network_info->identity_info.domain_name.string = domain;
360 network_info->identity_info.parameter_control = logon_parameters;
361 network_info->identity_info.logon_id_low = 0xdead;
362 network_info->identity_info.logon_id_high = 0xbeef;
363 network_info->identity_info.account_name.string = username;
364 network_info->identity_info.workstation.string = workstation_name_slash;
366 memcpy(network_info->challenge, chal, 8);
367 network_info->nt = nt;
368 network_info->lm = lm;
370 logon->network = network_info;
372 /* Marshall data and send request */
374 result = rpccli_netr_LogonSamLogon(cli, mem_ctx,
375 server_name_slash,
376 global_myname(),
377 &clnt_creds,
378 &ret_creds,
379 NetlogonNetworkInformation,
380 logon,
381 validation_level,
382 &validation,
383 &authoritative);
384 if (!NT_STATUS_IS_OK(result)) {
385 return result;
388 /* Always check returned credentials. */
389 if (!netlogon_creds_client_check(cli->dc, &ret_creds.cred)) {
390 DEBUG(0,("rpccli_netlogon_sam_network_logon: credentials chain check failed\n"));
391 return NT_STATUS_ACCESS_DENIED;
394 netlogon_creds_decrypt_samlogon(cli->dc, validation_level, &validation);
396 *info3 = validation.sam3;
398 return result;
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 DATA_BLOB lm_response,
410 DATA_BLOB nt_response,
411 struct netr_SamInfo3 **info3)
413 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
414 int validation_level = 3;
415 const char *workstation_name_slash;
416 const char *server_name_slash;
417 union netr_LogonLevel *logon = NULL;
418 struct netr_NetworkInfo *network_info;
419 uint8_t authoritative;
420 union netr_Validation validation;
421 struct netr_ChallengeResponse lm;
422 struct netr_ChallengeResponse nt;
423 uint32_t flags = 0;
425 *info3 = NULL;
427 ZERO_STRUCT(lm);
428 ZERO_STRUCT(nt);
430 logon = TALLOC_ZERO_P(mem_ctx, union netr_LogonLevel);
431 if (!logon) {
432 return NT_STATUS_NO_MEMORY;
435 network_info = TALLOC_ZERO_P(mem_ctx, struct netr_NetworkInfo);
436 if (!network_info) {
437 return NT_STATUS_NO_MEMORY;
440 if (server[0] != '\\' && server[1] != '\\') {
441 server_name_slash = talloc_asprintf(mem_ctx, "\\\\%s", server);
442 } else {
443 server_name_slash = server;
446 if (workstation[0] != '\\' && workstation[1] != '\\') {
447 workstation_name_slash = talloc_asprintf(mem_ctx, "\\\\%s", workstation);
448 } else {
449 workstation_name_slash = workstation;
452 if (!workstation_name_slash || !server_name_slash) {
453 DEBUG(0, ("talloc_asprintf failed!\n"));
454 return NT_STATUS_NO_MEMORY;
457 /* Initialise input parameters */
459 lm.data = lm_response.data;
460 lm.length = lm_response.length;
461 nt.data = nt_response.data;
462 nt.length = nt_response.length;
464 network_info->identity_info.domain_name.string = domain;
465 network_info->identity_info.parameter_control = logon_parameters;
466 network_info->identity_info.logon_id_low = 0xdead;
467 network_info->identity_info.logon_id_high = 0xbeef;
468 network_info->identity_info.account_name.string = username;
469 network_info->identity_info.workstation.string = workstation_name_slash;
471 memcpy(network_info->challenge, chal, 8);
472 network_info->nt = nt;
473 network_info->lm = lm;
475 logon->network = network_info;
477 /* Marshall data and send request */
479 result = rpccli_netr_LogonSamLogonEx(cli, mem_ctx,
480 server_name_slash,
481 global_myname(),
482 NetlogonNetworkInformation,
483 logon,
484 validation_level,
485 &validation,
486 &authoritative,
487 &flags);
488 if (!NT_STATUS_IS_OK(result)) {
489 return result;
492 netlogon_creds_decrypt_samlogon(cli->dc, validation_level, &validation);
494 *info3 = validation.sam3;
496 return result;
499 /*********************************************************
500 Change the domain password on the PDC.
502 Just changes the password betwen the two values specified.
504 Caller must have the cli connected to the netlogon pipe
505 already.
506 **********************************************************/
508 NTSTATUS rpccli_netlogon_set_trust_password(struct rpc_pipe_client *cli,
509 TALLOC_CTX *mem_ctx,
510 const char *account_name,
511 const unsigned char orig_trust_passwd_hash[16],
512 const char *new_trust_pwd_cleartext,
513 const unsigned char new_trust_passwd_hash[16],
514 enum netr_SchannelType sec_channel_type)
516 NTSTATUS result;
517 struct netr_Authenticator clnt_creds, srv_cred;
519 if (!cli->dc) {
520 uint32_t neg_flags = NETLOGON_NEG_AUTH2_ADS_FLAGS;
521 result = rpccli_netlogon_setup_creds(cli,
522 cli->desthost, /* server name */
523 lp_workgroup(), /* domain */
524 global_myname(), /* client name */
525 account_name, /* machine account name */
526 orig_trust_passwd_hash,
527 sec_channel_type,
528 &neg_flags);
529 if (!NT_STATUS_IS_OK(result)) {
530 DEBUG(3,("rpccli_netlogon_set_trust_password: unable to setup creds (%s)!\n",
531 nt_errstr(result)));
532 return result;
536 netlogon_creds_client_authenticator(cli->dc, &clnt_creds);
538 if (cli->dc->negotiate_flags & NETLOGON_NEG_PASSWORD_SET2) {
540 struct netr_CryptPassword new_password;
542 init_netr_CryptPassword(new_trust_pwd_cleartext,
543 cli->dc->session_key,
544 &new_password);
546 result = rpccli_netr_ServerPasswordSet2(cli, mem_ctx,
547 cli->srv_name_slash,
548 cli->dc->account_name,
549 sec_channel_type,
550 cli->dc->computer_name,
551 &clnt_creds,
552 &srv_cred,
553 &new_password);
554 if (!NT_STATUS_IS_OK(result)) {
555 DEBUG(0,("rpccli_netr_ServerPasswordSet2 failed: %s\n",
556 nt_errstr(result)));
557 return result;
559 } else {
561 struct samr_Password new_password;
562 memcpy(new_password.hash, new_trust_passwd_hash, sizeof(new_password.hash));
563 netlogon_creds_des_encrypt(cli->dc, &new_password);
565 result = rpccli_netr_ServerPasswordSet(cli, mem_ctx,
566 cli->srv_name_slash,
567 cli->dc->account_name,
568 sec_channel_type,
569 cli->dc->computer_name,
570 &clnt_creds,
571 &srv_cred,
572 &new_password);
573 if (!NT_STATUS_IS_OK(result)) {
574 DEBUG(0,("rpccli_netr_ServerPasswordSet failed: %s\n",
575 nt_errstr(result)));
576 return result;
580 /* Always check returned credentials. */
581 if (!netlogon_creds_client_check(cli->dc, &srv_cred.cred)) {
582 DEBUG(0,("credentials chain check failed\n"));
583 return NT_STATUS_ACCESS_DENIED;
586 return result;