[GLUE] Rsync SAMBA_3_0 SVN r25598 in order to create the v3-0-test branch.
[Samba.git] / source / rpc_client / cli_netlogon.c
blob13a31e81d45b3243a7c3c654283d25e17e1f2da5
1 /*
2 Unix SMB/CIFS implementation.
3 NT Domain Authentication SMB / MSRPC client
4 Copyright (C) Andrew Tridgell 1992-2000
5 Copyright (C) Jeremy Allison 1998.
6 Largely re-written by Jeremy Allison (C) 2005.
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.
23 #include "includes.h"
25 /* LSA Request Challenge. Sends our challenge to server, then gets
26 server response. These are used to generate the credentials.
27 The sent and received challenges are stored in the netlog pipe
28 private data. Only call this via rpccli_netlogon_setup_creds(). JRA.
31 static NTSTATUS rpccli_net_req_chal(struct rpc_pipe_client *cli,
32 TALLOC_CTX *mem_ctx,
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;
39 NET_Q_REQ_CHAL q;
40 NET_R_REQ_CHAL r;
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,
53 q, r,
54 qbuf, rbuf,
55 net_io_q_req_chal,
56 net_io_r_req_chal,
57 NT_STATUS_UNSUCCESSFUL);
59 result = r.status;
61 /* Return result */
63 if (NT_STATUS_IS_OK(result)) {
64 /* Store the returned server challenge. */
65 *srv_chal_out = r.srv_chal;
68 return result;
71 #if 0
72 /****************************************************************************
73 LSA Authenticate 2
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,
81 uint16 sec_chan,
82 uint32 *neg_flags, DOM_CHAL *srv_chal)
84 prs_struct qbuf, rbuf;
85 NET_Q_AUTH_2 q;
86 NET_R_AUTH_2 r;
87 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
88 fstring machine_acct;
90 if ( sec_chan == SEC_CHAN_DOMAIN )
91 fstr_sprintf( machine_acct, "%s$", lp_workgroup() );
92 else
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,
105 *neg_flags);
107 /* turn parameters into data stream */
109 CLI_DO_RPC(cli, mem_ctx, PI_NETLOGON, NET_AUTH2,
110 q, r,
111 qbuf, rbuf,
112 net_io_q_auth_2,
113 net_io_r_auth_2,
114 NT_STATUS_UNSUCCESSFUL);
116 result = r.status;
118 if (NT_STATUS_IS_OK(result)) {
119 UTIME zerotime;
122 * Check the returned value using the initial
123 * server received challenge.
126 zerotime.time = 0;
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;
139 return result;
141 #endif
143 /****************************************************************************
144 LSA Authenticate 2
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,
152 TALLOC_CTX *mem_ctx,
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;
162 NET_Q_AUTH_2 q;
163 NET_R_AUTH_2 r;
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,
170 *neg_flags_inout));
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,
180 q, r,
181 qbuf, rbuf,
182 net_io_q_auth_2,
183 net_io_r_auth_2,
184 NT_STATUS_UNSUCCESSFUL);
186 result = r.status;
188 if (NT_STATUS_IS_OK(result)) {
189 *srv_chal_out = r.srv_chal;
190 *neg_flags_inout = r.srv_flgs.neg_flags;
193 return result;
196 #if 0 /* not currebntly used */
197 /****************************************************************************
198 LSA Authenticate 3
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,
206 TALLOC_CTX *mem_ctx,
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;
216 NET_Q_AUTH_3 q;
217 NET_R_AUTH_3 r;
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,
233 q, r,
234 qbuf, rbuf,
235 net_io_q_auth_3,
236 net_io_r_auth_3,
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;
244 return result;
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,
256 const char *domain,
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;
266 struct dcinfo *dc;
268 SMB_ASSERT(cli->pipe_idx == PI_NETLOGON);
270 dc = cli->dc;
271 if (!dc) {
272 return NT_STATUS_INVALID_PARAMETER;
275 /* Ensure we don't reuse any of this state. */
276 ZERO_STRUCTP(dc);
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,
293 cli->mem_ctx,
294 dc->remote_machine,
295 clnt_name,
296 &clnt_chal_send,
297 &srv_chal_recv);
299 if (!NT_STATUS_IS_OK(result)) {
300 return result;
303 /* Calculate the session key and client credentials */
304 creds_client_init(*neg_flags_inout,
306 &clnt_chal_send,
307 &srv_chal_recv,
308 machine_pwd,
309 &clnt_chal_send);
312 * Send client auth-2 challenge and receive server repy.
315 result = rpccli_net_auth2(cli,
316 cli->mem_ctx,
317 dc->remote_machine,
318 dc->mach_acct,
319 sec_chan_type,
320 clnt_name,
321 neg_flags_inout,
322 &clnt_chal_send, /* input. */
323 &srv_chal_recv); /* output */
325 if (!NT_STATUS_IS_OK(result)) {
326 return 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 ));
348 return NT_STATUS_OK;
351 /* Logon Control 2 */
353 NTSTATUS rpccli_netlogon_logon_ctrl2(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
354 uint32 query_level)
356 prs_struct qbuf, rbuf;
357 NET_Q_LOGON_CTRL2 q;
358 NET_R_LOGON_CTRL2 r;
359 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
360 fstring server;
362 ZERO_STRUCT(q);
363 ZERO_STRUCT(r);
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,
373 q, r,
374 qbuf, rbuf,
375 net_io_q_logon_ctrl2,
376 net_io_r_logon_ctrl2,
377 NT_STATUS_UNSUCCESSFUL);
379 result = r.status;
380 return result;
383 /* GetAnyDCName */
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;
392 WERROR result;
393 fstring mydcname_slash;
395 ZERO_STRUCT(q);
396 ZERO_STRUCT(r);
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,
406 q, r,
407 qbuf, rbuf,
408 net_io_q_getanydcname,
409 net_io_r_getanydcname,
410 WERR_GENERAL_FAILURE);
412 result = r.status;
414 if (W_ERROR_IS_OK(result)) {
415 rpcstr_pull_unistr2_fstring(newdcname, &r.uni_dcname);
418 return result;
421 static WERROR pull_domain_controller_info_from_getdcname_reply(TALLOC_CTX *mem_ctx,
422 struct DS_DOMAIN_CONTROLLER_INFO **info_out,
423 NET_R_DSR_GETDCNAME *r)
425 struct DS_DOMAIN_CONTROLLER_INFO *info;
427 info = TALLOC_ZERO_P(mem_ctx, struct DS_DOMAIN_CONTROLLER_INFO);
428 if (!info) {
429 return WERR_NOMEM;
432 if (&r->uni_dc_unc) {
434 char *tmp;
435 tmp = rpcstr_pull_unistr2_talloc(mem_ctx, &r->uni_dc_unc);
436 if (tmp == NULL) {
437 return WERR_GENERAL_FAILURE;
439 if (*tmp == '\\') tmp += 1;
440 if (*tmp == '\\') tmp += 1;
442 info->domain_controller_name = talloc_strdup(mem_ctx, tmp);
443 if (info->domain_controller_name == NULL) {
444 return WERR_GENERAL_FAILURE;
448 if (&r->uni_dc_address) {
450 char *tmp;
451 tmp = rpcstr_pull_unistr2_talloc(mem_ctx, &r->uni_dc_address);
452 if (tmp == NULL) {
453 return WERR_GENERAL_FAILURE;
455 if (*tmp == '\\') tmp += 1;
456 if (*tmp == '\\') tmp += 1;
458 info->domain_controller_address = talloc_strdup(mem_ctx, tmp);
459 if (info->domain_controller_address == NULL) {
460 return WERR_GENERAL_FAILURE;
464 info->domain_controller_address_type = r->dc_address_type;
466 info->domain_guid = talloc_memdup(mem_ctx, &r->domain_guid, sizeof(struct GUID));
467 if (!info->domain_guid) {
468 return WERR_GENERAL_FAILURE;
471 if (&r->uni_domain_name) {
472 info->domain_name = rpcstr_pull_unistr2_talloc(mem_ctx, &r->uni_domain_name);
473 if (!info->domain_name) {
474 return WERR_GENERAL_FAILURE;
478 if (&r->uni_forest_name) {
479 info->dns_forest_name = rpcstr_pull_unistr2_talloc(mem_ctx, &r->uni_forest_name);
480 if (!info->dns_forest_name) {
481 return WERR_GENERAL_FAILURE;
485 info->flags = r->dc_flags;
487 if (&r->uni_dc_site_name) {
488 info->dc_site_name = rpcstr_pull_unistr2_talloc(mem_ctx, &r->uni_dc_site_name);
489 if (!info->dc_site_name) {
490 return WERR_GENERAL_FAILURE;
494 if (&r->uni_client_site_name) {
495 info->client_site_name = rpcstr_pull_unistr2_talloc(mem_ctx, &r->uni_client_site_name);
496 if (!info->client_site_name) {
497 return WERR_GENERAL_FAILURE;
501 *info_out = info;
503 return WERR_OK;
506 /* Dsr_GetDCName */
508 WERROR rpccli_netlogon_dsr_getdcname(struct rpc_pipe_client *cli,
509 TALLOC_CTX *mem_ctx,
510 const char *server_name,
511 const char *domain_name,
512 struct GUID *domain_guid,
513 struct GUID *site_guid,
514 uint32_t flags,
515 struct DS_DOMAIN_CONTROLLER_INFO **info_out)
517 prs_struct qbuf, rbuf;
518 NET_Q_DSR_GETDCNAME q;
519 NET_R_DSR_GETDCNAME r;
520 char *tmp_str;
522 ZERO_STRUCT(q);
523 ZERO_STRUCT(r);
525 /* Initialize input parameters */
527 tmp_str = talloc_asprintf(mem_ctx, "\\\\%s", server_name);
528 if (tmp_str == NULL) {
529 return WERR_NOMEM;
532 init_net_q_dsr_getdcname(&q, tmp_str, domain_name, domain_guid,
533 site_guid, flags);
535 /* Marshall data and send request */
537 CLI_DO_RPC_WERR(cli, mem_ctx, PI_NETLOGON, NET_DSR_GETDCNAME,
538 q, r,
539 qbuf, rbuf,
540 net_io_q_dsr_getdcname,
541 net_io_r_dsr_getdcname,
542 WERR_GENERAL_FAILURE);
544 if (!W_ERROR_IS_OK(r.result)) {
545 return r.result;
548 r.result = pull_domain_controller_info_from_getdcname_reply(mem_ctx, info_out, &r);
549 if (!W_ERROR_IS_OK(r.result)) {
550 return r.result;
553 return WERR_OK;
556 /* Dsr_GetDCNameEx */
558 WERROR rpccli_netlogon_dsr_getdcnameex(struct rpc_pipe_client *cli,
559 TALLOC_CTX *mem_ctx,
560 const char *server_name,
561 const char *domain_name,
562 struct GUID *domain_guid,
563 const char *site_name,
564 uint32_t flags,
565 struct DS_DOMAIN_CONTROLLER_INFO **info_out)
567 prs_struct qbuf, rbuf;
568 NET_Q_DSR_GETDCNAMEEX q;
569 NET_R_DSR_GETDCNAME r;
570 char *tmp_str;
572 ZERO_STRUCT(q);
573 ZERO_STRUCT(r);
575 /* Initialize input parameters */
577 tmp_str = talloc_asprintf(mem_ctx, "\\\\%s", server_name);
578 if (tmp_str == NULL) {
579 return WERR_NOMEM;
582 init_net_q_dsr_getdcnameex(&q, server_name, domain_name, domain_guid,
583 site_name, flags);
585 /* Marshall data and send request */
587 CLI_DO_RPC_WERR(cli, mem_ctx, PI_NETLOGON, NET_DSR_GETDCNAMEEX,
588 q, r,
589 qbuf, rbuf,
590 net_io_q_dsr_getdcnameex,
591 net_io_r_dsr_getdcname,
592 WERR_GENERAL_FAILURE);
594 if (!W_ERROR_IS_OK(r.result)) {
595 return r.result;
598 r.result = pull_domain_controller_info_from_getdcname_reply(mem_ctx, info_out, &r);
599 if (!W_ERROR_IS_OK(r.result)) {
600 return r.result;
603 return WERR_OK;
606 /* Dsr_GetDCNameEx */
608 WERROR rpccli_netlogon_dsr_getdcnameex2(struct rpc_pipe_client *cli,
609 TALLOC_CTX *mem_ctx,
610 const char *server_name,
611 const char *client_account,
612 uint32 mask,
613 const char *domain_name,
614 struct GUID *domain_guid,
615 const char *site_name,
616 uint32_t flags,
617 struct DS_DOMAIN_CONTROLLER_INFO **info_out)
619 prs_struct qbuf, rbuf;
620 NET_Q_DSR_GETDCNAMEEX2 q;
621 NET_R_DSR_GETDCNAME r;
622 char *tmp_str;
624 ZERO_STRUCT(q);
625 ZERO_STRUCT(r);
627 /* Initialize input parameters */
629 tmp_str = talloc_asprintf(mem_ctx, "\\\\%s", server_name);
630 if (tmp_str == NULL) {
631 return WERR_NOMEM;
634 init_net_q_dsr_getdcnameex2(&q, server_name, domain_name, client_account,
635 mask, domain_guid, site_name, flags);
637 /* Marshall data and send request */
639 CLI_DO_RPC_WERR(cli, mem_ctx, PI_NETLOGON, NET_DSR_GETDCNAMEEX2,
640 q, r,
641 qbuf, rbuf,
642 net_io_q_dsr_getdcnameex2,
643 net_io_r_dsr_getdcname,
644 WERR_GENERAL_FAILURE);
646 if (!W_ERROR_IS_OK(r.result)) {
647 return r.result;
650 r.result = pull_domain_controller_info_from_getdcname_reply(mem_ctx, info_out, &r);
651 if (!W_ERROR_IS_OK(r.result)) {
652 return r.result;
655 return WERR_OK;
659 /* Dsr_GetSiteName */
661 WERROR rpccli_netlogon_dsr_getsitename(struct rpc_pipe_client *cli,
662 TALLOC_CTX *mem_ctx,
663 const char *computer_name,
664 char **site_name)
666 prs_struct qbuf, rbuf;
667 NET_Q_DSR_GETSITENAME q;
668 NET_R_DSR_GETSITENAME r;
670 ZERO_STRUCT(q);
671 ZERO_STRUCT(r);
673 /* Initialize input parameters */
675 init_net_q_dsr_getsitename(&q, computer_name);
677 /* Marshall data and send request */
679 CLI_DO_RPC_WERR(cli, mem_ctx, PI_NETLOGON, NET_DSR_GETSITENAME,
680 q, r,
681 qbuf, rbuf,
682 net_io_q_dsr_getsitename,
683 net_io_r_dsr_getsitename,
684 WERR_GENERAL_FAILURE);
686 if (!W_ERROR_IS_OK(r.result)) {
687 return r.result;
690 if ((site_name != NULL) &&
691 ((*site_name = rpcstr_pull_unistr2_talloc(
692 mem_ctx, &r.uni_site_name)) == NULL)) {
693 return WERR_GENERAL_FAILURE;
696 return WERR_OK;
701 /* Sam synchronisation */
703 NTSTATUS rpccli_netlogon_sam_sync(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
704 uint32 database_id, uint32 next_rid, uint32 *num_deltas,
705 SAM_DELTA_HDR **hdr_deltas,
706 SAM_DELTA_CTR **deltas)
708 prs_struct qbuf, rbuf;
709 NET_Q_SAM_SYNC q;
710 NET_R_SAM_SYNC r;
711 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
712 DOM_CRED clnt_creds;
713 DOM_CRED ret_creds;
715 ZERO_STRUCT(q);
716 ZERO_STRUCT(r);
718 ZERO_STRUCT(ret_creds);
720 /* Initialise input parameters */
722 creds_client_step(cli->dc, &clnt_creds);
724 init_net_q_sam_sync(&q, cli->dc->remote_machine, global_myname(),
725 &clnt_creds, &ret_creds, database_id, next_rid);
727 /* Marshall data and send request */
729 CLI_DO_RPC_COPY_SESS_KEY(cli, mem_ctx, PI_NETLOGON, NET_SAM_SYNC,
730 q, r,
731 qbuf, rbuf,
732 net_io_q_sam_sync,
733 net_io_r_sam_sync,
734 NT_STATUS_UNSUCCESSFUL);
736 /* Return results */
738 result = r.status;
739 *num_deltas = r.num_deltas2;
740 *hdr_deltas = r.hdr_deltas;
741 *deltas = r.deltas;
743 if (!NT_STATUS_IS_ERR(result)) {
744 /* Check returned credentials. */
745 if (!creds_client_check(cli->dc, &r.srv_creds.challenge)) {
746 DEBUG(0,("cli_netlogon_sam_sync: credentials chain check failed\n"));
747 return NT_STATUS_ACCESS_DENIED;
751 return result;
754 /* Sam synchronisation */
756 NTSTATUS rpccli_netlogon_sam_deltas(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
757 uint32 database_id, uint64 seqnum,
758 uint32 *num_deltas,
759 SAM_DELTA_HDR **hdr_deltas,
760 SAM_DELTA_CTR **deltas)
762 prs_struct qbuf, rbuf;
763 NET_Q_SAM_DELTAS q;
764 NET_R_SAM_DELTAS r;
765 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
766 DOM_CRED clnt_creds;
768 ZERO_STRUCT(q);
769 ZERO_STRUCT(r);
771 /* Initialise input parameters */
773 creds_client_step(cli->dc, &clnt_creds);
775 init_net_q_sam_deltas(&q, cli->dc->remote_machine,
776 global_myname(), &clnt_creds,
777 database_id, seqnum);
779 /* Marshall data and send request */
781 CLI_DO_RPC(cli, mem_ctx, PI_NETLOGON, NET_SAM_DELTAS,
782 q, r,
783 qbuf, rbuf,
784 net_io_q_sam_deltas,
785 net_io_r_sam_deltas,
786 NT_STATUS_UNSUCCESSFUL);
788 /* Return results */
790 result = r.status;
791 *num_deltas = r.num_deltas2;
792 *hdr_deltas = r.hdr_deltas;
793 *deltas = r.deltas;
795 if (!NT_STATUS_IS_ERR(result)) {
796 /* Check returned credentials. */
797 if (!creds_client_check(cli->dc, &r.srv_creds.challenge)) {
798 DEBUG(0,("cli_netlogon_sam_sync: credentials chain check failed\n"));
799 return NT_STATUS_ACCESS_DENIED;
803 return result;
806 /* Logon domain user */
808 NTSTATUS rpccli_netlogon_sam_logon(struct rpc_pipe_client *cli,
809 TALLOC_CTX *mem_ctx,
810 uint32 logon_parameters,
811 const char *domain,
812 const char *username,
813 const char *password,
814 const char *workstation,
815 int logon_type)
817 prs_struct qbuf, rbuf;
818 NET_Q_SAM_LOGON q;
819 NET_R_SAM_LOGON r;
820 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
821 DOM_CRED clnt_creds;
822 DOM_CRED ret_creds;
823 NET_ID_INFO_CTR ctr;
824 NET_USER_INFO_3 user;
825 int validation_level = 3;
826 fstring clnt_name_slash;
828 ZERO_STRUCT(q);
829 ZERO_STRUCT(r);
830 ZERO_STRUCT(ret_creds);
832 if (workstation) {
833 fstr_sprintf( clnt_name_slash, "\\\\%s", workstation );
834 } else {
835 fstr_sprintf( clnt_name_slash, "\\\\%s", global_myname() );
838 /* Initialise input parameters */
840 creds_client_step(cli->dc, &clnt_creds);
842 q.validation_level = validation_level;
844 ctr.switch_value = logon_type;
846 switch (logon_type) {
847 case INTERACTIVE_LOGON_TYPE: {
848 unsigned char lm_owf_user_pwd[16], nt_owf_user_pwd[16];
850 nt_lm_owf_gen(password, nt_owf_user_pwd, lm_owf_user_pwd);
852 init_id_info1(&ctr.auth.id1, domain,
853 logon_parameters, /* param_ctrl */
854 0xdead, 0xbeef, /* LUID? */
855 username, clnt_name_slash,
856 (const char *)cli->dc->sess_key, lm_owf_user_pwd,
857 nt_owf_user_pwd);
859 break;
861 case NET_LOGON_TYPE: {
862 uint8 chal[8];
863 unsigned char local_lm_response[24];
864 unsigned char local_nt_response[24];
866 generate_random_buffer(chal, 8);
868 SMBencrypt(password, chal, local_lm_response);
869 SMBNTencrypt(password, chal, local_nt_response);
871 init_id_info2(&ctr.auth.id2, domain,
872 logon_parameters, /* param_ctrl */
873 0xdead, 0xbeef, /* LUID? */
874 username, clnt_name_slash, chal,
875 local_lm_response, 24, local_nt_response, 24);
876 break;
878 default:
879 DEBUG(0, ("switch value %d not supported\n",
880 ctr.switch_value));
881 return NT_STATUS_INVALID_INFO_CLASS;
884 r.user = &user;
886 init_sam_info(&q.sam_id, cli->dc->remote_machine, global_myname(),
887 &clnt_creds, &ret_creds, logon_type,
888 &ctr);
890 /* Marshall data and send request */
892 CLI_DO_RPC(cli, mem_ctx, PI_NETLOGON, NET_SAMLOGON,
893 q, r,
894 qbuf, rbuf,
895 net_io_q_sam_logon,
896 net_io_r_sam_logon,
897 NT_STATUS_UNSUCCESSFUL);
899 /* Return results */
901 result = r.status;
903 if (r.buffer_creds) {
904 /* Check returned credentials if present. */
905 if (!creds_client_check(cli->dc, &r.srv_creds.challenge)) {
906 DEBUG(0,("rpccli_netlogon_sam_logon: credentials chain check failed\n"));
907 return NT_STATUS_ACCESS_DENIED;
911 return result;
915 /**
916 * Logon domain user with an 'network' SAM logon
918 * @param info3 Pointer to a NET_USER_INFO_3 already allocated by the caller.
921 NTSTATUS rpccli_netlogon_sam_network_logon(struct rpc_pipe_client *cli,
922 TALLOC_CTX *mem_ctx,
923 uint32 logon_parameters,
924 const char *server,
925 const char *username,
926 const char *domain,
927 const char *workstation,
928 const uint8 chal[8],
929 DATA_BLOB lm_response,
930 DATA_BLOB nt_response,
931 NET_USER_INFO_3 *info3)
933 prs_struct qbuf, rbuf;
934 NET_Q_SAM_LOGON q;
935 NET_R_SAM_LOGON r;
936 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
937 NET_ID_INFO_CTR ctr;
938 int validation_level = 3;
939 const char *workstation_name_slash;
940 const char *server_name_slash;
941 static uint8 zeros[16];
942 DOM_CRED clnt_creds;
943 DOM_CRED ret_creds;
944 int i;
946 ZERO_STRUCT(q);
947 ZERO_STRUCT(r);
948 ZERO_STRUCT(ret_creds);
950 creds_client_step(cli->dc, &clnt_creds);
952 if (server[0] != '\\' && server[1] != '\\') {
953 server_name_slash = talloc_asprintf(mem_ctx, "\\\\%s", server);
954 } else {
955 server_name_slash = server;
958 if (workstation[0] != '\\' && workstation[1] != '\\') {
959 workstation_name_slash = talloc_asprintf(mem_ctx, "\\\\%s", workstation);
960 } else {
961 workstation_name_slash = workstation;
964 if (!workstation_name_slash || !server_name_slash) {
965 DEBUG(0, ("talloc_asprintf failed!\n"));
966 return NT_STATUS_NO_MEMORY;
969 /* Initialise input parameters */
971 q.validation_level = validation_level;
973 ctr.switch_value = NET_LOGON_TYPE;
975 init_id_info2(&ctr.auth.id2, domain,
976 logon_parameters, /* param_ctrl */
977 0xdead, 0xbeef, /* LUID? */
978 username, workstation_name_slash, (const uchar*)chal,
979 lm_response.data, lm_response.length, nt_response.data, nt_response.length);
981 init_sam_info(&q.sam_id, server_name_slash, global_myname(),
982 &clnt_creds, &ret_creds, NET_LOGON_TYPE,
983 &ctr);
985 r.user = info3;
987 /* Marshall data and send request */
989 CLI_DO_RPC(cli, mem_ctx, PI_NETLOGON, NET_SAMLOGON,
990 q, r,
991 qbuf, rbuf,
992 net_io_q_sam_logon,
993 net_io_r_sam_logon,
994 NT_STATUS_UNSUCCESSFUL);
996 if (memcmp(zeros, info3->user_sess_key, 16) != 0) {
997 SamOEMhash(info3->user_sess_key, cli->dc->sess_key, 16);
998 } else {
999 memset(info3->user_sess_key, '\0', 16);
1002 if (memcmp(zeros, info3->lm_sess_key, 8) != 0) {
1003 SamOEMhash(info3->lm_sess_key, cli->dc->sess_key, 8);
1004 } else {
1005 memset(info3->lm_sess_key, '\0', 8);
1008 for (i=0; i < 7; i++) {
1009 memset(&info3->unknown[i], '\0', 4);
1012 /* Return results */
1014 result = r.status;
1016 if (r.buffer_creds) {
1017 /* Check returned credentials if present. */
1018 if (!creds_client_check(cli->dc, &r.srv_creds.challenge)) {
1019 DEBUG(0,("rpccli_netlogon_sam_network_logon: credentials chain check failed\n"));
1020 return NT_STATUS_ACCESS_DENIED;
1024 return result;
1027 /***************************************************************************
1028 LSA Server Password Set.
1029 ****************************************************************************/
1031 NTSTATUS rpccli_net_srv_pwset(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
1032 const char *machine_name, const uint8 hashed_mach_pwd[16])
1034 prs_struct rbuf;
1035 prs_struct qbuf;
1036 DOM_CRED clnt_creds;
1037 NET_Q_SRV_PWSET q;
1038 NET_R_SRV_PWSET r;
1039 uint16 sec_chan_type = 2;
1040 NTSTATUS result;
1042 creds_client_step(cli->dc, &clnt_creds);
1044 DEBUG(4,("cli_net_srv_pwset: srv:%s acct:%s sc: %d mc: %s\n",
1045 cli->dc->remote_machine, cli->dc->mach_acct, sec_chan_type, machine_name));
1047 /* store the parameters */
1048 init_q_srv_pwset(&q, cli->dc->remote_machine, (const char *)cli->dc->sess_key,
1049 cli->dc->mach_acct, sec_chan_type, machine_name,
1050 &clnt_creds, hashed_mach_pwd);
1052 CLI_DO_RPC(cli, mem_ctx, PI_NETLOGON, NET_SRVPWSET,
1053 q, r,
1054 qbuf, rbuf,
1055 net_io_q_srv_pwset,
1056 net_io_r_srv_pwset,
1057 NT_STATUS_UNSUCCESSFUL);
1059 result = r.status;
1061 if (!NT_STATUS_IS_OK(result)) {
1062 /* report error code */
1063 DEBUG(0,("cli_net_srv_pwset: %s\n", nt_errstr(result)));
1066 /* Always check returned credentials. */
1067 if (!creds_client_check(cli->dc, &r.srv_cred.challenge)) {
1068 DEBUG(0,("rpccli_net_srv_pwset: credentials chain check failed\n"));
1069 return NT_STATUS_ACCESS_DENIED;
1072 return result;