r23210: Very funny, we thought to use netr_GetDcName (e.g. in winbind) but were using
[tprouty/samba.git] / source / rpc_client / cli_netlogon.c
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.
7
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.
12    
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.
17    
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.
21 */
22
23 #include "includes.h"
24
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.
29 */
30
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)
37 {
38         prs_struct qbuf, rbuf;
39         NET_Q_REQ_CHAL q;
40         NET_R_REQ_CHAL r;
41         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
42
43         /* create and send a MSRPC command with api NET_REQCHAL */
44
45         DEBUG(4,("cli_net_req_chal: LSA Request Challenge from %s to %s\n",
46                 clnt_name, server_name));
47         
48         /* store the parameters */
49         init_q_req_chal(&q, server_name, clnt_name, clnt_chal_in);
50
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);
58
59         result = r.status;
60
61         /* Return result */
62
63         if (NT_STATUS_IS_OK(result)) {
64                 /* Store the returned server challenge. */
65                 *srv_chal_out = r.srv_chal;
66         }
67
68         return result;
69 }
70
71 #if 0
72 /****************************************************************************
73 LSA Authenticate 2
74
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 ****************************************************************************/
79
80   NTSTATUS rpccli_net_auth2(struct rpc_pipe_client *cli, 
81                        uint16 sec_chan, 
82                        uint32 *neg_flags, DOM_CHAL *srv_chal)
83 {
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;
89
90         if ( sec_chan == SEC_CHAN_DOMAIN )
91                 fstr_sprintf( machine_acct, "%s$", lp_workgroup() );
92         else
93                 fstrcpy( machine_acct, cli->mach_acct );
94         
95         /* create and send a MSRPC command with api NET_AUTH2 */
96
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));
100
101         /* store the parameters */
102
103         init_q_auth_2(&q, cli->srv_name_slash, machine_acct, 
104                       sec_chan, global_myname(), &cli->clnt_cred.challenge, 
105                       *neg_flags);
106
107         /* turn parameters into data stream */
108
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);
115
116         result = r.status;
117
118         if (NT_STATUS_IS_OK(result)) {
119                 UTIME zerotime;
120                 
121                 /*
122                  * Check the returned value using the initial
123                  * server received challenge.
124                  */
125
126                 zerotime.time = 0;
127                 if (cred_assert( &r.srv_chal, cli->sess_key, srv_chal, zerotime) == 0) {
128
129                         /*
130                          * Server replied with bad credential. Fail.
131                          */
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;
135                 }
136                 *neg_flags = r.srv_flgs.neg_flags;
137         }
138
139         return result;
140 }
141 #endif
142
143 /****************************************************************************
144  LSA Authenticate 2
145
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 ****************************************************************************/
150
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)
160 {
161         prs_struct qbuf, rbuf;
162         NET_Q_AUTH_2 q;
163         NET_R_AUTH_2 r;
164         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
165
166         /* create and send a MSRPC command with api NET_AUTH2 */
167
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));
171
172         /* store the parameters */
173
174         init_q_auth_2(&q, server_name, account_name, sec_chan_type,
175                       computer_name, clnt_chal_in, *neg_flags_inout);
176
177         /* turn parameters into data stream */
178
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);
185
186         result = r.status;
187
188         if (NT_STATUS_IS_OK(result)) {
189                 *srv_chal_out = r.srv_chal;
190                 *neg_flags_inout = r.srv_flgs.neg_flags;
191         }
192
193         return result;
194 }
195
196 #if 0   /* not currebntly used */
197 /****************************************************************************
198  LSA Authenticate 3
199
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 ****************************************************************************/
204
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)
214 {
215         prs_struct qbuf, rbuf;
216         NET_Q_AUTH_3 q;
217         NET_R_AUTH_3 r;
218         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
219
220         /* create and send a MSRPC command with api NET_AUTH2 */
221
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));
225
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);
229
230         /* turn parameters into data stream */
231
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);
238
239         if (NT_STATUS_IS_OK(result)) {
240                 *srv_chal_out = r.srv_chal;
241                 *neg_flags_inout = r.srv_flgs.neg_flags;
242         }
243
244         return result;
245 }
246 #endif  /* not currebntly used */
247
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 ****************************************************************************/
253
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)
262 {
263         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
264         DOM_CHAL clnt_chal_send;
265         DOM_CHAL srv_chal_recv;
266         struct dcinfo *dc;
267
268         SMB_ASSERT(cli->pipe_idx == PI_NETLOGON);
269
270         dc = cli->dc;
271         if (!dc) {
272                 return NT_STATUS_INVALID_PARAMETER;
273         }
274
275         /* Ensure we don't reuse any of this state. */
276         ZERO_STRUCTP(dc);
277
278         /* Store the machine account password we're going to use. */
279         memcpy(dc->mach_pw, machine_pwd, 16);
280
281         fstrcpy(dc->remote_machine, "\\\\");
282         fstrcat(dc->remote_machine, server_name);
283
284         fstrcpy(dc->domain, domain);
285
286         fstr_sprintf( dc->mach_acct, "%s$", machine_account);
287
288         /* Create the client challenge. */
289         generate_random_buffer(clnt_chal_send.data, 8);
290
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);
298
299         if (!NT_STATUS_IS_OK(result)) {
300                 return result;
301         }
302
303         /* Calculate the session key and client credentials */
304         creds_client_init(*neg_flags_inout,
305                         dc,
306                         &clnt_chal_send,
307                         &srv_chal_recv,
308                         machine_pwd,
309                         &clnt_chal_send);
310
311         /*  
312          * Send client auth-2 challenge and receive server repy.
313          */
314
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 */
324
325         if (!NT_STATUS_IS_OK(result)) {
326                 return result;
327         }
328
329         /*
330          * Check the returned value using the initial
331          * server received challenge.
332          */
333
334         if (!creds_client_check(dc, &srv_chal_recv)) {
335                 /*
336                  * Server replied with bad credential. Fail.
337                  */
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;
342         }
343
344         DEBUG(5,("rpccli_netlogon_setup_creds: server %s credential "
345                 "chain established.\n",
346                 cli->cli->desthost ));
347
348         return NT_STATUS_OK;
349 }
350
351 /* Logon Control 2 */
352
353 NTSTATUS rpccli_netlogon_logon_ctrl2(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
354                                   uint32 query_level)
355 {
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;
361
362         ZERO_STRUCT(q);
363         ZERO_STRUCT(r);
364
365         /* Initialise input parameters */
366
367         slprintf(server, sizeof(fstring)-1, "\\\\%s", cli->cli->desthost);
368         init_net_q_logon_ctrl2(&q, server, query_level);
369
370         /* Marshall data and send request */
371
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);
378
379         result = r.status;
380         return result;
381 }
382
383 /* GetAnyDCName */
384
385 WERROR rpccli_netlogon_getanydcname(struct rpc_pipe_client *cli,
386                                     TALLOC_CTX *mem_ctx, const char *mydcname,
387                                     const char *domainname, fstring newdcname)
388 {
389         prs_struct qbuf, rbuf;
390         NET_Q_GETANYDCNAME q;
391         NET_R_GETANYDCNAME r;
392         WERROR result;
393         fstring mydcname_slash;
394
395         ZERO_STRUCT(q);
396         ZERO_STRUCT(r);
397
398         /* Initialise input parameters */
399
400         slprintf(mydcname_slash, sizeof(fstring)-1, "\\\\%s", mydcname);
401         init_net_q_getanydcname(&q, mydcname_slash, domainname);
402
403         /* Marshall data and send request */
404
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);
411
412         result = r.status;
413
414         if (W_ERROR_IS_OK(result)) {
415                 rpcstr_pull_unistr2_fstring(newdcname, &r.uni_dcname);
416         }
417
418         return result;
419 }
420
421 /* GetDCName */
422
423 NTSTATUS rpccli_netlogon_getdcname(struct rpc_pipe_client *cli,
424                                    TALLOC_CTX *mem_ctx, const char *mydcname,
425                                    const char *domainname, fstring newdcname)
426 {
427         prs_struct qbuf, rbuf;
428         NET_Q_GETDCNAME q;
429         NET_R_GETDCNAME r;
430         NTSTATUS result;
431         fstring mydcname_slash;
432
433         ZERO_STRUCT(q);
434         ZERO_STRUCT(r);
435
436         /* Initialise input parameters */
437
438         slprintf(mydcname_slash, sizeof(fstring)-1, "\\\\%s", mydcname);
439         init_net_q_getdcname(&q, mydcname_slash, domainname);
440
441         /* Marshall data and send request */
442
443         CLI_DO_RPC(cli, mem_ctx, PI_NETLOGON, NET_GETDCNAME,
444                 q, r,
445                 qbuf, rbuf,
446                 net_io_q_getdcname,
447                 net_io_r_getdcname,
448                 NT_STATUS_UNSUCCESSFUL);
449
450         result = r.status;
451
452         if (NT_STATUS_IS_OK(result)) {
453                 rpcstr_pull_unistr2_fstring(newdcname, &r.uni_dcname);
454         }
455
456         return result;
457 }
458
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)
462 {
463         struct DS_DOMAIN_CONTROLLER_INFO *info;
464
465         info = TALLOC_ZERO_P(mem_ctx, struct DS_DOMAIN_CONTROLLER_INFO);
466         if (!info) {
467                 return WERR_NOMEM;
468         }
469
470         if (&r->uni_dc_unc) {
471
472                 char *tmp;
473                 tmp = rpcstr_pull_unistr2_talloc(mem_ctx, &r->uni_dc_unc);
474                 if (tmp == NULL) {
475                         return WERR_GENERAL_FAILURE;
476                 }
477                 if (*tmp == '\\') tmp += 1;
478                 if (*tmp == '\\') tmp += 1;
479
480                 info->domain_controller_name = talloc_strdup(mem_ctx, tmp);
481                 if (info->domain_controller_name == NULL) {
482                         return WERR_GENERAL_FAILURE;
483                 }
484         }
485
486         if (&r->uni_dc_address) {
487
488                 char *tmp;
489                 tmp = rpcstr_pull_unistr2_talloc(mem_ctx, &r->uni_dc_address);
490                 if (tmp == NULL) {
491                         return WERR_GENERAL_FAILURE;
492                 }
493                 if (*tmp == '\\') tmp += 1;
494                 if (*tmp == '\\') tmp += 1;
495
496                 info->domain_controller_address = talloc_strdup(mem_ctx, tmp);
497                 if (info->domain_controller_address == NULL) {
498                         return WERR_GENERAL_FAILURE;
499                 }
500         }
501
502         info->domain_controller_address_type = r->dc_address_type;
503
504         info->domain_guid = talloc_memdup(mem_ctx, &r->domain_guid, sizeof(struct GUID));
505         if (!info->domain_guid) {
506                 return WERR_GENERAL_FAILURE;
507         }
508
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;
513                 }
514         }
515
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;
520                 }
521         }
522
523         info->flags = r->dc_flags;
524
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;
529                 }
530         }
531
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;
536                 }
537         }
538
539         *info_out = info;
540
541         return WERR_OK;
542 }
543
544 /* Dsr_GetDCName */
545
546 WERROR rpccli_netlogon_dsr_getdcname(struct rpc_pipe_client *cli,
547                                      TALLOC_CTX *mem_ctx,
548                                      const char *server_name,
549                                      const char *domain_name,
550                                      struct GUID *domain_guid,
551                                      struct GUID *site_guid,
552                                      uint32_t flags,
553                                      struct DS_DOMAIN_CONTROLLER_INFO **info_out)
554 {
555         prs_struct qbuf, rbuf;
556         NET_Q_DSR_GETDCNAME q;
557         NET_R_DSR_GETDCNAME r;
558         char *tmp_str;
559
560         ZERO_STRUCT(q);
561         ZERO_STRUCT(r);
562
563         /* Initialize input parameters */
564
565         tmp_str = talloc_asprintf(mem_ctx, "\\\\%s", server_name);
566         if (tmp_str == NULL) {
567                 return WERR_NOMEM;
568         }
569
570         init_net_q_dsr_getdcname(&q, tmp_str, domain_name, domain_guid,
571                                  site_guid, flags);
572
573         /* Marshall data and send request */
574
575         CLI_DO_RPC_WERR(cli, mem_ctx, PI_NETLOGON, NET_DSR_GETDCNAME,
576                         q, r,
577                         qbuf, rbuf,
578                         net_io_q_dsr_getdcname,
579                         net_io_r_dsr_getdcname,
580                         WERR_GENERAL_FAILURE);
581
582         if (!W_ERROR_IS_OK(r.result)) {
583                 return r.result;
584         }
585
586         r.result = pull_domain_controller_info_from_getdcname_reply(mem_ctx, info_out, &r);
587         if (!W_ERROR_IS_OK(r.result)) {
588                 return r.result;
589         }
590
591         return WERR_OK;
592 }
593
594 /* Dsr_GetDCNameEx */
595
596 WERROR rpccli_netlogon_dsr_getdcnameex(struct rpc_pipe_client *cli,
597                                        TALLOC_CTX *mem_ctx,
598                                        const char *server_name,
599                                        const char *domain_name,
600                                        struct GUID *domain_guid,
601                                        const char *site_name,
602                                        uint32_t flags,
603                                        struct DS_DOMAIN_CONTROLLER_INFO **info_out)
604 {
605         prs_struct qbuf, rbuf;
606         NET_Q_DSR_GETDCNAMEEX q;
607         NET_R_DSR_GETDCNAME r;
608         char *tmp_str;
609
610         ZERO_STRUCT(q);
611         ZERO_STRUCT(r);
612
613         /* Initialize input parameters */
614
615         tmp_str = talloc_asprintf(mem_ctx, "\\\\%s", server_name);
616         if (tmp_str == NULL) {
617                 return WERR_NOMEM;
618         }
619
620         init_net_q_dsr_getdcnameex(&q, server_name, domain_name, domain_guid,
621                                    site_name, flags);
622
623         /* Marshall data and send request */
624
625         CLI_DO_RPC_WERR(cli, mem_ctx, PI_NETLOGON, NET_DSR_GETDCNAMEEX,
626                         q, r,
627                         qbuf, rbuf,
628                         net_io_q_dsr_getdcnameex,
629                         net_io_r_dsr_getdcname,
630                         WERR_GENERAL_FAILURE);
631
632         if (!W_ERROR_IS_OK(r.result)) {
633                 return r.result;
634         }
635
636         r.result = pull_domain_controller_info_from_getdcname_reply(mem_ctx, info_out, &r);
637         if (!W_ERROR_IS_OK(r.result)) {
638                 return r.result;
639         }
640
641         return WERR_OK;
642 }
643
644 /* Dsr_GetDCNameEx */
645
646 WERROR rpccli_netlogon_dsr_getdcnameex2(struct rpc_pipe_client *cli,
647                                         TALLOC_CTX *mem_ctx,
648                                         const char *server_name,
649                                         const char *client_account,
650                                         uint32 mask,
651                                         const char *domain_name,
652                                         struct GUID *domain_guid,
653                                         const char *site_name,
654                                         uint32_t flags,
655                                         struct DS_DOMAIN_CONTROLLER_INFO **info_out)
656 {
657         prs_struct qbuf, rbuf;
658         NET_Q_DSR_GETDCNAMEEX2 q;
659         NET_R_DSR_GETDCNAME r;
660         char *tmp_str;
661
662         ZERO_STRUCT(q);
663         ZERO_STRUCT(r);
664
665         /* Initialize input parameters */
666
667         tmp_str = talloc_asprintf(mem_ctx, "\\\\%s", server_name);
668         if (tmp_str == NULL) {
669                 return WERR_NOMEM;
670         }
671
672         init_net_q_dsr_getdcnameex2(&q, server_name, domain_name, client_account,
673                                     mask, domain_guid, site_name, flags);
674
675         /* Marshall data and send request */
676
677         CLI_DO_RPC_WERR(cli, mem_ctx, PI_NETLOGON, NET_DSR_GETDCNAMEEX2,
678                         q, r,
679                         qbuf, rbuf,
680                         net_io_q_dsr_getdcnameex2,
681                         net_io_r_dsr_getdcname,
682                         WERR_GENERAL_FAILURE);
683
684         if (!W_ERROR_IS_OK(r.result)) {
685                 return r.result;
686         }
687
688         r.result = pull_domain_controller_info_from_getdcname_reply(mem_ctx, info_out, &r);
689         if (!W_ERROR_IS_OK(r.result)) {
690                 return r.result;
691         }
692
693         return WERR_OK;
694 }
695
696
697 /* Dsr_GetSiteName */
698
699 WERROR rpccli_netlogon_dsr_getsitename(struct rpc_pipe_client *cli,
700                                        TALLOC_CTX *mem_ctx,
701                                        const char *computer_name,
702                                        char **site_name)
703 {
704         prs_struct qbuf, rbuf;
705         NET_Q_DSR_GETSITENAME q;
706         NET_R_DSR_GETSITENAME r;
707
708         ZERO_STRUCT(q);
709         ZERO_STRUCT(r);
710
711         /* Initialize input parameters */
712
713         init_net_q_dsr_getsitename(&q, computer_name);
714
715         /* Marshall data and send request */
716
717         CLI_DO_RPC_WERR(cli, mem_ctx, PI_NETLOGON, NET_DSR_GETSITENAME,
718                         q, r,
719                         qbuf, rbuf,
720                         net_io_q_dsr_getsitename,
721                         net_io_r_dsr_getsitename,
722                         WERR_GENERAL_FAILURE);
723
724         if (!W_ERROR_IS_OK(r.result)) {
725                 return r.result;
726         }
727
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;
732         }
733
734         return WERR_OK;
735 }
736
737
738
739 /* Sam synchronisation */
740
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)
745 {
746         prs_struct qbuf, rbuf;
747         NET_Q_SAM_SYNC q;
748         NET_R_SAM_SYNC r;
749         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
750         DOM_CRED clnt_creds;
751         DOM_CRED ret_creds;
752
753         ZERO_STRUCT(q);
754         ZERO_STRUCT(r);
755
756         ZERO_STRUCT(ret_creds);
757
758         /* Initialise input parameters */
759
760         creds_client_step(cli->dc, &clnt_creds);
761
762         init_net_q_sam_sync(&q, cli->dc->remote_machine, global_myname(),
763                             &clnt_creds, &ret_creds, database_id, next_rid);
764
765         /* Marshall data and send request */
766
767         CLI_DO_RPC_COPY_SESS_KEY(cli, mem_ctx, PI_NETLOGON, NET_SAM_SYNC,
768                 q, r,
769                 qbuf, rbuf,
770                 net_io_q_sam_sync,
771                 net_io_r_sam_sync,
772                 NT_STATUS_UNSUCCESSFUL);
773
774         /* Return results */
775
776         result = r.status;
777         *num_deltas = r.num_deltas2;
778         *hdr_deltas = r.hdr_deltas;
779         *deltas = r.deltas;
780
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;
786                 }
787         }
788
789         return result;
790 }
791
792 /* Sam synchronisation */
793
794 NTSTATUS rpccli_netlogon_sam_deltas(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
795                                  uint32 database_id, uint64 seqnum,
796                                  uint32 *num_deltas, 
797                                  SAM_DELTA_HDR **hdr_deltas, 
798                                  SAM_DELTA_CTR **deltas)
799 {
800         prs_struct qbuf, rbuf;
801         NET_Q_SAM_DELTAS q;
802         NET_R_SAM_DELTAS r;
803         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
804         DOM_CRED clnt_creds;
805
806         ZERO_STRUCT(q);
807         ZERO_STRUCT(r);
808
809         /* Initialise input parameters */
810
811         creds_client_step(cli->dc, &clnt_creds);
812
813         init_net_q_sam_deltas(&q, cli->dc->remote_machine,
814                               global_myname(), &clnt_creds, 
815                               database_id, seqnum);
816
817         /* Marshall data and send request */
818
819         CLI_DO_RPC(cli, mem_ctx, PI_NETLOGON, NET_SAM_DELTAS,
820                 q, r,
821                 qbuf, rbuf,
822                 net_io_q_sam_deltas,
823                 net_io_r_sam_deltas,
824                 NT_STATUS_UNSUCCESSFUL);
825
826         /* Return results */
827
828         result = r.status;
829         *num_deltas = r.num_deltas2;
830         *hdr_deltas = r.hdr_deltas;
831         *deltas = r.deltas;
832
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;
838                 }
839         }
840
841         return result;
842 }
843
844 /* Logon domain user */
845
846 NTSTATUS rpccli_netlogon_sam_logon(struct rpc_pipe_client *cli,
847                                    TALLOC_CTX *mem_ctx,
848                                    uint32 logon_parameters,
849                                    const char *domain,
850                                    const char *username,
851                                    const char *password,
852                                    const char *workstation,
853                                    int logon_type)
854 {
855         prs_struct qbuf, rbuf;
856         NET_Q_SAM_LOGON q;
857         NET_R_SAM_LOGON r;
858         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
859         DOM_CRED clnt_creds;
860         DOM_CRED ret_creds;
861         NET_ID_INFO_CTR ctr;
862         NET_USER_INFO_3 user;
863         int validation_level = 3;
864         fstring clnt_name_slash;
865
866         ZERO_STRUCT(q);
867         ZERO_STRUCT(r);
868         ZERO_STRUCT(ret_creds);
869
870         if (workstation) {
871                 fstr_sprintf( clnt_name_slash, "\\\\%s", workstation );
872         } else {
873                 fstr_sprintf( clnt_name_slash, "\\\\%s", global_myname() );
874         }
875
876         /* Initialise input parameters */
877
878         creds_client_step(cli->dc, &clnt_creds);
879
880         q.validation_level = validation_level;
881
882         ctr.switch_value = logon_type;
883
884         switch (logon_type) {
885         case INTERACTIVE_LOGON_TYPE: {
886                 unsigned char lm_owf_user_pwd[16], nt_owf_user_pwd[16];
887
888                 nt_lm_owf_gen(password, nt_owf_user_pwd, lm_owf_user_pwd);
889
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,
895                               nt_owf_user_pwd);
896
897                 break;
898         }
899         case NET_LOGON_TYPE: {
900                 uint8 chal[8];
901                 unsigned char local_lm_response[24];
902                 unsigned char local_nt_response[24];
903
904                 generate_random_buffer(chal, 8);
905
906                 SMBencrypt(password, chal, local_lm_response);
907                 SMBNTencrypt(password, chal, local_nt_response);
908
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);
914                 break;
915         }
916         default:
917                 DEBUG(0, ("switch value %d not supported\n", 
918                           ctr.switch_value));
919                 return NT_STATUS_INVALID_INFO_CLASS;
920         }
921
922         r.user = &user;
923
924         init_sam_info(&q.sam_id, cli->dc->remote_machine, global_myname(),
925                       &clnt_creds, &ret_creds, logon_type,
926                       &ctr);
927
928         /* Marshall data and send request */
929
930         CLI_DO_RPC(cli, mem_ctx, PI_NETLOGON, NET_SAMLOGON,
931                 q, r,
932                 qbuf, rbuf,
933                 net_io_q_sam_logon,
934                 net_io_r_sam_logon,
935                 NT_STATUS_UNSUCCESSFUL);
936
937         /* Return results */
938
939         result = r.status;
940
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;
946                 }
947         }
948
949         return result;
950 }
951
952
953 /** 
954  * Logon domain user with an 'network' SAM logon 
955  *
956  * @param info3 Pointer to a NET_USER_INFO_3 already allocated by the caller.
957  **/
958
959 NTSTATUS rpccli_netlogon_sam_network_logon(struct rpc_pipe_client *cli,
960                                            TALLOC_CTX *mem_ctx,
961                                            uint32 logon_parameters,
962                                            const char *server,
963                                            const char *username,
964                                            const char *domain,
965                                            const char *workstation, 
966                                            const uint8 chal[8], 
967                                            DATA_BLOB lm_response,
968                                            DATA_BLOB nt_response,
969                                            NET_USER_INFO_3 *info3)
970 {
971         prs_struct qbuf, rbuf;
972         NET_Q_SAM_LOGON q;
973         NET_R_SAM_LOGON r;
974         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
975         NET_ID_INFO_CTR ctr;
976         int validation_level = 3;
977         const char *workstation_name_slash;
978         const char *server_name_slash;
979         static uint8 zeros[16];
980         DOM_CRED clnt_creds;
981         DOM_CRED ret_creds;
982         int i;
983         
984         ZERO_STRUCT(q);
985         ZERO_STRUCT(r);
986         ZERO_STRUCT(ret_creds);
987
988         creds_client_step(cli->dc, &clnt_creds);
989
990         if (server[0] != '\\' && server[1] != '\\') {
991                 server_name_slash = talloc_asprintf(mem_ctx, "\\\\%s", server);
992         } else {
993                 server_name_slash = server;
994         }
995
996         if (workstation[0] != '\\' && workstation[1] != '\\') {
997                 workstation_name_slash = talloc_asprintf(mem_ctx, "\\\\%s", workstation);
998         } else {
999                 workstation_name_slash = workstation;
1000         }
1001
1002         if (!workstation_name_slash || !server_name_slash) {
1003                 DEBUG(0, ("talloc_asprintf failed!\n"));
1004                 return NT_STATUS_NO_MEMORY;
1005         }
1006
1007         /* Initialise input parameters */
1008
1009         q.validation_level = validation_level;
1010
1011         ctr.switch_value = NET_LOGON_TYPE;
1012
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);
1018  
1019         init_sam_info(&q.sam_id, server_name_slash, global_myname(),
1020                       &clnt_creds, &ret_creds, NET_LOGON_TYPE,
1021                       &ctr);
1022
1023         r.user = info3;
1024
1025         /* Marshall data and send request */
1026
1027         CLI_DO_RPC(cli, mem_ctx, PI_NETLOGON, NET_SAMLOGON,
1028                 q, r,
1029                 qbuf, rbuf,
1030                 net_io_q_sam_logon,
1031                 net_io_r_sam_logon,
1032                 NT_STATUS_UNSUCCESSFUL);
1033
1034         if (memcmp(zeros, info3->user_sess_key, 16) != 0) {
1035                 SamOEMhash(info3->user_sess_key, cli->dc->sess_key, 16);
1036         } else {
1037                 memset(info3->user_sess_key, '\0', 16);
1038         }
1039
1040         if (memcmp(zeros, info3->lm_sess_key, 8) != 0) {
1041                 SamOEMhash(info3->lm_sess_key, cli->dc->sess_key, 8);
1042         } else {
1043                 memset(info3->lm_sess_key, '\0', 8);
1044         }
1045
1046         for (i=0; i < 7; i++) {
1047                 memset(&info3->unknown[i], '\0', 4);
1048         }
1049
1050         /* Return results */
1051
1052         result = r.status;
1053
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;
1059                 }
1060         }
1061
1062         return result;
1063 }
1064
1065 NTSTATUS rpccli_netlogon_sam_network_logon_ex(struct rpc_pipe_client *cli,
1066                                               TALLOC_CTX *mem_ctx,
1067                                               uint32 logon_parameters,
1068                                               const char *server,
1069                                               const char *username,
1070                                               const char *domain,
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)
1076 {
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];
1086         int i;
1087         
1088         ZERO_STRUCT(q);
1089         ZERO_STRUCT(r);
1090
1091         if (server[0] != '\\' && server[1] != '\\') {
1092                 server_name_slash = talloc_asprintf(mem_ctx, "\\\\%s", server);
1093         } else {
1094                 server_name_slash = server;
1095         }
1096
1097         if (workstation[0] != '\\' && workstation[1] != '\\') {
1098                 workstation_name_slash = talloc_asprintf(mem_ctx, "\\\\%s", workstation);
1099         } else {
1100                 workstation_name_slash = workstation;
1101         }
1102
1103         if (!workstation_name_slash || !server_name_slash) {
1104                 DEBUG(0, ("talloc_asprintf failed!\n"));
1105                 return NT_STATUS_NO_MEMORY;
1106         }
1107
1108         /* Initialise input parameters */
1109
1110         q.validation_level = validation_level;
1111
1112         ctr.switch_value = NET_LOGON_TYPE;
1113
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);
1120  
1121         init_sam_info_ex(&q.sam_id, server_name_slash, global_myname(),
1122                          NET_LOGON_TYPE, &ctr);
1123
1124         r.user = info3;
1125
1126         /* Marshall data and send request */
1127
1128         CLI_DO_RPC(cli, mem_ctx, PI_NETLOGON, NET_SAMLOGON_EX,
1129                    q, r, qbuf, rbuf,
1130                    net_io_q_sam_logon_ex,
1131                    net_io_r_sam_logon_ex,
1132                    NT_STATUS_UNSUCCESSFUL);
1133
1134         if (memcmp(zeros, info3->user_sess_key, 16) != 0) {
1135                 SamOEMhash(info3->user_sess_key, cli->dc->sess_key, 16);
1136         } else {
1137                 memset(info3->user_sess_key, '\0', 16);
1138         }
1139
1140         if (memcmp(zeros, info3->lm_sess_key, 8) != 0) {
1141                 SamOEMhash(info3->lm_sess_key, cli->dc->sess_key, 8);
1142         } else {
1143                 memset(info3->lm_sess_key, '\0', 8);
1144         }
1145
1146         for (i=0; i < 7; i++) {
1147                 memset(&info3->unknown[i], '\0', 4);
1148         }
1149
1150         /* Return results */
1151
1152         result = r.status;
1153
1154         return result;
1155 }
1156
1157 /***************************************************************************
1158 LSA Server Password Set.
1159 ****************************************************************************/
1160
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])
1163 {
1164         prs_struct rbuf;
1165         prs_struct qbuf; 
1166         DOM_CRED clnt_creds;
1167         NET_Q_SRV_PWSET q;
1168         NET_R_SRV_PWSET r;
1169         uint16 sec_chan_type = 2;
1170         NTSTATUS result;
1171
1172         creds_client_step(cli->dc, &clnt_creds);
1173         
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));
1176         
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);
1181         
1182         CLI_DO_RPC(cli, mem_ctx, PI_NETLOGON, NET_SRVPWSET,
1183                 q, r,
1184                 qbuf, rbuf,
1185                 net_io_q_srv_pwset,
1186                 net_io_r_srv_pwset,
1187                 NT_STATUS_UNSUCCESSFUL);
1188
1189         result = r.status;
1190
1191         if (!NT_STATUS_IS_OK(result)) {
1192                 /* report error code */
1193                 DEBUG(0,("cli_net_srv_pwset: %s\n", nt_errstr(result)));
1194         }
1195
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;
1200         }
1201
1202         return result;
1203 }