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 3 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 *clnt_name,
258 const char *machine_account,
259 const unsigned char machine_pwd[16],
260 uint32 sec_chan_type,
261 uint32 *neg_flags_inout)
263 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
264 DOM_CHAL clnt_chal_send;
265 DOM_CHAL srv_chal_recv;
268 SMB_ASSERT(cli->pipe_idx == PI_NETLOGON);
272 return NT_STATUS_INVALID_PARAMETER;
275 /* Ensure we don't reuse any of this state. */
278 /* Store the machine account password we're going to use. */
279 memcpy(dc->mach_pw, machine_pwd, 16);
281 fstrcpy(dc->remote_machine, "\\\\");
282 fstrcat(dc->remote_machine, server_name);
284 fstrcpy(dc->domain, domain);
286 fstr_sprintf( dc->mach_acct, "%s$", machine_account);
288 /* Create the client challenge. */
289 generate_random_buffer(clnt_chal_send.data, 8);
291 /* Get the server challenge. */
292 result = rpccli_net_req_chal(cli,
299 if (!NT_STATUS_IS_OK(result)) {
303 /* Calculate the session key and client credentials */
304 creds_client_init(*neg_flags_inout,
312 * Send client auth-2 challenge and receive server repy.
315 result = rpccli_net_auth2(cli,
322 &clnt_chal_send, /* input. */
323 &srv_chal_recv); /* output */
325 if (!NT_STATUS_IS_OK(result)) {
330 * Check the returned value using the initial
331 * server received challenge.
334 if (!creds_client_check(dc, &srv_chal_recv)) {
336 * Server replied with bad credential. Fail.
338 DEBUG(0,("rpccli_netlogon_setup_creds: server %s "
339 "replied with bad credential\n",
340 cli->cli->desthost ));
341 return NT_STATUS_ACCESS_DENIED;
344 DEBUG(5,("rpccli_netlogon_setup_creds: server %s credential "
345 "chain established.\n",
346 cli->cli->desthost ));
351 /* Logon Control 2 */
353 NTSTATUS rpccli_netlogon_logon_ctrl2(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
356 prs_struct qbuf, rbuf;
359 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
365 /* Initialise input parameters */
367 slprintf(server, sizeof(fstring)-1, "\\\\%s", cli->cli->desthost);
368 init_net_q_logon_ctrl2(&q, server, query_level);
370 /* Marshall data and send request */
372 CLI_DO_RPC(cli, mem_ctx, PI_NETLOGON, NET_LOGON_CTRL2,
375 net_io_q_logon_ctrl2,
376 net_io_r_logon_ctrl2,
377 NT_STATUS_UNSUCCESSFUL);
385 WERROR rpccli_netlogon_getanydcname(struct rpc_pipe_client *cli,
386 TALLOC_CTX *mem_ctx, const char *mydcname,
387 const char *domainname, fstring newdcname)
389 prs_struct qbuf, rbuf;
390 NET_Q_GETANYDCNAME q;
391 NET_R_GETANYDCNAME r;
393 fstring mydcname_slash;
398 /* Initialise input parameters */
400 slprintf(mydcname_slash, sizeof(fstring)-1, "\\\\%s", mydcname);
401 init_net_q_getanydcname(&q, mydcname_slash, domainname);
403 /* Marshall data and send request */
405 CLI_DO_RPC_WERR(cli, mem_ctx, PI_NETLOGON, NET_GETANYDCNAME,
408 net_io_q_getanydcname,
409 net_io_r_getanydcname,
410 WERR_GENERAL_FAILURE);
414 if (W_ERROR_IS_OK(result)) {
415 rpcstr_pull_unistr2_fstring(newdcname, &r.uni_dcname);
423 WERROR rpccli_netlogon_getdcname(struct rpc_pipe_client *cli,
424 TALLOC_CTX *mem_ctx, const char *mydcname,
425 const char *domainname, fstring newdcname)
427 prs_struct qbuf, rbuf;
431 fstring mydcname_slash;
436 /* Initialise input parameters */
438 slprintf(mydcname_slash, sizeof(fstring)-1, "\\\\%s", mydcname);
439 init_net_q_getdcname(&q, mydcname_slash, domainname);
441 /* Marshall data and send request */
443 CLI_DO_RPC_WERR(cli, mem_ctx, PI_NETLOGON, NET_GETDCNAME,
448 WERR_GENERAL_FAILURE);
452 if (W_ERROR_IS_OK(result)) {
453 rpcstr_pull_unistr2_fstring(newdcname, &r.uni_dcname);
459 static WERROR pull_domain_controller_info_from_getdcname_reply(TALLOC_CTX *mem_ctx,
460 struct DS_DOMAIN_CONTROLLER_INFO **info_out,
461 NET_R_DSR_GETDCNAME *r)
463 struct DS_DOMAIN_CONTROLLER_INFO *info;
465 info = TALLOC_ZERO_P(mem_ctx, struct DS_DOMAIN_CONTROLLER_INFO);
470 if (&r->uni_dc_unc) {
473 tmp = rpcstr_pull_unistr2_talloc(mem_ctx, &r->uni_dc_unc);
475 return WERR_GENERAL_FAILURE;
477 if (*tmp == '\\') tmp += 1;
478 if (*tmp == '\\') tmp += 1;
480 info->domain_controller_name = talloc_strdup(mem_ctx, tmp);
481 if (info->domain_controller_name == NULL) {
482 return WERR_GENERAL_FAILURE;
486 if (&r->uni_dc_address) {
489 tmp = rpcstr_pull_unistr2_talloc(mem_ctx, &r->uni_dc_address);
491 return WERR_GENERAL_FAILURE;
493 if (*tmp == '\\') tmp += 1;
494 if (*tmp == '\\') tmp += 1;
496 info->domain_controller_address = talloc_strdup(mem_ctx, tmp);
497 if (info->domain_controller_address == NULL) {
498 return WERR_GENERAL_FAILURE;
502 info->domain_controller_address_type = r->dc_address_type;
504 info->domain_guid = (struct GUID *)talloc_memdup(
505 mem_ctx, &r->domain_guid, sizeof(struct GUID));
506 if (!info->domain_guid) {
507 return WERR_GENERAL_FAILURE;
510 if (&r->uni_domain_name) {
511 info->domain_name = rpcstr_pull_unistr2_talloc(mem_ctx, &r->uni_domain_name);
512 if (!info->domain_name) {
513 return WERR_GENERAL_FAILURE;
517 if (&r->uni_forest_name) {
518 info->dns_forest_name = rpcstr_pull_unistr2_talloc(mem_ctx, &r->uni_forest_name);
519 if (!info->dns_forest_name) {
520 return WERR_GENERAL_FAILURE;
524 info->flags = r->dc_flags;
526 if (&r->uni_dc_site_name) {
527 info->dc_site_name = rpcstr_pull_unistr2_talloc(mem_ctx, &r->uni_dc_site_name);
528 if (!info->dc_site_name) {
529 return WERR_GENERAL_FAILURE;
533 if (&r->uni_client_site_name) {
534 info->client_site_name = rpcstr_pull_unistr2_talloc(mem_ctx, &r->uni_client_site_name);
535 if (!info->client_site_name) {
536 return WERR_GENERAL_FAILURE;
547 WERROR rpccli_netlogon_dsr_getdcname(struct rpc_pipe_client *cli,
549 const char *server_name,
550 const char *domain_name,
551 struct GUID *domain_guid,
552 struct GUID *site_guid,
554 struct DS_DOMAIN_CONTROLLER_INFO **info_out)
556 prs_struct qbuf, rbuf;
557 NET_Q_DSR_GETDCNAME q;
558 NET_R_DSR_GETDCNAME r;
564 /* Initialize input parameters */
566 tmp_str = talloc_asprintf(mem_ctx, "\\\\%s", server_name);
567 if (tmp_str == NULL) {
571 init_net_q_dsr_getdcname(&q, tmp_str, domain_name, domain_guid,
574 /* Marshall data and send request */
576 CLI_DO_RPC_WERR(cli, mem_ctx, PI_NETLOGON, NET_DSR_GETDCNAME,
579 net_io_q_dsr_getdcname,
580 net_io_r_dsr_getdcname,
581 WERR_GENERAL_FAILURE);
583 if (!W_ERROR_IS_OK(r.result)) {
587 r.result = pull_domain_controller_info_from_getdcname_reply(mem_ctx, info_out, &r);
588 if (!W_ERROR_IS_OK(r.result)) {
595 /* Dsr_GetDCNameEx */
597 WERROR rpccli_netlogon_dsr_getdcnameex(struct rpc_pipe_client *cli,
599 const char *server_name,
600 const char *domain_name,
601 struct GUID *domain_guid,
602 const char *site_name,
604 struct DS_DOMAIN_CONTROLLER_INFO **info_out)
606 prs_struct qbuf, rbuf;
607 NET_Q_DSR_GETDCNAMEEX q;
608 NET_R_DSR_GETDCNAME r;
614 /* Initialize input parameters */
616 tmp_str = talloc_asprintf(mem_ctx, "\\\\%s", server_name);
617 if (tmp_str == NULL) {
621 init_net_q_dsr_getdcnameex(&q, server_name, domain_name, domain_guid,
624 /* Marshall data and send request */
626 CLI_DO_RPC_WERR(cli, mem_ctx, PI_NETLOGON, NET_DSR_GETDCNAMEEX,
629 net_io_q_dsr_getdcnameex,
630 net_io_r_dsr_getdcname,
631 WERR_GENERAL_FAILURE);
633 if (!W_ERROR_IS_OK(r.result)) {
637 r.result = pull_domain_controller_info_from_getdcname_reply(mem_ctx, info_out, &r);
638 if (!W_ERROR_IS_OK(r.result)) {
645 /* Dsr_GetDCNameEx */
647 WERROR rpccli_netlogon_dsr_getdcnameex2(struct rpc_pipe_client *cli,
649 const char *server_name,
650 const char *client_account,
652 const char *domain_name,
653 struct GUID *domain_guid,
654 const char *site_name,
656 struct DS_DOMAIN_CONTROLLER_INFO **info_out)
658 prs_struct qbuf, rbuf;
659 NET_Q_DSR_GETDCNAMEEX2 q;
660 NET_R_DSR_GETDCNAME r;
666 /* Initialize input parameters */
668 tmp_str = talloc_asprintf(mem_ctx, "\\\\%s", server_name);
669 if (tmp_str == NULL) {
673 init_net_q_dsr_getdcnameex2(&q, server_name, domain_name, client_account,
674 mask, domain_guid, site_name, flags);
676 /* Marshall data and send request */
678 CLI_DO_RPC_WERR(cli, mem_ctx, PI_NETLOGON, NET_DSR_GETDCNAMEEX2,
681 net_io_q_dsr_getdcnameex2,
682 net_io_r_dsr_getdcname,
683 WERR_GENERAL_FAILURE);
685 if (!W_ERROR_IS_OK(r.result)) {
689 r.result = pull_domain_controller_info_from_getdcname_reply(mem_ctx, info_out, &r);
690 if (!W_ERROR_IS_OK(r.result)) {
698 /* Dsr_GetSiteName */
700 WERROR rpccli_netlogon_dsr_getsitename(struct rpc_pipe_client *cli,
702 const char *computer_name,
705 prs_struct qbuf, rbuf;
706 NET_Q_DSR_GETSITENAME q;
707 NET_R_DSR_GETSITENAME r;
712 /* Initialize input parameters */
714 init_net_q_dsr_getsitename(&q, computer_name);
716 /* Marshall data and send request */
718 CLI_DO_RPC_WERR(cli, mem_ctx, PI_NETLOGON, NET_DSR_GETSITENAME,
721 net_io_q_dsr_getsitename,
722 net_io_r_dsr_getsitename,
723 WERR_GENERAL_FAILURE);
725 if (!W_ERROR_IS_OK(r.result)) {
729 if ((site_name != NULL) &&
730 ((*site_name = rpcstr_pull_unistr2_talloc(
731 mem_ctx, &r.uni_site_name)) == NULL)) {
732 return WERR_GENERAL_FAILURE;
740 /* Sam synchronisation */
742 NTSTATUS rpccli_netlogon_sam_sync(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
743 uint32 database_id, uint32 next_rid, uint32 *num_deltas,
744 SAM_DELTA_HDR **hdr_deltas,
745 SAM_DELTA_CTR **deltas)
747 prs_struct qbuf, rbuf;
750 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
757 ZERO_STRUCT(ret_creds);
759 /* Initialise input parameters */
761 creds_client_step(cli->dc, &clnt_creds);
763 init_net_q_sam_sync(&q, cli->dc->remote_machine, global_myname(),
764 &clnt_creds, &ret_creds, database_id, next_rid);
766 /* Marshall data and send request */
768 CLI_DO_RPC_COPY_SESS_KEY(cli, mem_ctx, PI_NETLOGON, NET_SAM_SYNC,
773 NT_STATUS_UNSUCCESSFUL);
778 *num_deltas = r.num_deltas2;
779 *hdr_deltas = r.hdr_deltas;
782 if (!NT_STATUS_IS_ERR(result)) {
783 /* Check returned credentials. */
784 if (!creds_client_check(cli->dc, &r.srv_creds.challenge)) {
785 DEBUG(0,("cli_netlogon_sam_sync: credentials chain check failed\n"));
786 return NT_STATUS_ACCESS_DENIED;
793 /* Sam synchronisation */
795 NTSTATUS rpccli_netlogon_sam_deltas(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
796 uint32 database_id, uint64 seqnum,
798 SAM_DELTA_HDR **hdr_deltas,
799 SAM_DELTA_CTR **deltas)
801 prs_struct qbuf, rbuf;
804 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
810 /* Initialise input parameters */
812 creds_client_step(cli->dc, &clnt_creds);
814 init_net_q_sam_deltas(&q, cli->dc->remote_machine,
815 global_myname(), &clnt_creds,
816 database_id, seqnum);
818 /* Marshall data and send request */
820 CLI_DO_RPC(cli, mem_ctx, PI_NETLOGON, NET_SAM_DELTAS,
825 NT_STATUS_UNSUCCESSFUL);
830 *num_deltas = r.num_deltas2;
831 *hdr_deltas = r.hdr_deltas;
834 if (!NT_STATUS_IS_ERR(result)) {
835 /* Check returned credentials. */
836 if (!creds_client_check(cli->dc, &r.srv_creds.challenge)) {
837 DEBUG(0,("cli_netlogon_sam_sync: credentials chain check failed\n"));
838 return NT_STATUS_ACCESS_DENIED;
845 /* Logon domain user */
847 NTSTATUS rpccli_netlogon_sam_logon(struct rpc_pipe_client *cli,
849 uint32 logon_parameters,
851 const char *username,
852 const char *password,
853 const char *workstation,
856 prs_struct qbuf, rbuf;
859 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
863 NET_USER_INFO_3 user;
864 int validation_level = 3;
865 fstring clnt_name_slash;
869 ZERO_STRUCT(ret_creds);
872 fstr_sprintf( clnt_name_slash, "\\\\%s", workstation );
874 fstr_sprintf( clnt_name_slash, "\\\\%s", global_myname() );
877 /* Initialise input parameters */
879 creds_client_step(cli->dc, &clnt_creds);
881 q.validation_level = validation_level;
883 ctr.switch_value = logon_type;
885 switch (logon_type) {
886 case INTERACTIVE_LOGON_TYPE: {
887 unsigned char lm_owf_user_pwd[16], nt_owf_user_pwd[16];
889 nt_lm_owf_gen(password, nt_owf_user_pwd, lm_owf_user_pwd);
891 init_id_info1(&ctr.auth.id1, domain,
892 logon_parameters, /* param_ctrl */
893 0xdead, 0xbeef, /* LUID? */
894 username, clnt_name_slash,
895 (const char *)cli->dc->sess_key, lm_owf_user_pwd,
900 case NET_LOGON_TYPE: {
902 unsigned char local_lm_response[24];
903 unsigned char local_nt_response[24];
905 generate_random_buffer(chal, 8);
907 SMBencrypt(password, chal, local_lm_response);
908 SMBNTencrypt(password, chal, local_nt_response);
910 init_id_info2(&ctr.auth.id2, domain,
911 logon_parameters, /* param_ctrl */
912 0xdead, 0xbeef, /* LUID? */
913 username, clnt_name_slash, chal,
914 local_lm_response, 24, local_nt_response, 24);
918 DEBUG(0, ("switch value %d not supported\n",
920 return NT_STATUS_INVALID_INFO_CLASS;
925 init_sam_info(&q.sam_id, cli->dc->remote_machine, global_myname(),
926 &clnt_creds, &ret_creds, logon_type,
929 /* Marshall data and send request */
931 CLI_DO_RPC(cli, mem_ctx, PI_NETLOGON, NET_SAMLOGON,
936 NT_STATUS_UNSUCCESSFUL);
942 if (r.buffer_creds) {
943 /* Check returned credentials if present. */
944 if (!creds_client_check(cli->dc, &r.srv_creds.challenge)) {
945 DEBUG(0,("rpccli_netlogon_sam_logon: credentials chain check failed\n"));
946 return NT_STATUS_ACCESS_DENIED;
955 * Logon domain user with an 'network' SAM logon
957 * @param info3 Pointer to a NET_USER_INFO_3 already allocated by the caller.
960 NTSTATUS rpccli_netlogon_sam_network_logon(struct rpc_pipe_client *cli,
962 uint32 logon_parameters,
964 const char *username,
966 const char *workstation,
968 DATA_BLOB lm_response,
969 DATA_BLOB nt_response,
970 NET_USER_INFO_3 *info3)
972 prs_struct qbuf, rbuf;
975 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
977 int validation_level = 3;
978 const char *workstation_name_slash;
979 const char *server_name_slash;
980 static uint8 zeros[16];
987 ZERO_STRUCT(ret_creds);
989 creds_client_step(cli->dc, &clnt_creds);
991 if (server[0] != '\\' && server[1] != '\\') {
992 server_name_slash = talloc_asprintf(mem_ctx, "\\\\%s", server);
994 server_name_slash = server;
997 if (workstation[0] != '\\' && workstation[1] != '\\') {
998 workstation_name_slash = talloc_asprintf(mem_ctx, "\\\\%s", workstation);
1000 workstation_name_slash = workstation;
1003 if (!workstation_name_slash || !server_name_slash) {
1004 DEBUG(0, ("talloc_asprintf failed!\n"));
1005 return NT_STATUS_NO_MEMORY;
1008 /* Initialise input parameters */
1010 q.validation_level = validation_level;
1012 ctr.switch_value = NET_LOGON_TYPE;
1014 init_id_info2(&ctr.auth.id2, domain,
1015 logon_parameters, /* param_ctrl */
1016 0xdead, 0xbeef, /* LUID? */
1017 username, workstation_name_slash, (const uchar*)chal,
1018 lm_response.data, lm_response.length, nt_response.data, nt_response.length);
1020 init_sam_info(&q.sam_id, server_name_slash, global_myname(),
1021 &clnt_creds, &ret_creds, NET_LOGON_TYPE,
1026 /* Marshall data and send request */
1028 CLI_DO_RPC(cli, mem_ctx, PI_NETLOGON, NET_SAMLOGON,
1033 NT_STATUS_UNSUCCESSFUL);
1035 if (memcmp(zeros, info3->user_sess_key, 16) != 0) {
1036 SamOEMhash(info3->user_sess_key, cli->dc->sess_key, 16);
1038 memset(info3->user_sess_key, '\0', 16);
1041 if (memcmp(zeros, info3->lm_sess_key, 8) != 0) {
1042 SamOEMhash(info3->lm_sess_key, cli->dc->sess_key, 8);
1044 memset(info3->lm_sess_key, '\0', 8);
1047 for (i=0; i < 7; i++) {
1048 memset(&info3->unknown[i], '\0', 4);
1051 /* Return results */
1055 if (r.buffer_creds) {
1056 /* Check returned credentials if present. */
1057 if (!creds_client_check(cli->dc, &r.srv_creds.challenge)) {
1058 DEBUG(0,("rpccli_netlogon_sam_network_logon: credentials chain check failed\n"));
1059 return NT_STATUS_ACCESS_DENIED;
1066 NTSTATUS rpccli_netlogon_sam_network_logon_ex(struct rpc_pipe_client *cli,
1067 TALLOC_CTX *mem_ctx,
1068 uint32 logon_parameters,
1070 const char *username,
1072 const char *workstation,
1073 const uint8 chal[8],
1074 DATA_BLOB lm_response,
1075 DATA_BLOB nt_response,
1076 NET_USER_INFO_3 *info3)
1078 prs_struct qbuf, rbuf;
1079 NET_Q_SAM_LOGON_EX q;
1080 NET_R_SAM_LOGON_EX r;
1081 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
1082 NET_ID_INFO_CTR ctr;
1083 int validation_level = 3;
1084 const char *workstation_name_slash;
1085 const char *server_name_slash;
1086 static uint8 zeros[16];
1092 if (server[0] != '\\' && server[1] != '\\') {
1093 server_name_slash = talloc_asprintf(mem_ctx, "\\\\%s", server);
1095 server_name_slash = server;
1098 if (workstation[0] != '\\' && workstation[1] != '\\') {
1099 workstation_name_slash = talloc_asprintf(mem_ctx, "\\\\%s", workstation);
1101 workstation_name_slash = workstation;
1104 if (!workstation_name_slash || !server_name_slash) {
1105 DEBUG(0, ("talloc_asprintf failed!\n"));
1106 return NT_STATUS_NO_MEMORY;
1109 /* Initialise input parameters */
1111 q.validation_level = validation_level;
1113 ctr.switch_value = NET_LOGON_TYPE;
1115 init_id_info2(&ctr.auth.id2, domain,
1116 logon_parameters, /* param_ctrl */
1117 0xdead, 0xbeef, /* LUID? */
1118 username, workstation_name_slash, (const uchar*)chal,
1119 lm_response.data, lm_response.length, nt_response.data,
1120 nt_response.length);
1122 init_sam_info_ex(&q.sam_id, server_name_slash, global_myname(),
1123 NET_LOGON_TYPE, &ctr);
1127 /* Marshall data and send request */
1129 CLI_DO_RPC(cli, mem_ctx, PI_NETLOGON, NET_SAMLOGON_EX,
1131 net_io_q_sam_logon_ex,
1132 net_io_r_sam_logon_ex,
1133 NT_STATUS_UNSUCCESSFUL);
1135 if (memcmp(zeros, info3->user_sess_key, 16) != 0) {
1136 SamOEMhash(info3->user_sess_key, cli->dc->sess_key, 16);
1138 memset(info3->user_sess_key, '\0', 16);
1141 if (memcmp(zeros, info3->lm_sess_key, 8) != 0) {
1142 SamOEMhash(info3->lm_sess_key, cli->dc->sess_key, 8);
1144 memset(info3->lm_sess_key, '\0', 8);
1147 for (i=0; i < 7; i++) {
1148 memset(&info3->unknown[i], '\0', 4);
1151 /* Return results */
1158 /***************************************************************************
1159 LSA Server Password Set.
1160 ****************************************************************************/
1162 NTSTATUS rpccli_net_srv_pwset(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
1163 const char *machine_name, const uint8 hashed_mach_pwd[16])
1167 DOM_CRED clnt_creds;
1170 uint16 sec_chan_type = 2;
1173 creds_client_step(cli->dc, &clnt_creds);
1175 DEBUG(4,("cli_net_srv_pwset: srv:%s acct:%s sc: %d mc: %s\n",
1176 cli->dc->remote_machine, cli->dc->mach_acct, sec_chan_type, machine_name));
1178 /* store the parameters */
1179 init_q_srv_pwset(&q, cli->dc->remote_machine, (const char *)cli->dc->sess_key,
1180 cli->dc->mach_acct, sec_chan_type, machine_name,
1181 &clnt_creds, hashed_mach_pwd);
1183 CLI_DO_RPC(cli, mem_ctx, PI_NETLOGON, NET_SRVPWSET,
1188 NT_STATUS_UNSUCCESSFUL);
1192 if (!NT_STATUS_IS_OK(result)) {
1193 /* report error code */
1194 DEBUG(0,("cli_net_srv_pwset: %s\n", nt_errstr(result)));
1197 /* Always check returned credentials. */
1198 if (!creds_client_check(cli->dc, &r.srv_cred.challenge)) {
1199 DEBUG(0,("rpccli_net_srv_pwset: credentials chain check failed\n"));
1200 return NT_STATUS_ACCESS_DENIED;