r20970: Allow to define workstation for samlogon in rpcclient (for testing).
[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                                    const char *workstation,
737                                    int logon_type)
738 {
739         prs_struct qbuf, rbuf;
740         NET_Q_SAM_LOGON q;
741         NET_R_SAM_LOGON r;
742         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
743         DOM_CRED clnt_creds;
744         DOM_CRED ret_creds;
745         NET_ID_INFO_CTR ctr;
746         NET_USER_INFO_3 user;
747         int validation_level = 3;
748         fstring clnt_name_slash;
749
750         ZERO_STRUCT(q);
751         ZERO_STRUCT(r);
752         ZERO_STRUCT(ret_creds);
753
754         if (workstation) {
755                 fstr_sprintf( clnt_name_slash, "\\\\%s", workstation );
756         } else {
757                 fstr_sprintf( clnt_name_slash, "\\\\%s", global_myname() );
758         }
759
760         /* Initialise input parameters */
761
762         creds_client_step(cli->dc, &clnt_creds);
763
764         q.validation_level = validation_level;
765
766         ctr.switch_value = logon_type;
767
768         switch (logon_type) {
769         case INTERACTIVE_LOGON_TYPE: {
770                 unsigned char lm_owf_user_pwd[16], nt_owf_user_pwd[16];
771
772                 nt_lm_owf_gen(password, nt_owf_user_pwd, lm_owf_user_pwd);
773
774                 init_id_info1(&ctr.auth.id1, domain, 
775                               logon_parameters, /* param_ctrl */
776                               0xdead, 0xbeef, /* LUID? */
777                               username, clnt_name_slash,
778                               (const char *)cli->dc->sess_key, lm_owf_user_pwd,
779                               nt_owf_user_pwd);
780
781                 break;
782         }
783         case NET_LOGON_TYPE: {
784                 uint8 chal[8];
785                 unsigned char local_lm_response[24];
786                 unsigned char local_nt_response[24];
787
788                 generate_random_buffer(chal, 8);
789
790                 SMBencrypt(password, chal, local_lm_response);
791                 SMBNTencrypt(password, chal, local_nt_response);
792
793                 init_id_info2(&ctr.auth.id2, domain, 
794                               logon_parameters, /* param_ctrl */
795                               0xdead, 0xbeef, /* LUID? */
796                               username, clnt_name_slash, chal,
797                               local_lm_response, 24, local_nt_response, 24);
798                 break;
799         }
800         default:
801                 DEBUG(0, ("switch value %d not supported\n", 
802                           ctr.switch_value));
803                 return NT_STATUS_INVALID_INFO_CLASS;
804         }
805
806         r.user = &user;
807
808         init_sam_info(&q.sam_id, cli->dc->remote_machine, global_myname(),
809                       &clnt_creds, &ret_creds, logon_type,
810                       &ctr);
811
812         /* Marshall data and send request */
813
814         CLI_DO_RPC(cli, mem_ctx, PI_NETLOGON, NET_SAMLOGON,
815                 q, r,
816                 qbuf, rbuf,
817                 net_io_q_sam_logon,
818                 net_io_r_sam_logon,
819                 NT_STATUS_UNSUCCESSFUL);
820
821         /* Return results */
822
823         result = r.status;
824
825         if (r.buffer_creds) {
826                 /* Check returned credentials if present. */
827                 if (!creds_client_check(cli->dc, &r.srv_creds.challenge)) {
828                         DEBUG(0,("rpccli_netlogon_sam_logon: credentials chain check failed\n"));
829                         return NT_STATUS_ACCESS_DENIED;
830                 }
831         }
832
833         return result;
834 }
835
836
837 /** 
838  * Logon domain user with an 'network' SAM logon 
839  *
840  * @param info3 Pointer to a NET_USER_INFO_3 already allocated by the caller.
841  **/
842
843 NTSTATUS rpccli_netlogon_sam_network_logon(struct rpc_pipe_client *cli,
844                                            TALLOC_CTX *mem_ctx,
845                                            uint32 logon_parameters,
846                                            const char *server,
847                                            const char *username,
848                                            const char *domain,
849                                            const char *workstation, 
850                                            const uint8 chal[8], 
851                                            DATA_BLOB lm_response,
852                                            DATA_BLOB nt_response,
853                                            NET_USER_INFO_3 *info3)
854 {
855         prs_struct qbuf, rbuf;
856         NET_Q_SAM_LOGON q;
857         NET_R_SAM_LOGON r;
858         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
859         NET_ID_INFO_CTR ctr;
860         int validation_level = 3;
861         const char *workstation_name_slash;
862         const char *server_name_slash;
863         static uint8 zeros[16];
864         DOM_CRED clnt_creds;
865         DOM_CRED ret_creds;
866         int i;
867         
868         ZERO_STRUCT(q);
869         ZERO_STRUCT(r);
870         ZERO_STRUCT(ret_creds);
871
872         creds_client_step(cli->dc, &clnt_creds);
873
874         if (server[0] != '\\' && server[1] != '\\') {
875                 server_name_slash = talloc_asprintf(mem_ctx, "\\\\%s", server);
876         } else {
877                 server_name_slash = server;
878         }
879
880         if (workstation[0] != '\\' && workstation[1] != '\\') {
881                 workstation_name_slash = talloc_asprintf(mem_ctx, "\\\\%s", workstation);
882         } else {
883                 workstation_name_slash = workstation;
884         }
885
886         if (!workstation_name_slash || !server_name_slash) {
887                 DEBUG(0, ("talloc_asprintf failed!\n"));
888                 return NT_STATUS_NO_MEMORY;
889         }
890
891         /* Initialise input parameters */
892
893         q.validation_level = validation_level;
894
895         ctr.switch_value = NET_LOGON_TYPE;
896
897         init_id_info2(&ctr.auth.id2, domain,
898                       logon_parameters, /* param_ctrl */
899                       0xdead, 0xbeef, /* LUID? */
900                       username, workstation_name_slash, (const uchar*)chal,
901                       lm_response.data, lm_response.length, nt_response.data, nt_response.length);
902  
903         init_sam_info(&q.sam_id, server_name_slash, global_myname(),
904                       &clnt_creds, &ret_creds, NET_LOGON_TYPE,
905                       &ctr);
906
907         r.user = info3;
908
909         /* Marshall data and send request */
910
911         CLI_DO_RPC(cli, mem_ctx, PI_NETLOGON, NET_SAMLOGON,
912                 q, r,
913                 qbuf, rbuf,
914                 net_io_q_sam_logon,
915                 net_io_r_sam_logon,
916                 NT_STATUS_UNSUCCESSFUL);
917
918         if (memcmp(zeros, info3->user_sess_key, 16) != 0) {
919                 SamOEMhash(info3->user_sess_key, cli->dc->sess_key, 16);
920         } else {
921                 memset(info3->user_sess_key, '\0', 16);
922         }
923
924         if (memcmp(zeros, info3->lm_sess_key, 8) != 0) {
925                 SamOEMhash(info3->lm_sess_key, cli->dc->sess_key, 8);
926         } else {
927                 memset(info3->lm_sess_key, '\0', 8);
928         }
929
930         for (i=0; i < 7; i++) {
931                 memset(&info3->unknown[i], '\0', 4);
932         }
933
934         /* Return results */
935
936         result = r.status;
937
938         if (r.buffer_creds) {
939                 /* Check returned credentials if present. */
940                 if (!creds_client_check(cli->dc, &r.srv_creds.challenge)) {
941                         DEBUG(0,("rpccli_netlogon_sam_network_logon: credentials chain check failed\n"));
942                         return NT_STATUS_ACCESS_DENIED;
943                 }
944         }
945
946         return result;
947 }
948
949 /***************************************************************************
950 LSA Server Password Set.
951 ****************************************************************************/
952
953 NTSTATUS rpccli_net_srv_pwset(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, 
954                            const char *machine_name, const uint8 hashed_mach_pwd[16])
955 {
956         prs_struct rbuf;
957         prs_struct qbuf; 
958         DOM_CRED clnt_creds;
959         NET_Q_SRV_PWSET q;
960         NET_R_SRV_PWSET r;
961         uint16 sec_chan_type = 2;
962         NTSTATUS result;
963
964         creds_client_step(cli->dc, &clnt_creds);
965         
966         DEBUG(4,("cli_net_srv_pwset: srv:%s acct:%s sc: %d mc: %s\n",
967                  cli->dc->remote_machine, cli->dc->mach_acct, sec_chan_type, machine_name));
968         
969         /* store the parameters */
970         init_q_srv_pwset(&q, cli->dc->remote_machine, (const char *)cli->dc->sess_key,
971                          cli->dc->mach_acct, sec_chan_type, machine_name, 
972                          &clnt_creds, hashed_mach_pwd);
973         
974         CLI_DO_RPC(cli, mem_ctx, PI_NETLOGON, NET_SRVPWSET,
975                 q, r,
976                 qbuf, rbuf,
977                 net_io_q_srv_pwset,
978                 net_io_r_srv_pwset,
979                 NT_STATUS_UNSUCCESSFUL);
980
981         result = r.status;
982
983         if (!NT_STATUS_IS_OK(result)) {
984                 /* report error code */
985                 DEBUG(0,("cli_net_srv_pwset: %s\n", nt_errstr(result)));
986         }
987
988         /* Always check returned credentials. */
989         if (!creds_client_check(cli->dc, &r.srv_cred.challenge)) {
990                 DEBUG(0,("rpccli_net_srv_pwset: credentials chain check failed\n"));
991                 return NT_STATUS_ACCESS_DENIED;
992         }
993
994         return result;
995 }