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 "../libcli/auth/libcli_auth.h"
26 /****************************************************************************
27 Wrapper function that uses the auth and auth2 calls to set up a NETLOGON
28 credentials chain. Stores the credentials in the struct dcinfo in the
30 ****************************************************************************/
32 NTSTATUS rpccli_netlogon_setup_creds(struct rpc_pipe_client *cli,
33 const char *server_name,
35 const char *clnt_name,
36 const char *machine_account,
37 const unsigned char machine_pwd[16],
38 enum netr_SchannelType sec_chan_type,
39 uint32_t *neg_flags_inout)
41 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
42 struct netr_Credential clnt_chal_send;
43 struct netr_Credential srv_chal_recv;
44 struct samr_Password password;
48 SMB_ASSERT(ndr_syntax_id_equal(&cli->abstract_syntax,
49 &ndr_table_netlogon.syntax_id));
53 /* Store the machine account password we're going to use. */
54 memcpy(password.hash, machine_pwd, 16);
56 fstr_sprintf( mach_acct, "%s$", machine_account);
59 /* Create the client challenge. */
60 generate_random_buffer(clnt_chal_send.data, 8);
62 /* Get the server challenge. */
63 result = rpccli_netr_ServerReqChallenge(cli, talloc_tos(),
68 if (!NT_STATUS_IS_OK(result)) {
72 /* Calculate the session key and client credentials */
74 cli->dc = netlogon_creds_client_init(cli,
84 return NT_STATUS_NO_MEMORY;
88 * Send client auth-2 challenge and receive server repy.
91 result = rpccli_netr_ServerAuthenticate2(cli, talloc_tos(),
93 cli->dc->account_name,
95 cli->dc->computer_name,
96 &clnt_chal_send, /* input. */
97 &srv_chal_recv, /* output. */
100 /* we might be talking to NT4, so let's downgrade in that case and retry
101 * with the returned neg_flags - gd */
103 if (NT_STATUS_EQUAL(result, NT_STATUS_ACCESS_DENIED) && !retried) {
105 TALLOC_FREE(cli->dc);
109 if (!NT_STATUS_IS_OK(result)) {
114 * Check the returned value using the initial
115 * server received challenge.
118 if (!netlogon_creds_client_check(cli->dc, &srv_chal_recv)) {
120 * Server replied with bad credential. Fail.
122 DEBUG(0,("rpccli_netlogon_setup_creds: server %s "
123 "replied with bad credential\n",
125 return NT_STATUS_ACCESS_DENIED;
128 DEBUG(5,("rpccli_netlogon_setup_creds: server %s credential "
129 "chain established.\n",
135 /* Logon domain user */
137 NTSTATUS rpccli_netlogon_sam_logon(struct rpc_pipe_client *cli,
139 uint32 logon_parameters,
141 const char *username,
142 const char *password,
143 const char *workstation,
146 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
147 struct netr_Authenticator clnt_creds;
148 struct netr_Authenticator ret_creds;
149 union netr_LogonLevel *logon;
150 union netr_Validation validation;
151 uint8_t authoritative;
152 int validation_level = 3;
153 fstring clnt_name_slash;
156 ZERO_STRUCT(ret_creds);
159 logon = TALLOC_ZERO_P(mem_ctx, union netr_LogonLevel);
161 return NT_STATUS_NO_MEMORY;
165 fstr_sprintf( clnt_name_slash, "\\\\%s", workstation );
167 fstr_sprintf( clnt_name_slash, "\\\\%s", global_myname() );
170 /* Initialise input parameters */
172 netlogon_creds_client_authenticator(cli->dc, &clnt_creds);
174 switch (logon_type) {
175 case NetlogonInteractiveInformation: {
177 struct netr_PasswordInfo *password_info;
179 struct samr_Password lmpassword;
180 struct samr_Password ntpassword;
182 password_info = TALLOC_ZERO_P(mem_ctx, struct netr_PasswordInfo);
183 if (!password_info) {
184 return NT_STATUS_NO_MEMORY;
187 nt_lm_owf_gen(password, ntpassword.hash, lmpassword.hash);
189 if (cli->dc->negotiate_flags & NETLOGON_NEG_ARCFOUR) {
190 netlogon_creds_arcfour_crypt(cli->dc, lmpassword.hash, 16);
191 netlogon_creds_arcfour_crypt(cli->dc, ntpassword.hash, 16);
193 netlogon_creds_des_encrypt(cli->dc, &lmpassword);
194 netlogon_creds_des_encrypt(cli->dc, &ntpassword);
197 init_netr_PasswordInfo(password_info,
207 logon->password = password_info;
211 case NetlogonNetworkInformation: {
212 struct netr_NetworkInfo *network_info;
214 unsigned char local_lm_response[24];
215 unsigned char local_nt_response[24];
216 struct netr_ChallengeResponse lm;
217 struct netr_ChallengeResponse nt;
222 network_info = TALLOC_ZERO_P(mem_ctx, struct netr_NetworkInfo);
224 return NT_STATUS_NO_MEMORY;
227 generate_random_buffer(chal, 8);
229 SMBencrypt(password, chal, local_lm_response);
230 SMBNTencrypt(password, chal, local_nt_response);
233 lm.data = local_lm_response;
236 nt.data = local_nt_response;
238 init_netr_NetworkInfo(network_info,
249 logon->network = network_info;
254 DEBUG(0, ("switch value %d not supported\n",
256 return NT_STATUS_INVALID_INFO_CLASS;
259 result = rpccli_netr_LogonSamLogon(cli, mem_ctx,
270 /* Always check returned credentials */
271 if (!netlogon_creds_client_check(cli->dc, &ret_creds.cred)) {
272 DEBUG(0,("rpccli_netlogon_sam_logon: credentials chain check failed\n"));
273 return NT_STATUS_ACCESS_DENIED;
281 * Logon domain user with an 'network' SAM logon
283 * @param info3 Pointer to a NET_USER_INFO_3 already allocated by the caller.
286 NTSTATUS rpccli_netlogon_sam_network_logon(struct rpc_pipe_client *cli,
288 uint32 logon_parameters,
290 const char *username,
292 const char *workstation,
294 DATA_BLOB lm_response,
295 DATA_BLOB nt_response,
296 struct netr_SamInfo3 **info3)
298 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
299 int validation_level = 3;
300 const char *workstation_name_slash;
301 const char *server_name_slash;
303 struct netr_Authenticator clnt_creds;
304 struct netr_Authenticator ret_creds;
305 union netr_LogonLevel *logon = NULL;
306 struct netr_NetworkInfo *network_info;
307 uint8_t authoritative;
308 union netr_Validation validation;
309 struct netr_ChallengeResponse lm;
310 struct netr_ChallengeResponse nt;
315 ZERO_STRUCT(ret_creds);
320 logon = TALLOC_ZERO_P(mem_ctx, union netr_LogonLevel);
322 return NT_STATUS_NO_MEMORY;
325 network_info = TALLOC_ZERO_P(mem_ctx, struct netr_NetworkInfo);
327 return NT_STATUS_NO_MEMORY;
330 netlogon_creds_client_authenticator(cli->dc, &clnt_creds);
332 if (server[0] != '\\' && server[1] != '\\') {
333 server_name_slash = talloc_asprintf(mem_ctx, "\\\\%s", server);
335 server_name_slash = server;
338 if (workstation[0] != '\\' && workstation[1] != '\\') {
339 workstation_name_slash = talloc_asprintf(mem_ctx, "\\\\%s", workstation);
341 workstation_name_slash = workstation;
344 if (!workstation_name_slash || !server_name_slash) {
345 DEBUG(0, ("talloc_asprintf failed!\n"));
346 return NT_STATUS_NO_MEMORY;
349 /* Initialise input parameters */
351 lm.data = lm_response.data;
352 lm.length = lm_response.length;
353 nt.data = nt_response.data;
354 nt.length = nt_response.length;
356 init_netr_NetworkInfo(network_info,
362 workstation_name_slash,
367 logon->network = network_info;
369 /* Marshall data and send request */
371 result = rpccli_netr_LogonSamLogon(cli, mem_ctx,
376 NetlogonNetworkInformation,
381 if (!NT_STATUS_IS_OK(result)) {
385 /* Always check returned credentials. */
386 if (!netlogon_creds_client_check(cli->dc, &ret_creds.cred)) {
387 DEBUG(0,("rpccli_netlogon_sam_network_logon: credentials chain check failed\n"));
388 return NT_STATUS_ACCESS_DENIED;
391 netlogon_creds_decrypt_samlogon(cli->dc, validation_level, &validation);
393 *info3 = validation.sam3;
398 NTSTATUS rpccli_netlogon_sam_network_logon_ex(struct rpc_pipe_client *cli,
400 uint32 logon_parameters,
402 const char *username,
404 const char *workstation,
406 DATA_BLOB lm_response,
407 DATA_BLOB nt_response,
408 struct netr_SamInfo3 **info3)
410 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
411 int validation_level = 3;
412 const char *workstation_name_slash;
413 const char *server_name_slash;
415 union netr_LogonLevel *logon = NULL;
416 struct netr_NetworkInfo *network_info;
417 uint8_t authoritative;
418 union netr_Validation validation;
419 struct netr_ChallengeResponse lm;
420 struct netr_ChallengeResponse nt;
430 logon = TALLOC_ZERO_P(mem_ctx, union netr_LogonLevel);
432 return NT_STATUS_NO_MEMORY;
435 network_info = TALLOC_ZERO_P(mem_ctx, struct netr_NetworkInfo);
437 return NT_STATUS_NO_MEMORY;
440 if (server[0] != '\\' && server[1] != '\\') {
441 server_name_slash = talloc_asprintf(mem_ctx, "\\\\%s", server);
443 server_name_slash = server;
446 if (workstation[0] != '\\' && workstation[1] != '\\') {
447 workstation_name_slash = talloc_asprintf(mem_ctx, "\\\\%s", workstation);
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 init_netr_NetworkInfo(network_info,
470 workstation_name_slash,
475 logon->network = network_info;
477 /* Marshall data and send request */
479 result = rpccli_netr_LogonSamLogonEx(cli, mem_ctx,
482 NetlogonNetworkInformation,
488 if (!NT_STATUS_IS_OK(result)) {
492 netlogon_creds_decrypt_samlogon(cli->dc, validation_level, &validation);
494 *info3 = validation.sam3;
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
506 **********************************************************/
508 NTSTATUS rpccli_netlogon_set_trust_password(struct rpc_pipe_client *cli,
510 const unsigned char orig_trust_passwd_hash[16],
511 const char *new_trust_pwd_cleartext,
512 const unsigned char new_trust_passwd_hash[16],
513 uint32_t sec_channel_type)
516 uint32_t neg_flags = NETLOGON_NEG_AUTH2_ADS_FLAGS;
517 struct netr_Authenticator clnt_creds, srv_cred;
519 result = rpccli_netlogon_setup_creds(cli,
520 cli->desthost, /* server name */
521 lp_workgroup(), /* domain */
522 global_myname(), /* client name */
523 global_myname(), /* machine account name */
524 orig_trust_passwd_hash,
528 if (!NT_STATUS_IS_OK(result)) {
529 DEBUG(3,("rpccli_netlogon_set_trust_password: unable to setup creds (%s)!\n",
534 netlogon_creds_client_authenticator(cli->dc, &clnt_creds);
536 if (neg_flags & NETLOGON_NEG_PASSWORD_SET2) {
538 struct netr_CryptPassword new_password;
540 init_netr_CryptPassword(new_trust_pwd_cleartext,
541 cli->dc->session_key,
544 result = rpccli_netr_ServerPasswordSet2(cli, mem_ctx,
546 cli->dc->account_name,
548 cli->dc->computer_name,
552 if (!NT_STATUS_IS_OK(result)) {
553 DEBUG(0,("rpccli_netr_ServerPasswordSet2 failed: %s\n",
559 struct samr_Password new_password;
560 memcpy(new_password.hash, new_trust_passwd_hash, sizeof(new_password.hash));
561 netlogon_creds_des_encrypt(cli->dc, &new_password);
563 result = rpccli_netr_ServerPasswordSet(cli, mem_ctx,
565 cli->dc->account_name,
567 cli->dc->computer_name,
571 if (!NT_STATUS_IS_OK(result)) {
572 DEBUG(0,("rpccli_netr_ServerPasswordSet failed: %s\n",
578 /* Always check returned credentials. */
579 if (!netlogon_creds_client_check(cli->dc, &srv_cred.cred)) {
580 DEBUG(0,("credentials chain check failed\n"));
581 return NT_STATUS_ACCESS_DENIED;