Fix typo.
[Samba/gebeck_regimport.git] / source3 / rpc_client / cli_netlogon.c
blob4cd55dc5aac80325799c568b165a16f62f38877c
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.
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/>.
23 #include "includes.h"
25 /* LSA Request Challenge. Sends our challenge to server, then gets
26 server response. These are used to generate the credentials.
27 The sent and received challenges are stored in the netlog pipe
28 private data. Only call this via rpccli_netlogon_setup_creds(). JRA.
31 /* instead of rpccli_net_req_chal() we use rpccli_netr_ServerReqChallenge() now - gd */
33 #if 0
34 /****************************************************************************
35 LSA Authenticate 2
37 Send the client credential, receive back a server credential.
38 Ensure that the server credential returned matches the session key
39 encrypt of the server challenge originally received. JRA.
40 ****************************************************************************/
42 NTSTATUS rpccli_net_auth2(struct rpc_pipe_client *cli,
43 uint16 sec_chan,
44 uint32 *neg_flags, DOM_CHAL *srv_chal)
46 prs_struct qbuf, rbuf;
47 NET_Q_AUTH_2 q;
48 NET_R_AUTH_2 r;
49 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
50 fstring machine_acct;
52 if ( sec_chan == SEC_CHAN_DOMAIN )
53 fstr_sprintf( machine_acct, "%s$", lp_workgroup() );
54 else
55 fstrcpy( machine_acct, cli->mach_acct );
57 /* create and send a MSRPC command with api NET_AUTH2 */
59 DEBUG(4,("cli_net_auth2: srv:%s acct:%s sc:%x mc: %s chal %s neg: %x\n",
60 cli->srv_name_slash, machine_acct, sec_chan, global_myname(),
61 credstr(cli->clnt_cred.challenge.data), *neg_flags));
63 /* store the parameters */
65 init_q_auth_2(&q, cli->srv_name_slash, machine_acct,
66 sec_chan, global_myname(), &cli->clnt_cred.challenge,
67 *neg_flags);
69 /* turn parameters into data stream */
71 CLI_DO_RPC(cli, mem_ctx, PI_NETLOGON, NET_AUTH2,
72 q, r,
73 qbuf, rbuf,
74 net_io_q_auth_2,
75 net_io_r_auth_2,
76 NT_STATUS_UNSUCCESSFUL);
78 result = r.status;
80 if (NT_STATUS_IS_OK(result)) {
81 UTIME zerotime;
84 * Check the returned value using the initial
85 * server received challenge.
88 zerotime.time = 0;
89 if (cred_assert( &r.srv_chal, cli->sess_key, srv_chal, zerotime) == 0) {
92 * Server replied with bad credential. Fail.
94 DEBUG(0,("cli_net_auth2: server %s replied with bad credential (bad machine \
95 password ?).\n", cli->cli->desthost ));
96 return NT_STATUS_ACCESS_DENIED;
98 *neg_flags = r.srv_flgs.neg_flags;
101 return result;
103 #endif
105 /****************************************************************************
106 LSA Authenticate 2
108 Send the client credential, receive back a server credential.
109 The caller *must* ensure that the server credential returned matches the session key
110 encrypt of the server challenge originally received. JRA.
111 ****************************************************************************/
113 /* instead of rpccli_net_auth2() we use rpccli_netr_ServerAuthenticate2() now - gd */
116 /****************************************************************************
117 Wrapper function that uses the auth and auth2 calls to set up a NETLOGON
118 credentials chain. Stores the credentials in the struct dcinfo in the
119 netlogon pipe struct.
120 ****************************************************************************/
122 NTSTATUS rpccli_netlogon_setup_creds(struct rpc_pipe_client *cli,
123 const char *server_name,
124 const char *domain,
125 const char *clnt_name,
126 const char *machine_account,
127 const unsigned char machine_pwd[16],
128 enum netr_SchannelType sec_chan_type,
129 uint32_t *neg_flags_inout)
131 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
132 struct netr_Credential clnt_chal_send;
133 struct netr_Credential srv_chal_recv;
134 struct dcinfo *dc;
136 SMB_ASSERT(cli->pipe_idx == PI_NETLOGON);
138 dc = cli->dc;
139 if (!dc) {
140 return NT_STATUS_INVALID_PARAMETER;
143 /* Ensure we don't reuse any of this state. */
144 ZERO_STRUCTP(dc);
146 /* Store the machine account password we're going to use. */
147 memcpy(dc->mach_pw, machine_pwd, 16);
149 fstrcpy(dc->remote_machine, "\\\\");
150 fstrcat(dc->remote_machine, server_name);
152 fstrcpy(dc->domain, domain);
154 fstr_sprintf( dc->mach_acct, "%s$", machine_account);
156 /* Create the client challenge. */
157 generate_random_buffer(clnt_chal_send.data, 8);
159 /* Get the server challenge. */
160 result = rpccli_netr_ServerReqChallenge(cli, cli->mem_ctx,
161 dc->remote_machine,
162 clnt_name,
163 &clnt_chal_send,
164 &srv_chal_recv);
165 if (!NT_STATUS_IS_OK(result)) {
166 return result;
169 /* Calculate the session key and client credentials */
170 creds_client_init(*neg_flags_inout,
172 &clnt_chal_send,
173 &srv_chal_recv,
174 machine_pwd,
175 &clnt_chal_send);
178 * Send client auth-2 challenge and receive server repy.
181 result = rpccli_netr_ServerAuthenticate2(cli, cli->mem_ctx,
182 dc->remote_machine,
183 dc->mach_acct,
184 sec_chan_type,
185 clnt_name,
186 &clnt_chal_send, /* input. */
187 &srv_chal_recv, /* output. */
188 neg_flags_inout);
189 if (!NT_STATUS_IS_OK(result)) {
190 return result;
194 * Check the returned value using the initial
195 * server received challenge.
198 if (!netlogon_creds_client_check(dc, &srv_chal_recv)) {
200 * Server replied with bad credential. Fail.
202 DEBUG(0,("rpccli_netlogon_setup_creds: server %s "
203 "replied with bad credential\n",
204 cli->cli->desthost ));
205 return NT_STATUS_ACCESS_DENIED;
208 DEBUG(5,("rpccli_netlogon_setup_creds: server %s credential "
209 "chain established.\n",
210 cli->cli->desthost ));
212 return NT_STATUS_OK;
215 /* Logon domain user */
217 NTSTATUS rpccli_netlogon_sam_logon(struct rpc_pipe_client *cli,
218 TALLOC_CTX *mem_ctx,
219 uint32 logon_parameters,
220 const char *domain,
221 const char *username,
222 const char *password,
223 const char *workstation,
224 int logon_type)
226 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
227 struct netr_Authenticator clnt_creds;
228 struct netr_Authenticator ret_creds;
229 union netr_LogonLevel *logon;
230 union netr_Validation validation;
231 uint8_t authoritative;
232 int validation_level = 3;
233 fstring clnt_name_slash;
234 uint8 zeros[16];
236 ZERO_STRUCT(ret_creds);
237 ZERO_STRUCT(zeros);
239 logon = TALLOC_ZERO_P(mem_ctx, union netr_LogonLevel);
240 if (!logon) {
241 return NT_STATUS_NO_MEMORY;
244 if (workstation) {
245 fstr_sprintf( clnt_name_slash, "\\\\%s", workstation );
246 } else {
247 fstr_sprintf( clnt_name_slash, "\\\\%s", global_myname() );
250 /* Initialise input parameters */
252 netlogon_creds_client_step(cli->dc, &clnt_creds);
254 switch (logon_type) {
255 case INTERACTIVE_LOGON_TYPE: {
257 struct netr_PasswordInfo *password_info;
259 struct samr_Password lmpassword;
260 struct samr_Password ntpassword;
262 unsigned char lm_owf_user_pwd[16], nt_owf_user_pwd[16];
264 unsigned char lm_owf[16];
265 unsigned char nt_owf[16];
266 unsigned char key[16];
268 password_info = TALLOC_ZERO_P(mem_ctx, struct netr_PasswordInfo);
269 if (!password_info) {
270 return NT_STATUS_NO_MEMORY;
273 nt_lm_owf_gen(password, nt_owf_user_pwd, lm_owf_user_pwd);
275 #ifdef DEBUG_PASSWORD
276 DEBUG(100,("lm cypher:"));
277 dump_data(100, lm_owf_user_pwd, 16);
279 DEBUG(100,("nt cypher:"));
280 dump_data(100, nt_owf_user_pwd, 16);
281 #endif
282 memset(key, 0, 16);
283 memcpy(key, cli->dc->sess_key, 8);
285 memcpy(lm_owf, lm_owf_user_pwd, 16);
286 SamOEMhash(lm_owf, key, 16);
287 memcpy(nt_owf, nt_owf_user_pwd, 16);
288 SamOEMhash(nt_owf, key, 16);
290 #ifdef DEBUG_PASSWORD
291 DEBUG(100,("encrypt of lm owf password:"));
292 dump_data(100, lm_owf, 16);
294 DEBUG(100,("encrypt of nt owf password:"));
295 dump_data(100, nt_owf, 16);
296 #endif
297 memcpy(lmpassword.hash, lm_owf, 16);
298 memcpy(ntpassword.hash, nt_owf, 16);
300 init_netr_PasswordInfo(password_info,
301 domain,
302 logon_parameters,
303 0xdead,
304 0xbeef,
305 username,
306 clnt_name_slash,
307 lmpassword,
308 ntpassword);
310 logon->password = password_info;
312 break;
314 case NET_LOGON_TYPE: {
315 struct netr_NetworkInfo *network_info;
316 uint8 chal[8];
317 unsigned char local_lm_response[24];
318 unsigned char local_nt_response[24];
319 struct netr_ChallengeResponse lm;
320 struct netr_ChallengeResponse nt;
322 ZERO_STRUCT(lm);
323 ZERO_STRUCT(nt);
325 network_info = TALLOC_ZERO_P(mem_ctx, struct netr_NetworkInfo);
326 if (!network_info) {
327 return NT_STATUS_NO_MEMORY;
330 generate_random_buffer(chal, 8);
332 SMBencrypt(password, chal, local_lm_response);
333 SMBNTencrypt(password, chal, local_nt_response);
335 lm.length = 24;
336 lm.data = local_lm_response;
338 nt.length = 24;
339 nt.data = local_nt_response;
341 init_netr_NetworkInfo(network_info,
342 domain,
343 logon_parameters,
344 0xdead,
345 0xbeef,
346 username,
347 clnt_name_slash,
348 chal,
350 lm);
352 logon->network = network_info;
354 break;
356 default:
357 DEBUG(0, ("switch value %d not supported\n",
358 logon_type));
359 return NT_STATUS_INVALID_INFO_CLASS;
362 result = rpccli_netr_LogonSamLogon(cli, mem_ctx,
363 cli->dc->remote_machine,
364 global_myname(),
365 &clnt_creds,
366 &ret_creds,
367 logon_type,
368 logon,
369 validation_level,
370 &validation,
371 &authoritative);
373 if (memcmp(zeros, &ret_creds.cred.data, sizeof(ret_creds.cred.data)) != 0) {
374 /* Check returned credentials if present. */
375 if (!netlogon_creds_client_check(cli->dc, &ret_creds.cred)) {
376 DEBUG(0,("rpccli_netlogon_sam_logon: credentials chain check failed\n"));
377 return NT_STATUS_ACCESS_DENIED;
381 return result;
386 * Logon domain user with an 'network' SAM logon
388 * @param info3 Pointer to a NET_USER_INFO_3 already allocated by the caller.
391 NTSTATUS rpccli_netlogon_sam_network_logon(struct rpc_pipe_client *cli,
392 TALLOC_CTX *mem_ctx,
393 uint32 logon_parameters,
394 const char *server,
395 const char *username,
396 const char *domain,
397 const char *workstation,
398 const uint8 chal[8],
399 DATA_BLOB lm_response,
400 DATA_BLOB nt_response,
401 struct netr_SamInfo3 **info3)
403 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
404 int validation_level = 3;
405 const char *workstation_name_slash;
406 const char *server_name_slash;
407 uint8 zeros[16];
408 struct netr_Authenticator clnt_creds;
409 struct netr_Authenticator ret_creds;
410 union netr_LogonLevel *logon = NULL;
411 struct netr_NetworkInfo *network_info;
412 uint8_t authoritative;
413 union netr_Validation validation;
414 struct netr_ChallengeResponse lm;
415 struct netr_ChallengeResponse nt;
416 struct netr_UserSessionKey user_session_key;
417 struct netr_LMSessionKey lmsesskey;
419 *info3 = NULL;
421 ZERO_STRUCT(zeros);
422 ZERO_STRUCT(ret_creds);
424 ZERO_STRUCT(lm);
425 ZERO_STRUCT(nt);
427 logon = TALLOC_ZERO_P(mem_ctx, union netr_LogonLevel);
428 if (!logon) {
429 return NT_STATUS_NO_MEMORY;
432 network_info = TALLOC_ZERO_P(mem_ctx, struct netr_NetworkInfo);
433 if (!network_info) {
434 return NT_STATUS_NO_MEMORY;
437 netlogon_creds_client_step(cli->dc, &clnt_creds);
439 if (server[0] != '\\' && server[1] != '\\') {
440 server_name_slash = talloc_asprintf(mem_ctx, "\\\\%s", server);
441 } else {
442 server_name_slash = server;
445 if (workstation[0] != '\\' && workstation[1] != '\\') {
446 workstation_name_slash = talloc_asprintf(mem_ctx, "\\\\%s", workstation);
447 } else {
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,
464 domain,
465 logon_parameters,
466 0xdead,
467 0xbeef,
468 username,
469 workstation_name_slash,
470 (uint8_t *) chal,
472 lm);
474 logon->network = network_info;
476 /* Marshall data and send request */
478 result = rpccli_netr_LogonSamLogon(cli, mem_ctx,
479 server_name_slash,
480 global_myname(),
481 &clnt_creds,
482 &ret_creds,
483 NET_LOGON_TYPE,
484 logon,
485 validation_level,
486 &validation,
487 &authoritative);
488 if (!NT_STATUS_IS_OK(result)) {
489 return result;
492 user_session_key = validation.sam3->base.key;
493 lmsesskey = validation.sam3->base.LMSessKey;
495 if (memcmp(zeros, user_session_key.key, 16) != 0) {
496 SamOEMhash(user_session_key.key, cli->dc->sess_key, 16);
499 if (memcmp(zeros, lmsesskey.key, 8) != 0) {
500 SamOEMhash(lmsesskey.key, cli->dc->sess_key, 8);
503 if (memcmp(zeros, ret_creds.cred.data, sizeof(ret_creds.cred.data)) != 0) {
504 /* Check returned credentials if present. */
505 if (!netlogon_creds_client_check(cli->dc, &ret_creds.cred)) {
506 DEBUG(0,("rpccli_netlogon_sam_network_logon: credentials chain check failed\n"));
507 return NT_STATUS_ACCESS_DENIED;
511 *info3 = validation.sam3;
513 return result;
516 NTSTATUS rpccli_netlogon_sam_network_logon_ex(struct rpc_pipe_client *cli,
517 TALLOC_CTX *mem_ctx,
518 uint32 logon_parameters,
519 const char *server,
520 const char *username,
521 const char *domain,
522 const char *workstation,
523 const uint8 chal[8],
524 DATA_BLOB lm_response,
525 DATA_BLOB nt_response,
526 struct netr_SamInfo3 **info3)
528 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
529 int validation_level = 3;
530 const char *workstation_name_slash;
531 const char *server_name_slash;
532 uint8 zeros[16];
533 union netr_LogonLevel *logon = NULL;
534 struct netr_NetworkInfo *network_info;
535 uint8_t authoritative;
536 union netr_Validation validation;
537 struct netr_ChallengeResponse lm;
538 struct netr_ChallengeResponse nt;
539 struct netr_UserSessionKey user_session_key;
540 struct netr_LMSessionKey lmsesskey;
541 uint32_t flags = 0;
543 *info3 = NULL;
545 ZERO_STRUCT(zeros);
547 ZERO_STRUCT(lm);
548 ZERO_STRUCT(nt);
550 logon = TALLOC_ZERO_P(mem_ctx, union netr_LogonLevel);
551 if (!logon) {
552 return NT_STATUS_NO_MEMORY;
555 network_info = TALLOC_ZERO_P(mem_ctx, struct netr_NetworkInfo);
556 if (!network_info) {
557 return NT_STATUS_NO_MEMORY;
560 if (server[0] != '\\' && server[1] != '\\') {
561 server_name_slash = talloc_asprintf(mem_ctx, "\\\\%s", server);
562 } else {
563 server_name_slash = server;
566 if (workstation[0] != '\\' && workstation[1] != '\\') {
567 workstation_name_slash = talloc_asprintf(mem_ctx, "\\\\%s", workstation);
568 } else {
569 workstation_name_slash = workstation;
572 if (!workstation_name_slash || !server_name_slash) {
573 DEBUG(0, ("talloc_asprintf failed!\n"));
574 return NT_STATUS_NO_MEMORY;
577 /* Initialise input parameters */
579 lm.data = lm_response.data;
580 lm.length = lm_response.length;
581 nt.data = nt_response.data;
582 nt.length = nt_response.length;
584 init_netr_NetworkInfo(network_info,
585 domain,
586 logon_parameters,
587 0xdead,
588 0xbeef,
589 username,
590 workstation_name_slash,
591 (uint8_t *) chal,
593 lm);
595 logon->network = network_info;
597 /* Marshall data and send request */
599 result = rpccli_netr_LogonSamLogonEx(cli, mem_ctx,
600 server_name_slash,
601 global_myname(),
602 NET_LOGON_TYPE,
603 logon,
604 validation_level,
605 &validation,
606 &authoritative,
607 &flags);
608 if (!NT_STATUS_IS_OK(result)) {
609 return result;
612 user_session_key = validation.sam3->base.key;
613 lmsesskey = validation.sam3->base.LMSessKey;
615 if (memcmp(zeros, user_session_key.key, 16) != 0) {
616 SamOEMhash(user_session_key.key, cli->dc->sess_key, 16);
619 if (memcmp(zeros, lmsesskey.key, 8) != 0) {
620 SamOEMhash(lmsesskey.key, cli->dc->sess_key, 8);
623 *info3 = validation.sam3;
625 return result;