Remove unused marshalling for NET_DSR_GESITENAME.
[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 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 /* Sam synchronisation */
519
520 NTSTATUS rpccli_netlogon_sam_sync(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
521                                uint32 database_id, uint32 next_rid, uint32 *num_deltas,
522                                SAM_DELTA_HDR **hdr_deltas, 
523                                SAM_DELTA_CTR **deltas)
524 {
525         prs_struct qbuf, rbuf;
526         NET_Q_SAM_SYNC q;
527         NET_R_SAM_SYNC r;
528         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
529         DOM_CRED clnt_creds;
530         DOM_CRED ret_creds;
531
532         ZERO_STRUCT(q);
533         ZERO_STRUCT(r);
534
535         ZERO_STRUCT(ret_creds);
536
537         /* Initialise input parameters */
538
539         creds_client_step(cli->dc, &clnt_creds);
540
541         init_net_q_sam_sync(&q, cli->dc->remote_machine, global_myname(),
542                             &clnt_creds, &ret_creds, database_id, next_rid);
543
544         /* Marshall data and send request */
545
546         CLI_DO_RPC_COPY_SESS_KEY(cli, mem_ctx, PI_NETLOGON, NET_SAM_SYNC,
547                 q, r,
548                 qbuf, rbuf,
549                 net_io_q_sam_sync,
550                 net_io_r_sam_sync,
551                 NT_STATUS_UNSUCCESSFUL);
552
553         /* Return results */
554
555         result = r.status;
556         *num_deltas = r.num_deltas2;
557         *hdr_deltas = r.hdr_deltas;
558         *deltas = r.deltas;
559
560         if (!NT_STATUS_IS_ERR(result)) {
561                 /* Check returned credentials. */
562                 if (!creds_client_check(cli->dc, &r.srv_creds.challenge)) {
563                         DEBUG(0,("cli_netlogon_sam_sync: credentials chain check failed\n"));
564                         return NT_STATUS_ACCESS_DENIED;
565                 }
566         }
567
568         return result;
569 }
570
571 /* Sam synchronisation */
572
573 NTSTATUS rpccli_netlogon_sam_deltas(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
574                                  uint32 database_id, uint64 seqnum,
575                                  uint32 *num_deltas, 
576                                  SAM_DELTA_HDR **hdr_deltas, 
577                                  SAM_DELTA_CTR **deltas)
578 {
579         prs_struct qbuf, rbuf;
580         NET_Q_SAM_DELTAS q;
581         NET_R_SAM_DELTAS r;
582         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
583         DOM_CRED clnt_creds;
584
585         ZERO_STRUCT(q);
586         ZERO_STRUCT(r);
587
588         /* Initialise input parameters */
589
590         creds_client_step(cli->dc, &clnt_creds);
591
592         init_net_q_sam_deltas(&q, cli->dc->remote_machine,
593                               global_myname(), &clnt_creds, 
594                               database_id, seqnum);
595
596         /* Marshall data and send request */
597
598         CLI_DO_RPC(cli, mem_ctx, PI_NETLOGON, NET_SAM_DELTAS,
599                 q, r,
600                 qbuf, rbuf,
601                 net_io_q_sam_deltas,
602                 net_io_r_sam_deltas,
603                 NT_STATUS_UNSUCCESSFUL);
604
605         /* Return results */
606
607         result = r.status;
608         *num_deltas = r.num_deltas2;
609         *hdr_deltas = r.hdr_deltas;
610         *deltas = r.deltas;
611
612         if (!NT_STATUS_IS_ERR(result)) {
613                 /* Check returned credentials. */
614                 if (!creds_client_check(cli->dc, &r.srv_creds.challenge)) {
615                         DEBUG(0,("cli_netlogon_sam_sync: credentials chain check failed\n"));
616                         return NT_STATUS_ACCESS_DENIED;
617                 }
618         }
619
620         return result;
621 }
622
623 /* Logon domain user */
624
625 NTSTATUS rpccli_netlogon_sam_logon(struct rpc_pipe_client *cli,
626                                    TALLOC_CTX *mem_ctx,
627                                    uint32 logon_parameters,
628                                    const char *domain,
629                                    const char *username,
630                                    const char *password,
631                                    const char *workstation,
632                                    int logon_type)
633 {
634         prs_struct qbuf, rbuf;
635         NET_Q_SAM_LOGON q;
636         NET_R_SAM_LOGON r;
637         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
638         DOM_CRED clnt_creds;
639         DOM_CRED ret_creds;
640         NET_ID_INFO_CTR ctr;
641         NET_USER_INFO_3 user;
642         int validation_level = 3;
643         fstring clnt_name_slash;
644
645         ZERO_STRUCT(q);
646         ZERO_STRUCT(r);
647         ZERO_STRUCT(ret_creds);
648
649         if (workstation) {
650                 fstr_sprintf( clnt_name_slash, "\\\\%s", workstation );
651         } else {
652                 fstr_sprintf( clnt_name_slash, "\\\\%s", global_myname() );
653         }
654
655         /* Initialise input parameters */
656
657         creds_client_step(cli->dc, &clnt_creds);
658
659         q.validation_level = validation_level;
660
661         ctr.switch_value = logon_type;
662
663         switch (logon_type) {
664         case INTERACTIVE_LOGON_TYPE: {
665                 unsigned char lm_owf_user_pwd[16], nt_owf_user_pwd[16];
666
667                 nt_lm_owf_gen(password, nt_owf_user_pwd, lm_owf_user_pwd);
668
669                 init_id_info1(&ctr.auth.id1, domain, 
670                               logon_parameters, /* param_ctrl */
671                               0xdead, 0xbeef, /* LUID? */
672                               username, clnt_name_slash,
673                               (const char *)cli->dc->sess_key, lm_owf_user_pwd,
674                               nt_owf_user_pwd);
675
676                 break;
677         }
678         case NET_LOGON_TYPE: {
679                 uint8 chal[8];
680                 unsigned char local_lm_response[24];
681                 unsigned char local_nt_response[24];
682
683                 generate_random_buffer(chal, 8);
684
685                 SMBencrypt(password, chal, local_lm_response);
686                 SMBNTencrypt(password, chal, local_nt_response);
687
688                 init_id_info2(&ctr.auth.id2, domain, 
689                               logon_parameters, /* param_ctrl */
690                               0xdead, 0xbeef, /* LUID? */
691                               username, clnt_name_slash, chal,
692                               local_lm_response, 24, local_nt_response, 24);
693                 break;
694         }
695         default:
696                 DEBUG(0, ("switch value %d not supported\n", 
697                           ctr.switch_value));
698                 return NT_STATUS_INVALID_INFO_CLASS;
699         }
700
701         r.user = &user;
702
703         init_sam_info(&q.sam_id, cli->dc->remote_machine, global_myname(),
704                       &clnt_creds, &ret_creds, logon_type,
705                       &ctr);
706
707         /* Marshall data and send request */
708
709         CLI_DO_RPC(cli, mem_ctx, PI_NETLOGON, NET_SAMLOGON,
710                 q, r,
711                 qbuf, rbuf,
712                 net_io_q_sam_logon,
713                 net_io_r_sam_logon,
714                 NT_STATUS_UNSUCCESSFUL);
715
716         /* Return results */
717
718         result = r.status;
719
720         if (r.buffer_creds) {
721                 /* Check returned credentials if present. */
722                 if (!creds_client_check(cli->dc, &r.srv_creds.challenge)) {
723                         DEBUG(0,("rpccli_netlogon_sam_logon: credentials chain check failed\n"));
724                         return NT_STATUS_ACCESS_DENIED;
725                 }
726         }
727
728         return result;
729 }
730
731
732 /** 
733  * Logon domain user with an 'network' SAM logon 
734  *
735  * @param info3 Pointer to a NET_USER_INFO_3 already allocated by the caller.
736  **/
737
738 NTSTATUS rpccli_netlogon_sam_network_logon(struct rpc_pipe_client *cli,
739                                            TALLOC_CTX *mem_ctx,
740                                            uint32 logon_parameters,
741                                            const char *server,
742                                            const char *username,
743                                            const char *domain,
744                                            const char *workstation, 
745                                            const uint8 chal[8], 
746                                            DATA_BLOB lm_response,
747                                            DATA_BLOB nt_response,
748                                            NET_USER_INFO_3 *info3)
749 {
750         prs_struct qbuf, rbuf;
751         NET_Q_SAM_LOGON q;
752         NET_R_SAM_LOGON r;
753         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
754         NET_ID_INFO_CTR ctr;
755         int validation_level = 3;
756         const char *workstation_name_slash;
757         const char *server_name_slash;
758         uint8 zeros[16];
759         DOM_CRED clnt_creds;
760         DOM_CRED ret_creds;
761         int i;
762
763         ZERO_STRUCT(zeros);
764         ZERO_STRUCT(q);
765         ZERO_STRUCT(r);
766         ZERO_STRUCT(ret_creds);
767
768         creds_client_step(cli->dc, &clnt_creds);
769
770         if (server[0] != '\\' && server[1] != '\\') {
771                 server_name_slash = talloc_asprintf(mem_ctx, "\\\\%s", server);
772         } else {
773                 server_name_slash = server;
774         }
775
776         if (workstation[0] != '\\' && workstation[1] != '\\') {
777                 workstation_name_slash = talloc_asprintf(mem_ctx, "\\\\%s", workstation);
778         } else {
779                 workstation_name_slash = workstation;
780         }
781
782         if (!workstation_name_slash || !server_name_slash) {
783                 DEBUG(0, ("talloc_asprintf failed!\n"));
784                 return NT_STATUS_NO_MEMORY;
785         }
786
787         /* Initialise input parameters */
788
789         q.validation_level = validation_level;
790
791         ctr.switch_value = NET_LOGON_TYPE;
792
793         init_id_info2(&ctr.auth.id2, domain,
794                       logon_parameters, /* param_ctrl */
795                       0xdead, 0xbeef, /* LUID? */
796                       username, workstation_name_slash, (const uchar*)chal,
797                       lm_response.data, lm_response.length, nt_response.data, nt_response.length);
798  
799         init_sam_info(&q.sam_id, server_name_slash, global_myname(),
800                       &clnt_creds, &ret_creds, NET_LOGON_TYPE,
801                       &ctr);
802
803         r.user = info3;
804
805         /* Marshall data and send request */
806
807         CLI_DO_RPC(cli, mem_ctx, PI_NETLOGON, NET_SAMLOGON,
808                 q, r,
809                 qbuf, rbuf,
810                 net_io_q_sam_logon,
811                 net_io_r_sam_logon,
812                 NT_STATUS_UNSUCCESSFUL);
813
814         if (memcmp(zeros, info3->user_sess_key, 16) != 0) {
815                 SamOEMhash(info3->user_sess_key, cli->dc->sess_key, 16);
816         } else {
817                 memset(info3->user_sess_key, '\0', 16);
818         }
819
820         if (memcmp(zeros, info3->lm_sess_key, 8) != 0) {
821                 SamOEMhash(info3->lm_sess_key, cli->dc->sess_key, 8);
822         } else {
823                 memset(info3->lm_sess_key, '\0', 8);
824         }
825
826         for (i=0; i < 7; i++) {
827                 memset(&info3->unknown[i], '\0', 4);
828         }
829
830         /* Return results */
831
832         result = r.status;
833
834         if (r.buffer_creds) {
835                 /* Check returned credentials if present. */
836                 if (!creds_client_check(cli->dc, &r.srv_creds.challenge)) {
837                         DEBUG(0,("rpccli_netlogon_sam_network_logon: credentials chain check failed\n"));
838                         return NT_STATUS_ACCESS_DENIED;
839                 }
840         }
841
842         return result;
843 }
844
845 NTSTATUS rpccli_netlogon_sam_network_logon_ex(struct rpc_pipe_client *cli,
846                                               TALLOC_CTX *mem_ctx,
847                                               uint32 logon_parameters,
848                                               const char *server,
849                                               const char *username,
850                                               const char *domain,
851                                               const char *workstation, 
852                                               const uint8 chal[8], 
853                                               DATA_BLOB lm_response,
854                                               DATA_BLOB nt_response,
855                                               NET_USER_INFO_3 *info3)
856 {
857         prs_struct qbuf, rbuf;
858         NET_Q_SAM_LOGON_EX q;
859         NET_R_SAM_LOGON_EX r;
860         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
861         NET_ID_INFO_CTR ctr;
862         int validation_level = 3;
863         const char *workstation_name_slash;
864         const char *server_name_slash;
865         uint8 zeros[16];
866         int i;
867
868         ZERO_STRUCT(zeros);
869         ZERO_STRUCT(q);
870         ZERO_STRUCT(r);
871
872         if (server[0] != '\\' && server[1] != '\\') {
873                 server_name_slash = talloc_asprintf(mem_ctx, "\\\\%s", server);
874         } else {
875                 server_name_slash = server;
876         }
877
878         if (workstation[0] != '\\' && workstation[1] != '\\') {
879                 workstation_name_slash = talloc_asprintf(mem_ctx, "\\\\%s", workstation);
880         } else {
881                 workstation_name_slash = workstation;
882         }
883
884         if (!workstation_name_slash || !server_name_slash) {
885                 DEBUG(0, ("talloc_asprintf failed!\n"));
886                 return NT_STATUS_NO_MEMORY;
887         }
888
889         /* Initialise input parameters */
890
891         q.validation_level = validation_level;
892
893         ctr.switch_value = NET_LOGON_TYPE;
894
895         init_id_info2(&ctr.auth.id2, domain,
896                       logon_parameters, /* param_ctrl */
897                       0xdead, 0xbeef, /* LUID? */
898                       username, workstation_name_slash, (const uchar*)chal,
899                       lm_response.data, lm_response.length, nt_response.data,
900                       nt_response.length);
901  
902         init_sam_info_ex(&q.sam_id, server_name_slash, global_myname(),
903                          NET_LOGON_TYPE, &ctr);
904
905         r.user = info3;
906
907         /* Marshall data and send request */
908
909         CLI_DO_RPC(cli, mem_ctx, PI_NETLOGON, NET_SAMLOGON_EX,
910                    q, r, qbuf, rbuf,
911                    net_io_q_sam_logon_ex,
912                    net_io_r_sam_logon_ex,
913                    NT_STATUS_UNSUCCESSFUL);
914
915         if (memcmp(zeros, info3->user_sess_key, 16) != 0) {
916                 SamOEMhash(info3->user_sess_key, cli->dc->sess_key, 16);
917         } else {
918                 memset(info3->user_sess_key, '\0', 16);
919         }
920
921         if (memcmp(zeros, info3->lm_sess_key, 8) != 0) {
922                 SamOEMhash(info3->lm_sess_key, cli->dc->sess_key, 8);
923         } else {
924                 memset(info3->lm_sess_key, '\0', 8);
925         }
926
927         for (i=0; i < 7; i++) {
928                 memset(&info3->unknown[i], '\0', 4);
929         }
930
931         /* Return results */
932
933         result = r.status;
934
935         return result;
936 }
937
938 /***************************************************************************
939 LSA Server Password Set.
940 ****************************************************************************/
941
942 NTSTATUS rpccli_net_srv_pwset(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, 
943                            const char *machine_name, const uint8 hashed_mach_pwd[16])
944 {
945         prs_struct rbuf;
946         prs_struct qbuf; 
947         DOM_CRED clnt_creds;
948         NET_Q_SRV_PWSET q;
949         NET_R_SRV_PWSET r;
950         uint16 sec_chan_type = 2;
951         NTSTATUS result;
952
953         creds_client_step(cli->dc, &clnt_creds);
954         
955         DEBUG(4,("cli_net_srv_pwset: srv:%s acct:%s sc: %d mc: %s\n",
956                  cli->dc->remote_machine, cli->dc->mach_acct, sec_chan_type, machine_name));
957         
958         /* store the parameters */
959         init_q_srv_pwset(&q, cli->dc->remote_machine, (const char *)cli->dc->sess_key,
960                          cli->dc->mach_acct, sec_chan_type, machine_name, 
961                          &clnt_creds, hashed_mach_pwd);
962         
963         CLI_DO_RPC(cli, mem_ctx, PI_NETLOGON, NET_SRVPWSET,
964                 q, r,
965                 qbuf, rbuf,
966                 net_io_q_srv_pwset,
967                 net_io_r_srv_pwset,
968                 NT_STATUS_UNSUCCESSFUL);
969
970         result = r.status;
971
972         if (!NT_STATUS_IS_OK(result)) {
973                 /* report error code */
974                 DEBUG(0,("cli_net_srv_pwset: %s\n", nt_errstr(result)));
975         }
976
977         /* Always check returned credentials. */
978         if (!creds_client_check(cli->dc, &r.srv_cred.challenge)) {
979                 DEBUG(0,("rpccli_net_srv_pwset: credentials chain check failed\n"));
980                 return NT_STATUS_ACCESS_DENIED;
981         }
982
983         return result;
984 }