r23380: netr_getdcname returns WERROR not NTSTATUS.
[nivanova/samba-autobuild/.git] / source3 / 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 WERROR 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         WERROR 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_WERR(cli, mem_ctx, PI_NETLOGON, NET_GETDCNAME,
444                 q, r,
445                 qbuf, rbuf,
446                 net_io_q_getdcname,
447                 net_io_r_getdcname,
448                 WERR_GENERAL_FAILURE);
449
450         result = r.status;
451
452         if (W_ERROR_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 = (struct GUID *)talloc_memdup(
505                 mem_ctx, &r->domain_guid, sizeof(struct GUID));
506         if (!info->domain_guid) {
507                 return WERR_GENERAL_FAILURE;
508         }
509
510         if (&r->uni_domain_name) {
511                 info->domain_name = rpcstr_pull_unistr2_talloc(mem_ctx, &r->uni_domain_name);
512                 if (!info->domain_name) {
513                         return WERR_GENERAL_FAILURE;
514                 }
515         }
516
517         if (&r->uni_forest_name) {
518                 info->dns_forest_name = rpcstr_pull_unistr2_talloc(mem_ctx, &r->uni_forest_name);
519                 if (!info->dns_forest_name) {
520                         return WERR_GENERAL_FAILURE;
521                 }
522         }
523
524         info->flags = r->dc_flags;
525
526         if (&r->uni_dc_site_name) {
527                 info->dc_site_name = rpcstr_pull_unistr2_talloc(mem_ctx, &r->uni_dc_site_name);
528                 if (!info->dc_site_name) {
529                         return WERR_GENERAL_FAILURE;
530                 }
531         }
532
533         if (&r->uni_client_site_name) {
534                 info->client_site_name = rpcstr_pull_unistr2_talloc(mem_ctx, &r->uni_client_site_name);
535                 if (!info->client_site_name) {
536                         return WERR_GENERAL_FAILURE;
537                 }
538         }
539
540         *info_out = info;
541
542         return WERR_OK;
543 }
544
545 /* Dsr_GetDCName */
546
547 WERROR rpccli_netlogon_dsr_getdcname(struct rpc_pipe_client *cli,
548                                      TALLOC_CTX *mem_ctx,
549                                      const char *server_name,
550                                      const char *domain_name,
551                                      struct GUID *domain_guid,
552                                      struct GUID *site_guid,
553                                      uint32_t flags,
554                                      struct DS_DOMAIN_CONTROLLER_INFO **info_out)
555 {
556         prs_struct qbuf, rbuf;
557         NET_Q_DSR_GETDCNAME q;
558         NET_R_DSR_GETDCNAME r;
559         char *tmp_str;
560
561         ZERO_STRUCT(q);
562         ZERO_STRUCT(r);
563
564         /* Initialize input parameters */
565
566         tmp_str = talloc_asprintf(mem_ctx, "\\\\%s", server_name);
567         if (tmp_str == NULL) {
568                 return WERR_NOMEM;
569         }
570
571         init_net_q_dsr_getdcname(&q, tmp_str, domain_name, domain_guid,
572                                  site_guid, flags);
573
574         /* Marshall data and send request */
575
576         CLI_DO_RPC_WERR(cli, mem_ctx, PI_NETLOGON, NET_DSR_GETDCNAME,
577                         q, r,
578                         qbuf, rbuf,
579                         net_io_q_dsr_getdcname,
580                         net_io_r_dsr_getdcname,
581                         WERR_GENERAL_FAILURE);
582
583         if (!W_ERROR_IS_OK(r.result)) {
584                 return r.result;
585         }
586
587         r.result = pull_domain_controller_info_from_getdcname_reply(mem_ctx, info_out, &r);
588         if (!W_ERROR_IS_OK(r.result)) {
589                 return r.result;
590         }
591
592         return WERR_OK;
593 }
594
595 /* Dsr_GetDCNameEx */
596
597 WERROR rpccli_netlogon_dsr_getdcnameex(struct rpc_pipe_client *cli,
598                                        TALLOC_CTX *mem_ctx,
599                                        const char *server_name,
600                                        const char *domain_name,
601                                        struct GUID *domain_guid,
602                                        const char *site_name,
603                                        uint32_t flags,
604                                        struct DS_DOMAIN_CONTROLLER_INFO **info_out)
605 {
606         prs_struct qbuf, rbuf;
607         NET_Q_DSR_GETDCNAMEEX q;
608         NET_R_DSR_GETDCNAME r;
609         char *tmp_str;
610
611         ZERO_STRUCT(q);
612         ZERO_STRUCT(r);
613
614         /* Initialize input parameters */
615
616         tmp_str = talloc_asprintf(mem_ctx, "\\\\%s", server_name);
617         if (tmp_str == NULL) {
618                 return WERR_NOMEM;
619         }
620
621         init_net_q_dsr_getdcnameex(&q, server_name, domain_name, domain_guid,
622                                    site_name, flags);
623
624         /* Marshall data and send request */
625
626         CLI_DO_RPC_WERR(cli, mem_ctx, PI_NETLOGON, NET_DSR_GETDCNAMEEX,
627                         q, r,
628                         qbuf, rbuf,
629                         net_io_q_dsr_getdcnameex,
630                         net_io_r_dsr_getdcname,
631                         WERR_GENERAL_FAILURE);
632
633         if (!W_ERROR_IS_OK(r.result)) {
634                 return r.result;
635         }
636
637         r.result = pull_domain_controller_info_from_getdcname_reply(mem_ctx, info_out, &r);
638         if (!W_ERROR_IS_OK(r.result)) {
639                 return r.result;
640         }
641
642         return WERR_OK;
643 }
644
645 /* Dsr_GetDCNameEx */
646
647 WERROR rpccli_netlogon_dsr_getdcnameex2(struct rpc_pipe_client *cli,
648                                         TALLOC_CTX *mem_ctx,
649                                         const char *server_name,
650                                         const char *client_account,
651                                         uint32 mask,
652                                         const char *domain_name,
653                                         struct GUID *domain_guid,
654                                         const char *site_name,
655                                         uint32_t flags,
656                                         struct DS_DOMAIN_CONTROLLER_INFO **info_out)
657 {
658         prs_struct qbuf, rbuf;
659         NET_Q_DSR_GETDCNAMEEX2 q;
660         NET_R_DSR_GETDCNAME r;
661         char *tmp_str;
662
663         ZERO_STRUCT(q);
664         ZERO_STRUCT(r);
665
666         /* Initialize input parameters */
667
668         tmp_str = talloc_asprintf(mem_ctx, "\\\\%s", server_name);
669         if (tmp_str == NULL) {
670                 return WERR_NOMEM;
671         }
672
673         init_net_q_dsr_getdcnameex2(&q, server_name, domain_name, client_account,
674                                     mask, domain_guid, site_name, flags);
675
676         /* Marshall data and send request */
677
678         CLI_DO_RPC_WERR(cli, mem_ctx, PI_NETLOGON, NET_DSR_GETDCNAMEEX2,
679                         q, r,
680                         qbuf, rbuf,
681                         net_io_q_dsr_getdcnameex2,
682                         net_io_r_dsr_getdcname,
683                         WERR_GENERAL_FAILURE);
684
685         if (!W_ERROR_IS_OK(r.result)) {
686                 return r.result;
687         }
688
689         r.result = pull_domain_controller_info_from_getdcname_reply(mem_ctx, info_out, &r);
690         if (!W_ERROR_IS_OK(r.result)) {
691                 return r.result;
692         }
693
694         return WERR_OK;
695 }
696
697
698 /* Dsr_GetSiteName */
699
700 WERROR rpccli_netlogon_dsr_getsitename(struct rpc_pipe_client *cli,
701                                        TALLOC_CTX *mem_ctx,
702                                        const char *computer_name,
703                                        char **site_name)
704 {
705         prs_struct qbuf, rbuf;
706         NET_Q_DSR_GETSITENAME q;
707         NET_R_DSR_GETSITENAME r;
708
709         ZERO_STRUCT(q);
710         ZERO_STRUCT(r);
711
712         /* Initialize input parameters */
713
714         init_net_q_dsr_getsitename(&q, computer_name);
715
716         /* Marshall data and send request */
717
718         CLI_DO_RPC_WERR(cli, mem_ctx, PI_NETLOGON, NET_DSR_GETSITENAME,
719                         q, r,
720                         qbuf, rbuf,
721                         net_io_q_dsr_getsitename,
722                         net_io_r_dsr_getsitename,
723                         WERR_GENERAL_FAILURE);
724
725         if (!W_ERROR_IS_OK(r.result)) {
726                 return r.result;
727         }
728
729         if ((site_name != NULL) &&
730             ((*site_name = rpcstr_pull_unistr2_talloc(
731                       mem_ctx, &r.uni_site_name)) == NULL)) {
732                 return WERR_GENERAL_FAILURE;
733         }
734
735         return WERR_OK;
736 }
737
738
739
740 /* Sam synchronisation */
741
742 NTSTATUS rpccli_netlogon_sam_sync(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
743                                uint32 database_id, uint32 next_rid, uint32 *num_deltas,
744                                SAM_DELTA_HDR **hdr_deltas, 
745                                SAM_DELTA_CTR **deltas)
746 {
747         prs_struct qbuf, rbuf;
748         NET_Q_SAM_SYNC q;
749         NET_R_SAM_SYNC r;
750         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
751         DOM_CRED clnt_creds;
752         DOM_CRED ret_creds;
753
754         ZERO_STRUCT(q);
755         ZERO_STRUCT(r);
756
757         ZERO_STRUCT(ret_creds);
758
759         /* Initialise input parameters */
760
761         creds_client_step(cli->dc, &clnt_creds);
762
763         init_net_q_sam_sync(&q, cli->dc->remote_machine, global_myname(),
764                             &clnt_creds, &ret_creds, database_id, next_rid);
765
766         /* Marshall data and send request */
767
768         CLI_DO_RPC_COPY_SESS_KEY(cli, mem_ctx, PI_NETLOGON, NET_SAM_SYNC,
769                 q, r,
770                 qbuf, rbuf,
771                 net_io_q_sam_sync,
772                 net_io_r_sam_sync,
773                 NT_STATUS_UNSUCCESSFUL);
774
775         /* Return results */
776
777         result = r.status;
778         *num_deltas = r.num_deltas2;
779         *hdr_deltas = r.hdr_deltas;
780         *deltas = r.deltas;
781
782         if (!NT_STATUS_IS_ERR(result)) {
783                 /* Check returned credentials. */
784                 if (!creds_client_check(cli->dc, &r.srv_creds.challenge)) {
785                         DEBUG(0,("cli_netlogon_sam_sync: credentials chain check failed\n"));
786                         return NT_STATUS_ACCESS_DENIED;
787                 }
788         }
789
790         return result;
791 }
792
793 /* Sam synchronisation */
794
795 NTSTATUS rpccli_netlogon_sam_deltas(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
796                                  uint32 database_id, uint64 seqnum,
797                                  uint32 *num_deltas, 
798                                  SAM_DELTA_HDR **hdr_deltas, 
799                                  SAM_DELTA_CTR **deltas)
800 {
801         prs_struct qbuf, rbuf;
802         NET_Q_SAM_DELTAS q;
803         NET_R_SAM_DELTAS r;
804         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
805         DOM_CRED clnt_creds;
806
807         ZERO_STRUCT(q);
808         ZERO_STRUCT(r);
809
810         /* Initialise input parameters */
811
812         creds_client_step(cli->dc, &clnt_creds);
813
814         init_net_q_sam_deltas(&q, cli->dc->remote_machine,
815                               global_myname(), &clnt_creds, 
816                               database_id, seqnum);
817
818         /* Marshall data and send request */
819
820         CLI_DO_RPC(cli, mem_ctx, PI_NETLOGON, NET_SAM_DELTAS,
821                 q, r,
822                 qbuf, rbuf,
823                 net_io_q_sam_deltas,
824                 net_io_r_sam_deltas,
825                 NT_STATUS_UNSUCCESSFUL);
826
827         /* Return results */
828
829         result = r.status;
830         *num_deltas = r.num_deltas2;
831         *hdr_deltas = r.hdr_deltas;
832         *deltas = r.deltas;
833
834         if (!NT_STATUS_IS_ERR(result)) {
835                 /* Check returned credentials. */
836                 if (!creds_client_check(cli->dc, &r.srv_creds.challenge)) {
837                         DEBUG(0,("cli_netlogon_sam_sync: credentials chain check failed\n"));
838                         return NT_STATUS_ACCESS_DENIED;
839                 }
840         }
841
842         return result;
843 }
844
845 /* Logon domain user */
846
847 NTSTATUS rpccli_netlogon_sam_logon(struct rpc_pipe_client *cli,
848                                    TALLOC_CTX *mem_ctx,
849                                    uint32 logon_parameters,
850                                    const char *domain,
851                                    const char *username,
852                                    const char *password,
853                                    const char *workstation,
854                                    int logon_type)
855 {
856         prs_struct qbuf, rbuf;
857         NET_Q_SAM_LOGON q;
858         NET_R_SAM_LOGON r;
859         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
860         DOM_CRED clnt_creds;
861         DOM_CRED ret_creds;
862         NET_ID_INFO_CTR ctr;
863         NET_USER_INFO_3 user;
864         int validation_level = 3;
865         fstring clnt_name_slash;
866
867         ZERO_STRUCT(q);
868         ZERO_STRUCT(r);
869         ZERO_STRUCT(ret_creds);
870
871         if (workstation) {
872                 fstr_sprintf( clnt_name_slash, "\\\\%s", workstation );
873         } else {
874                 fstr_sprintf( clnt_name_slash, "\\\\%s", global_myname() );
875         }
876
877         /* Initialise input parameters */
878
879         creds_client_step(cli->dc, &clnt_creds);
880
881         q.validation_level = validation_level;
882
883         ctr.switch_value = logon_type;
884
885         switch (logon_type) {
886         case INTERACTIVE_LOGON_TYPE: {
887                 unsigned char lm_owf_user_pwd[16], nt_owf_user_pwd[16];
888
889                 nt_lm_owf_gen(password, nt_owf_user_pwd, lm_owf_user_pwd);
890
891                 init_id_info1(&ctr.auth.id1, domain, 
892                               logon_parameters, /* param_ctrl */
893                               0xdead, 0xbeef, /* LUID? */
894                               username, clnt_name_slash,
895                               (const char *)cli->dc->sess_key, lm_owf_user_pwd,
896                               nt_owf_user_pwd);
897
898                 break;
899         }
900         case NET_LOGON_TYPE: {
901                 uint8 chal[8];
902                 unsigned char local_lm_response[24];
903                 unsigned char local_nt_response[24];
904
905                 generate_random_buffer(chal, 8);
906
907                 SMBencrypt(password, chal, local_lm_response);
908                 SMBNTencrypt(password, chal, local_nt_response);
909
910                 init_id_info2(&ctr.auth.id2, domain, 
911                               logon_parameters, /* param_ctrl */
912                               0xdead, 0xbeef, /* LUID? */
913                               username, clnt_name_slash, chal,
914                               local_lm_response, 24, local_nt_response, 24);
915                 break;
916         }
917         default:
918                 DEBUG(0, ("switch value %d not supported\n", 
919                           ctr.switch_value));
920                 return NT_STATUS_INVALID_INFO_CLASS;
921         }
922
923         r.user = &user;
924
925         init_sam_info(&q.sam_id, cli->dc->remote_machine, global_myname(),
926                       &clnt_creds, &ret_creds, logon_type,
927                       &ctr);
928
929         /* Marshall data and send request */
930
931         CLI_DO_RPC(cli, mem_ctx, PI_NETLOGON, NET_SAMLOGON,
932                 q, r,
933                 qbuf, rbuf,
934                 net_io_q_sam_logon,
935                 net_io_r_sam_logon,
936                 NT_STATUS_UNSUCCESSFUL);
937
938         /* Return results */
939
940         result = r.status;
941
942         if (r.buffer_creds) {
943                 /* Check returned credentials if present. */
944                 if (!creds_client_check(cli->dc, &r.srv_creds.challenge)) {
945                         DEBUG(0,("rpccli_netlogon_sam_logon: credentials chain check failed\n"));
946                         return NT_STATUS_ACCESS_DENIED;
947                 }
948         }
949
950         return result;
951 }
952
953
954 /** 
955  * Logon domain user with an 'network' SAM logon 
956  *
957  * @param info3 Pointer to a NET_USER_INFO_3 already allocated by the caller.
958  **/
959
960 NTSTATUS rpccli_netlogon_sam_network_logon(struct rpc_pipe_client *cli,
961                                            TALLOC_CTX *mem_ctx,
962                                            uint32 logon_parameters,
963                                            const char *server,
964                                            const char *username,
965                                            const char *domain,
966                                            const char *workstation, 
967                                            const uint8 chal[8], 
968                                            DATA_BLOB lm_response,
969                                            DATA_BLOB nt_response,
970                                            NET_USER_INFO_3 *info3)
971 {
972         prs_struct qbuf, rbuf;
973         NET_Q_SAM_LOGON q;
974         NET_R_SAM_LOGON r;
975         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
976         NET_ID_INFO_CTR ctr;
977         int validation_level = 3;
978         const char *workstation_name_slash;
979         const char *server_name_slash;
980         static uint8 zeros[16];
981         DOM_CRED clnt_creds;
982         DOM_CRED ret_creds;
983         int i;
984         
985         ZERO_STRUCT(q);
986         ZERO_STRUCT(r);
987         ZERO_STRUCT(ret_creds);
988
989         creds_client_step(cli->dc, &clnt_creds);
990
991         if (server[0] != '\\' && server[1] != '\\') {
992                 server_name_slash = talloc_asprintf(mem_ctx, "\\\\%s", server);
993         } else {
994                 server_name_slash = server;
995         }
996
997         if (workstation[0] != '\\' && workstation[1] != '\\') {
998                 workstation_name_slash = talloc_asprintf(mem_ctx, "\\\\%s", workstation);
999         } else {
1000                 workstation_name_slash = workstation;
1001         }
1002
1003         if (!workstation_name_slash || !server_name_slash) {
1004                 DEBUG(0, ("talloc_asprintf failed!\n"));
1005                 return NT_STATUS_NO_MEMORY;
1006         }
1007
1008         /* Initialise input parameters */
1009
1010         q.validation_level = validation_level;
1011
1012         ctr.switch_value = NET_LOGON_TYPE;
1013
1014         init_id_info2(&ctr.auth.id2, domain,
1015                       logon_parameters, /* param_ctrl */
1016                       0xdead, 0xbeef, /* LUID? */
1017                       username, workstation_name_slash, (const uchar*)chal,
1018                       lm_response.data, lm_response.length, nt_response.data, nt_response.length);
1019  
1020         init_sam_info(&q.sam_id, server_name_slash, global_myname(),
1021                       &clnt_creds, &ret_creds, NET_LOGON_TYPE,
1022                       &ctr);
1023
1024         r.user = info3;
1025
1026         /* Marshall data and send request */
1027
1028         CLI_DO_RPC(cli, mem_ctx, PI_NETLOGON, NET_SAMLOGON,
1029                 q, r,
1030                 qbuf, rbuf,
1031                 net_io_q_sam_logon,
1032                 net_io_r_sam_logon,
1033                 NT_STATUS_UNSUCCESSFUL);
1034
1035         if (memcmp(zeros, info3->user_sess_key, 16) != 0) {
1036                 SamOEMhash(info3->user_sess_key, cli->dc->sess_key, 16);
1037         } else {
1038                 memset(info3->user_sess_key, '\0', 16);
1039         }
1040
1041         if (memcmp(zeros, info3->lm_sess_key, 8) != 0) {
1042                 SamOEMhash(info3->lm_sess_key, cli->dc->sess_key, 8);
1043         } else {
1044                 memset(info3->lm_sess_key, '\0', 8);
1045         }
1046
1047         for (i=0; i < 7; i++) {
1048                 memset(&info3->unknown[i], '\0', 4);
1049         }
1050
1051         /* Return results */
1052
1053         result = r.status;
1054
1055         if (r.buffer_creds) {
1056                 /* Check returned credentials if present. */
1057                 if (!creds_client_check(cli->dc, &r.srv_creds.challenge)) {
1058                         DEBUG(0,("rpccli_netlogon_sam_network_logon: credentials chain check failed\n"));
1059                         return NT_STATUS_ACCESS_DENIED;
1060                 }
1061         }
1062
1063         return result;
1064 }
1065
1066 NTSTATUS rpccli_netlogon_sam_network_logon_ex(struct rpc_pipe_client *cli,
1067                                               TALLOC_CTX *mem_ctx,
1068                                               uint32 logon_parameters,
1069                                               const char *server,
1070                                               const char *username,
1071                                               const char *domain,
1072                                               const char *workstation, 
1073                                               const uint8 chal[8], 
1074                                               DATA_BLOB lm_response,
1075                                               DATA_BLOB nt_response,
1076                                               NET_USER_INFO_3 *info3)
1077 {
1078         prs_struct qbuf, rbuf;
1079         NET_Q_SAM_LOGON_EX q;
1080         NET_R_SAM_LOGON_EX r;
1081         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
1082         NET_ID_INFO_CTR ctr;
1083         int validation_level = 3;
1084         const char *workstation_name_slash;
1085         const char *server_name_slash;
1086         static uint8 zeros[16];
1087         int i;
1088         
1089         ZERO_STRUCT(q);
1090         ZERO_STRUCT(r);
1091
1092         if (server[0] != '\\' && server[1] != '\\') {
1093                 server_name_slash = talloc_asprintf(mem_ctx, "\\\\%s", server);
1094         } else {
1095                 server_name_slash = server;
1096         }
1097
1098         if (workstation[0] != '\\' && workstation[1] != '\\') {
1099                 workstation_name_slash = talloc_asprintf(mem_ctx, "\\\\%s", workstation);
1100         } else {
1101                 workstation_name_slash = workstation;
1102         }
1103
1104         if (!workstation_name_slash || !server_name_slash) {
1105                 DEBUG(0, ("talloc_asprintf failed!\n"));
1106                 return NT_STATUS_NO_MEMORY;
1107         }
1108
1109         /* Initialise input parameters */
1110
1111         q.validation_level = validation_level;
1112
1113         ctr.switch_value = NET_LOGON_TYPE;
1114
1115         init_id_info2(&ctr.auth.id2, domain,
1116                       logon_parameters, /* param_ctrl */
1117                       0xdead, 0xbeef, /* LUID? */
1118                       username, workstation_name_slash, (const uchar*)chal,
1119                       lm_response.data, lm_response.length, nt_response.data,
1120                       nt_response.length);
1121  
1122         init_sam_info_ex(&q.sam_id, server_name_slash, global_myname(),
1123                          NET_LOGON_TYPE, &ctr);
1124
1125         r.user = info3;
1126
1127         /* Marshall data and send request */
1128
1129         CLI_DO_RPC(cli, mem_ctx, PI_NETLOGON, NET_SAMLOGON_EX,
1130                    q, r, qbuf, rbuf,
1131                    net_io_q_sam_logon_ex,
1132                    net_io_r_sam_logon_ex,
1133                    NT_STATUS_UNSUCCESSFUL);
1134
1135         if (memcmp(zeros, info3->user_sess_key, 16) != 0) {
1136                 SamOEMhash(info3->user_sess_key, cli->dc->sess_key, 16);
1137         } else {
1138                 memset(info3->user_sess_key, '\0', 16);
1139         }
1140
1141         if (memcmp(zeros, info3->lm_sess_key, 8) != 0) {
1142                 SamOEMhash(info3->lm_sess_key, cli->dc->sess_key, 8);
1143         } else {
1144                 memset(info3->lm_sess_key, '\0', 8);
1145         }
1146
1147         for (i=0; i < 7; i++) {
1148                 memset(&info3->unknown[i], '\0', 4);
1149         }
1150
1151         /* Return results */
1152
1153         result = r.status;
1154
1155         return result;
1156 }
1157
1158 /***************************************************************************
1159 LSA Server Password Set.
1160 ****************************************************************************/
1161
1162 NTSTATUS rpccli_net_srv_pwset(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, 
1163                            const char *machine_name, const uint8 hashed_mach_pwd[16])
1164 {
1165         prs_struct rbuf;
1166         prs_struct qbuf; 
1167         DOM_CRED clnt_creds;
1168         NET_Q_SRV_PWSET q;
1169         NET_R_SRV_PWSET r;
1170         uint16 sec_chan_type = 2;
1171         NTSTATUS result;
1172
1173         creds_client_step(cli->dc, &clnt_creds);
1174         
1175         DEBUG(4,("cli_net_srv_pwset: srv:%s acct:%s sc: %d mc: %s\n",
1176                  cli->dc->remote_machine, cli->dc->mach_acct, sec_chan_type, machine_name));
1177         
1178         /* store the parameters */
1179         init_q_srv_pwset(&q, cli->dc->remote_machine, (const char *)cli->dc->sess_key,
1180                          cli->dc->mach_acct, sec_chan_type, machine_name, 
1181                          &clnt_creds, hashed_mach_pwd);
1182         
1183         CLI_DO_RPC(cli, mem_ctx, PI_NETLOGON, NET_SRVPWSET,
1184                 q, r,
1185                 qbuf, rbuf,
1186                 net_io_q_srv_pwset,
1187                 net_io_r_srv_pwset,
1188                 NT_STATUS_UNSUCCESSFUL);
1189
1190         result = r.status;
1191
1192         if (!NT_STATUS_IS_OK(result)) {
1193                 /* report error code */
1194                 DEBUG(0,("cli_net_srv_pwset: %s\n", nt_errstr(result)));
1195         }
1196
1197         /* Always check returned credentials. */
1198         if (!creds_client_check(cli->dc, &r.srv_cred.challenge)) {
1199                 DEBUG(0,("rpccli_net_srv_pwset: credentials chain check failed\n"));
1200                 return NT_STATUS_ACCESS_DENIED;
1201         }
1202
1203         return result;
1204 }