Merge branch 'v3-2-test' of ssh://git.samba.org/data/git/samba into v3-2-test
[kai/samba.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 3 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, see <http://www.gnu.org/licenses/>.
20 */
21
22 #include "includes.h"
23
24 /* LSA Request Challenge. Sends our challenge to server, then gets
25    server response. These are used to generate the credentials.
26  The sent and received challenges are stored in the netlog pipe
27  private data. Only call this via rpccli_netlogon_setup_creds(). JRA.
28 */
29
30 static NTSTATUS rpccli_net_req_chal(struct rpc_pipe_client *cli,
31                                 TALLOC_CTX *mem_ctx,
32                                 const char *server_name,
33                                 const char *clnt_name,
34                                 const DOM_CHAL *clnt_chal_in,
35                                 DOM_CHAL *srv_chal_out)
36 {
37         prs_struct qbuf, rbuf;
38         NET_Q_REQ_CHAL q;
39         NET_R_REQ_CHAL r;
40         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
41
42         /* create and send a MSRPC command with api NET_REQCHAL */
43
44         DEBUG(4,("cli_net_req_chal: LSA Request Challenge from %s to %s\n",
45                 clnt_name, server_name));
46         
47         /* store the parameters */
48         init_q_req_chal(&q, server_name, clnt_name, clnt_chal_in);
49
50         /* Marshall data and send request */
51         CLI_DO_RPC(cli, mem_ctx, PI_NETLOGON, NET_REQCHAL,
52                 q, r,
53                 qbuf, rbuf,
54                 net_io_q_req_chal,
55                 net_io_r_req_chal,
56                 NT_STATUS_UNSUCCESSFUL);
57
58         result = r.status;
59
60         /* Return result */
61
62         if (NT_STATUS_IS_OK(result)) {
63                 /* Store the returned server challenge. */
64                 *srv_chal_out = r.srv_chal;
65         }
66
67         return result;
68 }
69
70 #if 0
71 /****************************************************************************
72 LSA Authenticate 2
73
74 Send the client credential, receive back a server credential.
75 Ensure that the server credential returned matches the session key 
76 encrypt of the server challenge originally received. JRA.
77 ****************************************************************************/
78
79   NTSTATUS rpccli_net_auth2(struct rpc_pipe_client *cli, 
80                        uint16 sec_chan, 
81                        uint32 *neg_flags, DOM_CHAL *srv_chal)
82 {
83         prs_struct qbuf, rbuf;
84         NET_Q_AUTH_2 q;
85         NET_R_AUTH_2 r;
86         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
87         fstring machine_acct;
88
89         if ( sec_chan == SEC_CHAN_DOMAIN )
90                 fstr_sprintf( machine_acct, "%s$", lp_workgroup() );
91         else
92                 fstrcpy( machine_acct, cli->mach_acct );
93         
94         /* create and send a MSRPC command with api NET_AUTH2 */
95
96         DEBUG(4,("cli_net_auth2: srv:%s acct:%s sc:%x mc: %s chal %s neg: %x\n",
97                  cli->srv_name_slash, machine_acct, sec_chan, global_myname(),
98                  credstr(cli->clnt_cred.challenge.data), *neg_flags));
99
100         /* store the parameters */
101
102         init_q_auth_2(&q, cli->srv_name_slash, machine_acct, 
103                       sec_chan, global_myname(), &cli->clnt_cred.challenge, 
104                       *neg_flags);
105
106         /* turn parameters into data stream */
107
108         CLI_DO_RPC(cli, mem_ctx, PI_NETLOGON, NET_AUTH2,
109                 q, r,
110                 qbuf, rbuf,
111                 net_io_q_auth_2,
112                 net_io_r_auth_2,
113                 NT_STATUS_UNSUCCESSFUL);
114
115         result = r.status;
116
117         if (NT_STATUS_IS_OK(result)) {
118                 UTIME zerotime;
119                 
120                 /*
121                  * Check the returned value using the initial
122                  * server received challenge.
123                  */
124
125                 zerotime.time = 0;
126                 if (cred_assert( &r.srv_chal, cli->sess_key, srv_chal, zerotime) == 0) {
127
128                         /*
129                          * Server replied with bad credential. Fail.
130                          */
131                         DEBUG(0,("cli_net_auth2: server %s replied with bad credential (bad machine \
132 password ?).\n", cli->cli->desthost ));
133                         return NT_STATUS_ACCESS_DENIED;
134                 }
135                 *neg_flags = r.srv_flgs.neg_flags;
136         }
137
138         return result;
139 }
140 #endif
141
142 /****************************************************************************
143  LSA Authenticate 2
144
145  Send the client credential, receive back a server credential.
146  The caller *must* ensure that the server credential returned matches the session key 
147  encrypt of the server challenge originally received. JRA.
148 ****************************************************************************/
149
150 static NTSTATUS rpccli_net_auth2(struct rpc_pipe_client *cli,
151                         TALLOC_CTX *mem_ctx,
152                         const char *server_name,
153                         const char *account_name,
154                         uint16 sec_chan_type,
155                         const char *computer_name,
156                         uint32 *neg_flags_inout,
157                         const DOM_CHAL *clnt_chal_in,
158                         DOM_CHAL *srv_chal_out)
159 {
160         prs_struct qbuf, rbuf;
161         NET_Q_AUTH_2 q;
162         NET_R_AUTH_2 r;
163         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
164
165         /* create and send a MSRPC command with api NET_AUTH2 */
166
167         DEBUG(4,("cli_net_auth2: srv:%s acct:%s sc:%x mc: %s neg: %x\n",
168                  server_name, account_name, sec_chan_type, computer_name,
169                  *neg_flags_inout));
170
171         /* store the parameters */
172
173         init_q_auth_2(&q, server_name, account_name, sec_chan_type,
174                       computer_name, clnt_chal_in, *neg_flags_inout);
175
176         /* turn parameters into data stream */
177
178         CLI_DO_RPC(cli, mem_ctx, PI_NETLOGON, NET_AUTH2,
179                 q, r,
180                 qbuf, rbuf,
181                 net_io_q_auth_2,
182                 net_io_r_auth_2,
183                 NT_STATUS_UNSUCCESSFUL);
184
185         result = r.status;
186
187         if (NT_STATUS_IS_OK(result)) {
188                 *srv_chal_out = r.srv_chal;
189                 *neg_flags_inout = r.srv_flgs.neg_flags;
190         }
191
192         return result;
193 }
194
195 #if 0   /* not currebntly used */
196 /****************************************************************************
197  LSA Authenticate 3
198
199  Send the client credential, receive back a server credential.
200  The caller *must* ensure that the server credential returned matches the session key 
201  encrypt of the server challenge originally received. JRA.
202 ****************************************************************************/
203
204 static NTSTATUS rpccli_net_auth3(struct rpc_pipe_client *cli, 
205                         TALLOC_CTX *mem_ctx,
206                         const char *server_name,
207                         const char *account_name,
208                         uint16 sec_chan_type,
209                         const char *computer_name,
210                         uint32 *neg_flags_inout,
211                         const DOM_CHAL *clnt_chal_in,
212                         DOM_CHAL *srv_chal_out)
213 {
214         prs_struct qbuf, rbuf;
215         NET_Q_AUTH_3 q;
216         NET_R_AUTH_3 r;
217         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
218
219         /* create and send a MSRPC command with api NET_AUTH2 */
220
221         DEBUG(4,("cli_net_auth3: srv:%s acct:%s sc:%x mc: %s chal %s neg: %x\n",
222                 server_name, account_name, sec_chan_type, computer_name,
223                 credstr(clnt_chal_in->data), *neg_flags_inout));
224
225         /* store the parameters */
226         init_q_auth_3(&q, server_name, account_name, sec_chan_type,
227                         computer_name, clnt_chal_in, *neg_flags_inout);
228
229         /* turn parameters into data stream */
230
231         CLI_DO_RPC(cli, mem_ctx, PI_NETLOGON, NET_AUTH3,
232                 q, r,
233                 qbuf, rbuf,
234                 net_io_q_auth_3,
235                 net_io_r_auth_3,
236                 NT_STATUS_UNSUCCESSFUL);
237
238         if (NT_STATUS_IS_OK(result)) {
239                 *srv_chal_out = r.srv_chal;
240                 *neg_flags_inout = r.srv_flgs.neg_flags;
241         }
242
243         return result;
244 }
245 #endif  /* not currebntly used */
246
247 /****************************************************************************
248  Wrapper function that uses the auth and auth2 calls to set up a NETLOGON
249  credentials chain. Stores the credentials in the struct dcinfo in the
250  netlogon pipe struct.
251 ****************************************************************************/
252
253 NTSTATUS rpccli_netlogon_setup_creds(struct rpc_pipe_client *cli,
254                                 const char *server_name,
255                                 const char *domain,
256                                 const char *clnt_name,
257                                 const char *machine_account,
258                                 const unsigned char machine_pwd[16],
259                                 uint32 sec_chan_type,
260                                 uint32 *neg_flags_inout)
261 {
262         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
263         DOM_CHAL clnt_chal_send;
264         DOM_CHAL srv_chal_recv;
265         struct dcinfo *dc;
266
267         SMB_ASSERT(cli->pipe_idx == PI_NETLOGON);
268
269         dc = cli->dc;
270         if (!dc) {
271                 return NT_STATUS_INVALID_PARAMETER;
272         }
273
274         /* Ensure we don't reuse any of this state. */
275         ZERO_STRUCTP(dc);
276
277         /* Store the machine account password we're going to use. */
278         memcpy(dc->mach_pw, machine_pwd, 16);
279
280         fstrcpy(dc->remote_machine, "\\\\");
281         fstrcat(dc->remote_machine, server_name);
282
283         fstrcpy(dc->domain, domain);
284
285         fstr_sprintf( dc->mach_acct, "%s$", machine_account);
286
287         /* Create the client challenge. */
288         generate_random_buffer(clnt_chal_send.data, 8);
289
290         /* Get the server challenge. */
291         result = rpccli_net_req_chal(cli,
292                                 cli->mem_ctx,
293                                 dc->remote_machine,
294                                 clnt_name,
295                                 &clnt_chal_send,
296                                 &srv_chal_recv);
297
298         if (!NT_STATUS_IS_OK(result)) {
299                 return result;
300         }
301
302         /* Calculate the session key and client credentials */
303         creds_client_init(*neg_flags_inout,
304                         dc,
305                         &clnt_chal_send,
306                         &srv_chal_recv,
307                         machine_pwd,
308                         &clnt_chal_send);
309
310         /*  
311          * Send client auth-2 challenge and receive server repy.
312          */
313
314         result = rpccli_net_auth2(cli,
315                         cli->mem_ctx,
316                         dc->remote_machine,
317                         dc->mach_acct,
318                         sec_chan_type,
319                         clnt_name,
320                         neg_flags_inout,
321                         &clnt_chal_send, /* input. */
322                         &srv_chal_recv); /* output */
323
324         if (!NT_STATUS_IS_OK(result)) {
325                 return result;
326         }
327
328         /*
329          * Check the returned value using the initial
330          * server received challenge.
331          */
332
333         if (!creds_client_check(dc, &srv_chal_recv)) {
334                 /*
335                  * Server replied with bad credential. Fail.
336                  */
337                 DEBUG(0,("rpccli_netlogon_setup_creds: server %s "
338                         "replied with bad credential\n",
339                         cli->cli->desthost ));
340                 return NT_STATUS_ACCESS_DENIED;
341         }
342
343         DEBUG(5,("rpccli_netlogon_setup_creds: server %s credential "
344                 "chain established.\n",
345                 cli->cli->desthost ));
346
347         return NT_STATUS_OK;
348 }
349
350 /* Logon Control 2 */
351
352 NTSTATUS rpccli_netlogon_logon_ctrl2(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
353                                   uint32 query_level)
354 {
355         prs_struct qbuf, rbuf;
356         NET_Q_LOGON_CTRL2 q;
357         NET_R_LOGON_CTRL2 r;
358         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
359         fstring server;
360
361         ZERO_STRUCT(q);
362         ZERO_STRUCT(r);
363
364         /* Initialise input parameters */
365
366         slprintf(server, sizeof(fstring)-1, "\\\\%s", cli->cli->desthost);
367         init_net_q_logon_ctrl2(&q, server, query_level);
368
369         /* Marshall data and send request */
370
371         CLI_DO_RPC(cli, mem_ctx, PI_NETLOGON, NET_LOGON_CTRL2,
372                 q, r,
373                 qbuf, rbuf,
374                 net_io_q_logon_ctrl2,
375                 net_io_r_logon_ctrl2,
376                 NT_STATUS_UNSUCCESSFUL);
377
378         result = r.status;
379         return result;
380 }
381
382 /* GetAnyDCName */
383
384 WERROR rpccli_netlogon_getanydcname(struct rpc_pipe_client *cli,
385                                     TALLOC_CTX *mem_ctx, const char *mydcname,
386                                     const char *domainname, char **newdcname)
387 {
388         prs_struct qbuf, rbuf;
389         NET_Q_GETANYDCNAME q;
390         NET_R_GETANYDCNAME r;
391         WERROR result;
392         fstring mydcname_slash;
393
394         ZERO_STRUCT(q);
395         ZERO_STRUCT(r);
396
397         /* Initialise input parameters */
398
399         slprintf(mydcname_slash, sizeof(fstring)-1, "\\\\%s", mydcname);
400         init_net_q_getanydcname(&q, mydcname_slash, domainname);
401
402         /* Marshall data and send request */
403
404         CLI_DO_RPC_WERR(cli, mem_ctx, PI_NETLOGON, NET_GETANYDCNAME,
405                 q, r,
406                 qbuf, rbuf,
407                 net_io_q_getanydcname,
408                 net_io_r_getanydcname,
409                 WERR_GENERAL_FAILURE);
410
411         result = r.status;
412
413         if (W_ERROR_IS_OK(result) && newdcname) {
414                 *newdcname = rpcstr_pull_unistr2_talloc(mem_ctx, &r.uni_dcname);
415                 W_ERROR_HAVE_NO_MEMORY(*newdcname);
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, char **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) && newdcname) {
453                 *newdcname = rpcstr_pull_unistr2_talloc(mem_ctx, &r.uni_dcname);
454                 W_ERROR_HAVE_NO_MEMORY(*newdcname);
455         }
456
457         return result;
458 }
459
460 static WERROR pull_domain_controller_info_from_getdcname_reply(TALLOC_CTX *mem_ctx,
461                                                                struct DS_DOMAIN_CONTROLLER_INFO **info_out, 
462                                                                NET_R_DSR_GETDCNAME *r)
463 {
464         struct DS_DOMAIN_CONTROLLER_INFO *info;
465
466         info = TALLOC_ZERO_P(mem_ctx, struct DS_DOMAIN_CONTROLLER_INFO);
467         if (!info) {
468                 return WERR_NOMEM;
469         }
470
471         if (&r->uni_dc_unc) {
472
473                 char *tmp;
474                 tmp = rpcstr_pull_unistr2_talloc(mem_ctx, &r->uni_dc_unc);
475                 if (tmp == NULL) {
476                         return WERR_GENERAL_FAILURE;
477                 }
478                 if (*tmp == '\\') tmp += 1;
479                 if (*tmp == '\\') tmp += 1;
480
481                 info->domain_controller_name = talloc_strdup(mem_ctx, tmp);
482                 if (info->domain_controller_name == NULL) {
483                         return WERR_GENERAL_FAILURE;
484                 }
485         }
486
487         if (&r->uni_dc_address) {
488
489                 char *tmp;
490                 tmp = rpcstr_pull_unistr2_talloc(mem_ctx, &r->uni_dc_address);
491                 if (tmp == NULL) {
492                         return WERR_GENERAL_FAILURE;
493                 }
494                 if (*tmp == '\\') tmp += 1;
495                 if (*tmp == '\\') tmp += 1;
496
497                 info->domain_controller_address = talloc_strdup(mem_ctx, tmp);
498                 if (info->domain_controller_address == NULL) {
499                         return WERR_GENERAL_FAILURE;
500                 }
501         }
502
503         info->domain_controller_address_type = r->dc_address_type;
504
505         info->domain_guid = (struct GUID *)talloc_memdup(
506                 mem_ctx, &r->domain_guid, sizeof(struct GUID));
507         if (!info->domain_guid) {
508                 return WERR_GENERAL_FAILURE;
509         }
510
511         if (&r->uni_domain_name) {
512                 info->domain_name = rpcstr_pull_unistr2_talloc(mem_ctx, &r->uni_domain_name);
513                 if (!info->domain_name) {
514                         return WERR_GENERAL_FAILURE;
515                 }
516         }
517
518         if (&r->uni_forest_name) {
519                 info->dns_forest_name = rpcstr_pull_unistr2_talloc(mem_ctx, &r->uni_forest_name);
520                 if (!info->dns_forest_name) {
521                         return WERR_GENERAL_FAILURE;
522                 }
523         }
524
525         info->flags = r->dc_flags;
526
527         if (&r->uni_dc_site_name) {
528                 info->dc_site_name = rpcstr_pull_unistr2_talloc(mem_ctx, &r->uni_dc_site_name);
529                 if (!info->dc_site_name) {
530                         return WERR_GENERAL_FAILURE;
531                 }
532         }
533
534         if (&r->uni_client_site_name) {
535                 info->client_site_name = rpcstr_pull_unistr2_talloc(mem_ctx, &r->uni_client_site_name);
536                 if (!info->client_site_name) {
537                         return WERR_GENERAL_FAILURE;
538                 }
539         }
540
541         *info_out = info;
542
543         return WERR_OK;
544 }
545
546 /* Dsr_GetDCName */
547
548 WERROR rpccli_netlogon_dsr_getdcname(struct rpc_pipe_client *cli,
549                                      TALLOC_CTX *mem_ctx,
550                                      const char *server_name,
551                                      const char *domain_name,
552                                      struct GUID *domain_guid,
553                                      struct GUID *site_guid,
554                                      uint32_t flags,
555                                      struct DS_DOMAIN_CONTROLLER_INFO **info_out)
556 {
557         prs_struct qbuf, rbuf;
558         NET_Q_DSR_GETDCNAME q;
559         NET_R_DSR_GETDCNAME r;
560         char *tmp_str;
561
562         ZERO_STRUCT(q);
563         ZERO_STRUCT(r);
564
565         /* Initialize input parameters */
566
567         tmp_str = talloc_asprintf(mem_ctx, "\\\\%s", server_name);
568         if (tmp_str == NULL) {
569                 return WERR_NOMEM;
570         }
571
572         init_net_q_dsr_getdcname(&q, tmp_str, domain_name, domain_guid,
573                                  site_guid, flags);
574
575         /* Marshall data and send request */
576
577         CLI_DO_RPC_WERR(cli, mem_ctx, PI_NETLOGON, NET_DSR_GETDCNAME,
578                         q, r,
579                         qbuf, rbuf,
580                         net_io_q_dsr_getdcname,
581                         net_io_r_dsr_getdcname,
582                         WERR_GENERAL_FAILURE);
583
584         if (!W_ERROR_IS_OK(r.result)) {
585                 return r.result;
586         }
587
588         r.result = pull_domain_controller_info_from_getdcname_reply(mem_ctx, info_out, &r);
589         if (!W_ERROR_IS_OK(r.result)) {
590                 return r.result;
591         }
592
593         return WERR_OK;
594 }
595
596 /* Dsr_GetDCNameEx */
597
598 WERROR rpccli_netlogon_dsr_getdcnameex(struct rpc_pipe_client *cli,
599                                        TALLOC_CTX *mem_ctx,
600                                        const char *server_name,
601                                        const char *domain_name,
602                                        struct GUID *domain_guid,
603                                        const char *site_name,
604                                        uint32_t flags,
605                                        struct DS_DOMAIN_CONTROLLER_INFO **info_out)
606 {
607         prs_struct qbuf, rbuf;
608         NET_Q_DSR_GETDCNAMEEX q;
609         NET_R_DSR_GETDCNAME r;
610         char *tmp_str;
611
612         ZERO_STRUCT(q);
613         ZERO_STRUCT(r);
614
615         /* Initialize input parameters */
616
617         tmp_str = talloc_asprintf(mem_ctx, "\\\\%s", server_name);
618         if (tmp_str == NULL) {
619                 return WERR_NOMEM;
620         }
621
622         init_net_q_dsr_getdcnameex(&q, server_name, domain_name, domain_guid,
623                                    site_name, flags);
624
625         /* Marshall data and send request */
626
627         CLI_DO_RPC_WERR(cli, mem_ctx, PI_NETLOGON, NET_DSR_GETDCNAMEEX,
628                         q, r,
629                         qbuf, rbuf,
630                         net_io_q_dsr_getdcnameex,
631                         net_io_r_dsr_getdcname,
632                         WERR_GENERAL_FAILURE);
633
634         if (!W_ERROR_IS_OK(r.result)) {
635                 return r.result;
636         }
637
638         r.result = pull_domain_controller_info_from_getdcname_reply(mem_ctx, info_out, &r);
639         if (!W_ERROR_IS_OK(r.result)) {
640                 return r.result;
641         }
642
643         return WERR_OK;
644 }
645
646 /* Dsr_GetDCNameEx */
647
648 WERROR rpccli_netlogon_dsr_getdcnameex2(struct rpc_pipe_client *cli,
649                                         TALLOC_CTX *mem_ctx,
650                                         const char *server_name,
651                                         const char *client_account,
652                                         uint32 mask,
653                                         const char *domain_name,
654                                         struct GUID *domain_guid,
655                                         const char *site_name,
656                                         uint32_t flags,
657                                         struct DS_DOMAIN_CONTROLLER_INFO **info_out)
658 {
659         prs_struct qbuf, rbuf;
660         NET_Q_DSR_GETDCNAMEEX2 q;
661         NET_R_DSR_GETDCNAME r;
662         char *tmp_str;
663
664         ZERO_STRUCT(q);
665         ZERO_STRUCT(r);
666
667         /* Initialize input parameters */
668
669         tmp_str = talloc_asprintf(mem_ctx, "\\\\%s", server_name);
670         if (tmp_str == NULL) {
671                 return WERR_NOMEM;
672         }
673
674         init_net_q_dsr_getdcnameex2(&q, server_name, domain_name, client_account,
675                                     mask, domain_guid, site_name, flags);
676
677         /* Marshall data and send request */
678
679         CLI_DO_RPC_WERR(cli, mem_ctx, PI_NETLOGON, NET_DSR_GETDCNAMEEX2,
680                         q, r,
681                         qbuf, rbuf,
682                         net_io_q_dsr_getdcnameex2,
683                         net_io_r_dsr_getdcname,
684                         WERR_GENERAL_FAILURE);
685
686         if (!W_ERROR_IS_OK(r.result)) {
687                 return r.result;
688         }
689
690         r.result = pull_domain_controller_info_from_getdcname_reply(mem_ctx, info_out, &r);
691         if (!W_ERROR_IS_OK(r.result)) {
692                 return r.result;
693         }
694
695         return WERR_OK;
696 }
697
698
699 /* Dsr_GetSiteName */
700
701 WERROR rpccli_netlogon_dsr_getsitename(struct rpc_pipe_client *cli,
702                                        TALLOC_CTX *mem_ctx,
703                                        const char *computer_name,
704                                        char **site_name)
705 {
706         prs_struct qbuf, rbuf;
707         NET_Q_DSR_GETSITENAME q;
708         NET_R_DSR_GETSITENAME r;
709
710         ZERO_STRUCT(q);
711         ZERO_STRUCT(r);
712
713         /* Initialize input parameters */
714
715         init_net_q_dsr_getsitename(&q, computer_name);
716
717         /* Marshall data and send request */
718
719         CLI_DO_RPC_WERR(cli, mem_ctx, PI_NETLOGON, NET_DSR_GETSITENAME,
720                         q, r,
721                         qbuf, rbuf,
722                         net_io_q_dsr_getsitename,
723                         net_io_r_dsr_getsitename,
724                         WERR_GENERAL_FAILURE);
725
726         if (!W_ERROR_IS_OK(r.result)) {
727                 return r.result;
728         }
729
730         if ((site_name != NULL) &&
731             ((*site_name = rpcstr_pull_unistr2_talloc(
732                       mem_ctx, &r.uni_site_name)) == NULL)) {
733                 return WERR_GENERAL_FAILURE;
734         }
735
736         return WERR_OK;
737 }
738
739
740
741 /* Sam synchronisation */
742
743 NTSTATUS rpccli_netlogon_sam_sync(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
744                                uint32 database_id, uint32 next_rid, uint32 *num_deltas,
745                                SAM_DELTA_HDR **hdr_deltas, 
746                                SAM_DELTA_CTR **deltas)
747 {
748         prs_struct qbuf, rbuf;
749         NET_Q_SAM_SYNC q;
750         NET_R_SAM_SYNC r;
751         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
752         DOM_CRED clnt_creds;
753         DOM_CRED ret_creds;
754
755         ZERO_STRUCT(q);
756         ZERO_STRUCT(r);
757
758         ZERO_STRUCT(ret_creds);
759
760         /* Initialise input parameters */
761
762         creds_client_step(cli->dc, &clnt_creds);
763
764         init_net_q_sam_sync(&q, cli->dc->remote_machine, global_myname(),
765                             &clnt_creds, &ret_creds, database_id, next_rid);
766
767         /* Marshall data and send request */
768
769         CLI_DO_RPC_COPY_SESS_KEY(cli, mem_ctx, PI_NETLOGON, NET_SAM_SYNC,
770                 q, r,
771                 qbuf, rbuf,
772                 net_io_q_sam_sync,
773                 net_io_r_sam_sync,
774                 NT_STATUS_UNSUCCESSFUL);
775
776         /* Return results */
777
778         result = r.status;
779         *num_deltas = r.num_deltas2;
780         *hdr_deltas = r.hdr_deltas;
781         *deltas = r.deltas;
782
783         if (!NT_STATUS_IS_ERR(result)) {
784                 /* Check returned credentials. */
785                 if (!creds_client_check(cli->dc, &r.srv_creds.challenge)) {
786                         DEBUG(0,("cli_netlogon_sam_sync: credentials chain check failed\n"));
787                         return NT_STATUS_ACCESS_DENIED;
788                 }
789         }
790
791         return result;
792 }
793
794 /* Sam synchronisation */
795
796 NTSTATUS rpccli_netlogon_sam_deltas(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
797                                  uint32 database_id, uint64 seqnum,
798                                  uint32 *num_deltas, 
799                                  SAM_DELTA_HDR **hdr_deltas, 
800                                  SAM_DELTA_CTR **deltas)
801 {
802         prs_struct qbuf, rbuf;
803         NET_Q_SAM_DELTAS q;
804         NET_R_SAM_DELTAS r;
805         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
806         DOM_CRED clnt_creds;
807
808         ZERO_STRUCT(q);
809         ZERO_STRUCT(r);
810
811         /* Initialise input parameters */
812
813         creds_client_step(cli->dc, &clnt_creds);
814
815         init_net_q_sam_deltas(&q, cli->dc->remote_machine,
816                               global_myname(), &clnt_creds, 
817                               database_id, seqnum);
818
819         /* Marshall data and send request */
820
821         CLI_DO_RPC(cli, mem_ctx, PI_NETLOGON, NET_SAM_DELTAS,
822                 q, r,
823                 qbuf, rbuf,
824                 net_io_q_sam_deltas,
825                 net_io_r_sam_deltas,
826                 NT_STATUS_UNSUCCESSFUL);
827
828         /* Return results */
829
830         result = r.status;
831         *num_deltas = r.num_deltas2;
832         *hdr_deltas = r.hdr_deltas;
833         *deltas = r.deltas;
834
835         if (!NT_STATUS_IS_ERR(result)) {
836                 /* Check returned credentials. */
837                 if (!creds_client_check(cli->dc, &r.srv_creds.challenge)) {
838                         DEBUG(0,("cli_netlogon_sam_sync: credentials chain check failed\n"));
839                         return NT_STATUS_ACCESS_DENIED;
840                 }
841         }
842
843         return result;
844 }
845
846 /* Logon domain user */
847
848 NTSTATUS rpccli_netlogon_sam_logon(struct rpc_pipe_client *cli,
849                                    TALLOC_CTX *mem_ctx,
850                                    uint32 logon_parameters,
851                                    const char *domain,
852                                    const char *username,
853                                    const char *password,
854                                    const char *workstation,
855                                    int logon_type)
856 {
857         prs_struct qbuf, rbuf;
858         NET_Q_SAM_LOGON q;
859         NET_R_SAM_LOGON r;
860         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
861         DOM_CRED clnt_creds;
862         DOM_CRED ret_creds;
863         NET_ID_INFO_CTR ctr;
864         NET_USER_INFO_3 user;
865         int validation_level = 3;
866         fstring clnt_name_slash;
867
868         ZERO_STRUCT(q);
869         ZERO_STRUCT(r);
870         ZERO_STRUCT(ret_creds);
871
872         if (workstation) {
873                 fstr_sprintf( clnt_name_slash, "\\\\%s", workstation );
874         } else {
875                 fstr_sprintf( clnt_name_slash, "\\\\%s", global_myname() );
876         }
877
878         /* Initialise input parameters */
879
880         creds_client_step(cli->dc, &clnt_creds);
881
882         q.validation_level = validation_level;
883
884         ctr.switch_value = logon_type;
885
886         switch (logon_type) {
887         case INTERACTIVE_LOGON_TYPE: {
888                 unsigned char lm_owf_user_pwd[16], nt_owf_user_pwd[16];
889
890                 nt_lm_owf_gen(password, nt_owf_user_pwd, lm_owf_user_pwd);
891
892                 init_id_info1(&ctr.auth.id1, domain, 
893                               logon_parameters, /* param_ctrl */
894                               0xdead, 0xbeef, /* LUID? */
895                               username, clnt_name_slash,
896                               (const char *)cli->dc->sess_key, lm_owf_user_pwd,
897                               nt_owf_user_pwd);
898
899                 break;
900         }
901         case NET_LOGON_TYPE: {
902                 uint8 chal[8];
903                 unsigned char local_lm_response[24];
904                 unsigned char local_nt_response[24];
905
906                 generate_random_buffer(chal, 8);
907
908                 SMBencrypt(password, chal, local_lm_response);
909                 SMBNTencrypt(password, chal, local_nt_response);
910
911                 init_id_info2(&ctr.auth.id2, domain, 
912                               logon_parameters, /* param_ctrl */
913                               0xdead, 0xbeef, /* LUID? */
914                               username, clnt_name_slash, chal,
915                               local_lm_response, 24, local_nt_response, 24);
916                 break;
917         }
918         default:
919                 DEBUG(0, ("switch value %d not supported\n", 
920                           ctr.switch_value));
921                 return NT_STATUS_INVALID_INFO_CLASS;
922         }
923
924         r.user = &user;
925
926         init_sam_info(&q.sam_id, cli->dc->remote_machine, global_myname(),
927                       &clnt_creds, &ret_creds, logon_type,
928                       &ctr);
929
930         /* Marshall data and send request */
931
932         CLI_DO_RPC(cli, mem_ctx, PI_NETLOGON, NET_SAMLOGON,
933                 q, r,
934                 qbuf, rbuf,
935                 net_io_q_sam_logon,
936                 net_io_r_sam_logon,
937                 NT_STATUS_UNSUCCESSFUL);
938
939         /* Return results */
940
941         result = r.status;
942
943         if (r.buffer_creds) {
944                 /* Check returned credentials if present. */
945                 if (!creds_client_check(cli->dc, &r.srv_creds.challenge)) {
946                         DEBUG(0,("rpccli_netlogon_sam_logon: credentials chain check failed\n"));
947                         return NT_STATUS_ACCESS_DENIED;
948                 }
949         }
950
951         return result;
952 }
953
954
955 /** 
956  * Logon domain user with an 'network' SAM logon 
957  *
958  * @param info3 Pointer to a NET_USER_INFO_3 already allocated by the caller.
959  **/
960
961 NTSTATUS rpccli_netlogon_sam_network_logon(struct rpc_pipe_client *cli,
962                                            TALLOC_CTX *mem_ctx,
963                                            uint32 logon_parameters,
964                                            const char *server,
965                                            const char *username,
966                                            const char *domain,
967                                            const char *workstation, 
968                                            const uint8 chal[8], 
969                                            DATA_BLOB lm_response,
970                                            DATA_BLOB nt_response,
971                                            NET_USER_INFO_3 *info3)
972 {
973         prs_struct qbuf, rbuf;
974         NET_Q_SAM_LOGON q;
975         NET_R_SAM_LOGON r;
976         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
977         NET_ID_INFO_CTR ctr;
978         int validation_level = 3;
979         const char *workstation_name_slash;
980         const char *server_name_slash;
981         uint8 zeros[16];
982         DOM_CRED clnt_creds;
983         DOM_CRED ret_creds;
984         int i;
985
986         ZERO_STRUCT(zeros);
987         ZERO_STRUCT(q);
988         ZERO_STRUCT(r);
989         ZERO_STRUCT(ret_creds);
990
991         creds_client_step(cli->dc, &clnt_creds);
992
993         if (server[0] != '\\' && server[1] != '\\') {
994                 server_name_slash = talloc_asprintf(mem_ctx, "\\\\%s", server);
995         } else {
996                 server_name_slash = server;
997         }
998
999         if (workstation[0] != '\\' && workstation[1] != '\\') {
1000                 workstation_name_slash = talloc_asprintf(mem_ctx, "\\\\%s", workstation);
1001         } else {
1002                 workstation_name_slash = workstation;
1003         }
1004
1005         if (!workstation_name_slash || !server_name_slash) {
1006                 DEBUG(0, ("talloc_asprintf failed!\n"));
1007                 return NT_STATUS_NO_MEMORY;
1008         }
1009
1010         /* Initialise input parameters */
1011
1012         q.validation_level = validation_level;
1013
1014         ctr.switch_value = NET_LOGON_TYPE;
1015
1016         init_id_info2(&ctr.auth.id2, domain,
1017                       logon_parameters, /* param_ctrl */
1018                       0xdead, 0xbeef, /* LUID? */
1019                       username, workstation_name_slash, (const uchar*)chal,
1020                       lm_response.data, lm_response.length, nt_response.data, nt_response.length);
1021  
1022         init_sam_info(&q.sam_id, server_name_slash, global_myname(),
1023                       &clnt_creds, &ret_creds, NET_LOGON_TYPE,
1024                       &ctr);
1025
1026         r.user = info3;
1027
1028         /* Marshall data and send request */
1029
1030         CLI_DO_RPC(cli, mem_ctx, PI_NETLOGON, NET_SAMLOGON,
1031                 q, r,
1032                 qbuf, rbuf,
1033                 net_io_q_sam_logon,
1034                 net_io_r_sam_logon,
1035                 NT_STATUS_UNSUCCESSFUL);
1036
1037         if (memcmp(zeros, info3->user_sess_key, 16) != 0) {
1038                 SamOEMhash(info3->user_sess_key, cli->dc->sess_key, 16);
1039         } else {
1040                 memset(info3->user_sess_key, '\0', 16);
1041         }
1042
1043         if (memcmp(zeros, info3->lm_sess_key, 8) != 0) {
1044                 SamOEMhash(info3->lm_sess_key, cli->dc->sess_key, 8);
1045         } else {
1046                 memset(info3->lm_sess_key, '\0', 8);
1047         }
1048
1049         for (i=0; i < 7; i++) {
1050                 memset(&info3->unknown[i], '\0', 4);
1051         }
1052
1053         /* Return results */
1054
1055         result = r.status;
1056
1057         if (r.buffer_creds) {
1058                 /* Check returned credentials if present. */
1059                 if (!creds_client_check(cli->dc, &r.srv_creds.challenge)) {
1060                         DEBUG(0,("rpccli_netlogon_sam_network_logon: credentials chain check failed\n"));
1061                         return NT_STATUS_ACCESS_DENIED;
1062                 }
1063         }
1064
1065         return result;
1066 }
1067
1068 NTSTATUS rpccli_netlogon_sam_network_logon_ex(struct rpc_pipe_client *cli,
1069                                               TALLOC_CTX *mem_ctx,
1070                                               uint32 logon_parameters,
1071                                               const char *server,
1072                                               const char *username,
1073                                               const char *domain,
1074                                               const char *workstation, 
1075                                               const uint8 chal[8], 
1076                                               DATA_BLOB lm_response,
1077                                               DATA_BLOB nt_response,
1078                                               NET_USER_INFO_3 *info3)
1079 {
1080         prs_struct qbuf, rbuf;
1081         NET_Q_SAM_LOGON_EX q;
1082         NET_R_SAM_LOGON_EX r;
1083         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
1084         NET_ID_INFO_CTR ctr;
1085         int validation_level = 3;
1086         const char *workstation_name_slash;
1087         const char *server_name_slash;
1088         uint8 zeros[16];
1089         int i;
1090
1091         ZERO_STRUCT(zeros);
1092         ZERO_STRUCT(q);
1093         ZERO_STRUCT(r);
1094
1095         if (server[0] != '\\' && server[1] != '\\') {
1096                 server_name_slash = talloc_asprintf(mem_ctx, "\\\\%s", server);
1097         } else {
1098                 server_name_slash = server;
1099         }
1100
1101         if (workstation[0] != '\\' && workstation[1] != '\\') {
1102                 workstation_name_slash = talloc_asprintf(mem_ctx, "\\\\%s", workstation);
1103         } else {
1104                 workstation_name_slash = workstation;
1105         }
1106
1107         if (!workstation_name_slash || !server_name_slash) {
1108                 DEBUG(0, ("talloc_asprintf failed!\n"));
1109                 return NT_STATUS_NO_MEMORY;
1110         }
1111
1112         /* Initialise input parameters */
1113
1114         q.validation_level = validation_level;
1115
1116         ctr.switch_value = NET_LOGON_TYPE;
1117
1118         init_id_info2(&ctr.auth.id2, domain,
1119                       logon_parameters, /* param_ctrl */
1120                       0xdead, 0xbeef, /* LUID? */
1121                       username, workstation_name_slash, (const uchar*)chal,
1122                       lm_response.data, lm_response.length, nt_response.data,
1123                       nt_response.length);
1124  
1125         init_sam_info_ex(&q.sam_id, server_name_slash, global_myname(),
1126                          NET_LOGON_TYPE, &ctr);
1127
1128         r.user = info3;
1129
1130         /* Marshall data and send request */
1131
1132         CLI_DO_RPC(cli, mem_ctx, PI_NETLOGON, NET_SAMLOGON_EX,
1133                    q, r, qbuf, rbuf,
1134                    net_io_q_sam_logon_ex,
1135                    net_io_r_sam_logon_ex,
1136                    NT_STATUS_UNSUCCESSFUL);
1137
1138         if (memcmp(zeros, info3->user_sess_key, 16) != 0) {
1139                 SamOEMhash(info3->user_sess_key, cli->dc->sess_key, 16);
1140         } else {
1141                 memset(info3->user_sess_key, '\0', 16);
1142         }
1143
1144         if (memcmp(zeros, info3->lm_sess_key, 8) != 0) {
1145                 SamOEMhash(info3->lm_sess_key, cli->dc->sess_key, 8);
1146         } else {
1147                 memset(info3->lm_sess_key, '\0', 8);
1148         }
1149
1150         for (i=0; i < 7; i++) {
1151                 memset(&info3->unknown[i], '\0', 4);
1152         }
1153
1154         /* Return results */
1155
1156         result = r.status;
1157
1158         return result;
1159 }
1160
1161 /***************************************************************************
1162 LSA Server Password Set.
1163 ****************************************************************************/
1164
1165 NTSTATUS rpccli_net_srv_pwset(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, 
1166                            const char *machine_name, const uint8 hashed_mach_pwd[16])
1167 {
1168         prs_struct rbuf;
1169         prs_struct qbuf; 
1170         DOM_CRED clnt_creds;
1171         NET_Q_SRV_PWSET q;
1172         NET_R_SRV_PWSET r;
1173         uint16 sec_chan_type = 2;
1174         NTSTATUS result;
1175
1176         creds_client_step(cli->dc, &clnt_creds);
1177         
1178         DEBUG(4,("cli_net_srv_pwset: srv:%s acct:%s sc: %d mc: %s\n",
1179                  cli->dc->remote_machine, cli->dc->mach_acct, sec_chan_type, machine_name));
1180         
1181         /* store the parameters */
1182         init_q_srv_pwset(&q, cli->dc->remote_machine, (const char *)cli->dc->sess_key,
1183                          cli->dc->mach_acct, sec_chan_type, machine_name, 
1184                          &clnt_creds, hashed_mach_pwd);
1185         
1186         CLI_DO_RPC(cli, mem_ctx, PI_NETLOGON, NET_SRVPWSET,
1187                 q, r,
1188                 qbuf, rbuf,
1189                 net_io_q_srv_pwset,
1190                 net_io_r_srv_pwset,
1191                 NT_STATUS_UNSUCCESSFUL);
1192
1193         result = r.status;
1194
1195         if (!NT_STATUS_IS_OK(result)) {
1196                 /* report error code */
1197                 DEBUG(0,("cli_net_srv_pwset: %s\n", nt_errstr(result)));
1198         }
1199
1200         /* Always check returned credentials. */
1201         if (!creds_client_check(cli->dc, &r.srv_cred.challenge)) {
1202                 DEBUG(0,("rpccli_net_srv_pwset: credentials chain check failed\n"));
1203                 return NT_STATUS_ACCESS_DENIED;
1204         }
1205
1206         return result;
1207 }