source: vendor/current/source3/rpc_client/cli_netlogon.c@ 414

Last change on this file since 414 was 414, checked in by Herwig Bauernfeind, 16 years ago

Samba 3.5.0: Initial import

File size: 16.2 KB
Line 
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.
8
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.
13
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.
18
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/>.
21*/
22
23#include "includes.h"
24#include "../libcli/auth/libcli_auth.h"
25#include "../librpc/gen_ndr/cli_netlogon.h"
26
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****************************************************************************/
32
33NTSTATUS 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)
41{
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;
49
50 if (!ndr_syntax_id_equal(&cli->abstract_syntax,
51 &ndr_table_netlogon.syntax_id)) {
52 return NT_STATUS_INVALID_PARAMETER;
53 }
54
55 TALLOC_FREE(cli->dc);
56
57 /* Store the machine account password we're going to use. */
58 memcpy(password.hash, machine_pwd, 16);
59
60 fstr_sprintf( mach_acct, "%s$", machine_account);
61
62 again:
63 /* Create the client challenge. */
64 generate_random_buffer(clnt_chal_send.data, 8);
65
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;
74 }
75
76 /* Calculate the session key and client credentials */
77
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);
86
87 if (!cli->dc) {
88 return NT_STATUS_NO_MEMORY;
89 }
90
91 /*
92 * Send client auth-2 challenge and receive server repy.
93 */
94
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);
103
104 /* we might be talking to NT4, so let's downgrade in that case and retry
105 * with the returned neg_flags - gd */
106
107 if (NT_STATUS_EQUAL(result, NT_STATUS_ACCESS_DENIED) && !retried) {
108 retried = true;
109 TALLOC_FREE(cli->dc);
110 goto again;
111 }
112
113 if (!NT_STATUS_IS_OK(result)) {
114 return result;
115 }
116
117 /*
118 * Check the returned value using the initial
119 * server received challenge.
120 */
121
122 if (!netlogon_creds_client_check(cli->dc, &srv_chal_recv)) {
123 /*
124 * Server replied with bad credential. Fail.
125 */
126 DEBUG(0,("rpccli_netlogon_setup_creds: server %s "
127 "replied with bad credential\n",
128 cli->desthost ));
129 return NT_STATUS_ACCESS_DENIED;
130 }
131
132 DEBUG(5,("rpccli_netlogon_setup_creds: server %s credential "
133 "chain established.\n",
134 cli->desthost ));
135
136 cli->dc->negotiate_flags = neg_flags;
137 *neg_flags_inout = neg_flags;
138
139 return NT_STATUS_OK;
140}
141
142/* Logon domain user */
143
144NTSTATUS 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)
152{
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;
161 uint8 zeros[16];
162
163 ZERO_STRUCT(ret_creds);
164 ZERO_STRUCT(zeros);
165
166 logon = TALLOC_ZERO_P(mem_ctx, union netr_LogonLevel);
167 if (!logon) {
168 return NT_STATUS_NO_MEMORY;
169 }
170
171 if (workstation) {
172 fstr_sprintf( clnt_name_slash, "\\\\%s", workstation );
173 } else {
174 fstr_sprintf( clnt_name_slash, "\\\\%s", global_myname() );
175 }
176
177 /* Initialise input parameters */
178
179 netlogon_creds_client_authenticator(cli->dc, &clnt_creds);
180
181 switch (logon_type) {
182 case NetlogonInteractiveInformation: {
183
184 struct netr_PasswordInfo *password_info;
185
186 struct samr_Password lmpassword;
187 struct samr_Password ntpassword;
188
189 password_info = TALLOC_ZERO_P(mem_ctx, struct netr_PasswordInfo);
190 if (!password_info) {
191 return NT_STATUS_NO_MEMORY;
192 }
193
194 nt_lm_owf_gen(password, ntpassword.hash, lmpassword.hash);
195
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);
202 }
203
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;
210
211 password_info->lmpassword = lmpassword;
212 password_info->ntpassword = ntpassword;
213
214 logon->password = password_info;
215
216 break;
217 }
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;
225
226 ZERO_STRUCT(lm);
227 ZERO_STRUCT(nt);
228
229 network_info = TALLOC_ZERO_P(mem_ctx, struct netr_NetworkInfo);
230 if (!network_info) {
231 return NT_STATUS_NO_MEMORY;
232 }
233
234 generate_random_buffer(chal, 8);
235
236 SMBencrypt(password, chal, local_lm_response);
237 SMBNTencrypt(password, chal, local_nt_response);
238
239 lm.length = 24;
240 lm.data = local_lm_response;
241
242 nt.length = 24;
243 nt.data = local_nt_response;
244
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;
251
252 memcpy(network_info->challenge, chal, 8);
253 network_info->nt = nt;
254 network_info->lm = lm;
255
256 logon->network = network_info;
257
258 break;
259 }
260 default:
261 DEBUG(0, ("switch value %d not supported\n",
262 logon_type));
263 return NT_STATUS_INVALID_INFO_CLASS;
264 }
265
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);
276
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;
281 }
282
283 return result;
284}
285
286
287/**
288 * Logon domain user with an 'network' SAM logon
289 *
290 * @param info3 Pointer to a NET_USER_INFO_3 already allocated by the caller.
291 **/
292
293NTSTATUS 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)
304{
305 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
306 int validation_level = 3;
307 const char *workstation_name_slash;
308 const char *server_name_slash;
309 uint8 zeros[16];
310 struct netr_Authenticator clnt_creds;
311 struct netr_Authenticator ret_creds;
312 union netr_LogonLevel *logon = NULL;
313 struct netr_NetworkInfo *network_info;
314 uint8_t authoritative;
315 union netr_Validation validation;
316 struct netr_ChallengeResponse lm;
317 struct netr_ChallengeResponse nt;
318
319 *info3 = NULL;
320
321 ZERO_STRUCT(zeros);
322 ZERO_STRUCT(ret_creds);
323
324 ZERO_STRUCT(lm);
325 ZERO_STRUCT(nt);
326
327 logon = TALLOC_ZERO_P(mem_ctx, union netr_LogonLevel);
328 if (!logon) {
329 return NT_STATUS_NO_MEMORY;
330 }
331
332 network_info = TALLOC_ZERO_P(mem_ctx, struct netr_NetworkInfo);
333 if (!network_info) {
334 return NT_STATUS_NO_MEMORY;
335 }
336
337 netlogon_creds_client_authenticator(cli->dc, &clnt_creds);
338
339 if (server[0] != '\\' && server[1] != '\\') {
340 server_name_slash = talloc_asprintf(mem_ctx, "\\\\%s", server);
341 } else {
342 server_name_slash = server;
343 }
344
345 if (workstation[0] != '\\' && workstation[1] != '\\') {
346 workstation_name_slash = talloc_asprintf(mem_ctx, "\\\\%s", workstation);
347 } else {
348 workstation_name_slash = workstation;
349 }
350
351 if (!workstation_name_slash || !server_name_slash) {
352 DEBUG(0, ("talloc_asprintf failed!\n"));
353 return NT_STATUS_NO_MEMORY;
354 }
355
356 /* Initialise input parameters */
357
358 lm.data = lm_response.data;
359 lm.length = lm_response.length;
360 nt.data = nt_response.data;
361 nt.length = nt_response.length;
362
363 network_info->identity_info.domain_name.string = domain;
364 network_info->identity_info.parameter_control = logon_parameters;
365 network_info->identity_info.logon_id_low = 0xdead;
366 network_info->identity_info.logon_id_high = 0xbeef;
367 network_info->identity_info.account_name.string = username;
368 network_info->identity_info.workstation.string = workstation_name_slash;
369
370 memcpy(network_info->challenge, chal, 8);
371 network_info->nt = nt;
372 network_info->lm = lm;
373
374 logon->network = network_info;
375
376 /* Marshall data and send request */
377
378 result = rpccli_netr_LogonSamLogon(cli, mem_ctx,
379 server_name_slash,
380 global_myname(),
381 &clnt_creds,
382 &ret_creds,
383 NetlogonNetworkInformation,
384 logon,
385 validation_level,
386 &validation,
387 &authoritative);
388 if (!NT_STATUS_IS_OK(result)) {
389 return result;
390 }
391
392 /* Always check returned credentials. */
393 if (!netlogon_creds_client_check(cli->dc, &ret_creds.cred)) {
394 DEBUG(0,("rpccli_netlogon_sam_network_logon: credentials chain check failed\n"));
395 return NT_STATUS_ACCESS_DENIED;
396 }
397
398 netlogon_creds_decrypt_samlogon(cli->dc, validation_level, &validation);
399
400 *info3 = validation.sam3;
401
402 return result;
403}
404
405NTSTATUS rpccli_netlogon_sam_network_logon_ex(struct rpc_pipe_client *cli,
406 TALLOC_CTX *mem_ctx,
407 uint32 logon_parameters,
408 const char *server,
409 const char *username,
410 const char *domain,
411 const char *workstation,
412 const uint8 chal[8],
413 DATA_BLOB lm_response,
414 DATA_BLOB nt_response,
415 struct netr_SamInfo3 **info3)
416{
417 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
418 int validation_level = 3;
419 const char *workstation_name_slash;
420 const char *server_name_slash;
421 uint8 zeros[16];
422 union netr_LogonLevel *logon = NULL;
423 struct netr_NetworkInfo *network_info;
424 uint8_t authoritative;
425 union netr_Validation validation;
426 struct netr_ChallengeResponse lm;
427 struct netr_ChallengeResponse nt;
428 uint32_t flags = 0;
429
430 *info3 = NULL;
431
432 ZERO_STRUCT(zeros);
433
434 ZERO_STRUCT(lm);
435 ZERO_STRUCT(nt);
436
437 logon = TALLOC_ZERO_P(mem_ctx, union netr_LogonLevel);
438 if (!logon) {
439 return NT_STATUS_NO_MEMORY;
440 }
441
442 network_info = TALLOC_ZERO_P(mem_ctx, struct netr_NetworkInfo);
443 if (!network_info) {
444 return NT_STATUS_NO_MEMORY;
445 }
446
447 if (server[0] != '\\' && server[1] != '\\') {
448 server_name_slash = talloc_asprintf(mem_ctx, "\\\\%s", server);
449 } else {
450 server_name_slash = server;
451 }
452
453 if (workstation[0] != '\\' && workstation[1] != '\\') {
454 workstation_name_slash = talloc_asprintf(mem_ctx, "\\\\%s", workstation);
455 } else {
456 workstation_name_slash = workstation;
457 }
458
459 if (!workstation_name_slash || !server_name_slash) {
460 DEBUG(0, ("talloc_asprintf failed!\n"));
461 return NT_STATUS_NO_MEMORY;
462 }
463
464 /* Initialise input parameters */
465
466 lm.data = lm_response.data;
467 lm.length = lm_response.length;
468 nt.data = nt_response.data;
469 nt.length = nt_response.length;
470
471 network_info->identity_info.domain_name.string = domain;
472 network_info->identity_info.parameter_control = logon_parameters;
473 network_info->identity_info.logon_id_low = 0xdead;
474 network_info->identity_info.logon_id_high = 0xbeef;
475 network_info->identity_info.account_name.string = username;
476 network_info->identity_info.workstation.string = workstation_name_slash;
477
478 memcpy(network_info->challenge, chal, 8);
479 network_info->nt = nt;
480 network_info->lm = lm;
481
482 logon->network = network_info;
483
484 /* Marshall data and send request */
485
486 result = rpccli_netr_LogonSamLogonEx(cli, mem_ctx,
487 server_name_slash,
488 global_myname(),
489 NetlogonNetworkInformation,
490 logon,
491 validation_level,
492 &validation,
493 &authoritative,
494 &flags);
495 if (!NT_STATUS_IS_OK(result)) {
496 return result;
497 }
498
499 netlogon_creds_decrypt_samlogon(cli->dc, validation_level, &validation);
500
501 *info3 = validation.sam3;
502
503 return result;
504}
505
506/*********************************************************
507 Change the domain password on the PDC.
508
509 Just changes the password betwen the two values specified.
510
511 Caller must have the cli connected to the netlogon pipe
512 already.
513**********************************************************/
514
515NTSTATUS rpccli_netlogon_set_trust_password(struct rpc_pipe_client *cli,
516 TALLOC_CTX *mem_ctx,
517 const char *account_name,
518 const unsigned char orig_trust_passwd_hash[16],
519 const char *new_trust_pwd_cleartext,
520 const unsigned char new_trust_passwd_hash[16],
521 enum netr_SchannelType sec_channel_type)
522{
523 NTSTATUS result;
524 struct netr_Authenticator clnt_creds, srv_cred;
525
526 if (!cli->dc) {
527 uint32_t neg_flags = NETLOGON_NEG_AUTH2_ADS_FLAGS;
528 result = rpccli_netlogon_setup_creds(cli,
529 cli->desthost, /* server name */
530 lp_workgroup(), /* domain */
531 global_myname(), /* client name */
532 account_name, /* machine account name */
533 orig_trust_passwd_hash,
534 sec_channel_type,
535 &neg_flags);
536 if (!NT_STATUS_IS_OK(result)) {
537 DEBUG(3,("rpccli_netlogon_set_trust_password: unable to setup creds (%s)!\n",
538 nt_errstr(result)));
539 return result;
540 }
541 }
542
543 netlogon_creds_client_authenticator(cli->dc, &clnt_creds);
544
545 if (cli->dc->negotiate_flags & NETLOGON_NEG_PASSWORD_SET2) {
546
547 struct netr_CryptPassword new_password;
548
549 init_netr_CryptPassword(new_trust_pwd_cleartext,
550 cli->dc->session_key,
551 &new_password);
552
553 result = rpccli_netr_ServerPasswordSet2(cli, mem_ctx,
554 cli->srv_name_slash,
555 cli->dc->account_name,
556 sec_channel_type,
557 cli->dc->computer_name,
558 &clnt_creds,
559 &srv_cred,
560 &new_password);
561 if (!NT_STATUS_IS_OK(result)) {
562 DEBUG(0,("rpccli_netr_ServerPasswordSet2 failed: %s\n",
563 nt_errstr(result)));
564 return result;
565 }
566 } else {
567
568 struct samr_Password new_password;
569 memcpy(new_password.hash, new_trust_passwd_hash, sizeof(new_password.hash));
570 netlogon_creds_des_encrypt(cli->dc, &new_password);
571
572 result = rpccli_netr_ServerPasswordSet(cli, mem_ctx,
573 cli->srv_name_slash,
574 cli->dc->account_name,
575 sec_channel_type,
576 cli->dc->computer_name,
577 &clnt_creds,
578 &srv_cred,
579 &new_password);
580 if (!NT_STATUS_IS_OK(result)) {
581 DEBUG(0,("rpccli_netr_ServerPasswordSet failed: %s\n",
582 nt_errstr(result)));
583 return result;
584 }
585 }
586
587 /* Always check returned credentials. */
588 if (!netlogon_creds_client_check(cli->dc, &srv_cred.cred)) {
589 DEBUG(0,("credentials chain check failed\n"));
590 return NT_STATUS_ACCESS_DENIED;
591 }
592
593 return result;
594}
595
Note: See TracBrowser for help on using the repository browser.