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