Merge branch 'ctdb-merge' into dmapi-integration
[gd/samba/.git] / source / rpc_client / cli_netlogon.c
1 /* 
2    Unix SMB/CIFS implementation.
3    NT Domain Authentication SMB / MSRPC client
4    Copyright (C) Andrew Tridgell 1992-2000
5    Copyright (C) Jeremy Allison                    1998.
6    Largely re-written by Jeremy Allison (C)        2005.
7
8    This program is free software; you can redistribute it and/or modify
9    it under the terms of the GNU General Public License as published by
10    the Free Software Foundation; either version 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_GetSiteName */
597
598 WERROR rpccli_netlogon_dsr_getsitename(struct rpc_pipe_client *cli,
599                                        TALLOC_CTX *mem_ctx,
600                                        const char *computer_name,
601                                        char **site_name)
602 {
603         prs_struct qbuf, rbuf;
604         NET_Q_DSR_GETSITENAME q;
605         NET_R_DSR_GETSITENAME r;
606
607         ZERO_STRUCT(q);
608         ZERO_STRUCT(r);
609
610         /* Initialize input parameters */
611
612         init_net_q_dsr_getsitename(&q, computer_name);
613
614         /* Marshall data and send request */
615
616         CLI_DO_RPC_WERR(cli, mem_ctx, PI_NETLOGON, NET_DSR_GETSITENAME,
617                         q, r,
618                         qbuf, rbuf,
619                         net_io_q_dsr_getsitename,
620                         net_io_r_dsr_getsitename,
621                         WERR_GENERAL_FAILURE);
622
623         if (!W_ERROR_IS_OK(r.result)) {
624                 return r.result;
625         }
626
627         if ((site_name != NULL) &&
628             ((*site_name = rpcstr_pull_unistr2_talloc(
629                       mem_ctx, &r.uni_site_name)) == NULL)) {
630                 return WERR_GENERAL_FAILURE;
631         }
632
633         return WERR_OK;
634 }
635
636
637
638 /* Sam synchronisation */
639
640 NTSTATUS rpccli_netlogon_sam_sync(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
641                                uint32 database_id, uint32 next_rid, uint32 *num_deltas,
642                                SAM_DELTA_HDR **hdr_deltas, 
643                                SAM_DELTA_CTR **deltas)
644 {
645         prs_struct qbuf, rbuf;
646         NET_Q_SAM_SYNC q;
647         NET_R_SAM_SYNC r;
648         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
649         DOM_CRED clnt_creds;
650         DOM_CRED ret_creds;
651
652         ZERO_STRUCT(q);
653         ZERO_STRUCT(r);
654
655         ZERO_STRUCT(ret_creds);
656
657         /* Initialise input parameters */
658
659         creds_client_step(cli->dc, &clnt_creds);
660
661         init_net_q_sam_sync(&q, cli->dc->remote_machine, global_myname(),
662                             &clnt_creds, &ret_creds, database_id, next_rid);
663
664         /* Marshall data and send request */
665
666         CLI_DO_RPC_COPY_SESS_KEY(cli, mem_ctx, PI_NETLOGON, NET_SAM_SYNC,
667                 q, r,
668                 qbuf, rbuf,
669                 net_io_q_sam_sync,
670                 net_io_r_sam_sync,
671                 NT_STATUS_UNSUCCESSFUL);
672
673         /* Return results */
674
675         result = r.status;
676         *num_deltas = r.num_deltas2;
677         *hdr_deltas = r.hdr_deltas;
678         *deltas = r.deltas;
679
680         if (!NT_STATUS_IS_ERR(result)) {
681                 /* Check returned credentials. */
682                 if (!creds_client_check(cli->dc, &r.srv_creds.challenge)) {
683                         DEBUG(0,("cli_netlogon_sam_sync: credentials chain check failed\n"));
684                         return NT_STATUS_ACCESS_DENIED;
685                 }
686         }
687
688         return result;
689 }
690
691 /* Sam synchronisation */
692
693 NTSTATUS rpccli_netlogon_sam_deltas(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
694                                  uint32 database_id, uint64 seqnum,
695                                  uint32 *num_deltas, 
696                                  SAM_DELTA_HDR **hdr_deltas, 
697                                  SAM_DELTA_CTR **deltas)
698 {
699         prs_struct qbuf, rbuf;
700         NET_Q_SAM_DELTAS q;
701         NET_R_SAM_DELTAS r;
702         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
703         DOM_CRED clnt_creds;
704
705         ZERO_STRUCT(q);
706         ZERO_STRUCT(r);
707
708         /* Initialise input parameters */
709
710         creds_client_step(cli->dc, &clnt_creds);
711
712         init_net_q_sam_deltas(&q, cli->dc->remote_machine,
713                               global_myname(), &clnt_creds, 
714                               database_id, seqnum);
715
716         /* Marshall data and send request */
717
718         CLI_DO_RPC(cli, mem_ctx, PI_NETLOGON, NET_SAM_DELTAS,
719                 q, r,
720                 qbuf, rbuf,
721                 net_io_q_sam_deltas,
722                 net_io_r_sam_deltas,
723                 NT_STATUS_UNSUCCESSFUL);
724
725         /* Return results */
726
727         result = r.status;
728         *num_deltas = r.num_deltas2;
729         *hdr_deltas = r.hdr_deltas;
730         *deltas = r.deltas;
731
732         if (!NT_STATUS_IS_ERR(result)) {
733                 /* Check returned credentials. */
734                 if (!creds_client_check(cli->dc, &r.srv_creds.challenge)) {
735                         DEBUG(0,("cli_netlogon_sam_sync: credentials chain check failed\n"));
736                         return NT_STATUS_ACCESS_DENIED;
737                 }
738         }
739
740         return result;
741 }
742
743 /* Logon domain user */
744
745 NTSTATUS rpccli_netlogon_sam_logon(struct rpc_pipe_client *cli,
746                                    TALLOC_CTX *mem_ctx,
747                                    uint32 logon_parameters,
748                                    const char *domain,
749                                    const char *username,
750                                    const char *password,
751                                    const char *workstation,
752                                    int logon_type)
753 {
754         prs_struct qbuf, rbuf;
755         NET_Q_SAM_LOGON q;
756         NET_R_SAM_LOGON r;
757         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
758         DOM_CRED clnt_creds;
759         DOM_CRED ret_creds;
760         NET_ID_INFO_CTR ctr;
761         NET_USER_INFO_3 user;
762         int validation_level = 3;
763         fstring clnt_name_slash;
764
765         ZERO_STRUCT(q);
766         ZERO_STRUCT(r);
767         ZERO_STRUCT(ret_creds);
768
769         if (workstation) {
770                 fstr_sprintf( clnt_name_slash, "\\\\%s", workstation );
771         } else {
772                 fstr_sprintf( clnt_name_slash, "\\\\%s", global_myname() );
773         }
774
775         /* Initialise input parameters */
776
777         creds_client_step(cli->dc, &clnt_creds);
778
779         q.validation_level = validation_level;
780
781         ctr.switch_value = logon_type;
782
783         switch (logon_type) {
784         case INTERACTIVE_LOGON_TYPE: {
785                 unsigned char lm_owf_user_pwd[16], nt_owf_user_pwd[16];
786
787                 nt_lm_owf_gen(password, nt_owf_user_pwd, lm_owf_user_pwd);
788
789                 init_id_info1(&ctr.auth.id1, domain, 
790                               logon_parameters, /* param_ctrl */
791                               0xdead, 0xbeef, /* LUID? */
792                               username, clnt_name_slash,
793                               (const char *)cli->dc->sess_key, lm_owf_user_pwd,
794                               nt_owf_user_pwd);
795
796                 break;
797         }
798         case NET_LOGON_TYPE: {
799                 uint8 chal[8];
800                 unsigned char local_lm_response[24];
801                 unsigned char local_nt_response[24];
802
803                 generate_random_buffer(chal, 8);
804
805                 SMBencrypt(password, chal, local_lm_response);
806                 SMBNTencrypt(password, chal, local_nt_response);
807
808                 init_id_info2(&ctr.auth.id2, domain, 
809                               logon_parameters, /* param_ctrl */
810                               0xdead, 0xbeef, /* LUID? */
811                               username, clnt_name_slash, chal,
812                               local_lm_response, 24, local_nt_response, 24);
813                 break;
814         }
815         default:
816                 DEBUG(0, ("switch value %d not supported\n", 
817                           ctr.switch_value));
818                 return NT_STATUS_INVALID_INFO_CLASS;
819         }
820
821         r.user = &user;
822
823         init_sam_info(&q.sam_id, cli->dc->remote_machine, global_myname(),
824                       &clnt_creds, &ret_creds, logon_type,
825                       &ctr);
826
827         /* Marshall data and send request */
828
829         CLI_DO_RPC(cli, mem_ctx, PI_NETLOGON, NET_SAMLOGON,
830                 q, r,
831                 qbuf, rbuf,
832                 net_io_q_sam_logon,
833                 net_io_r_sam_logon,
834                 NT_STATUS_UNSUCCESSFUL);
835
836         /* Return results */
837
838         result = r.status;
839
840         if (r.buffer_creds) {
841                 /* Check returned credentials if present. */
842                 if (!creds_client_check(cli->dc, &r.srv_creds.challenge)) {
843                         DEBUG(0,("rpccli_netlogon_sam_logon: credentials chain check failed\n"));
844                         return NT_STATUS_ACCESS_DENIED;
845                 }
846         }
847
848         return result;
849 }
850
851
852 /** 
853  * Logon domain user with an 'network' SAM logon 
854  *
855  * @param info3 Pointer to a NET_USER_INFO_3 already allocated by the caller.
856  **/
857
858 NTSTATUS rpccli_netlogon_sam_network_logon(struct rpc_pipe_client *cli,
859                                            TALLOC_CTX *mem_ctx,
860                                            uint32 logon_parameters,
861                                            const char *server,
862                                            const char *username,
863                                            const char *domain,
864                                            const char *workstation, 
865                                            const uint8 chal[8], 
866                                            DATA_BLOB lm_response,
867                                            DATA_BLOB nt_response,
868                                            NET_USER_INFO_3 *info3)
869 {
870         prs_struct qbuf, rbuf;
871         NET_Q_SAM_LOGON q;
872         NET_R_SAM_LOGON r;
873         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
874         NET_ID_INFO_CTR ctr;
875         int validation_level = 3;
876         const char *workstation_name_slash;
877         const char *server_name_slash;
878         uint8 zeros[16];
879         DOM_CRED clnt_creds;
880         DOM_CRED ret_creds;
881         int i;
882
883         ZERO_STRUCT(zeros);
884         ZERO_STRUCT(q);
885         ZERO_STRUCT(r);
886         ZERO_STRUCT(ret_creds);
887
888         creds_client_step(cli->dc, &clnt_creds);
889
890         if (server[0] != '\\' && server[1] != '\\') {
891                 server_name_slash = talloc_asprintf(mem_ctx, "\\\\%s", server);
892         } else {
893                 server_name_slash = server;
894         }
895
896         if (workstation[0] != '\\' && workstation[1] != '\\') {
897                 workstation_name_slash = talloc_asprintf(mem_ctx, "\\\\%s", workstation);
898         } else {
899                 workstation_name_slash = workstation;
900         }
901
902         if (!workstation_name_slash || !server_name_slash) {
903                 DEBUG(0, ("talloc_asprintf failed!\n"));
904                 return NT_STATUS_NO_MEMORY;
905         }
906
907         /* Initialise input parameters */
908
909         q.validation_level = validation_level;
910
911         ctr.switch_value = NET_LOGON_TYPE;
912
913         init_id_info2(&ctr.auth.id2, domain,
914                       logon_parameters, /* param_ctrl */
915                       0xdead, 0xbeef, /* LUID? */
916                       username, workstation_name_slash, (const uchar*)chal,
917                       lm_response.data, lm_response.length, nt_response.data, nt_response.length);
918  
919         init_sam_info(&q.sam_id, server_name_slash, global_myname(),
920                       &clnt_creds, &ret_creds, NET_LOGON_TYPE,
921                       &ctr);
922
923         r.user = info3;
924
925         /* Marshall data and send request */
926
927         CLI_DO_RPC(cli, mem_ctx, PI_NETLOGON, NET_SAMLOGON,
928                 q, r,
929                 qbuf, rbuf,
930                 net_io_q_sam_logon,
931                 net_io_r_sam_logon,
932                 NT_STATUS_UNSUCCESSFUL);
933
934         if (memcmp(zeros, info3->user_sess_key, 16) != 0) {
935                 SamOEMhash(info3->user_sess_key, cli->dc->sess_key, 16);
936         } else {
937                 memset(info3->user_sess_key, '\0', 16);
938         }
939
940         if (memcmp(zeros, info3->lm_sess_key, 8) != 0) {
941                 SamOEMhash(info3->lm_sess_key, cli->dc->sess_key, 8);
942         } else {
943                 memset(info3->lm_sess_key, '\0', 8);
944         }
945
946         for (i=0; i < 7; i++) {
947                 memset(&info3->unknown[i], '\0', 4);
948         }
949
950         /* Return results */
951
952         result = r.status;
953
954         if (r.buffer_creds) {
955                 /* Check returned credentials if present. */
956                 if (!creds_client_check(cli->dc, &r.srv_creds.challenge)) {
957                         DEBUG(0,("rpccli_netlogon_sam_network_logon: credentials chain check failed\n"));
958                         return NT_STATUS_ACCESS_DENIED;
959                 }
960         }
961
962         return result;
963 }
964
965 NTSTATUS rpccli_netlogon_sam_network_logon_ex(struct rpc_pipe_client *cli,
966                                               TALLOC_CTX *mem_ctx,
967                                               uint32 logon_parameters,
968                                               const char *server,
969                                               const char *username,
970                                               const char *domain,
971                                               const char *workstation, 
972                                               const uint8 chal[8], 
973                                               DATA_BLOB lm_response,
974                                               DATA_BLOB nt_response,
975                                               NET_USER_INFO_3 *info3)
976 {
977         prs_struct qbuf, rbuf;
978         NET_Q_SAM_LOGON_EX q;
979         NET_R_SAM_LOGON_EX r;
980         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
981         NET_ID_INFO_CTR ctr;
982         int validation_level = 3;
983         const char *workstation_name_slash;
984         const char *server_name_slash;
985         uint8 zeros[16];
986         int i;
987
988         ZERO_STRUCT(zeros);
989         ZERO_STRUCT(q);
990         ZERO_STRUCT(r);
991
992         if (server[0] != '\\' && server[1] != '\\') {
993                 server_name_slash = talloc_asprintf(mem_ctx, "\\\\%s", server);
994         } else {
995                 server_name_slash = server;
996         }
997
998         if (workstation[0] != '\\' && workstation[1] != '\\') {
999                 workstation_name_slash = talloc_asprintf(mem_ctx, "\\\\%s", workstation);
1000         } else {
1001                 workstation_name_slash = workstation;
1002         }
1003
1004         if (!workstation_name_slash || !server_name_slash) {
1005                 DEBUG(0, ("talloc_asprintf failed!\n"));
1006                 return NT_STATUS_NO_MEMORY;
1007         }
1008
1009         /* Initialise input parameters */
1010
1011         q.validation_level = validation_level;
1012
1013         ctr.switch_value = NET_LOGON_TYPE;
1014
1015         init_id_info2(&ctr.auth.id2, domain,
1016                       logon_parameters, /* param_ctrl */
1017                       0xdead, 0xbeef, /* LUID? */
1018                       username, workstation_name_slash, (const uchar*)chal,
1019                       lm_response.data, lm_response.length, nt_response.data,
1020                       nt_response.length);
1021  
1022         init_sam_info_ex(&q.sam_id, server_name_slash, global_myname(),
1023                          NET_LOGON_TYPE, &ctr);
1024
1025         r.user = info3;
1026
1027         /* Marshall data and send request */
1028
1029         CLI_DO_RPC(cli, mem_ctx, PI_NETLOGON, NET_SAMLOGON_EX,
1030                    q, r, qbuf, rbuf,
1031                    net_io_q_sam_logon_ex,
1032                    net_io_r_sam_logon_ex,
1033                    NT_STATUS_UNSUCCESSFUL);
1034
1035         if (memcmp(zeros, info3->user_sess_key, 16) != 0) {
1036                 SamOEMhash(info3->user_sess_key, cli->dc->sess_key, 16);
1037         } else {
1038                 memset(info3->user_sess_key, '\0', 16);
1039         }
1040
1041         if (memcmp(zeros, info3->lm_sess_key, 8) != 0) {
1042                 SamOEMhash(info3->lm_sess_key, cli->dc->sess_key, 8);
1043         } else {
1044                 memset(info3->lm_sess_key, '\0', 8);
1045         }
1046
1047         for (i=0; i < 7; i++) {
1048                 memset(&info3->unknown[i], '\0', 4);
1049         }
1050
1051         /* Return results */
1052
1053         result = r.status;
1054
1055         return result;
1056 }
1057
1058 /***************************************************************************
1059 LSA Server Password Set.
1060 ****************************************************************************/
1061
1062 NTSTATUS rpccli_net_srv_pwset(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, 
1063                            const char *machine_name, const uint8 hashed_mach_pwd[16])
1064 {
1065         prs_struct rbuf;
1066         prs_struct qbuf; 
1067         DOM_CRED clnt_creds;
1068         NET_Q_SRV_PWSET q;
1069         NET_R_SRV_PWSET r;
1070         uint16 sec_chan_type = 2;
1071         NTSTATUS result;
1072
1073         creds_client_step(cli->dc, &clnt_creds);
1074         
1075         DEBUG(4,("cli_net_srv_pwset: srv:%s acct:%s sc: %d mc: %s\n",
1076                  cli->dc->remote_machine, cli->dc->mach_acct, sec_chan_type, machine_name));
1077         
1078         /* store the parameters */
1079         init_q_srv_pwset(&q, cli->dc->remote_machine, (const char *)cli->dc->sess_key,
1080                          cli->dc->mach_acct, sec_chan_type, machine_name, 
1081                          &clnt_creds, hashed_mach_pwd);
1082         
1083         CLI_DO_RPC(cli, mem_ctx, PI_NETLOGON, NET_SRVPWSET,
1084                 q, r,
1085                 qbuf, rbuf,
1086                 net_io_q_srv_pwset,
1087                 net_io_r_srv_pwset,
1088                 NT_STATUS_UNSUCCESSFUL);
1089
1090         result = r.status;
1091
1092         if (!NT_STATUS_IS_OK(result)) {
1093                 /* report error code */
1094                 DEBUG(0,("cli_net_srv_pwset: %s\n", nt_errstr(result)));
1095         }
1096
1097         /* Always check returned credentials. */
1098         if (!creds_client_check(cli->dc, &r.srv_cred.challenge)) {
1099                 DEBUG(0,("rpccli_net_srv_pwset: credentials chain check failed\n"));
1100                 return NT_STATUS_ACCESS_DENIED;
1101         }
1102
1103         return result;
1104 }