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) {
104 TALLOC_FREE(cli->dc);
108 if (!NT_STATUS_IS_OK(result)) {
113 * Check the returned value using the initial
114 * server received challenge.
117 if (!netlogon_creds_client_check(cli->dc, &srv_chal_recv)) {
119 * Server replied with bad credential. Fail.
121 DEBUG(0,("rpccli_netlogon_setup_creds: server %s "
122 "replied with bad credential\n",
124 return NT_STATUS_ACCESS_DENIED;
127 DEBUG(5,("rpccli_netlogon_setup_creds: server %s credential "
128 "chain established.\n",
134 /* Logon domain user */
136 NTSTATUS rpccli_netlogon_sam_logon(struct rpc_pipe_client *cli,
138 uint32 logon_parameters,
140 const char *username,
141 const char *password,
142 const char *workstation,
145 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
146 struct netr_Authenticator clnt_creds;
147 struct netr_Authenticator ret_creds;
148 union netr_LogonLevel *logon;
149 union netr_Validation validation;
150 uint8_t authoritative;
151 int validation_level = 3;
152 fstring clnt_name_slash;
155 ZERO_STRUCT(ret_creds);
158 logon = TALLOC_ZERO_P(mem_ctx, union netr_LogonLevel);
160 return NT_STATUS_NO_MEMORY;
164 fstr_sprintf( clnt_name_slash, "\\\\%s", workstation );
166 fstr_sprintf( clnt_name_slash, "\\\\%s", global_myname() );
169 /* Initialise input parameters */
171 netlogon_creds_client_authenticator(cli->dc, &clnt_creds);
173 switch (logon_type) {
174 case NetlogonInteractiveInformation: {
176 struct netr_PasswordInfo *password_info;
178 struct samr_Password lmpassword;
179 struct samr_Password ntpassword;
181 password_info = TALLOC_ZERO_P(mem_ctx, struct netr_PasswordInfo);
182 if (!password_info) {
183 return NT_STATUS_NO_MEMORY;
186 nt_lm_owf_gen(password, ntpassword.hash, lmpassword.hash);
188 if (cli->dc->negotiate_flags & NETLOGON_NEG_ARCFOUR) {
189 netlogon_creds_arcfour_crypt(cli->dc, lmpassword.hash, 16);
190 netlogon_creds_arcfour_crypt(cli->dc, ntpassword.hash, 16);
192 netlogon_creds_des_encrypt(cli->dc, &lmpassword);
193 netlogon_creds_des_encrypt(cli->dc, &ntpassword);
196 init_netr_PasswordInfo(password_info,
206 logon->password = password_info;
210 case NetlogonNetworkInformation: {
211 struct netr_NetworkInfo *network_info;
213 unsigned char local_lm_response[24];
214 unsigned char local_nt_response[24];
215 struct netr_ChallengeResponse lm;
216 struct netr_ChallengeResponse nt;
221 network_info = TALLOC_ZERO_P(mem_ctx, struct netr_NetworkInfo);
223 return NT_STATUS_NO_MEMORY;
226 generate_random_buffer(chal, 8);
228 SMBencrypt(password, chal, local_lm_response);
229 SMBNTencrypt(password, chal, local_nt_response);
232 lm.data = local_lm_response;
235 nt.data = local_nt_response;
237 init_netr_NetworkInfo(network_info,
248 logon->network = network_info;
253 DEBUG(0, ("switch value %d not supported\n",
255 return NT_STATUS_INVALID_INFO_CLASS;
258 result = rpccli_netr_LogonSamLogon(cli, mem_ctx,
269 /* Always check returned credentials */
270 if (!netlogon_creds_client_check(cli->dc, &ret_creds.cred)) {
271 DEBUG(0,("rpccli_netlogon_sam_logon: credentials chain check failed\n"));
272 return NT_STATUS_ACCESS_DENIED;
280 * Logon domain user with an 'network' SAM logon
282 * @param info3 Pointer to a NET_USER_INFO_3 already allocated by the caller.
285 NTSTATUS rpccli_netlogon_sam_network_logon(struct rpc_pipe_client *cli,
287 uint32 logon_parameters,
289 const char *username,
291 const char *workstation,
293 DATA_BLOB lm_response,
294 DATA_BLOB nt_response,
295 struct netr_SamInfo3 **info3)
297 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
298 int validation_level = 3;
299 const char *workstation_name_slash;
300 const char *server_name_slash;
302 struct netr_Authenticator clnt_creds;
303 struct netr_Authenticator ret_creds;
304 union netr_LogonLevel *logon = NULL;
305 struct netr_NetworkInfo *network_info;
306 uint8_t authoritative;
307 union netr_Validation validation;
308 struct netr_ChallengeResponse lm;
309 struct netr_ChallengeResponse nt;
314 ZERO_STRUCT(ret_creds);
319 logon = TALLOC_ZERO_P(mem_ctx, union netr_LogonLevel);
321 return NT_STATUS_NO_MEMORY;
324 network_info = TALLOC_ZERO_P(mem_ctx, struct netr_NetworkInfo);
326 return NT_STATUS_NO_MEMORY;
329 netlogon_creds_client_authenticator(cli->dc, &clnt_creds);
331 if (server[0] != '\\' && server[1] != '\\') {
332 server_name_slash = talloc_asprintf(mem_ctx, "\\\\%s", server);
334 server_name_slash = server;
337 if (workstation[0] != '\\' && workstation[1] != '\\') {
338 workstation_name_slash = talloc_asprintf(mem_ctx, "\\\\%s", workstation);
340 workstation_name_slash = workstation;
343 if (!workstation_name_slash || !server_name_slash) {
344 DEBUG(0, ("talloc_asprintf failed!\n"));
345 return NT_STATUS_NO_MEMORY;
348 /* Initialise input parameters */
350 lm.data = lm_response.data;
351 lm.length = lm_response.length;
352 nt.data = nt_response.data;
353 nt.length = nt_response.length;
355 init_netr_NetworkInfo(network_info,
361 workstation_name_slash,
366 logon->network = network_info;
368 /* Marshall data and send request */
370 result = rpccli_netr_LogonSamLogon(cli, mem_ctx,
375 NetlogonNetworkInformation,
380 if (!NT_STATUS_IS_OK(result)) {
384 /* Always check returned credentials. */
385 if (!netlogon_creds_client_check(cli->dc, &ret_creds.cred)) {
386 DEBUG(0,("rpccli_netlogon_sam_network_logon: credentials chain check failed\n"));
387 return NT_STATUS_ACCESS_DENIED;
390 netlogon_creds_decrypt_samlogon(cli->dc, validation_level, &validation);
392 *info3 = validation.sam3;
397 NTSTATUS rpccli_netlogon_sam_network_logon_ex(struct rpc_pipe_client *cli,
399 uint32 logon_parameters,
401 const char *username,
403 const char *workstation,
405 DATA_BLOB lm_response,
406 DATA_BLOB nt_response,
407 struct netr_SamInfo3 **info3)
409 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
410 int validation_level = 3;
411 const char *workstation_name_slash;
412 const char *server_name_slash;
414 union netr_LogonLevel *logon = NULL;
415 struct netr_NetworkInfo *network_info;
416 uint8_t authoritative;
417 union netr_Validation validation;
418 struct netr_ChallengeResponse lm;
419 struct netr_ChallengeResponse nt;
429 logon = TALLOC_ZERO_P(mem_ctx, union netr_LogonLevel);
431 return NT_STATUS_NO_MEMORY;
434 network_info = TALLOC_ZERO_P(mem_ctx, struct netr_NetworkInfo);
436 return NT_STATUS_NO_MEMORY;
439 if (server[0] != '\\' && server[1] != '\\') {
440 server_name_slash = talloc_asprintf(mem_ctx, "\\\\%s", server);
442 server_name_slash = server;
445 if (workstation[0] != '\\' && workstation[1] != '\\') {
446 workstation_name_slash = talloc_asprintf(mem_ctx, "\\\\%s", workstation);
448 workstation_name_slash = workstation;
451 if (!workstation_name_slash || !server_name_slash) {
452 DEBUG(0, ("talloc_asprintf failed!\n"));
453 return NT_STATUS_NO_MEMORY;
456 /* Initialise input parameters */
458 lm.data = lm_response.data;
459 lm.length = lm_response.length;
460 nt.data = nt_response.data;
461 nt.length = nt_response.length;
463 init_netr_NetworkInfo(network_info,
469 workstation_name_slash,
474 logon->network = network_info;
476 /* Marshall data and send request */
478 result = rpccli_netr_LogonSamLogonEx(cli, mem_ctx,
481 NetlogonNetworkInformation,
487 if (!NT_STATUS_IS_OK(result)) {
491 netlogon_creds_decrypt_samlogon(cli->dc, validation_level, &validation);
493 *info3 = validation.sam3;
498 /*********************************************************
499 Change the domain password on the PDC.
501 Just changes the password betwen the two values specified.
503 Caller must have the cli connected to the netlogon pipe
505 **********************************************************/
507 NTSTATUS rpccli_netlogon_set_trust_password(struct rpc_pipe_client *cli,
509 const unsigned char orig_trust_passwd_hash[16],
510 const char *new_trust_pwd_cleartext,
511 const unsigned char new_trust_passwd_hash[16],
512 uint32_t sec_channel_type)
515 uint32_t neg_flags = NETLOGON_NEG_AUTH2_ADS_FLAGS;
516 struct netr_Authenticator clnt_creds, srv_cred;
518 result = rpccli_netlogon_setup_creds(cli,
519 cli->desthost, /* server name */
520 lp_workgroup(), /* domain */
521 global_myname(), /* client name */
522 global_myname(), /* machine account name */
523 orig_trust_passwd_hash,
527 if (!NT_STATUS_IS_OK(result)) {
528 DEBUG(3,("rpccli_netlogon_set_trust_password: unable to setup creds (%s)!\n",
533 netlogon_creds_client_authenticator(cli->dc, &clnt_creds);
535 if (neg_flags & NETLOGON_NEG_PASSWORD_SET2) {
537 struct netr_CryptPassword new_password;
539 init_netr_CryptPassword(new_trust_pwd_cleartext,
540 cli->dc->session_key,
543 result = rpccli_netr_ServerPasswordSet2(cli, mem_ctx,
545 cli->dc->account_name,
547 cli->dc->computer_name,
551 if (!NT_STATUS_IS_OK(result)) {
552 DEBUG(0,("rpccli_netr_ServerPasswordSet2 failed: %s\n",
558 struct samr_Password new_password;
559 memcpy(new_password.hash, new_trust_passwd_hash, sizeof(new_password.hash));
560 netlogon_creds_des_encrypt(cli->dc, &new_password);
562 result = rpccli_netr_ServerPasswordSet(cli, mem_ctx,
564 cli->dc->account_name,
566 cli->dc->computer_name,
570 if (!NT_STATUS_IS_OK(result)) {
571 DEBUG(0,("rpccli_netr_ServerPasswordSet failed: %s\n",
577 /* Always check returned credentials. */
578 if (!netlogon_creds_client_check(cli->dc, &srv_cred.cred)) {
579 DEBUG(0,("credentials chain check failed\n"));
580 return NT_STATUS_ACCESS_DENIED;