r19161: Add NET_GETANYDCNAME (getdcname only gives the PDC while getanydcname
[ddiss/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 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 /* GetDCName */
384
385 WERROR rpccli_netlogon_getdcname(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_GETDCNAME q;
391         NET_R_GETDCNAME 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_getdcname(&q, mydcname_slash, domainname);
402
403         /* Marshall data and send request */
404
405         CLI_DO_RPC_WERR(cli, mem_ctx, PI_NETLOGON, NET_GETDCNAME,
406                 q, r,
407                 qbuf, rbuf,
408                 net_io_q_getdcname,
409                 net_io_r_getdcname,
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 /* GetAnyDCName */
422
423 WERROR rpccli_netlogon_getanydcname(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_GETANYDCNAME q;
429         NET_R_GETANYDCNAME 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_getanydcname(&q, mydcname_slash, domainname);
440
441         /* Marshall data and send request */
442
443         CLI_DO_RPC_WERR(cli, mem_ctx, PI_NETLOGON, NET_GETANYDCNAME,
444                 q, r,
445                 qbuf, rbuf,
446                 net_io_q_getanydcname,
447                 net_io_r_getanydcname,
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 /* Dsr_GetDCName */
460
461 WERROR rpccli_netlogon_dsr_getdcname(struct rpc_pipe_client *cli,
462                                      TALLOC_CTX *mem_ctx,
463                                      const char *server_name,
464                                      const char *domain_name,
465                                      struct GUID *domain_guid,
466                                      struct GUID *site_guid,
467                                      uint32_t flags,
468                                      char **dc_unc, char **dc_address,
469                                      int32 *dc_address_type,
470                                      struct GUID *domain_guid_out,
471                                      char **domain_name_out,
472                                      char **forest_name,
473                                      uint32 *dc_flags,
474                                      char **dc_site_name,
475                                      char **client_site_name)
476 {
477         prs_struct qbuf, rbuf;
478         NET_Q_DSR_GETDCNAME q;
479         NET_R_DSR_GETDCNAME r;
480         char *tmp_str;
481
482         ZERO_STRUCT(q);
483         ZERO_STRUCT(r);
484
485         /* Initialize input parameters */
486
487         tmp_str = talloc_asprintf(mem_ctx, "\\\\%s", server_name);
488         if (tmp_str == NULL) {
489                 return WERR_NOMEM;
490         }
491
492         init_net_q_dsr_getdcname(&q, tmp_str, domain_name, domain_guid,
493                                  site_guid, flags);
494
495         /* Marshall data and send request */
496
497         CLI_DO_RPC_WERR(cli, mem_ctx, PI_NETLOGON, NET_DSR_GETDCNAME,
498                         q, r,
499                         qbuf, rbuf,
500                         net_io_q_dsr_getdcname,
501                         net_io_r_dsr_getdcname,
502                         WERR_GENERAL_FAILURE);
503
504         if (!W_ERROR_IS_OK(r.result)) {
505                 return r.result;
506         }
507
508         if (dc_unc != NULL) {
509                 char *tmp;
510                 tmp = rpcstr_pull_unistr2_talloc(mem_ctx, &r.uni_dc_unc);
511                 if (tmp == NULL) {
512                         return WERR_GENERAL_FAILURE;
513                 }
514                 if (*tmp == '\\') tmp += 1;
515                 if (*tmp == '\\') tmp += 1;
516
517                 /* We have to talloc_strdup, otherwise a talloc_steal would
518                    fail */
519                 *dc_unc = talloc_strdup(mem_ctx, tmp);
520                 if (*dc_unc == NULL) {
521                         return WERR_NOMEM;
522                 }
523         }
524
525         if (dc_address != NULL) {
526                 char *tmp;
527                 tmp = rpcstr_pull_unistr2_talloc(mem_ctx, &r.uni_dc_address);
528                 if (tmp == NULL) {
529                         return WERR_GENERAL_FAILURE;
530                 }
531                 if (*tmp == '\\') tmp += 1;
532                 if (*tmp == '\\') tmp += 1;
533
534                 /* We have to talloc_strdup, otherwise a talloc_steal would
535                    fail */
536                 *dc_address = talloc_strdup(mem_ctx, tmp);
537                 if (*dc_address == NULL) {
538                         return WERR_NOMEM;
539                 }
540         }
541
542         if (dc_address_type != NULL) {
543                 *dc_address_type = r.dc_address_type;
544         }
545
546         if (domain_guid_out != NULL) {
547                 *domain_guid_out = r.domain_guid;
548         }
549
550         if ((domain_name_out != NULL) &&
551             ((*domain_name_out = rpcstr_pull_unistr2_talloc(
552                     mem_ctx, &r.uni_domain_name)) == NULL)) {
553                 return WERR_GENERAL_FAILURE;
554         }
555
556         if ((forest_name != NULL) &&
557             ((*forest_name = rpcstr_pull_unistr2_talloc(
558                       mem_ctx, &r.uni_forest_name)) == NULL)) {
559                 return WERR_GENERAL_FAILURE;
560         }
561
562         if (dc_flags != NULL) {
563                 *dc_flags = r.dc_flags;
564         }
565
566         if ((dc_site_name != NULL) &&
567             ((*dc_site_name = rpcstr_pull_unistr2_talloc(
568                       mem_ctx, &r.uni_dc_site_name)) == NULL)) {
569                 return WERR_GENERAL_FAILURE;
570         }
571
572         if ((client_site_name != NULL) &&
573             ((*client_site_name = rpcstr_pull_unistr2_talloc(
574                       mem_ctx, &r.uni_client_site_name)) == NULL)) {
575                 return WERR_GENERAL_FAILURE;
576         }
577
578         return WERR_OK;
579 }
580
581 /* Dsr_GetSiteName */
582
583 WERROR rpccli_netlogon_dsr_getsitename(struct rpc_pipe_client *cli,
584                                        TALLOC_CTX *mem_ctx,
585                                        const char *computer_name,
586                                        char **site_name)
587 {
588         prs_struct qbuf, rbuf;
589         NET_Q_DSR_GETSITENAME q;
590         NET_R_DSR_GETSITENAME r;
591
592         ZERO_STRUCT(q);
593         ZERO_STRUCT(r);
594
595         /* Initialize input parameters */
596
597         init_net_q_dsr_getsitename(&q, computer_name);
598
599         /* Marshall data and send request */
600
601         CLI_DO_RPC_WERR(cli, mem_ctx, PI_NETLOGON, NET_DSR_GETSITENAME,
602                         q, r,
603                         qbuf, rbuf,
604                         net_io_q_dsr_getsitename,
605                         net_io_r_dsr_getsitename,
606                         WERR_GENERAL_FAILURE);
607
608         if (!W_ERROR_IS_OK(r.result)) {
609                 return r.result;
610         }
611
612         if ((site_name != NULL) &&
613             ((*site_name = rpcstr_pull_unistr2_talloc(
614                       mem_ctx, &r.uni_site_name)) == NULL)) {
615                 return WERR_GENERAL_FAILURE;
616         }
617
618         return WERR_OK;
619 }
620
621
622
623 /* Sam synchronisation */
624
625 NTSTATUS rpccli_netlogon_sam_sync(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
626                                uint32 database_id, uint32 next_rid, uint32 *num_deltas,
627                                SAM_DELTA_HDR **hdr_deltas, 
628                                SAM_DELTA_CTR **deltas)
629 {
630         prs_struct qbuf, rbuf;
631         NET_Q_SAM_SYNC q;
632         NET_R_SAM_SYNC r;
633         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
634         DOM_CRED clnt_creds;
635         DOM_CRED ret_creds;
636
637         ZERO_STRUCT(q);
638         ZERO_STRUCT(r);
639
640         ZERO_STRUCT(ret_creds);
641
642         /* Initialise input parameters */
643
644         creds_client_step(cli->dc, &clnt_creds);
645
646         init_net_q_sam_sync(&q, cli->dc->remote_machine, global_myname(),
647                             &clnt_creds, &ret_creds, database_id, next_rid);
648
649         /* Marshall data and send request */
650
651         CLI_DO_RPC_COPY_SESS_KEY(cli, mem_ctx, PI_NETLOGON, NET_SAM_SYNC,
652                 q, r,
653                 qbuf, rbuf,
654                 net_io_q_sam_sync,
655                 net_io_r_sam_sync,
656                 NT_STATUS_UNSUCCESSFUL);
657
658         /* Return results */
659
660         result = r.status;
661         *num_deltas = r.num_deltas2;
662         *hdr_deltas = r.hdr_deltas;
663         *deltas = r.deltas;
664
665         if (!NT_STATUS_IS_ERR(result)) {
666                 /* Check returned credentials. */
667                 if (!creds_client_check(cli->dc, &r.srv_creds.challenge)) {
668                         DEBUG(0,("cli_netlogon_sam_sync: credentials chain check failed\n"));
669                         return NT_STATUS_ACCESS_DENIED;
670                 }
671         }
672
673         return result;
674 }
675
676 /* Sam synchronisation */
677
678 NTSTATUS rpccli_netlogon_sam_deltas(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
679                                  uint32 database_id, uint64 seqnum,
680                                  uint32 *num_deltas, 
681                                  SAM_DELTA_HDR **hdr_deltas, 
682                                  SAM_DELTA_CTR **deltas)
683 {
684         prs_struct qbuf, rbuf;
685         NET_Q_SAM_DELTAS q;
686         NET_R_SAM_DELTAS r;
687         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
688         DOM_CRED clnt_creds;
689
690         ZERO_STRUCT(q);
691         ZERO_STRUCT(r);
692
693         /* Initialise input parameters */
694
695         creds_client_step(cli->dc, &clnt_creds);
696
697         init_net_q_sam_deltas(&q, cli->dc->remote_machine,
698                               global_myname(), &clnt_creds, 
699                               database_id, seqnum);
700
701         /* Marshall data and send request */
702
703         CLI_DO_RPC(cli, mem_ctx, PI_NETLOGON, NET_SAM_DELTAS,
704                 q, r,
705                 qbuf, rbuf,
706                 net_io_q_sam_deltas,
707                 net_io_r_sam_deltas,
708                 NT_STATUS_UNSUCCESSFUL);
709
710         /* Return results */
711
712         result = r.status;
713         *num_deltas = r.num_deltas2;
714         *hdr_deltas = r.hdr_deltas;
715         *deltas = r.deltas;
716
717         if (!NT_STATUS_IS_ERR(result)) {
718                 /* Check returned credentials. */
719                 if (!creds_client_check(cli->dc, &r.srv_creds.challenge)) {
720                         DEBUG(0,("cli_netlogon_sam_sync: credentials chain check failed\n"));
721                         return NT_STATUS_ACCESS_DENIED;
722                 }
723         }
724
725         return result;
726 }
727
728 /* Logon domain user */
729
730 NTSTATUS rpccli_netlogon_sam_logon(struct rpc_pipe_client *cli,
731                                    TALLOC_CTX *mem_ctx,
732                                    uint32 logon_parameters,
733                                    const char *domain,
734                                    const char *username,
735                                    const char *password,
736                                    int logon_type)
737 {
738         prs_struct qbuf, rbuf;
739         NET_Q_SAM_LOGON q;
740         NET_R_SAM_LOGON r;
741         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
742         DOM_CRED clnt_creds;
743         DOM_CRED ret_creds;
744         NET_ID_INFO_CTR ctr;
745         NET_USER_INFO_3 user;
746         int validation_level = 3;
747         fstring clnt_name_slash;
748
749         ZERO_STRUCT(q);
750         ZERO_STRUCT(r);
751         ZERO_STRUCT(ret_creds);
752
753         fstr_sprintf( clnt_name_slash, "\\\\%s", global_myname() );
754
755         /* Initialise input parameters */
756
757         creds_client_step(cli->dc, &clnt_creds);
758
759         q.validation_level = validation_level;
760
761         ctr.switch_value = logon_type;
762
763         switch (logon_type) {
764         case INTERACTIVE_LOGON_TYPE: {
765                 unsigned char lm_owf_user_pwd[16], nt_owf_user_pwd[16];
766
767                 nt_lm_owf_gen(password, nt_owf_user_pwd, lm_owf_user_pwd);
768
769                 init_id_info1(&ctr.auth.id1, domain, 
770                               logon_parameters, /* param_ctrl */
771                               0xdead, 0xbeef, /* LUID? */
772                               username, clnt_name_slash,
773                               (const char *)cli->dc->sess_key, lm_owf_user_pwd,
774                               nt_owf_user_pwd);
775
776                 break;
777         }
778         case NET_LOGON_TYPE: {
779                 uint8 chal[8];
780                 unsigned char local_lm_response[24];
781                 unsigned char local_nt_response[24];
782
783                 generate_random_buffer(chal, 8);
784
785                 SMBencrypt(password, chal, local_lm_response);
786                 SMBNTencrypt(password, chal, local_nt_response);
787
788                 init_id_info2(&ctr.auth.id2, domain, 
789                               logon_parameters, /* param_ctrl */
790                               0xdead, 0xbeef, /* LUID? */
791                               username, clnt_name_slash, chal,
792                               local_lm_response, 24, local_nt_response, 24);
793                 break;
794         }
795         default:
796                 DEBUG(0, ("switch value %d not supported\n", 
797                           ctr.switch_value));
798                 return NT_STATUS_INVALID_INFO_CLASS;
799         }
800
801         r.user = &user;
802
803         init_sam_info(&q.sam_id, cli->dc->remote_machine, global_myname(),
804                       &clnt_creds, &ret_creds, logon_type,
805                       &ctr);
806
807         /* Marshall data and send request */
808
809         CLI_DO_RPC(cli, mem_ctx, PI_NETLOGON, NET_SAMLOGON,
810                 q, r,
811                 qbuf, rbuf,
812                 net_io_q_sam_logon,
813                 net_io_r_sam_logon,
814                 NT_STATUS_UNSUCCESSFUL);
815
816         /* Return results */
817
818         result = r.status;
819
820         if (r.buffer_creds) {
821                 /* Check returned credentials if present. */
822                 if (!creds_client_check(cli->dc, &r.srv_creds.challenge)) {
823                         DEBUG(0,("rpccli_netlogon_sam_logon: credentials chain check failed\n"));
824                         return NT_STATUS_ACCESS_DENIED;
825                 }
826         }
827
828         return result;
829 }
830
831
832 /** 
833  * Logon domain user with an 'network' SAM logon 
834  *
835  * @param info3 Pointer to a NET_USER_INFO_3 already allocated by the caller.
836  **/
837
838 NTSTATUS rpccli_netlogon_sam_network_logon(struct rpc_pipe_client *cli,
839                                            TALLOC_CTX *mem_ctx,
840                                            uint32 logon_parameters,
841                                            const char *server,
842                                            const char *username,
843                                            const char *domain,
844                                            const char *workstation, 
845                                            const uint8 chal[8], 
846                                            DATA_BLOB lm_response,
847                                            DATA_BLOB nt_response,
848                                            NET_USER_INFO_3 *info3)
849 {
850         prs_struct qbuf, rbuf;
851         NET_Q_SAM_LOGON q;
852         NET_R_SAM_LOGON r;
853         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
854         NET_ID_INFO_CTR ctr;
855         int validation_level = 3;
856         const char *workstation_name_slash;
857         const char *server_name_slash;
858         static uint8 zeros[16];
859         DOM_CRED clnt_creds;
860         DOM_CRED ret_creds;
861         int i;
862         
863         ZERO_STRUCT(q);
864         ZERO_STRUCT(r);
865         ZERO_STRUCT(ret_creds);
866
867         creds_client_step(cli->dc, &clnt_creds);
868
869         if (server[0] != '\\' && server[1] != '\\') {
870                 server_name_slash = talloc_asprintf(mem_ctx, "\\\\%s", server);
871         } else {
872                 server_name_slash = server;
873         }
874
875         if (workstation[0] != '\\' && workstation[1] != '\\') {
876                 workstation_name_slash = talloc_asprintf(mem_ctx, "\\\\%s", workstation);
877         } else {
878                 workstation_name_slash = workstation;
879         }
880
881         if (!workstation_name_slash || !server_name_slash) {
882                 DEBUG(0, ("talloc_asprintf failed!\n"));
883                 return NT_STATUS_NO_MEMORY;
884         }
885
886         /* Initialise input parameters */
887
888         q.validation_level = validation_level;
889
890         ctr.switch_value = NET_LOGON_TYPE;
891
892         init_id_info2(&ctr.auth.id2, domain,
893                       logon_parameters, /* param_ctrl */
894                       0xdead, 0xbeef, /* LUID? */
895                       username, workstation_name_slash, (const uchar*)chal,
896                       lm_response.data, lm_response.length, nt_response.data, nt_response.length);
897  
898         init_sam_info(&q.sam_id, server_name_slash, global_myname(),
899                       &clnt_creds, &ret_creds, NET_LOGON_TYPE,
900                       &ctr);
901
902         r.user = info3;
903
904         /* Marshall data and send request */
905
906         CLI_DO_RPC(cli, mem_ctx, PI_NETLOGON, NET_SAMLOGON,
907                 q, r,
908                 qbuf, rbuf,
909                 net_io_q_sam_logon,
910                 net_io_r_sam_logon,
911                 NT_STATUS_UNSUCCESSFUL);
912
913         if (memcmp(zeros, info3->user_sess_key, 16) != 0) {
914                 SamOEMhash(info3->user_sess_key, cli->dc->sess_key, 16);
915         } else {
916                 memset(info3->user_sess_key, '\0', 16);
917         }
918
919         if (memcmp(zeros, info3->lm_sess_key, 8) != 0) {
920                 SamOEMhash(info3->lm_sess_key, cli->dc->sess_key, 8);
921         } else {
922                 memset(info3->lm_sess_key, '\0', 8);
923         }
924
925         for (i=0; i < 7; i++) {
926                 memset(&info3->unknown[i], '\0', 4);
927         }
928
929         /* Return results */
930
931         result = r.status;
932
933         if (r.buffer_creds) {
934                 /* Check returned credentials if present. */
935                 if (!creds_client_check(cli->dc, &r.srv_creds.challenge)) {
936                         DEBUG(0,("rpccli_netlogon_sam_network_logon: credentials chain check failed\n"));
937                         return NT_STATUS_ACCESS_DENIED;
938                 }
939         }
940
941         return result;
942 }
943
944 /***************************************************************************
945 LSA Server Password Set.
946 ****************************************************************************/
947
948 NTSTATUS rpccli_net_srv_pwset(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, 
949                            const char *machine_name, const uint8 hashed_mach_pwd[16])
950 {
951         prs_struct rbuf;
952         prs_struct qbuf; 
953         DOM_CRED clnt_creds;
954         NET_Q_SRV_PWSET q;
955         NET_R_SRV_PWSET r;
956         uint16 sec_chan_type = 2;
957         NTSTATUS result;
958
959         creds_client_step(cli->dc, &clnt_creds);
960         
961         DEBUG(4,("cli_net_srv_pwset: srv:%s acct:%s sc: %d mc: %s\n",
962                  cli->dc->remote_machine, cli->dc->mach_acct, sec_chan_type, machine_name));
963         
964         /* store the parameters */
965         init_q_srv_pwset(&q, cli->dc->remote_machine, (const char *)cli->dc->sess_key,
966                          cli->dc->mach_acct, sec_chan_type, machine_name, 
967                          &clnt_creds, hashed_mach_pwd);
968         
969         CLI_DO_RPC(cli, mem_ctx, PI_NETLOGON, NET_SRVPWSET,
970                 q, r,
971                 qbuf, rbuf,
972                 net_io_q_srv_pwset,
973                 net_io_r_srv_pwset,
974                 NT_STATUS_UNSUCCESSFUL);
975
976         result = r.status;
977
978         if (!NT_STATUS_IS_OK(result)) {
979                 /* report error code */
980                 DEBUG(0,("cli_net_srv_pwset: %s\n", nt_errstr(result)));
981         }
982
983         /* Always check returned credentials. */
984         if (!creds_client_check(cli->dc, &r.srv_cred.challenge)) {
985                 DEBUG(0,("rpccli_net_srv_pwset: credentials chain check failed\n"));
986                 return NT_STATUS_ACCESS_DENIED;
987         }
988
989         return result;
990 }