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/>.
24 #include "libsmb/libsmb.h"
25 #include "rpc_client/rpc_client.h"
26 #include "rpc_client/cli_pipe.h"
27 #include "../libcli/auth/libcli_auth.h"
28 #include "../libcli/auth/netlogon_creds_cli.h"
29 #include "../librpc/gen_ndr/ndr_netlogon_c.h"
30 #include "../librpc/gen_ndr/schannel.h"
31 #include "rpc_client/cli_netlogon.h"
32 #include "rpc_client/init_netlogon.h"
33 #include "rpc_client/util_netlogon.h"
34 #include "../libcli/security/security.h"
35 #include "lib/param/param.h"
36 #include "libcli/smb/smbXcli_base.h"
38 /****************************************************************************
39 Wrapper function that uses the auth and auth2 calls to set up a NETLOGON
40 credentials chain. Stores the credentials in the struct dcinfo in the
42 ****************************************************************************/
44 NTSTATUS rpccli_netlogon_setup_creds(struct rpc_pipe_client *cli,
45 const char *server_name,
47 const char *clnt_name,
48 const char *machine_account,
49 const unsigned char machine_pwd[16],
50 enum netr_SchannelType sec_chan_type,
51 uint32_t *neg_flags_inout)
53 TALLOC_CTX *frame = talloc_stackframe();
54 struct loadparm_context *lp_ctx;
56 struct samr_Password password;
58 struct dcerpc_binding_handle *b = cli->binding_handle;
59 struct netlogon_creds_CredentialState *creds = NULL;
61 if (!ndr_syntax_id_equal(&cli->abstract_syntax,
62 &ndr_table_netlogon.syntax_id)) {
64 return NT_STATUS_INVALID_PARAMETER;
67 if (!strequal(lp_netbios_name(), clnt_name)) {
69 return NT_STATUS_INVALID_PARAMETER;
72 TALLOC_FREE(cli->netlogon_creds);
74 fstr_sprintf( mach_acct, "%s$", machine_account);
76 lp_ctx = loadparm_init_s3(frame, loadparm_s3_helpers());
79 return NT_STATUS_NO_MEMORY;
81 status = netlogon_creds_cli_context_global(lp_ctx,
87 cli, &cli->netlogon_creds);
88 talloc_unlink(frame, lp_ctx);
89 if (!NT_STATUS_IS_OK(status)) {
94 status = netlogon_creds_cli_get(cli->netlogon_creds,
96 if (NT_STATUS_IS_OK(status)) {
97 DEBUG(5,("rpccli_netlogon_setup_creds: server %s using "
98 "cached credential\n",
100 *neg_flags_inout = creds->negotiate_flags;
105 /* Store the machine account password we're going to use. */
106 memcpy(password.hash, machine_pwd, 16);
108 DEBUG(5,("rpccli_netlogon_setup_creds: server %s credential "
109 "chain established.\n",
112 status = netlogon_creds_cli_auth(cli->netlogon_creds, b,
114 if (!NT_STATUS_IS_OK(status)) {
119 status = netlogon_creds_cli_get(cli->netlogon_creds,
121 if (!NT_STATUS_IS_OK(status)) {
123 return NT_STATUS_INTERNAL_ERROR;
126 *neg_flags_inout = creds->negotiate_flags;
131 NTSTATUS rpccli_pre_open_netlogon_creds(void)
133 TALLOC_CTX *frame = talloc_stackframe();
134 struct loadparm_context *lp_ctx;
137 lp_ctx = loadparm_init_s3(frame, loadparm_s3_helpers());
138 if (lp_ctx == NULL) {
140 return NT_STATUS_NO_MEMORY;
143 status = netlogon_creds_cli_open_global_db(lp_ctx);
145 if (!NT_STATUS_IS_OK(status)) {
152 NTSTATUS rpccli_create_netlogon_creds(const char *server_computer,
153 const char *server_netbios_domain,
154 const char *client_account,
155 enum netr_SchannelType sec_chan_type,
156 struct messaging_context *msg_ctx,
158 struct netlogon_creds_cli_context **netlogon_creds)
160 TALLOC_CTX *frame = talloc_stackframe();
161 struct loadparm_context *lp_ctx;
164 lp_ctx = loadparm_init_s3(frame, loadparm_s3_helpers());
165 if (lp_ctx == NULL) {
167 return NT_STATUS_NO_MEMORY;
169 status = netlogon_creds_cli_context_global(lp_ctx,
174 server_netbios_domain,
175 mem_ctx, netlogon_creds);
177 if (!NT_STATUS_IS_OK(status)) {
184 NTSTATUS rpccli_setup_netlogon_creds(struct cli_state *cli,
185 struct netlogon_creds_cli_context *netlogon_creds,
187 struct samr_Password current_nt_hash,
188 const struct samr_Password *previous_nt_hash)
190 TALLOC_CTX *frame = talloc_stackframe();
191 struct rpc_pipe_client *netlogon_pipe = NULL;
192 struct netlogon_creds_CredentialState *creds = NULL;
195 status = netlogon_creds_cli_get(netlogon_creds,
197 if (NT_STATUS_IS_OK(status)) {
198 const char *action = "using";
201 action = "overwrite";
204 DEBUG(5,("%s: %s cached netlogon_creds cli[%s/%s] to %s\n",
205 __FUNCTION__, action,
206 creds->account_name, creds->computer_name,
207 smbXcli_conn_remote_name(cli->conn)));
215 status = cli_rpc_pipe_open_noauth(cli,
218 if (!NT_STATUS_IS_OK(status)) {
219 DEBUG(5,("%s: failed to open noauth netlogon connection to %s - %s\n",
221 smbXcli_conn_remote_name(cli->conn),
226 talloc_steal(frame, netlogon_pipe);
228 status = netlogon_creds_cli_auth(netlogon_creds,
229 netlogon_pipe->binding_handle,
232 if (!NT_STATUS_IS_OK(status)) {
237 status = netlogon_creds_cli_get(netlogon_creds,
239 if (!NT_STATUS_IS_OK(status)) {
241 return NT_STATUS_INTERNAL_ERROR;
244 DEBUG(5,("%s: using new netlogon_creds cli[%s/%s] to %s\n",
246 creds->account_name, creds->computer_name,
247 smbXcli_conn_remote_name(cli->conn)));
253 /* Logon domain user */
255 NTSTATUS rpccli_netlogon_sam_logon(struct rpc_pipe_client *cli,
257 uint32 logon_parameters,
259 const char *username,
260 const char *password,
261 const char *workstation,
262 uint16_t _ignored_validation_level,
266 union netr_LogonLevel *logon;
267 uint16_t validation_level = 0;
268 union netr_Validation *validation = NULL;
269 uint8_t authoritative = 0;
271 fstring clnt_name_slash;
273 logon = talloc_zero(mem_ctx, union netr_LogonLevel);
275 return NT_STATUS_NO_MEMORY;
279 fstr_sprintf( clnt_name_slash, "\\\\%s", workstation );
281 fstr_sprintf( clnt_name_slash, "\\\\%s", lp_netbios_name() );
284 /* Initialise input parameters */
286 switch (logon_type) {
287 case NetlogonInteractiveInformation: {
289 struct netr_PasswordInfo *password_info;
291 struct samr_Password lmpassword;
292 struct samr_Password ntpassword;
294 password_info = talloc_zero(mem_ctx, struct netr_PasswordInfo);
295 if (!password_info) {
296 return NT_STATUS_NO_MEMORY;
299 nt_lm_owf_gen(password, ntpassword.hash, lmpassword.hash);
301 password_info->identity_info.domain_name.string = domain;
302 password_info->identity_info.parameter_control = logon_parameters;
303 password_info->identity_info.logon_id_low = 0xdead;
304 password_info->identity_info.logon_id_high = 0xbeef;
305 password_info->identity_info.account_name.string = username;
306 password_info->identity_info.workstation.string = clnt_name_slash;
308 password_info->lmpassword = lmpassword;
309 password_info->ntpassword = ntpassword;
311 logon->password = password_info;
315 case NetlogonNetworkInformation: {
316 struct netr_NetworkInfo *network_info;
318 unsigned char local_lm_response[24];
319 unsigned char local_nt_response[24];
320 struct netr_ChallengeResponse lm;
321 struct netr_ChallengeResponse nt;
326 network_info = talloc_zero(mem_ctx, struct netr_NetworkInfo);
328 return NT_STATUS_NO_MEMORY;
331 generate_random_buffer(chal, 8);
333 SMBencrypt(password, chal, local_lm_response);
334 SMBNTencrypt(password, chal, local_nt_response);
337 lm.data = local_lm_response;
340 nt.data = local_nt_response;
342 network_info->identity_info.domain_name.string = domain;
343 network_info->identity_info.parameter_control = logon_parameters;
344 network_info->identity_info.logon_id_low = 0xdead;
345 network_info->identity_info.logon_id_high = 0xbeef;
346 network_info->identity_info.account_name.string = username;
347 network_info->identity_info.workstation.string = clnt_name_slash;
349 memcpy(network_info->challenge, chal, 8);
350 network_info->nt = nt;
351 network_info->lm = lm;
353 logon->network = network_info;
358 DEBUG(0, ("switch value %d not supported\n",
360 return NT_STATUS_INVALID_INFO_CLASS;
363 status = netlogon_creds_cli_LogonSamLogon(cli->netlogon_creds,
372 if (!NT_STATUS_IS_OK(status)) {
379 static NTSTATUS map_validation_to_info3(TALLOC_CTX *mem_ctx,
380 uint16_t validation_level,
381 union netr_Validation *validation,
382 struct netr_SamInfo3 **info3_p)
384 struct netr_SamInfo3 *info3;
387 if (validation == NULL) {
388 return NT_STATUS_INVALID_PARAMETER;
391 switch (validation_level) {
393 if (validation->sam3 == NULL) {
394 return NT_STATUS_INVALID_PARAMETER;
397 info3 = talloc_move(mem_ctx, &validation->sam3);
400 if (validation->sam6 == NULL) {
401 return NT_STATUS_INVALID_PARAMETER;
404 info3 = talloc_zero(mem_ctx, struct netr_SamInfo3);
406 return NT_STATUS_NO_MEMORY;
408 status = copy_netr_SamBaseInfo(info3, &validation->sam6->base, &info3->base);
409 if (!NT_STATUS_IS_OK(status)) {
414 info3->sidcount = validation->sam6->sidcount;
415 info3->sids = talloc_move(info3, &validation->sam6->sids);
418 return NT_STATUS_BAD_VALIDATION_CLASS;
427 * Logon domain user with an 'network' SAM logon
429 * @param info3 Pointer to a NET_USER_INFO_3 already allocated by the caller.
432 NTSTATUS rpccli_netlogon_sam_network_logon(struct rpc_pipe_client *cli,
434 uint32 logon_parameters,
436 const char *username,
438 const char *workstation,
440 uint16_t _ignored_validation_level,
441 DATA_BLOB lm_response,
442 DATA_BLOB nt_response,
443 struct netr_SamInfo3 **info3)
446 const char *workstation_name_slash;
447 union netr_LogonLevel *logon = NULL;
448 struct netr_NetworkInfo *network_info;
449 uint16_t validation_level = 0;
450 union netr_Validation *validation = NULL;
451 uint8_t authoritative = 0;
453 struct netr_ChallengeResponse lm;
454 struct netr_ChallengeResponse nt;
461 logon = talloc_zero(mem_ctx, union netr_LogonLevel);
463 return NT_STATUS_NO_MEMORY;
466 network_info = talloc_zero(mem_ctx, struct netr_NetworkInfo);
468 return NT_STATUS_NO_MEMORY;
471 if (workstation[0] != '\\' && workstation[1] != '\\') {
472 workstation_name_slash = talloc_asprintf(mem_ctx, "\\\\%s", workstation);
474 workstation_name_slash = workstation;
477 if (!workstation_name_slash) {
478 DEBUG(0, ("talloc_asprintf failed!\n"));
479 return NT_STATUS_NO_MEMORY;
482 /* Initialise input parameters */
484 lm.data = lm_response.data;
485 lm.length = lm_response.length;
486 nt.data = nt_response.data;
487 nt.length = nt_response.length;
489 network_info->identity_info.domain_name.string = domain;
490 network_info->identity_info.parameter_control = logon_parameters;
491 network_info->identity_info.logon_id_low = 0xdead;
492 network_info->identity_info.logon_id_high = 0xbeef;
493 network_info->identity_info.account_name.string = username;
494 network_info->identity_info.workstation.string = workstation_name_slash;
496 memcpy(network_info->challenge, chal, 8);
497 network_info->nt = nt;
498 network_info->lm = lm;
500 logon->network = network_info;
502 /* Marshall data and send request */
504 status = netlogon_creds_cli_LogonSamLogon(cli->netlogon_creds,
506 NetlogonNetworkInformation,
513 if (!NT_STATUS_IS_OK(status)) {
517 status = map_validation_to_info3(mem_ctx,
518 validation_level, validation,
520 if (!NT_STATUS_IS_OK(status)) {
527 NTSTATUS rpccli_netlogon_network_logon(struct netlogon_creds_cli_context *creds,
528 struct dcerpc_binding_handle *binding_handle,
530 uint32_t logon_parameters,
531 const char *username,
533 const char *workstation,
535 DATA_BLOB lm_response,
536 DATA_BLOB nt_response,
537 uint8_t *authoritative,
539 struct netr_SamInfo3 **info3)
542 const char *workstation_name_slash;
543 union netr_LogonLevel *logon = NULL;
544 struct netr_NetworkInfo *network_info;
545 uint16_t validation_level = 0;
546 union netr_Validation *validation = NULL;
547 uint8_t _authoritative = 0;
549 struct netr_ChallengeResponse lm;
550 struct netr_ChallengeResponse nt;
554 if (authoritative == NULL) {
555 authoritative = &_authoritative;
564 logon = talloc_zero(mem_ctx, union netr_LogonLevel);
566 return NT_STATUS_NO_MEMORY;
569 network_info = talloc_zero(mem_ctx, struct netr_NetworkInfo);
571 return NT_STATUS_NO_MEMORY;
574 if (workstation[0] != '\\' && workstation[1] != '\\') {
575 workstation_name_slash = talloc_asprintf(mem_ctx, "\\\\%s", workstation);
577 workstation_name_slash = workstation;
580 if (!workstation_name_slash) {
581 DEBUG(0, ("talloc_asprintf failed!\n"));
582 return NT_STATUS_NO_MEMORY;
585 /* Initialise input parameters */
587 lm.data = lm_response.data;
588 lm.length = lm_response.length;
589 nt.data = nt_response.data;
590 nt.length = nt_response.length;
592 network_info->identity_info.domain_name.string = domain;
593 network_info->identity_info.parameter_control = logon_parameters;
594 network_info->identity_info.logon_id_low = 0xdead;
595 network_info->identity_info.logon_id_high = 0xbeef;
596 network_info->identity_info.account_name.string = username;
597 network_info->identity_info.workstation.string = workstation_name_slash;
599 memcpy(network_info->challenge, chal, 8);
600 network_info->nt = nt;
601 network_info->lm = lm;
603 logon->network = network_info;
605 /* Marshall data and send request */
607 status = netlogon_creds_cli_LogonSamLogon(creds,
609 NetlogonNetworkInformation,
616 if (!NT_STATUS_IS_OK(status)) {
620 status = map_validation_to_info3(mem_ctx,
621 validation_level, validation,
623 if (!NT_STATUS_IS_OK(status)) {
630 /*********************************************************
631 Change the domain password on the PDC.
633 Just changes the password betwen the two values specified.
635 Caller must have the cli connected to the netlogon pipe
637 **********************************************************/
639 NTSTATUS rpccli_netlogon_set_trust_password(struct rpc_pipe_client *cli,
641 const char *account_name,
642 const unsigned char orig_trust_passwd_hash[16],
643 const char *new_trust_pwd_cleartext,
644 const unsigned char new_trust_passwd_hash[16],
645 enum netr_SchannelType sec_channel_type)
649 if (cli->netlogon_creds == NULL) {
650 uint32_t neg_flags = NETLOGON_NEG_AUTH2_ADS_FLAGS |
651 NETLOGON_NEG_SUPPORTS_AES;
652 result = rpccli_netlogon_setup_creds(cli,
653 cli->desthost, /* server name */
654 lp_workgroup(), /* domain */
655 lp_netbios_name(), /* client name */
656 account_name, /* machine account name */
657 orig_trust_passwd_hash,
660 if (!NT_STATUS_IS_OK(result)) {
661 DEBUG(3,("rpccli_netlogon_set_trust_password: unable to setup creds (%s)!\n",
667 result = netlogon_creds_cli_ServerPasswordSet(cli->netlogon_creds,
669 new_trust_pwd_cleartext,
670 NULL); /* new_version */
671 if (!NT_STATUS_IS_OK(result)) {
672 DEBUG(0,("netlogon_creds_cli_ServerPasswordSet failed: %s\n",