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