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.
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2 of the License, or
11 (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
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 static NTSTATUS rpccli_net_req_chal(struct rpc_pipe_client *cli,
33 const char *server_name,
34 const char *clnt_name,
35 const DOM_CHAL *clnt_chal_in,
36 DOM_CHAL *srv_chal_out)
38 prs_struct qbuf, rbuf;
41 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
43 /* create and send a MSRPC command with api NET_REQCHAL */
45 DEBUG(4,("cli_net_req_chal: LSA Request Challenge from %s to %s\n",
46 clnt_name, server_name));
48 /* store the parameters */
49 init_q_req_chal(&q, server_name, clnt_name, clnt_chal_in);
51 /* Marshall data and send request */
52 CLI_DO_RPC(cli, mem_ctx, PI_NETLOGON, NET_REQCHAL,
57 NT_STATUS_UNSUCCESSFUL);
63 if (NT_STATUS_IS_OK(result)) {
64 /* Store the returned server challenge. */
65 *srv_chal_out = r.srv_chal;
72 /****************************************************************************
75 Send the client credential, receive back a server credential.
76 Ensure that the server credential returned matches the session key
77 encrypt of the server challenge originally received. JRA.
78 ****************************************************************************/
80 NTSTATUS rpccli_net_auth2(struct rpc_pipe_client *cli,
82 uint32 *neg_flags, DOM_CHAL *srv_chal)
84 prs_struct qbuf, rbuf;
87 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
90 if ( sec_chan == SEC_CHAN_DOMAIN )
91 fstr_sprintf( machine_acct, "%s$", lp_workgroup() );
93 fstrcpy( machine_acct, cli->mach_acct );
95 /* create and send a MSRPC command with api NET_AUTH2 */
97 DEBUG(4,("cli_net_auth2: srv:%s acct:%s sc:%x mc: %s chal %s neg: %x\n",
98 cli->srv_name_slash, machine_acct, sec_chan, global_myname(),
99 credstr(cli->clnt_cred.challenge.data), *neg_flags));
101 /* store the parameters */
103 init_q_auth_2(&q, cli->srv_name_slash, machine_acct,
104 sec_chan, global_myname(), &cli->clnt_cred.challenge,
107 /* turn parameters into data stream */
109 CLI_DO_RPC(cli, mem_ctx, PI_NETLOGON, NET_AUTH2,
114 NT_STATUS_UNSUCCESSFUL);
118 if (NT_STATUS_IS_OK(result)) {
122 * Check the returned value using the initial
123 * server received challenge.
127 if (cred_assert( &r.srv_chal, cli->sess_key, srv_chal, zerotime) == 0) {
130 * Server replied with bad credential. Fail.
132 DEBUG(0,("cli_net_auth2: server %s replied with bad credential (bad machine \
133 password ?).\n", cli->cli->desthost ));
134 return NT_STATUS_ACCESS_DENIED;
136 *neg_flags = r.srv_flgs.neg_flags;
143 /****************************************************************************
146 Send the client credential, receive back a server credential.
147 The caller *must* ensure that the server credential returned matches the session key
148 encrypt of the server challenge originally received. JRA.
149 ****************************************************************************/
151 static NTSTATUS rpccli_net_auth2(struct rpc_pipe_client *cli,
153 const char *server_name,
154 const char *account_name,
155 uint16 sec_chan_type,
156 const char *computer_name,
157 uint32 *neg_flags_inout,
158 const DOM_CHAL *clnt_chal_in,
159 DOM_CHAL *srv_chal_out)
161 prs_struct qbuf, rbuf;
164 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
166 /* create and send a MSRPC command with api NET_AUTH2 */
168 DEBUG(4,("cli_net_auth2: srv:%s acct:%s sc:%x mc: %s neg: %x\n",
169 server_name, account_name, sec_chan_type, computer_name,
172 /* store the parameters */
174 init_q_auth_2(&q, server_name, account_name, sec_chan_type,
175 computer_name, clnt_chal_in, *neg_flags_inout);
177 /* turn parameters into data stream */
179 CLI_DO_RPC(cli, mem_ctx, PI_NETLOGON, NET_AUTH2,
184 NT_STATUS_UNSUCCESSFUL);
188 if (NT_STATUS_IS_OK(result)) {
189 *srv_chal_out = r.srv_chal;
190 *neg_flags_inout = r.srv_flgs.neg_flags;
196 #if 0 /* not currebntly used */
197 /****************************************************************************
200 Send the client credential, receive back a server credential.
201 The caller *must* ensure that the server credential returned matches the session key
202 encrypt of the server challenge originally received. JRA.
203 ****************************************************************************/
205 static NTSTATUS rpccli_net_auth3(struct rpc_pipe_client *cli,
207 const char *server_name,
208 const char *account_name,
209 uint16 sec_chan_type,
210 const char *computer_name,
211 uint32 *neg_flags_inout,
212 const DOM_CHAL *clnt_chal_in,
213 DOM_CHAL *srv_chal_out)
215 prs_struct qbuf, rbuf;
218 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
220 /* create and send a MSRPC command with api NET_AUTH2 */
222 DEBUG(4,("cli_net_auth3: srv:%s acct:%s sc:%x mc: %s chal %s neg: %x\n",
223 server_name, account_name, sec_chan_type, computer_name,
224 credstr(clnt_chal_in->data), *neg_flags_inout));
226 /* store the parameters */
227 init_q_auth_3(&q, server_name, account_name, sec_chan_type,
228 computer_name, clnt_chal_in, *neg_flags_inout);
230 /* turn parameters into data stream */
232 CLI_DO_RPC(cli, mem_ctx, PI_NETLOGON, NET_AUTH3,
237 NT_STATUS_UNSUCCESSFUL);
239 if (NT_STATUS_IS_OK(result)) {
240 *srv_chal_out = r.srv_chal;
241 *neg_flags_inout = r.srv_flgs.neg_flags;
246 #endif /* not currebntly used */
248 /****************************************************************************
249 Wrapper function that uses the auth and auth2 calls to set up a NETLOGON
250 credentials chain. Stores the credentials in the struct dcinfo in the
251 netlogon pipe struct.
252 ****************************************************************************/
254 NTSTATUS rpccli_netlogon_setup_creds(struct rpc_pipe_client *cli,
255 const char *server_name,
257 const char *machine_account,
258 const unsigned char machine_pwd[16],
259 uint32 sec_chan_type,
260 uint32 *neg_flags_inout)
263 DOM_CHAL clnt_chal_send;
264 DOM_CHAL srv_chal_recv;
267 SMB_ASSERT(cli->pipe_idx == PI_NETLOGON);
271 return NT_STATUS_INVALID_PARAMETER;
274 /* Ensure we don't reuse any of this state. */
277 /* Store the machine account password we're going to use. */
278 memcpy(dc->mach_pw, machine_pwd, 16);
280 fstrcpy(dc->remote_machine, "\\\\");
281 fstrcat(dc->remote_machine, server_name);
283 fstrcpy(dc->domain, domain);
285 fstr_sprintf( dc->mach_acct, "%s$", machine_account);
287 /* Create the client challenge. */
288 generate_random_buffer(clnt_chal_send.data, 8);
290 /* Get the server challenge. */
291 result = rpccli_net_req_chal(cli,
298 if (!NT_STATUS_IS_OK(result)) {
302 /* Calculate the session key and client credentials */
303 creds_client_init(dc,
310 * Send client auth-2 challenge and receive server repy.
313 result = rpccli_net_auth2(cli,
320 &clnt_chal_send, /* input. */
321 &srv_chal_recv); /* output */
323 if (!NT_STATUS_IS_OK(result)) {
328 * Check the returned value using the initial
329 * server received challenge.
332 if (!creds_client_check(dc, &srv_chal_recv)) {
334 * Server replied with bad credential. Fail.
336 DEBUG(0,("rpccli_netlogon_setup_creds: server %s "
337 "replied with bad credential\n",
338 cli->cli->desthost ));
339 return NT_STATUS_ACCESS_DENIED;
342 DEBUG(5,("rpccli_netlogon_setup_creds: server %s credential "
343 "chain established.\n",
344 cli->cli->desthost ));
349 /* Logon Control 2 */
351 NTSTATUS rpccli_netlogon_logon_ctrl2(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
354 prs_struct qbuf, rbuf;
357 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
363 /* Initialise input parameters */
365 slprintf(server, sizeof(fstring)-1, "\\\\%s", cli->cli->desthost);
366 init_net_q_logon_ctrl2(&q, server, query_level);
368 /* Marshall data and send request */
370 CLI_DO_RPC(cli, mem_ctx, PI_NETLOGON, NET_LOGON_CTRL2,
373 net_io_q_logon_ctrl2,
374 net_io_r_logon_ctrl2,
375 NT_STATUS_UNSUCCESSFUL);
383 NTSTATUS rpccli_netlogon_getdcname(struct rpc_pipe_client *cli,
384 TALLOC_CTX *mem_ctx, const char *mydcname,
385 const char *domainname, fstring newdcname)
387 prs_struct qbuf, rbuf;
390 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
395 /* Initialise input parameters */
397 init_net_q_getdcname(&q, mydcname, domainname);
399 /* Marshall data and send request */
401 CLI_DO_RPC(cli, mem_ctx, PI_NETLOGON, NET_GETDCNAME,
406 NT_STATUS_UNSUCCESSFUL);
408 if (NT_STATUS_IS_OK(result)) {
409 rpcstr_pull_unistr2_fstring(newdcname, &r.uni_dcname);
415 /* Sam synchronisation */
417 NTSTATUS rpccli_netlogon_sam_sync(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
418 uint32 database_id, uint32 next_rid, uint32 *num_deltas,
419 SAM_DELTA_HDR **hdr_deltas,
420 SAM_DELTA_CTR **deltas)
422 prs_struct qbuf, rbuf;
425 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
432 ZERO_STRUCT(ret_creds);
434 /* Initialise input parameters */
436 creds_client_step(cli->dc, &clnt_creds);
438 prs_set_session_key(&qbuf, (const char *)cli->dc->sess_key);
439 prs_set_session_key(&rbuf, (const char *)cli->dc->sess_key);
441 init_net_q_sam_sync(&q, cli->dc->remote_machine, global_myname(),
442 &clnt_creds, &ret_creds, database_id, next_rid);
444 /* Marshall data and send request */
446 CLI_DO_RPC(cli, mem_ctx, PI_NETLOGON, NET_SAM_SYNC,
451 NT_STATUS_UNSUCCESSFUL);
456 *num_deltas = r.num_deltas2;
457 *hdr_deltas = r.hdr_deltas;
460 if (!NT_STATUS_IS_ERR(result)) {
461 /* Check returned credentials. */
462 if (!creds_client_check(cli->dc, &r.srv_creds.challenge)) {
463 DEBUG(0,("cli_netlogon_sam_sync: credentials chain check failed\n"));
464 return NT_STATUS_ACCESS_DENIED;
471 /* Sam synchronisation */
473 NTSTATUS rpccli_netlogon_sam_deltas(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
474 uint32 database_id, UINT64_S seqnum,
476 SAM_DELTA_HDR **hdr_deltas,
477 SAM_DELTA_CTR **deltas)
479 prs_struct qbuf, rbuf;
482 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
488 /* Initialise input parameters */
490 creds_client_step(cli->dc, &clnt_creds);
492 init_net_q_sam_deltas(&q, cli->dc->remote_machine,
493 global_myname(), &clnt_creds,
494 database_id, seqnum);
496 /* Marshall data and send request */
498 CLI_DO_RPC(cli, mem_ctx, PI_NETLOGON, NET_SAM_DELTAS,
503 NT_STATUS_UNSUCCESSFUL);
508 *num_deltas = r.num_deltas2;
509 *hdr_deltas = r.hdr_deltas;
512 if (!NT_STATUS_IS_ERR(result)) {
513 /* Check returned credentials. */
514 if (!creds_client_check(cli->dc, &r.srv_creds.challenge)) {
515 DEBUG(0,("cli_netlogon_sam_sync: credentials chain check failed\n"));
516 return NT_STATUS_ACCESS_DENIED;
523 /* Logon domain user */
525 NTSTATUS rpccli_netlogon_sam_logon(struct rpc_pipe_client *cli,
528 const char *username,
529 const char *password,
532 prs_struct qbuf, rbuf;
535 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
539 NET_USER_INFO_3 user;
540 int validation_level = 3;
541 fstring clnt_name_slash;
545 ZERO_STRUCT(ret_creds);
547 fstr_sprintf( clnt_name_slash, "\\\\%s", global_myname() );
549 /* Initialise input parameters */
551 creds_client_step(cli->dc, &clnt_creds);
553 q.validation_level = validation_level;
555 ctr.switch_value = logon_type;
557 switch (logon_type) {
558 case INTERACTIVE_LOGON_TYPE: {
559 unsigned char lm_owf_user_pwd[16], nt_owf_user_pwd[16];
561 nt_lm_owf_gen(password, nt_owf_user_pwd, lm_owf_user_pwd);
563 init_id_info1(&ctr.auth.id1, domain,
565 0xdead, 0xbeef, /* LUID? */
566 username, clnt_name_slash,
567 (const char *)cli->dc->sess_key, lm_owf_user_pwd,
572 case NET_LOGON_TYPE: {
574 unsigned char local_lm_response[24];
575 unsigned char local_nt_response[24];
577 generate_random_buffer(chal, 8);
579 SMBencrypt(password, chal, local_lm_response);
580 SMBNTencrypt(password, chal, local_nt_response);
582 init_id_info2(&ctr.auth.id2, domain,
584 0xdead, 0xbeef, /* LUID? */
585 username, clnt_name_slash, chal,
586 local_lm_response, 24, local_nt_response, 24);
590 DEBUG(0, ("switch value %d not supported\n",
592 return NT_STATUS_INVALID_INFO_CLASS;
597 init_sam_info(&q.sam_id, cli->dc->remote_machine, global_myname(),
598 &clnt_creds, &ret_creds, logon_type,
601 /* Marshall data and send request */
603 CLI_DO_RPC(cli, mem_ctx, PI_NETLOGON, NET_SAMLOGON,
608 NT_STATUS_UNSUCCESSFUL);
614 if (r.buffer_creds) {
615 /* Check returned credentials if present. */
616 if (!creds_client_check(cli->dc, &r.srv_creds.challenge)) {
617 DEBUG(0,("rpccli_netlogon_sam_logon: credentials chain check failed\n"));
618 return NT_STATUS_ACCESS_DENIED;
627 * Logon domain user with an 'network' SAM logon
629 * @param info3 Pointer to a NET_USER_INFO_3 already allocated by the caller.
632 NTSTATUS rpccli_netlogon_sam_network_logon(struct rpc_pipe_client *cli,
635 const char *username,
637 const char *workstation,
639 DATA_BLOB lm_response,
640 DATA_BLOB nt_response,
641 NET_USER_INFO_3 *info3)
643 prs_struct qbuf, rbuf;
646 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
648 int validation_level = 3;
649 const char *workstation_name_slash;
650 const char *server_name_slash;
651 static uint8 zeros[16];
658 ZERO_STRUCT(ret_creds);
660 creds_client_step(cli->dc, &clnt_creds);
662 if (server[0] != '\\' && server[1] != '\\') {
663 server_name_slash = talloc_asprintf(mem_ctx, "\\\\%s", server);
665 server_name_slash = server;
668 if (workstation[0] != '\\' && workstation[1] != '\\') {
669 workstation_name_slash = talloc_asprintf(mem_ctx, "\\\\%s", workstation);
671 workstation_name_slash = workstation;
674 if (!workstation_name_slash || !server_name_slash) {
675 DEBUG(0, ("talloc_asprintf failed!\n"));
676 return NT_STATUS_NO_MEMORY;
679 /* Initialise input parameters */
681 q.validation_level = validation_level;
683 ctr.switch_value = NET_LOGON_TYPE;
685 init_id_info2(&ctr.auth.id2, domain,
687 0xdead, 0xbeef, /* LUID? */
688 username, workstation_name_slash, (const uchar*)chal,
689 lm_response.data, lm_response.length, nt_response.data, nt_response.length);
691 init_sam_info(&q.sam_id, server_name_slash, global_myname(),
692 &clnt_creds, &ret_creds, NET_LOGON_TYPE,
697 /* Marshall data and send request */
699 CLI_DO_RPC(cli, mem_ctx, PI_NETLOGON, NET_SAMLOGON,
704 NT_STATUS_UNSUCCESSFUL);
706 if (memcmp(zeros, info3->user_sess_key, 16) != 0) {
707 SamOEMhash(info3->user_sess_key, cli->dc->sess_key, 16);
709 memset(info3->user_sess_key, '\0', 16);
712 if (memcmp(zeros, info3->lm_sess_key, 8) != 0) {
713 SamOEMhash(info3->lm_sess_key, cli->dc->sess_key, 8);
715 memset(info3->lm_sess_key, '\0', 8);
718 memset(&info3->acct_flags, '\0', 4);
719 for (i=0; i < 7; i++) {
720 memset(&info3->unknown[i], '\0', 4);
727 if (r.buffer_creds) {
728 /* Check returned credentials if present. */
729 if (!creds_client_check(cli->dc, &r.srv_creds.challenge)) {
730 DEBUG(0,("rpccli_netlogon_sam_network_logon: credentials chain check failed\n"));
731 return NT_STATUS_ACCESS_DENIED;
738 /***************************************************************************
739 LSA Server Password Set.
740 ****************************************************************************/
742 NTSTATUS rpccli_net_srv_pwset(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
743 const char *machine_name, const uint8 hashed_mach_pwd[16])
750 uint16 sec_chan_type = 2;
753 creds_client_step(cli->dc, &clnt_creds);
755 DEBUG(4,("cli_net_srv_pwset: srv:%s acct:%s sc: %d mc: %s\n",
756 cli->dc->remote_machine, cli->dc->mach_acct, sec_chan_type, machine_name));
758 /* store the parameters */
759 init_q_srv_pwset(&q, cli->dc->remote_machine, (const char *)cli->dc->sess_key,
760 cli->dc->mach_acct, sec_chan_type, machine_name,
761 &clnt_creds, hashed_mach_pwd);
763 CLI_DO_RPC(cli, mem_ctx, PI_NETLOGON, NET_SRVPWSET,
768 NT_STATUS_UNSUCCESSFUL);
772 if (!NT_STATUS_IS_OK(result)) {
773 /* report error code */
774 DEBUG(0,("cli_net_srv_pwset: %s\n", nt_errstr(result)));
777 /* Always check returned credentials. */
778 if (!creds_client_check(cli->dc, &r.srv_cred.challenge)) {
779 DEBUG(0,("rpccli_net_srv_pwset: credentials chain check failed\n"));
780 return NT_STATUS_ACCESS_DENIED;