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