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, see <http://www.gnu.org/licenses/>.
24 /* LSA Request Challenge. Sends our challenge to server, then gets
25 server response. These are used to generate the credentials.
26 The sent and received challenges are stored in the netlog pipe
27 private data. Only call this via rpccli_netlogon_setup_creds(). JRA.
30 static NTSTATUS rpccli_net_req_chal(struct rpc_pipe_client *cli,
32 const char *server_name,
33 const char *clnt_name,
34 const DOM_CHAL *clnt_chal_in,
35 DOM_CHAL *srv_chal_out)
37 prs_struct qbuf, rbuf;
40 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
42 /* create and send a MSRPC command with api NET_REQCHAL */
44 DEBUG(4,("cli_net_req_chal: LSA Request Challenge from %s to %s\n",
45 clnt_name, server_name));
47 /* store the parameters */
48 init_q_req_chal(&q, server_name, clnt_name, clnt_chal_in);
50 /* Marshall data and send request */
51 CLI_DO_RPC(cli, mem_ctx, PI_NETLOGON, NET_REQCHAL,
56 NT_STATUS_UNSUCCESSFUL);
62 if (NT_STATUS_IS_OK(result)) {
63 /* Store the returned server challenge. */
64 *srv_chal_out = r.srv_chal;
71 /****************************************************************************
74 Send the client credential, receive back a server credential.
75 Ensure that the server credential returned matches the session key
76 encrypt of the server challenge originally received. JRA.
77 ****************************************************************************/
79 NTSTATUS rpccli_net_auth2(struct rpc_pipe_client *cli,
81 uint32 *neg_flags, DOM_CHAL *srv_chal)
83 prs_struct qbuf, rbuf;
86 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
89 if ( sec_chan == SEC_CHAN_DOMAIN )
90 fstr_sprintf( machine_acct, "%s$", lp_workgroup() );
92 fstrcpy( machine_acct, cli->mach_acct );
94 /* create and send a MSRPC command with api NET_AUTH2 */
96 DEBUG(4,("cli_net_auth2: srv:%s acct:%s sc:%x mc: %s chal %s neg: %x\n",
97 cli->srv_name_slash, machine_acct, sec_chan, global_myname(),
98 credstr(cli->clnt_cred.challenge.data), *neg_flags));
100 /* store the parameters */
102 init_q_auth_2(&q, cli->srv_name_slash, machine_acct,
103 sec_chan, global_myname(), &cli->clnt_cred.challenge,
106 /* turn parameters into data stream */
108 CLI_DO_RPC(cli, mem_ctx, PI_NETLOGON, NET_AUTH2,
113 NT_STATUS_UNSUCCESSFUL);
117 if (NT_STATUS_IS_OK(result)) {
121 * Check the returned value using the initial
122 * server received challenge.
126 if (cred_assert( &r.srv_chal, cli->sess_key, srv_chal, zerotime) == 0) {
129 * Server replied with bad credential. Fail.
131 DEBUG(0,("cli_net_auth2: server %s replied with bad credential (bad machine \
132 password ?).\n", cli->cli->desthost ));
133 return NT_STATUS_ACCESS_DENIED;
135 *neg_flags = r.srv_flgs.neg_flags;
142 /****************************************************************************
145 Send the client credential, receive back a server credential.
146 The caller *must* ensure that the server credential returned matches the session key
147 encrypt of the server challenge originally received. JRA.
148 ****************************************************************************/
150 static NTSTATUS rpccli_net_auth2(struct rpc_pipe_client *cli,
152 const char *server_name,
153 const char *account_name,
154 uint16 sec_chan_type,
155 const char *computer_name,
156 uint32 *neg_flags_inout,
157 const DOM_CHAL *clnt_chal_in,
158 DOM_CHAL *srv_chal_out)
160 prs_struct qbuf, rbuf;
163 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
165 /* create and send a MSRPC command with api NET_AUTH2 */
167 DEBUG(4,("cli_net_auth2: srv:%s acct:%s sc:%x mc: %s neg: %x\n",
168 server_name, account_name, sec_chan_type, computer_name,
171 /* store the parameters */
173 init_q_auth_2(&q, server_name, account_name, sec_chan_type,
174 computer_name, clnt_chal_in, *neg_flags_inout);
176 /* turn parameters into data stream */
178 CLI_DO_RPC(cli, mem_ctx, PI_NETLOGON, NET_AUTH2,
183 NT_STATUS_UNSUCCESSFUL);
187 if (NT_STATUS_IS_OK(result)) {
188 *srv_chal_out = r.srv_chal;
189 *neg_flags_inout = r.srv_flgs.neg_flags;
195 #if 0 /* not currebntly used */
196 /****************************************************************************
199 Send the client credential, receive back a server credential.
200 The caller *must* ensure that the server credential returned matches the session key
201 encrypt of the server challenge originally received. JRA.
202 ****************************************************************************/
204 static NTSTATUS rpccli_net_auth3(struct rpc_pipe_client *cli,
206 const char *server_name,
207 const char *account_name,
208 uint16 sec_chan_type,
209 const char *computer_name,
210 uint32 *neg_flags_inout,
211 const DOM_CHAL *clnt_chal_in,
212 DOM_CHAL *srv_chal_out)
214 prs_struct qbuf, rbuf;
217 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
219 /* create and send a MSRPC command with api NET_AUTH2 */
221 DEBUG(4,("cli_net_auth3: srv:%s acct:%s sc:%x mc: %s chal %s neg: %x\n",
222 server_name, account_name, sec_chan_type, computer_name,
223 credstr(clnt_chal_in->data), *neg_flags_inout));
225 /* store the parameters */
226 init_q_auth_3(&q, server_name, account_name, sec_chan_type,
227 computer_name, clnt_chal_in, *neg_flags_inout);
229 /* turn parameters into data stream */
231 CLI_DO_RPC(cli, mem_ctx, PI_NETLOGON, NET_AUTH3,
236 NT_STATUS_UNSUCCESSFUL);
238 if (NT_STATUS_IS_OK(result)) {
239 *srv_chal_out = r.srv_chal;
240 *neg_flags_inout = r.srv_flgs.neg_flags;
245 #endif /* not currebntly used */
247 /****************************************************************************
248 Wrapper function that uses the auth and auth2 calls to set up a NETLOGON
249 credentials chain. Stores the credentials in the struct dcinfo in the
250 netlogon pipe struct.
251 ****************************************************************************/
253 NTSTATUS rpccli_netlogon_setup_creds(struct rpc_pipe_client *cli,
254 const char *server_name,
256 const char *clnt_name,
257 const char *machine_account,
258 const unsigned char machine_pwd[16],
259 uint32 sec_chan_type,
260 uint32 *neg_flags_inout)
262 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
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(*neg_flags_inout,
311 * Send client auth-2 challenge and receive server repy.
314 result = rpccli_net_auth2(cli,
321 &clnt_chal_send, /* input. */
322 &srv_chal_recv); /* output */
324 if (!NT_STATUS_IS_OK(result)) {
329 * Check the returned value using the initial
330 * server received challenge.
333 if (!creds_client_check(dc, &srv_chal_recv)) {
335 * Server replied with bad credential. Fail.
337 DEBUG(0,("rpccli_netlogon_setup_creds: server %s "
338 "replied with bad credential\n",
339 cli->cli->desthost ));
340 return NT_STATUS_ACCESS_DENIED;
343 DEBUG(5,("rpccli_netlogon_setup_creds: server %s credential "
344 "chain established.\n",
345 cli->cli->desthost ));
350 /* Logon Control 2 */
352 NTSTATUS rpccli_netlogon_logon_ctrl2(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
355 prs_struct qbuf, rbuf;
358 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
364 /* Initialise input parameters */
366 slprintf(server, sizeof(fstring)-1, "\\\\%s", cli->cli->desthost);
367 init_net_q_logon_ctrl2(&q, server, query_level);
369 /* Marshall data and send request */
371 CLI_DO_RPC(cli, mem_ctx, PI_NETLOGON, NET_LOGON_CTRL2,
374 net_io_q_logon_ctrl2,
375 net_io_r_logon_ctrl2,
376 NT_STATUS_UNSUCCESSFUL);
384 WERROR rpccli_netlogon_getanydcname(struct rpc_pipe_client *cli,
385 TALLOC_CTX *mem_ctx, const char *mydcname,
386 const char *domainname, char **newdcname)
388 prs_struct qbuf, rbuf;
389 NET_Q_GETANYDCNAME q;
390 NET_R_GETANYDCNAME r;
392 fstring mydcname_slash;
397 /* Initialise input parameters */
399 slprintf(mydcname_slash, sizeof(fstring)-1, "\\\\%s", mydcname);
400 init_net_q_getanydcname(&q, mydcname_slash, domainname);
402 /* Marshall data and send request */
404 CLI_DO_RPC_WERR(cli, mem_ctx, PI_NETLOGON, NET_GETANYDCNAME,
407 net_io_q_getanydcname,
408 net_io_r_getanydcname,
409 WERR_GENERAL_FAILURE);
413 if (W_ERROR_IS_OK(result) && newdcname) {
414 *newdcname = rpcstr_pull_unistr2_talloc(mem_ctx, &r.uni_dcname);
415 W_ERROR_HAVE_NO_MEMORY(*newdcname);
423 WERROR rpccli_netlogon_getdcname(struct rpc_pipe_client *cli,
424 TALLOC_CTX *mem_ctx, const char *mydcname,
425 const char *domainname, char **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) && newdcname) {
453 *newdcname = rpcstr_pull_unistr2_talloc(mem_ctx, &r.uni_dcname);
454 W_ERROR_HAVE_NO_MEMORY(*newdcname);
460 static WERROR pull_domain_controller_info_from_getdcname_reply(TALLOC_CTX *mem_ctx,
461 struct DS_DOMAIN_CONTROLLER_INFO **info_out,
462 NET_R_DSR_GETDCNAME *r)
464 struct DS_DOMAIN_CONTROLLER_INFO *info;
466 info = TALLOC_ZERO_P(mem_ctx, struct DS_DOMAIN_CONTROLLER_INFO);
471 if (&r->uni_dc_unc) {
474 tmp = rpcstr_pull_unistr2_talloc(mem_ctx, &r->uni_dc_unc);
476 return WERR_GENERAL_FAILURE;
478 if (*tmp == '\\') tmp += 1;
479 if (*tmp == '\\') tmp += 1;
481 info->domain_controller_name = talloc_strdup(mem_ctx, tmp);
482 if (info->domain_controller_name == NULL) {
483 return WERR_GENERAL_FAILURE;
487 if (&r->uni_dc_address) {
490 tmp = rpcstr_pull_unistr2_talloc(mem_ctx, &r->uni_dc_address);
492 return WERR_GENERAL_FAILURE;
494 if (*tmp == '\\') tmp += 1;
495 if (*tmp == '\\') tmp += 1;
497 info->domain_controller_address = talloc_strdup(mem_ctx, tmp);
498 if (info->domain_controller_address == NULL) {
499 return WERR_GENERAL_FAILURE;
503 info->domain_controller_address_type = r->dc_address_type;
505 info->domain_guid = (struct GUID *)talloc_memdup(
506 mem_ctx, &r->domain_guid, sizeof(struct GUID));
507 if (!info->domain_guid) {
508 return WERR_GENERAL_FAILURE;
511 if (&r->uni_domain_name) {
512 info->domain_name = rpcstr_pull_unistr2_talloc(mem_ctx, &r->uni_domain_name);
513 if (!info->domain_name) {
514 return WERR_GENERAL_FAILURE;
518 if (&r->uni_forest_name) {
519 info->dns_forest_name = rpcstr_pull_unistr2_talloc(mem_ctx, &r->uni_forest_name);
520 if (!info->dns_forest_name) {
521 return WERR_GENERAL_FAILURE;
525 info->flags = r->dc_flags;
527 if (&r->uni_dc_site_name) {
528 info->dc_site_name = rpcstr_pull_unistr2_talloc(mem_ctx, &r->uni_dc_site_name);
529 if (!info->dc_site_name) {
530 return WERR_GENERAL_FAILURE;
534 if (&r->uni_client_site_name) {
535 info->client_site_name = rpcstr_pull_unistr2_talloc(mem_ctx, &r->uni_client_site_name);
536 if (!info->client_site_name) {
537 return WERR_GENERAL_FAILURE;
548 WERROR rpccli_netlogon_dsr_getdcname(struct rpc_pipe_client *cli,
550 const char *server_name,
551 const char *domain_name,
552 struct GUID *domain_guid,
553 struct GUID *site_guid,
555 struct DS_DOMAIN_CONTROLLER_INFO **info_out)
557 prs_struct qbuf, rbuf;
558 NET_Q_DSR_GETDCNAME q;
559 NET_R_DSR_GETDCNAME r;
565 /* Initialize input parameters */
567 tmp_str = talloc_asprintf(mem_ctx, "\\\\%s", server_name);
568 if (tmp_str == NULL) {
572 init_net_q_dsr_getdcname(&q, tmp_str, domain_name, domain_guid,
575 /* Marshall data and send request */
577 CLI_DO_RPC_WERR(cli, mem_ctx, PI_NETLOGON, NET_DSR_GETDCNAME,
580 net_io_q_dsr_getdcname,
581 net_io_r_dsr_getdcname,
582 WERR_GENERAL_FAILURE);
584 if (!W_ERROR_IS_OK(r.result)) {
588 r.result = pull_domain_controller_info_from_getdcname_reply(mem_ctx, info_out, &r);
589 if (!W_ERROR_IS_OK(r.result)) {
596 /* Dsr_GetDCNameEx */
598 WERROR rpccli_netlogon_dsr_getdcnameex(struct rpc_pipe_client *cli,
600 const char *server_name,
601 const char *domain_name,
602 struct GUID *domain_guid,
603 const char *site_name,
605 struct DS_DOMAIN_CONTROLLER_INFO **info_out)
607 prs_struct qbuf, rbuf;
608 NET_Q_DSR_GETDCNAMEEX q;
609 NET_R_DSR_GETDCNAME r;
615 /* Initialize input parameters */
617 tmp_str = talloc_asprintf(mem_ctx, "\\\\%s", server_name);
618 if (tmp_str == NULL) {
622 init_net_q_dsr_getdcnameex(&q, server_name, domain_name, domain_guid,
625 /* Marshall data and send request */
627 CLI_DO_RPC_WERR(cli, mem_ctx, PI_NETLOGON, NET_DSR_GETDCNAMEEX,
630 net_io_q_dsr_getdcnameex,
631 net_io_r_dsr_getdcname,
632 WERR_GENERAL_FAILURE);
634 if (!W_ERROR_IS_OK(r.result)) {
638 r.result = pull_domain_controller_info_from_getdcname_reply(mem_ctx, info_out, &r);
639 if (!W_ERROR_IS_OK(r.result)) {
646 /* Dsr_GetDCNameEx */
648 WERROR rpccli_netlogon_dsr_getdcnameex2(struct rpc_pipe_client *cli,
650 const char *server_name,
651 const char *client_account,
653 const char *domain_name,
654 struct GUID *domain_guid,
655 const char *site_name,
657 struct DS_DOMAIN_CONTROLLER_INFO **info_out)
659 prs_struct qbuf, rbuf;
660 NET_Q_DSR_GETDCNAMEEX2 q;
661 NET_R_DSR_GETDCNAME r;
667 /* Initialize input parameters */
669 tmp_str = talloc_asprintf(mem_ctx, "\\\\%s", server_name);
670 if (tmp_str == NULL) {
674 init_net_q_dsr_getdcnameex2(&q, server_name, domain_name, client_account,
675 mask, domain_guid, site_name, flags);
677 /* Marshall data and send request */
679 CLI_DO_RPC_WERR(cli, mem_ctx, PI_NETLOGON, NET_DSR_GETDCNAMEEX2,
682 net_io_q_dsr_getdcnameex2,
683 net_io_r_dsr_getdcname,
684 WERR_GENERAL_FAILURE);
686 if (!W_ERROR_IS_OK(r.result)) {
690 r.result = pull_domain_controller_info_from_getdcname_reply(mem_ctx, info_out, &r);
691 if (!W_ERROR_IS_OK(r.result)) {
699 /* Dsr_GetSiteName */
701 WERROR rpccli_netlogon_dsr_getsitename(struct rpc_pipe_client *cli,
703 const char *computer_name,
706 prs_struct qbuf, rbuf;
707 NET_Q_DSR_GETSITENAME q;
708 NET_R_DSR_GETSITENAME r;
713 /* Initialize input parameters */
715 init_net_q_dsr_getsitename(&q, computer_name);
717 /* Marshall data and send request */
719 CLI_DO_RPC_WERR(cli, mem_ctx, PI_NETLOGON, NET_DSR_GETSITENAME,
722 net_io_q_dsr_getsitename,
723 net_io_r_dsr_getsitename,
724 WERR_GENERAL_FAILURE);
726 if (!W_ERROR_IS_OK(r.result)) {
730 if ((site_name != NULL) &&
731 ((*site_name = rpcstr_pull_unistr2_talloc(
732 mem_ctx, &r.uni_site_name)) == NULL)) {
733 return WERR_GENERAL_FAILURE;
741 /* Sam synchronisation */
743 NTSTATUS rpccli_netlogon_sam_sync(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
744 uint32 database_id, uint32 next_rid, uint32 *num_deltas,
745 SAM_DELTA_HDR **hdr_deltas,
746 SAM_DELTA_CTR **deltas)
748 prs_struct qbuf, rbuf;
751 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
758 ZERO_STRUCT(ret_creds);
760 /* Initialise input parameters */
762 creds_client_step(cli->dc, &clnt_creds);
764 init_net_q_sam_sync(&q, cli->dc->remote_machine, global_myname(),
765 &clnt_creds, &ret_creds, database_id, next_rid);
767 /* Marshall data and send request */
769 CLI_DO_RPC_COPY_SESS_KEY(cli, mem_ctx, PI_NETLOGON, NET_SAM_SYNC,
774 NT_STATUS_UNSUCCESSFUL);
779 *num_deltas = r.num_deltas2;
780 *hdr_deltas = r.hdr_deltas;
783 if (!NT_STATUS_IS_ERR(result)) {
784 /* Check returned credentials. */
785 if (!creds_client_check(cli->dc, &r.srv_creds.challenge)) {
786 DEBUG(0,("cli_netlogon_sam_sync: credentials chain check failed\n"));
787 return NT_STATUS_ACCESS_DENIED;
794 /* Sam synchronisation */
796 NTSTATUS rpccli_netlogon_sam_deltas(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
797 uint32 database_id, uint64 seqnum,
799 SAM_DELTA_HDR **hdr_deltas,
800 SAM_DELTA_CTR **deltas)
802 prs_struct qbuf, rbuf;
805 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
811 /* Initialise input parameters */
813 creds_client_step(cli->dc, &clnt_creds);
815 init_net_q_sam_deltas(&q, cli->dc->remote_machine,
816 global_myname(), &clnt_creds,
817 database_id, seqnum);
819 /* Marshall data and send request */
821 CLI_DO_RPC(cli, mem_ctx, PI_NETLOGON, NET_SAM_DELTAS,
826 NT_STATUS_UNSUCCESSFUL);
831 *num_deltas = r.num_deltas2;
832 *hdr_deltas = r.hdr_deltas;
835 if (!NT_STATUS_IS_ERR(result)) {
836 /* Check returned credentials. */
837 if (!creds_client_check(cli->dc, &r.srv_creds.challenge)) {
838 DEBUG(0,("cli_netlogon_sam_sync: credentials chain check failed\n"));
839 return NT_STATUS_ACCESS_DENIED;
846 /* Logon domain user */
848 NTSTATUS rpccli_netlogon_sam_logon(struct rpc_pipe_client *cli,
850 uint32 logon_parameters,
852 const char *username,
853 const char *password,
854 const char *workstation,
857 prs_struct qbuf, rbuf;
860 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
864 NET_USER_INFO_3 user;
865 int validation_level = 3;
866 fstring clnt_name_slash;
870 ZERO_STRUCT(ret_creds);
873 fstr_sprintf( clnt_name_slash, "\\\\%s", workstation );
875 fstr_sprintf( clnt_name_slash, "\\\\%s", global_myname() );
878 /* Initialise input parameters */
880 creds_client_step(cli->dc, &clnt_creds);
882 q.validation_level = validation_level;
884 ctr.switch_value = logon_type;
886 switch (logon_type) {
887 case INTERACTIVE_LOGON_TYPE: {
888 unsigned char lm_owf_user_pwd[16], nt_owf_user_pwd[16];
890 nt_lm_owf_gen(password, nt_owf_user_pwd, lm_owf_user_pwd);
892 init_id_info1(&ctr.auth.id1, domain,
893 logon_parameters, /* param_ctrl */
894 0xdead, 0xbeef, /* LUID? */
895 username, clnt_name_slash,
896 (const char *)cli->dc->sess_key, lm_owf_user_pwd,
901 case NET_LOGON_TYPE: {
903 unsigned char local_lm_response[24];
904 unsigned char local_nt_response[24];
906 generate_random_buffer(chal, 8);
908 SMBencrypt(password, chal, local_lm_response);
909 SMBNTencrypt(password, chal, local_nt_response);
911 init_id_info2(&ctr.auth.id2, domain,
912 logon_parameters, /* param_ctrl */
913 0xdead, 0xbeef, /* LUID? */
914 username, clnt_name_slash, chal,
915 local_lm_response, 24, local_nt_response, 24);
919 DEBUG(0, ("switch value %d not supported\n",
921 return NT_STATUS_INVALID_INFO_CLASS;
926 init_sam_info(&q.sam_id, cli->dc->remote_machine, global_myname(),
927 &clnt_creds, &ret_creds, logon_type,
930 /* Marshall data and send request */
932 CLI_DO_RPC(cli, mem_ctx, PI_NETLOGON, NET_SAMLOGON,
937 NT_STATUS_UNSUCCESSFUL);
943 if (r.buffer_creds) {
944 /* Check returned credentials if present. */
945 if (!creds_client_check(cli->dc, &r.srv_creds.challenge)) {
946 DEBUG(0,("rpccli_netlogon_sam_logon: credentials chain check failed\n"));
947 return NT_STATUS_ACCESS_DENIED;
956 * Logon domain user with an 'network' SAM logon
958 * @param info3 Pointer to a NET_USER_INFO_3 already allocated by the caller.
961 NTSTATUS rpccli_netlogon_sam_network_logon(struct rpc_pipe_client *cli,
963 uint32 logon_parameters,
965 const char *username,
967 const char *workstation,
969 DATA_BLOB lm_response,
970 DATA_BLOB nt_response,
971 NET_USER_INFO_3 *info3)
973 prs_struct qbuf, rbuf;
976 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
978 int validation_level = 3;
979 const char *workstation_name_slash;
980 const char *server_name_slash;
989 ZERO_STRUCT(ret_creds);
991 creds_client_step(cli->dc, &clnt_creds);
993 if (server[0] != '\\' && server[1] != '\\') {
994 server_name_slash = talloc_asprintf(mem_ctx, "\\\\%s", server);
996 server_name_slash = server;
999 if (workstation[0] != '\\' && workstation[1] != '\\') {
1000 workstation_name_slash = talloc_asprintf(mem_ctx, "\\\\%s", workstation);
1002 workstation_name_slash = workstation;
1005 if (!workstation_name_slash || !server_name_slash) {
1006 DEBUG(0, ("talloc_asprintf failed!\n"));
1007 return NT_STATUS_NO_MEMORY;
1010 /* Initialise input parameters */
1012 q.validation_level = validation_level;
1014 ctr.switch_value = NET_LOGON_TYPE;
1016 init_id_info2(&ctr.auth.id2, domain,
1017 logon_parameters, /* param_ctrl */
1018 0xdead, 0xbeef, /* LUID? */
1019 username, workstation_name_slash, (const uchar*)chal,
1020 lm_response.data, lm_response.length, nt_response.data, nt_response.length);
1022 init_sam_info(&q.sam_id, server_name_slash, global_myname(),
1023 &clnt_creds, &ret_creds, NET_LOGON_TYPE,
1028 /* Marshall data and send request */
1030 CLI_DO_RPC(cli, mem_ctx, PI_NETLOGON, NET_SAMLOGON,
1035 NT_STATUS_UNSUCCESSFUL);
1037 if (memcmp(zeros, info3->user_sess_key, 16) != 0) {
1038 SamOEMhash(info3->user_sess_key, cli->dc->sess_key, 16);
1040 memset(info3->user_sess_key, '\0', 16);
1043 if (memcmp(zeros, info3->lm_sess_key, 8) != 0) {
1044 SamOEMhash(info3->lm_sess_key, cli->dc->sess_key, 8);
1046 memset(info3->lm_sess_key, '\0', 8);
1049 for (i=0; i < 7; i++) {
1050 memset(&info3->unknown[i], '\0', 4);
1053 /* Return results */
1057 if (r.buffer_creds) {
1058 /* Check returned credentials if present. */
1059 if (!creds_client_check(cli->dc, &r.srv_creds.challenge)) {
1060 DEBUG(0,("rpccli_netlogon_sam_network_logon: credentials chain check failed\n"));
1061 return NT_STATUS_ACCESS_DENIED;
1068 NTSTATUS rpccli_netlogon_sam_network_logon_ex(struct rpc_pipe_client *cli,
1069 TALLOC_CTX *mem_ctx,
1070 uint32 logon_parameters,
1072 const char *username,
1074 const char *workstation,
1075 const uint8 chal[8],
1076 DATA_BLOB lm_response,
1077 DATA_BLOB nt_response,
1078 NET_USER_INFO_3 *info3)
1080 prs_struct qbuf, rbuf;
1081 NET_Q_SAM_LOGON_EX q;
1082 NET_R_SAM_LOGON_EX r;
1083 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
1084 NET_ID_INFO_CTR ctr;
1085 int validation_level = 3;
1086 const char *workstation_name_slash;
1087 const char *server_name_slash;
1095 if (server[0] != '\\' && server[1] != '\\') {
1096 server_name_slash = talloc_asprintf(mem_ctx, "\\\\%s", server);
1098 server_name_slash = server;
1101 if (workstation[0] != '\\' && workstation[1] != '\\') {
1102 workstation_name_slash = talloc_asprintf(mem_ctx, "\\\\%s", workstation);
1104 workstation_name_slash = workstation;
1107 if (!workstation_name_slash || !server_name_slash) {
1108 DEBUG(0, ("talloc_asprintf failed!\n"));
1109 return NT_STATUS_NO_MEMORY;
1112 /* Initialise input parameters */
1114 q.validation_level = validation_level;
1116 ctr.switch_value = NET_LOGON_TYPE;
1118 init_id_info2(&ctr.auth.id2, domain,
1119 logon_parameters, /* param_ctrl */
1120 0xdead, 0xbeef, /* LUID? */
1121 username, workstation_name_slash, (const uchar*)chal,
1122 lm_response.data, lm_response.length, nt_response.data,
1123 nt_response.length);
1125 init_sam_info_ex(&q.sam_id, server_name_slash, global_myname(),
1126 NET_LOGON_TYPE, &ctr);
1130 /* Marshall data and send request */
1132 CLI_DO_RPC(cli, mem_ctx, PI_NETLOGON, NET_SAMLOGON_EX,
1134 net_io_q_sam_logon_ex,
1135 net_io_r_sam_logon_ex,
1136 NT_STATUS_UNSUCCESSFUL);
1138 if (memcmp(zeros, info3->user_sess_key, 16) != 0) {
1139 SamOEMhash(info3->user_sess_key, cli->dc->sess_key, 16);
1141 memset(info3->user_sess_key, '\0', 16);
1144 if (memcmp(zeros, info3->lm_sess_key, 8) != 0) {
1145 SamOEMhash(info3->lm_sess_key, cli->dc->sess_key, 8);
1147 memset(info3->lm_sess_key, '\0', 8);
1150 for (i=0; i < 7; i++) {
1151 memset(&info3->unknown[i], '\0', 4);
1154 /* Return results */
1161 /***************************************************************************
1162 LSA Server Password Set.
1163 ****************************************************************************/
1165 NTSTATUS rpccli_net_srv_pwset(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
1166 const char *machine_name, const uint8 hashed_mach_pwd[16])
1170 DOM_CRED clnt_creds;
1173 uint16 sec_chan_type = 2;
1176 creds_client_step(cli->dc, &clnt_creds);
1178 DEBUG(4,("cli_net_srv_pwset: srv:%s acct:%s sc: %d mc: %s\n",
1179 cli->dc->remote_machine, cli->dc->mach_acct, sec_chan_type, machine_name));
1181 /* store the parameters */
1182 init_q_srv_pwset(&q, cli->dc->remote_machine, (const char *)cli->dc->sess_key,
1183 cli->dc->mach_acct, sec_chan_type, machine_name,
1184 &clnt_creds, hashed_mach_pwd);
1186 CLI_DO_RPC(cli, mem_ctx, PI_NETLOGON, NET_SRVPWSET,
1191 NT_STATUS_UNSUCCESSFUL);
1195 if (!NT_STATUS_IS_OK(result)) {
1196 /* report error code */
1197 DEBUG(0,("cli_net_srv_pwset: %s\n", nt_errstr(result)));
1200 /* Always check returned credentials. */
1201 if (!creds_client_check(cli->dc, &r.srv_cred.challenge)) {
1202 DEBUG(0,("rpccli_net_srv_pwset: credentials chain check failed\n"));
1203 return NT_STATUS_ACCESS_DENIED;