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 *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 NTSTATUS 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(cli, mem_ctx, PI_NETLOGON, NET_GETDCNAME,
448 NT_STATUS_UNSUCCESSFUL);
452 if (NT_STATUS_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 = talloc_memdup(mem_ctx, &r->domain_guid, sizeof(struct GUID));
505 if (!info->domain_guid) {
506 return WERR_GENERAL_FAILURE;
509 if (&r->uni_domain_name) {
510 info->domain_name = rpcstr_pull_unistr2_talloc(mem_ctx, &r->uni_domain_name);
511 if (!info->domain_name) {
512 return WERR_GENERAL_FAILURE;
516 if (&r->uni_forest_name) {
517 info->dns_forest_name = rpcstr_pull_unistr2_talloc(mem_ctx, &r->uni_forest_name);
518 if (!info->dns_forest_name) {
519 return WERR_GENERAL_FAILURE;
523 info->flags = r->dc_flags;
525 if (&r->uni_dc_site_name) {
526 info->dc_site_name = rpcstr_pull_unistr2_talloc(mem_ctx, &r->uni_dc_site_name);
527 if (!info->dc_site_name) {
528 return WERR_GENERAL_FAILURE;
532 if (&r->uni_client_site_name) {
533 info->client_site_name = rpcstr_pull_unistr2_talloc(mem_ctx, &r->uni_client_site_name);
534 if (!info->client_site_name) {
535 return WERR_GENERAL_FAILURE;
546 WERROR rpccli_netlogon_dsr_getdcname(struct rpc_pipe_client *cli,
548 const char *server_name,
549 const char *domain_name,
550 struct GUID *domain_guid,
551 struct GUID *site_guid,
553 struct DS_DOMAIN_CONTROLLER_INFO **info_out)
555 prs_struct qbuf, rbuf;
556 NET_Q_DSR_GETDCNAME q;
557 NET_R_DSR_GETDCNAME r;
563 /* Initialize input parameters */
565 tmp_str = talloc_asprintf(mem_ctx, "\\\\%s", server_name);
566 if (tmp_str == NULL) {
570 init_net_q_dsr_getdcname(&q, tmp_str, domain_name, domain_guid,
573 /* Marshall data and send request */
575 CLI_DO_RPC_WERR(cli, mem_ctx, PI_NETLOGON, NET_DSR_GETDCNAME,
578 net_io_q_dsr_getdcname,
579 net_io_r_dsr_getdcname,
580 WERR_GENERAL_FAILURE);
582 if (!W_ERROR_IS_OK(r.result)) {
586 r.result = pull_domain_controller_info_from_getdcname_reply(mem_ctx, info_out, &r);
587 if (!W_ERROR_IS_OK(r.result)) {
594 /* Dsr_GetDCNameEx */
596 WERROR rpccli_netlogon_dsr_getdcnameex(struct rpc_pipe_client *cli,
598 const char *server_name,
599 const char *domain_name,
600 struct GUID *domain_guid,
601 const char *site_name,
603 struct DS_DOMAIN_CONTROLLER_INFO **info_out)
605 prs_struct qbuf, rbuf;
606 NET_Q_DSR_GETDCNAMEEX q;
607 NET_R_DSR_GETDCNAME r;
613 /* Initialize input parameters */
615 tmp_str = talloc_asprintf(mem_ctx, "\\\\%s", server_name);
616 if (tmp_str == NULL) {
620 init_net_q_dsr_getdcnameex(&q, server_name, domain_name, domain_guid,
623 /* Marshall data and send request */
625 CLI_DO_RPC_WERR(cli, mem_ctx, PI_NETLOGON, NET_DSR_GETDCNAMEEX,
628 net_io_q_dsr_getdcnameex,
629 net_io_r_dsr_getdcname,
630 WERR_GENERAL_FAILURE);
632 if (!W_ERROR_IS_OK(r.result)) {
636 r.result = pull_domain_controller_info_from_getdcname_reply(mem_ctx, info_out, &r);
637 if (!W_ERROR_IS_OK(r.result)) {
644 /* Dsr_GetDCNameEx */
646 WERROR rpccli_netlogon_dsr_getdcnameex2(struct rpc_pipe_client *cli,
648 const char *server_name,
649 const char *client_account,
651 const char *domain_name,
652 struct GUID *domain_guid,
653 const char *site_name,
655 struct DS_DOMAIN_CONTROLLER_INFO **info_out)
657 prs_struct qbuf, rbuf;
658 NET_Q_DSR_GETDCNAMEEX2 q;
659 NET_R_DSR_GETDCNAME r;
665 /* Initialize input parameters */
667 tmp_str = talloc_asprintf(mem_ctx, "\\\\%s", server_name);
668 if (tmp_str == NULL) {
672 init_net_q_dsr_getdcnameex2(&q, server_name, domain_name, client_account,
673 mask, domain_guid, site_name, flags);
675 /* Marshall data and send request */
677 CLI_DO_RPC_WERR(cli, mem_ctx, PI_NETLOGON, NET_DSR_GETDCNAMEEX2,
680 net_io_q_dsr_getdcnameex2,
681 net_io_r_dsr_getdcname,
682 WERR_GENERAL_FAILURE);
684 if (!W_ERROR_IS_OK(r.result)) {
688 r.result = pull_domain_controller_info_from_getdcname_reply(mem_ctx, info_out, &r);
689 if (!W_ERROR_IS_OK(r.result)) {
697 /* Dsr_GetSiteName */
699 WERROR rpccli_netlogon_dsr_getsitename(struct rpc_pipe_client *cli,
701 const char *computer_name,
704 prs_struct qbuf, rbuf;
705 NET_Q_DSR_GETSITENAME q;
706 NET_R_DSR_GETSITENAME r;
711 /* Initialize input parameters */
713 init_net_q_dsr_getsitename(&q, computer_name);
715 /* Marshall data and send request */
717 CLI_DO_RPC_WERR(cli, mem_ctx, PI_NETLOGON, NET_DSR_GETSITENAME,
720 net_io_q_dsr_getsitename,
721 net_io_r_dsr_getsitename,
722 WERR_GENERAL_FAILURE);
724 if (!W_ERROR_IS_OK(r.result)) {
728 if ((site_name != NULL) &&
729 ((*site_name = rpcstr_pull_unistr2_talloc(
730 mem_ctx, &r.uni_site_name)) == NULL)) {
731 return WERR_GENERAL_FAILURE;
739 /* Sam synchronisation */
741 NTSTATUS rpccli_netlogon_sam_sync(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
742 uint32 database_id, uint32 next_rid, uint32 *num_deltas,
743 SAM_DELTA_HDR **hdr_deltas,
744 SAM_DELTA_CTR **deltas)
746 prs_struct qbuf, rbuf;
749 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
756 ZERO_STRUCT(ret_creds);
758 /* Initialise input parameters */
760 creds_client_step(cli->dc, &clnt_creds);
762 init_net_q_sam_sync(&q, cli->dc->remote_machine, global_myname(),
763 &clnt_creds, &ret_creds, database_id, next_rid);
765 /* Marshall data and send request */
767 CLI_DO_RPC_COPY_SESS_KEY(cli, mem_ctx, PI_NETLOGON, NET_SAM_SYNC,
772 NT_STATUS_UNSUCCESSFUL);
777 *num_deltas = r.num_deltas2;
778 *hdr_deltas = r.hdr_deltas;
781 if (!NT_STATUS_IS_ERR(result)) {
782 /* Check returned credentials. */
783 if (!creds_client_check(cli->dc, &r.srv_creds.challenge)) {
784 DEBUG(0,("cli_netlogon_sam_sync: credentials chain check failed\n"));
785 return NT_STATUS_ACCESS_DENIED;
792 /* Sam synchronisation */
794 NTSTATUS rpccli_netlogon_sam_deltas(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
795 uint32 database_id, uint64 seqnum,
797 SAM_DELTA_HDR **hdr_deltas,
798 SAM_DELTA_CTR **deltas)
800 prs_struct qbuf, rbuf;
803 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
809 /* Initialise input parameters */
811 creds_client_step(cli->dc, &clnt_creds);
813 init_net_q_sam_deltas(&q, cli->dc->remote_machine,
814 global_myname(), &clnt_creds,
815 database_id, seqnum);
817 /* Marshall data and send request */
819 CLI_DO_RPC(cli, mem_ctx, PI_NETLOGON, NET_SAM_DELTAS,
824 NT_STATUS_UNSUCCESSFUL);
829 *num_deltas = r.num_deltas2;
830 *hdr_deltas = r.hdr_deltas;
833 if (!NT_STATUS_IS_ERR(result)) {
834 /* Check returned credentials. */
835 if (!creds_client_check(cli->dc, &r.srv_creds.challenge)) {
836 DEBUG(0,("cli_netlogon_sam_sync: credentials chain check failed\n"));
837 return NT_STATUS_ACCESS_DENIED;
844 /* Logon domain user */
846 NTSTATUS rpccli_netlogon_sam_logon(struct rpc_pipe_client *cli,
848 uint32 logon_parameters,
850 const char *username,
851 const char *password,
852 const char *workstation,
855 prs_struct qbuf, rbuf;
858 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
862 NET_USER_INFO_3 user;
863 int validation_level = 3;
864 fstring clnt_name_slash;
868 ZERO_STRUCT(ret_creds);
871 fstr_sprintf( clnt_name_slash, "\\\\%s", workstation );
873 fstr_sprintf( clnt_name_slash, "\\\\%s", global_myname() );
876 /* Initialise input parameters */
878 creds_client_step(cli->dc, &clnt_creds);
880 q.validation_level = validation_level;
882 ctr.switch_value = logon_type;
884 switch (logon_type) {
885 case INTERACTIVE_LOGON_TYPE: {
886 unsigned char lm_owf_user_pwd[16], nt_owf_user_pwd[16];
888 nt_lm_owf_gen(password, nt_owf_user_pwd, lm_owf_user_pwd);
890 init_id_info1(&ctr.auth.id1, domain,
891 logon_parameters, /* param_ctrl */
892 0xdead, 0xbeef, /* LUID? */
893 username, clnt_name_slash,
894 (const char *)cli->dc->sess_key, lm_owf_user_pwd,
899 case NET_LOGON_TYPE: {
901 unsigned char local_lm_response[24];
902 unsigned char local_nt_response[24];
904 generate_random_buffer(chal, 8);
906 SMBencrypt(password, chal, local_lm_response);
907 SMBNTencrypt(password, chal, local_nt_response);
909 init_id_info2(&ctr.auth.id2, domain,
910 logon_parameters, /* param_ctrl */
911 0xdead, 0xbeef, /* LUID? */
912 username, clnt_name_slash, chal,
913 local_lm_response, 24, local_nt_response, 24);
917 DEBUG(0, ("switch value %d not supported\n",
919 return NT_STATUS_INVALID_INFO_CLASS;
924 init_sam_info(&q.sam_id, cli->dc->remote_machine, global_myname(),
925 &clnt_creds, &ret_creds, logon_type,
928 /* Marshall data and send request */
930 CLI_DO_RPC(cli, mem_ctx, PI_NETLOGON, NET_SAMLOGON,
935 NT_STATUS_UNSUCCESSFUL);
941 if (r.buffer_creds) {
942 /* Check returned credentials if present. */
943 if (!creds_client_check(cli->dc, &r.srv_creds.challenge)) {
944 DEBUG(0,("rpccli_netlogon_sam_logon: credentials chain check failed\n"));
945 return NT_STATUS_ACCESS_DENIED;
954 * Logon domain user with an 'network' SAM logon
956 * @param info3 Pointer to a NET_USER_INFO_3 already allocated by the caller.
959 NTSTATUS rpccli_netlogon_sam_network_logon(struct rpc_pipe_client *cli,
961 uint32 logon_parameters,
963 const char *username,
965 const char *workstation,
967 DATA_BLOB lm_response,
968 DATA_BLOB nt_response,
969 NET_USER_INFO_3 *info3)
971 prs_struct qbuf, rbuf;
974 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
976 int validation_level = 3;
977 const char *workstation_name_slash;
978 const char *server_name_slash;
979 static uint8 zeros[16];
986 ZERO_STRUCT(ret_creds);
988 creds_client_step(cli->dc, &clnt_creds);
990 if (server[0] != '\\' && server[1] != '\\') {
991 server_name_slash = talloc_asprintf(mem_ctx, "\\\\%s", server);
993 server_name_slash = server;
996 if (workstation[0] != '\\' && workstation[1] != '\\') {
997 workstation_name_slash = talloc_asprintf(mem_ctx, "\\\\%s", workstation);
999 workstation_name_slash = workstation;
1002 if (!workstation_name_slash || !server_name_slash) {
1003 DEBUG(0, ("talloc_asprintf failed!\n"));
1004 return NT_STATUS_NO_MEMORY;
1007 /* Initialise input parameters */
1009 q.validation_level = validation_level;
1011 ctr.switch_value = NET_LOGON_TYPE;
1013 init_id_info2(&ctr.auth.id2, domain,
1014 logon_parameters, /* param_ctrl */
1015 0xdead, 0xbeef, /* LUID? */
1016 username, workstation_name_slash, (const uchar*)chal,
1017 lm_response.data, lm_response.length, nt_response.data, nt_response.length);
1019 init_sam_info(&q.sam_id, server_name_slash, global_myname(),
1020 &clnt_creds, &ret_creds, NET_LOGON_TYPE,
1025 /* Marshall data and send request */
1027 CLI_DO_RPC(cli, mem_ctx, PI_NETLOGON, NET_SAMLOGON,
1032 NT_STATUS_UNSUCCESSFUL);
1034 if (memcmp(zeros, info3->user_sess_key, 16) != 0) {
1035 SamOEMhash(info3->user_sess_key, cli->dc->sess_key, 16);
1037 memset(info3->user_sess_key, '\0', 16);
1040 if (memcmp(zeros, info3->lm_sess_key, 8) != 0) {
1041 SamOEMhash(info3->lm_sess_key, cli->dc->sess_key, 8);
1043 memset(info3->lm_sess_key, '\0', 8);
1046 for (i=0; i < 7; i++) {
1047 memset(&info3->unknown[i], '\0', 4);
1050 /* Return results */
1054 if (r.buffer_creds) {
1055 /* Check returned credentials if present. */
1056 if (!creds_client_check(cli->dc, &r.srv_creds.challenge)) {
1057 DEBUG(0,("rpccli_netlogon_sam_network_logon: credentials chain check failed\n"));
1058 return NT_STATUS_ACCESS_DENIED;
1065 NTSTATUS rpccli_netlogon_sam_network_logon_ex(struct rpc_pipe_client *cli,
1066 TALLOC_CTX *mem_ctx,
1067 uint32 logon_parameters,
1069 const char *username,
1071 const char *workstation,
1072 const uint8 chal[8],
1073 DATA_BLOB lm_response,
1074 DATA_BLOB nt_response,
1075 NET_USER_INFO_3 *info3)
1077 prs_struct qbuf, rbuf;
1078 NET_Q_SAM_LOGON_EX q;
1079 NET_R_SAM_LOGON_EX r;
1080 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
1081 NET_ID_INFO_CTR ctr;
1082 int validation_level = 3;
1083 const char *workstation_name_slash;
1084 const char *server_name_slash;
1085 static uint8 zeros[16];
1091 if (server[0] != '\\' && server[1] != '\\') {
1092 server_name_slash = talloc_asprintf(mem_ctx, "\\\\%s", server);
1094 server_name_slash = server;
1097 if (workstation[0] != '\\' && workstation[1] != '\\') {
1098 workstation_name_slash = talloc_asprintf(mem_ctx, "\\\\%s", workstation);
1100 workstation_name_slash = workstation;
1103 if (!workstation_name_slash || !server_name_slash) {
1104 DEBUG(0, ("talloc_asprintf failed!\n"));
1105 return NT_STATUS_NO_MEMORY;
1108 /* Initialise input parameters */
1110 q.validation_level = validation_level;
1112 ctr.switch_value = NET_LOGON_TYPE;
1114 init_id_info2(&ctr.auth.id2, domain,
1115 logon_parameters, /* param_ctrl */
1116 0xdead, 0xbeef, /* LUID? */
1117 username, workstation_name_slash, (const uchar*)chal,
1118 lm_response.data, lm_response.length, nt_response.data,
1119 nt_response.length);
1121 init_sam_info_ex(&q.sam_id, server_name_slash, global_myname(),
1122 NET_LOGON_TYPE, &ctr);
1126 /* Marshall data and send request */
1128 CLI_DO_RPC(cli, mem_ctx, PI_NETLOGON, NET_SAMLOGON_EX,
1130 net_io_q_sam_logon_ex,
1131 net_io_r_sam_logon_ex,
1132 NT_STATUS_UNSUCCESSFUL);
1134 if (memcmp(zeros, info3->user_sess_key, 16) != 0) {
1135 SamOEMhash(info3->user_sess_key, cli->dc->sess_key, 16);
1137 memset(info3->user_sess_key, '\0', 16);
1140 if (memcmp(zeros, info3->lm_sess_key, 8) != 0) {
1141 SamOEMhash(info3->lm_sess_key, cli->dc->sess_key, 8);
1143 memset(info3->lm_sess_key, '\0', 8);
1146 for (i=0; i < 7; i++) {
1147 memset(&info3->unknown[i], '\0', 4);
1150 /* Return results */
1157 /***************************************************************************
1158 LSA Server Password Set.
1159 ****************************************************************************/
1161 NTSTATUS rpccli_net_srv_pwset(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
1162 const char *machine_name, const uint8 hashed_mach_pwd[16])
1166 DOM_CRED clnt_creds;
1169 uint16 sec_chan_type = 2;
1172 creds_client_step(cli->dc, &clnt_creds);
1174 DEBUG(4,("cli_net_srv_pwset: srv:%s acct:%s sc: %d mc: %s\n",
1175 cli->dc->remote_machine, cli->dc->mach_acct, sec_chan_type, machine_name));
1177 /* store the parameters */
1178 init_q_srv_pwset(&q, cli->dc->remote_machine, (const char *)cli->dc->sess_key,
1179 cli->dc->mach_acct, sec_chan_type, machine_name,
1180 &clnt_creds, hashed_mach_pwd);
1182 CLI_DO_RPC(cli, mem_ctx, PI_NETLOGON, NET_SRVPWSET,
1187 NT_STATUS_UNSUCCESSFUL);
1191 if (!NT_STATUS_IS_OK(result)) {
1192 /* report error code */
1193 DEBUG(0,("cli_net_srv_pwset: %s\n", nt_errstr(result)));
1196 /* Always check returned credentials. */
1197 if (!creds_client_check(cli->dc, &r.srv_cred.challenge)) {
1198 DEBUG(0,("rpccli_net_srv_pwset: credentials chain check failed\n"));
1199 return NT_STATUS_ACCESS_DENIED;