source: branches/samba-3.3.x/source/rpc_client/cli_netlogon.c@ 342

Last change on this file since 342 was 342, checked in by Herwig Bauernfeind, 15 years ago

Update 3.3 to 3.3.9

File size: 16.5 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
25/****************************************************************************
26 Wrapper function that uses the auth and auth2 calls to set up a NETLOGON
27 credentials chain. Stores the credentials in the struct dcinfo in the
28 netlogon pipe struct.
29****************************************************************************/
30
31NTSTATUS rpccli_netlogon_setup_creds(struct rpc_pipe_client *cli,
32 const char *server_name,
33 const char *domain,
34 const char *clnt_name,
35 const char *machine_account,
36 const unsigned char machine_pwd[16],
37 enum netr_SchannelType sec_chan_type,
38 uint32_t *neg_flags_inout)
39{
40 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
41 struct netr_Credential clnt_chal_send;
42 struct netr_Credential srv_chal_recv;
43 struct dcinfo *dc;
44 bool retried = false;
45
46 SMB_ASSERT(ndr_syntax_id_equal(&cli->abstract_syntax,
47 &ndr_table_netlogon.syntax_id));
48
49 TALLOC_FREE(cli->dc);
50 cli->dc = talloc_zero(cli, struct dcinfo);
51 if (cli->dc == NULL) {
52 return NT_STATUS_NO_MEMORY;
53 }
54 dc = cli->dc;
55
56 /* Store the machine account password we're going to use. */
57 memcpy(dc->mach_pw, machine_pwd, 16);
58
59 fstrcpy(dc->remote_machine, "\\\\");
60 fstrcat(dc->remote_machine, server_name);
61
62 fstrcpy(dc->domain, domain);
63
64 fstr_sprintf( dc->mach_acct, "%s$", machine_account);
65
66 again:
67 /* Create the client challenge. */
68 generate_random_buffer(clnt_chal_send.data, 8);
69
70 /* Get the server challenge. */
71 result = rpccli_netr_ServerReqChallenge(cli, talloc_tos(),
72 dc->remote_machine,
73 clnt_name,
74 &clnt_chal_send,
75 &srv_chal_recv);
76 if (!NT_STATUS_IS_OK(result)) {
77 return result;
78 }
79
80 /* Calculate the session key and client credentials */
81 creds_client_init(*neg_flags_inout,
82 dc,
83 &clnt_chal_send,
84 &srv_chal_recv,
85 machine_pwd,
86 &clnt_chal_send);
87
88 /*
89 * Send client auth-2 challenge and receive server repy.
90 */
91
92 result = rpccli_netr_ServerAuthenticate2(cli, talloc_tos(),
93 dc->remote_machine,
94 dc->mach_acct,
95 sec_chan_type,
96 clnt_name,
97 &clnt_chal_send, /* input. */
98 &srv_chal_recv, /* output. */
99 neg_flags_inout);
100
101 /* we might be talking to NT4, so let's downgrade in that case and retry
102 * with the returned neg_flags - gd */
103
104 if (NT_STATUS_EQUAL(result, NT_STATUS_ACCESS_DENIED) && !retried) {
105 retried = true;
106 goto again;
107 }
108
109 if (!NT_STATUS_IS_OK(result)) {
110 return result;
111 }
112
113 /*
114 * Check the returned value using the initial
115 * server received challenge.
116 */
117
118 if (!netlogon_creds_client_check(dc, &srv_chal_recv)) {
119 /*
120 * Server replied with bad credential. Fail.
121 */
122 DEBUG(0,("rpccli_netlogon_setup_creds: server %s "
123 "replied with bad credential\n",
124 cli->desthost ));
125 return NT_STATUS_ACCESS_DENIED;
126 }
127
128 DEBUG(5,("rpccli_netlogon_setup_creds: server %s credential "
129 "chain established.\n",
130 cli->desthost ));
131
132 return NT_STATUS_OK;
133}
134
135/* Logon domain user */
136
137NTSTATUS rpccli_netlogon_sam_logon(struct rpc_pipe_client *cli,
138 TALLOC_CTX *mem_ctx,
139 uint32 logon_parameters,
140 const char *domain,
141 const char *username,
142 const char *password,
143 const char *workstation,
144 int logon_type)
145{
146 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
147 struct netr_Authenticator clnt_creds;
148 struct netr_Authenticator ret_creds;
149 union netr_LogonInfo *logon;
150 union netr_Validation validation;
151 uint8_t authoritative;
152 int validation_level = 3;
153 fstring clnt_name_slash;
154 uint8 zeros[16];
155
156 ZERO_STRUCT(ret_creds);
157 ZERO_STRUCT(zeros);
158
159 logon = TALLOC_ZERO_P(mem_ctx, union netr_LogonInfo);
160 if (!logon) {
161 return NT_STATUS_NO_MEMORY;
162 }
163
164 if (workstation) {
165 fstr_sprintf( clnt_name_slash, "\\\\%s", workstation );
166 } else {
167 fstr_sprintf( clnt_name_slash, "\\\\%s", global_myname() );
168 }
169
170 /* Initialise input parameters */
171
172 netlogon_creds_client_step(cli->dc, &clnt_creds);
173
174 switch (logon_type) {
175 case INTERACTIVE_LOGON_TYPE: {
176
177 struct netr_PasswordInfo *password_info;
178
179 struct samr_Password lmpassword;
180 struct samr_Password ntpassword;
181
182 unsigned char lm_owf_user_pwd[16], nt_owf_user_pwd[16];
183
184 unsigned char lm_owf[16];
185 unsigned char nt_owf[16];
186 unsigned char key[16];
187
188 password_info = TALLOC_ZERO_P(mem_ctx, struct netr_PasswordInfo);
189 if (!password_info) {
190 return NT_STATUS_NO_MEMORY;
191 }
192
193 nt_lm_owf_gen(password, nt_owf_user_pwd, lm_owf_user_pwd);
194
195#ifdef DEBUG_PASSWORD
196 DEBUG(100,("lm cypher:"));
197 dump_data(100, lm_owf_user_pwd, 16);
198
199 DEBUG(100,("nt cypher:"));
200 dump_data(100, nt_owf_user_pwd, 16);
201#endif
202 memset(key, 0, 16);
203 memcpy(key, cli->dc->sess_key, 8);
204
205 memcpy(lm_owf, lm_owf_user_pwd, 16);
206 SamOEMhash(lm_owf, key, 16);
207 memcpy(nt_owf, nt_owf_user_pwd, 16);
208 SamOEMhash(nt_owf, key, 16);
209
210#ifdef DEBUG_PASSWORD
211 DEBUG(100,("encrypt of lm owf password:"));
212 dump_data(100, lm_owf, 16);
213
214 DEBUG(100,("encrypt of nt owf password:"));
215 dump_data(100, nt_owf, 16);
216#endif
217 memcpy(lmpassword.hash, lm_owf, 16);
218 memcpy(ntpassword.hash, nt_owf, 16);
219
220 init_netr_PasswordInfo(password_info,
221 domain,
222 logon_parameters,
223 0xdead,
224 0xbeef,
225 username,
226 clnt_name_slash,
227 lmpassword,
228 ntpassword);
229
230 logon->password = password_info;
231
232 break;
233 }
234 case NET_LOGON_TYPE: {
235 struct netr_NetworkInfo *network_info;
236 uint8 chal[8];
237 unsigned char local_lm_response[24];
238 unsigned char local_nt_response[24];
239 struct netr_ChallengeResponse lm;
240 struct netr_ChallengeResponse nt;
241
242 ZERO_STRUCT(lm);
243 ZERO_STRUCT(nt);
244
245 network_info = TALLOC_ZERO_P(mem_ctx, struct netr_NetworkInfo);
246 if (!network_info) {
247 return NT_STATUS_NO_MEMORY;
248 }
249
250 generate_random_buffer(chal, 8);
251
252 SMBencrypt(password, chal, local_lm_response);
253 SMBNTencrypt(password, chal, local_nt_response);
254
255 lm.length = 24;
256 lm.data = local_lm_response;
257
258 nt.length = 24;
259 nt.data = local_nt_response;
260
261 init_netr_NetworkInfo(network_info,
262 domain,
263 logon_parameters,
264 0xdead,
265 0xbeef,
266 username,
267 clnt_name_slash,
268 chal,
269 nt,
270 lm);
271
272 logon->network = network_info;
273
274 break;
275 }
276 default:
277 DEBUG(0, ("switch value %d not supported\n",
278 logon_type));
279 return NT_STATUS_INVALID_INFO_CLASS;
280 }
281
282 result = rpccli_netr_LogonSamLogon(cli, mem_ctx,
283 cli->dc->remote_machine,
284 global_myname(),
285 &clnt_creds,
286 &ret_creds,
287 logon_type,
288 logon,
289 validation_level,
290 &validation,
291 &authoritative);
292
293 if (memcmp(zeros, &ret_creds.cred.data, sizeof(ret_creds.cred.data)) != 0) {
294 /* Check returned credentials if present. */
295 if (!netlogon_creds_client_check(cli->dc, &ret_creds.cred)) {
296 DEBUG(0,("rpccli_netlogon_sam_logon: credentials chain check failed\n"));
297 return NT_STATUS_ACCESS_DENIED;
298 }
299 }
300
301 return result;
302}
303
304
305/**
306 * Logon domain user with an 'network' SAM logon
307 *
308 * @param info3 Pointer to a NET_USER_INFO_3 already allocated by the caller.
309 **/
310
311NTSTATUS rpccli_netlogon_sam_network_logon(struct rpc_pipe_client *cli,
312 TALLOC_CTX *mem_ctx,
313 uint32 logon_parameters,
314 const char *server,
315 const char *username,
316 const char *domain,
317 const char *workstation,
318 const uint8 chal[8],
319 DATA_BLOB lm_response,
320 DATA_BLOB nt_response,
321 struct netr_SamInfo3 **info3)
322{
323 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
324 int validation_level = 3;
325 const char *workstation_name_slash;
326 const char *server_name_slash;
327 uint8 zeros[16];
328 struct netr_Authenticator clnt_creds;
329 struct netr_Authenticator ret_creds;
330 union netr_LogonInfo *logon = NULL;
331 struct netr_NetworkInfo *network_info;
332 uint8_t authoritative;
333 union netr_Validation validation;
334 struct netr_ChallengeResponse lm;
335 struct netr_ChallengeResponse nt;
336
337 *info3 = NULL;
338
339 ZERO_STRUCT(zeros);
340 ZERO_STRUCT(ret_creds);
341
342 ZERO_STRUCT(lm);
343 ZERO_STRUCT(nt);
344
345 logon = TALLOC_ZERO_P(mem_ctx, union netr_LogonInfo);
346 if (!logon) {
347 return NT_STATUS_NO_MEMORY;
348 }
349
350 network_info = TALLOC_ZERO_P(mem_ctx, struct netr_NetworkInfo);
351 if (!network_info) {
352 return NT_STATUS_NO_MEMORY;
353 }
354
355 netlogon_creds_client_step(cli->dc, &clnt_creds);
356
357 if (server[0] != '\\' && server[1] != '\\') {
358 server_name_slash = talloc_asprintf(mem_ctx, "\\\\%s", server);
359 } else {
360 server_name_slash = server;
361 }
362
363 if (workstation[0] != '\\' && workstation[1] != '\\') {
364 workstation_name_slash = talloc_asprintf(mem_ctx, "\\\\%s", workstation);
365 } else {
366 workstation_name_slash = workstation;
367 }
368
369 if (!workstation_name_slash || !server_name_slash) {
370 DEBUG(0, ("talloc_asprintf failed!\n"));
371 return NT_STATUS_NO_MEMORY;
372 }
373
374 /* Initialise input parameters */
375
376 lm.data = lm_response.data;
377 lm.length = lm_response.length;
378 nt.data = nt_response.data;
379 nt.length = nt_response.length;
380
381 init_netr_NetworkInfo(network_info,
382 domain,
383 logon_parameters,
384 0xdead,
385 0xbeef,
386 username,
387 workstation_name_slash,
388 (uint8_t *) chal,
389 nt,
390 lm);
391
392 logon->network = network_info;
393
394 /* Marshall data and send request */
395
396 result = rpccli_netr_LogonSamLogon(cli, mem_ctx,
397 server_name_slash,
398 global_myname(),
399 &clnt_creds,
400 &ret_creds,
401 NET_LOGON_TYPE,
402 logon,
403 validation_level,
404 &validation,
405 &authoritative);
406 if (!NT_STATUS_IS_OK(result)) {
407 return result;
408 }
409
410 if (memcmp(zeros, validation.sam3->base.key.key, 16) != 0) {
411 SamOEMhash(validation.sam3->base.key.key,
412 cli->dc->sess_key, 16);
413 }
414
415 if (memcmp(zeros, validation.sam3->base.LMSessKey.key, 8) != 0) {
416 SamOEMhash(validation.sam3->base.LMSessKey.key,
417 cli->dc->sess_key, 8);
418 }
419
420 if (memcmp(zeros, ret_creds.cred.data, sizeof(ret_creds.cred.data)) != 0) {
421 /* Check returned credentials if present. */
422 if (!netlogon_creds_client_check(cli->dc, &ret_creds.cred)) {
423 DEBUG(0,("rpccli_netlogon_sam_network_logon: credentials chain check failed\n"));
424 return NT_STATUS_ACCESS_DENIED;
425 }
426 }
427
428 *info3 = validation.sam3;
429
430 return result;
431}
432
433NTSTATUS rpccli_netlogon_sam_network_logon_ex(struct rpc_pipe_client *cli,
434 TALLOC_CTX *mem_ctx,
435 uint32 logon_parameters,
436 const char *server,
437 const char *username,
438 const char *domain,
439 const char *workstation,
440 const uint8 chal[8],
441 DATA_BLOB lm_response,
442 DATA_BLOB nt_response,
443 struct netr_SamInfo3 **info3)
444{
445 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
446 int validation_level = 3;
447 const char *workstation_name_slash;
448 const char *server_name_slash;
449 uint8 zeros[16];
450 union netr_LogonInfo *logon = NULL;
451 struct netr_NetworkInfo *network_info;
452 uint8_t authoritative;
453 union netr_Validation validation;
454 struct netr_ChallengeResponse lm;
455 struct netr_ChallengeResponse nt;
456 uint32_t flags = 0;
457
458 *info3 = NULL;
459
460 ZERO_STRUCT(zeros);
461
462 ZERO_STRUCT(lm);
463 ZERO_STRUCT(nt);
464
465 logon = TALLOC_ZERO_P(mem_ctx, union netr_LogonInfo);
466 if (!logon) {
467 return NT_STATUS_NO_MEMORY;
468 }
469
470 network_info = TALLOC_ZERO_P(mem_ctx, struct netr_NetworkInfo);
471 if (!network_info) {
472 return NT_STATUS_NO_MEMORY;
473 }
474
475 if (server[0] != '\\' && server[1] != '\\') {
476 server_name_slash = talloc_asprintf(mem_ctx, "\\\\%s", server);
477 } else {
478 server_name_slash = server;
479 }
480
481 if (workstation[0] != '\\' && workstation[1] != '\\') {
482 workstation_name_slash = talloc_asprintf(mem_ctx, "\\\\%s", workstation);
483 } else {
484 workstation_name_slash = workstation;
485 }
486
487 if (!workstation_name_slash || !server_name_slash) {
488 DEBUG(0, ("talloc_asprintf failed!\n"));
489 return NT_STATUS_NO_MEMORY;
490 }
491
492 /* Initialise input parameters */
493
494 lm.data = lm_response.data;
495 lm.length = lm_response.length;
496 nt.data = nt_response.data;
497 nt.length = nt_response.length;
498
499 init_netr_NetworkInfo(network_info,
500 domain,
501 logon_parameters,
502 0xdead,
503 0xbeef,
504 username,
505 workstation_name_slash,
506 (uint8_t *) chal,
507 nt,
508 lm);
509
510 logon->network = network_info;
511
512 /* Marshall data and send request */
513
514 result = rpccli_netr_LogonSamLogonEx(cli, mem_ctx,
515 server_name_slash,
516 global_myname(),
517 NET_LOGON_TYPE,
518 logon,
519 validation_level,
520 &validation,
521 &authoritative,
522 &flags);
523 if (!NT_STATUS_IS_OK(result)) {
524 return result;
525 }
526
527 if (memcmp(zeros, validation.sam3->base.key.key, 16) != 0) {
528 SamOEMhash(validation.sam3->base.key.key,
529 cli->dc->sess_key, 16);
530 }
531
532 if (memcmp(zeros, validation.sam3->base.LMSessKey.key, 8) != 0) {
533 SamOEMhash(validation.sam3->base.LMSessKey.key,
534 cli->dc->sess_key, 8);
535 }
536
537 *info3 = validation.sam3;
538
539 return result;
540}
541
542/*********************************************************
543 Change the domain password on the PDC.
544
545 Just changes the password betwen the two values specified.
546
547 Caller must have the cli connected to the netlogon pipe
548 already.
549**********************************************************/
550
551NTSTATUS rpccli_netlogon_set_trust_password(struct rpc_pipe_client *cli,
552 TALLOC_CTX *mem_ctx,
553 const unsigned char orig_trust_passwd_hash[16],
554 const char *new_trust_pwd_cleartext,
555 const unsigned char new_trust_passwd_hash[16],
556 uint32_t sec_channel_type)
557{
558 NTSTATUS result;
559 uint32_t neg_flags = NETLOGON_NEG_AUTH2_ADS_FLAGS;
560 struct netr_Authenticator clnt_creds, srv_cred;
561
562 result = rpccli_netlogon_setup_creds(cli,
563 cli->desthost, /* server name */
564 lp_workgroup(), /* domain */
565 global_myname(), /* client name */
566 global_myname(), /* machine account name */
567 orig_trust_passwd_hash,
568 sec_channel_type,
569 &neg_flags);
570
571 if (!NT_STATUS_IS_OK(result)) {
572 DEBUG(3,("rpccli_netlogon_set_trust_password: unable to setup creds (%s)!\n",
573 nt_errstr(result)));
574 return result;
575 }
576
577 netlogon_creds_client_step(cli->dc, &clnt_creds);
578
579 if (neg_flags & NETLOGON_NEG_PASSWORD_SET2) {
580
581 struct netr_CryptPassword new_password;
582
583 init_netr_CryptPassword(new_trust_pwd_cleartext,
584 cli->dc->sess_key,
585 &new_password);
586
587 result = rpccli_netr_ServerPasswordSet2(cli, mem_ctx,
588 cli->dc->remote_machine,
589 cli->dc->mach_acct,
590 sec_channel_type,
591 global_myname(),
592 &clnt_creds,
593 &srv_cred,
594 &new_password);
595 if (!NT_STATUS_IS_OK(result)) {
596 DEBUG(0,("rpccli_netr_ServerPasswordSet2 failed: %s\n",
597 nt_errstr(result)));
598 return result;
599 }
600 } else {
601
602 struct samr_Password new_password;
603
604 des_crypt112_16(new_password.hash,
605 new_trust_passwd_hash,
606 cli->dc->sess_key, 1);
607
608 result = rpccli_netr_ServerPasswordSet(cli, mem_ctx,
609 cli->dc->remote_machine,
610 cli->dc->mach_acct,
611 sec_channel_type,
612 global_myname(),
613 &clnt_creds,
614 &srv_cred,
615 &new_password);
616 if (!NT_STATUS_IS_OK(result)) {
617 DEBUG(0,("rpccli_netr_ServerPasswordSet failed: %s\n",
618 nt_errstr(result)));
619 return result;
620 }
621 }
622
623 /* Always check returned credentials. */
624 if (!netlogon_creds_client_check(cli->dc, &srv_cred.cred)) {
625 DEBUG(0,("credentials chain check failed\n"));
626 return NT_STATUS_ACCESS_DENIED;
627 }
628
629 return result;
630}
631
Note: See TracBrowser for help on using the repository browser.