spoolss: Add PRINTER_DRIVER_CATEGORY_3D driver define
[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    Copyright (C) Guenther Deschner                 2008.
8
9    This program is free software; you can redistribute it and/or modify
10    it under the terms of the GNU General Public License as published by
11    the Free Software Foundation; either version 3 of the License, or
12    (at your option) any later version.
13
14    This program is distributed in the hope that it will be useful,
15    but WITHOUT ANY WARRANTY; without even the implied warranty of
16    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17    GNU General Public License for more details.
18
19    You should have received a copy of the GNU General Public License
20    along with this program.  If not, see <http://www.gnu.org/licenses/>.
21 */
22
23 #include "includes.h"
24 #include "system/filesys.h"
25 #include "libsmb/libsmb.h"
26 #include "rpc_client/rpc_client.h"
27 #include "rpc_client/cli_pipe.h"
28 #include "../libcli/auth/libcli_auth.h"
29 #include "../libcli/auth/netlogon_creds_cli.h"
30 #include "../librpc/gen_ndr/ndr_netlogon_c.h"
31 #include "../librpc/gen_ndr/schannel.h"
32 #include "rpc_client/cli_netlogon.h"
33 #include "rpc_client/util_netlogon.h"
34 #include "../libcli/security/security.h"
35 #include "lib/param/param.h"
36 #include "libcli/smb/smbXcli_base.h"
37 #include "dbwrap/dbwrap.h"
38 #include "dbwrap/dbwrap_open.h"
39 #include "util_tdb.h"
40
41
42 NTSTATUS rpccli_pre_open_netlogon_creds(void)
43 {
44         static bool already_open = false;
45         TALLOC_CTX *frame;
46         struct loadparm_context *lp_ctx;
47         char *fname;
48         struct db_context *global_db;
49         NTSTATUS status;
50
51         if (already_open) {
52                 return NT_STATUS_OK;
53         }
54
55         frame = talloc_stackframe();
56
57         lp_ctx = loadparm_init_s3(frame, loadparm_s3_helpers());
58         if (lp_ctx == NULL) {
59                 TALLOC_FREE(frame);
60                 return NT_STATUS_NO_MEMORY;
61         }
62
63         fname = lpcfg_private_db_path(frame, lp_ctx, "netlogon_creds_cli");
64         if (fname == NULL) {
65                 TALLOC_FREE(frame);
66                 return NT_STATUS_NO_MEMORY;
67         }
68
69         global_db = db_open(frame, fname,
70                             0, TDB_CLEAR_IF_FIRST|TDB_INCOMPATIBLE_HASH,
71                             O_RDWR|O_CREAT, 0600, DBWRAP_LOCK_ORDER_2,
72                             DBWRAP_FLAG_OPTIMIZE_READONLY_ACCESS);
73         if (global_db == NULL) {
74                 TALLOC_FREE(frame);
75                 return NT_STATUS_NO_MEMORY;
76         }
77
78         status = netlogon_creds_cli_set_global_db(&global_db);
79         TALLOC_FREE(frame);
80         if (!NT_STATUS_IS_OK(status)) {
81                 return status;
82         }
83
84         already_open = true;
85         return NT_STATUS_OK;
86 }
87
88 static NTSTATUS rpccli_create_netlogon_creds(
89         const char *server_computer,
90         const char *server_netbios_domain,
91         const char *server_dns_domain,
92         const char *client_account,
93         enum netr_SchannelType sec_chan_type,
94         struct messaging_context *msg_ctx,
95         TALLOC_CTX *mem_ctx,
96         struct netlogon_creds_cli_context **netlogon_creds)
97 {
98         TALLOC_CTX *frame = talloc_stackframe();
99         struct loadparm_context *lp_ctx;
100         NTSTATUS status;
101
102         status = rpccli_pre_open_netlogon_creds();
103         if (!NT_STATUS_IS_OK(status)) {
104                 TALLOC_FREE(frame);
105                 return status;
106         }
107
108         lp_ctx = loadparm_init_s3(frame, loadparm_s3_helpers());
109         if (lp_ctx == NULL) {
110                 TALLOC_FREE(frame);
111                 return NT_STATUS_NO_MEMORY;
112         }
113         status = netlogon_creds_cli_context_global(lp_ctx,
114                                                    msg_ctx,
115                                                    client_account,
116                                                    sec_chan_type,
117                                                    server_computer,
118                                                    server_netbios_domain,
119                                                    server_dns_domain,
120                                                    mem_ctx, netlogon_creds);
121         TALLOC_FREE(frame);
122         if (!NT_STATUS_IS_OK(status)) {
123                 return status;
124         }
125
126         return NT_STATUS_OK;
127 }
128
129 NTSTATUS rpccli_create_netlogon_creds_ctx(
130         struct cli_credentials *creds,
131         const char *server_computer,
132         struct messaging_context *msg_ctx,
133         TALLOC_CTX *mem_ctx,
134         struct netlogon_creds_cli_context **creds_ctx)
135 {
136         enum netr_SchannelType sec_chan_type;
137         const char *server_netbios_domain;
138         const char *server_dns_domain;
139         const char *client_account;
140
141         sec_chan_type = cli_credentials_get_secure_channel_type(creds);
142         client_account = cli_credentials_get_username(creds);
143         server_netbios_domain = cli_credentials_get_domain(creds);
144         server_dns_domain = cli_credentials_get_realm(creds);
145
146         return rpccli_create_netlogon_creds(server_computer,
147                                             server_netbios_domain,
148                                             server_dns_domain,
149                                             client_account,
150                                             sec_chan_type,
151                                             msg_ctx, mem_ctx,
152                                             creds_ctx);
153 }
154
155 NTSTATUS rpccli_setup_netlogon_creds_locked(
156         struct cli_state *cli,
157         enum dcerpc_transport_t transport,
158         struct netlogon_creds_cli_context *creds_ctx,
159         bool force_reauth,
160         struct cli_credentials *cli_creds,
161         uint32_t *negotiate_flags)
162 {
163         TALLOC_CTX *frame = talloc_stackframe();
164         struct rpc_pipe_client *netlogon_pipe = NULL;
165         struct netlogon_creds_CredentialState *creds = NULL;
166         uint8_t num_nt_hashes = 0;
167         const struct samr_Password *nt_hashes[2] = { NULL, NULL };
168         uint8_t idx_nt_hashes = 0;
169         NTSTATUS status;
170
171         status = netlogon_creds_cli_get(creds_ctx, frame, &creds);
172         if (NT_STATUS_IS_OK(status)) {
173                 const char *action = "using";
174
175                 if (force_reauth) {
176                         action = "overwrite";
177                 }
178
179                 DEBUG(5,("%s: %s cached netlogon_creds cli[%s/%s] to %s\n",
180                          __FUNCTION__, action,
181                          creds->account_name, creds->computer_name,
182                          smbXcli_conn_remote_name(cli->conn)));
183                 if (!force_reauth) {
184                         goto done;
185                 }
186                 TALLOC_FREE(creds);
187         }
188
189         nt_hashes[0] = cli_credentials_get_nt_hash(cli_creds, talloc_tos());
190         if (nt_hashes[0] == NULL) {
191                 TALLOC_FREE(frame);
192                 return NT_STATUS_NO_MEMORY;
193         }
194         num_nt_hashes = 1;
195
196         nt_hashes[1] = cli_credentials_get_old_nt_hash(cli_creds,
197                                                        talloc_tos());
198         if (nt_hashes[1] != NULL) {
199                 num_nt_hashes = 2;
200         }
201
202         status = cli_rpc_pipe_open_noauth_transport(cli,
203                                                     transport,
204                                                     &ndr_table_netlogon,
205                                                     &netlogon_pipe);
206         if (!NT_STATUS_IS_OK(status)) {
207                 DEBUG(5,("%s: failed to open noauth netlogon connection to %s - %s\n",
208                          __FUNCTION__,
209                          smbXcli_conn_remote_name(cli->conn),
210                          nt_errstr(status)));
211                 TALLOC_FREE(frame);
212                 return status;
213         }
214         talloc_steal(frame, netlogon_pipe);
215
216         status = netlogon_creds_cli_auth(creds_ctx,
217                                          netlogon_pipe->binding_handle,
218                                          num_nt_hashes,
219                                          nt_hashes,
220                                          &idx_nt_hashes);
221         if (!NT_STATUS_IS_OK(status)) {
222                 TALLOC_FREE(frame);
223                 return status;
224         }
225
226         status = netlogon_creds_cli_get(creds_ctx, frame, &creds);
227         if (!NT_STATUS_IS_OK(status)) {
228                 TALLOC_FREE(frame);
229                 return NT_STATUS_INTERNAL_ERROR;
230         }
231
232         DEBUG(5,("%s: using new netlogon_creds cli[%s/%s] to %s\n",
233                  __FUNCTION__,
234                  creds->account_name, creds->computer_name,
235                  smbXcli_conn_remote_name(cli->conn)));
236
237 done:
238         if (negotiate_flags != NULL) {
239                 *negotiate_flags = creds->negotiate_flags;
240         }
241
242         TALLOC_FREE(frame);
243         return NT_STATUS_OK;
244 }
245
246 NTSTATUS rpccli_setup_netlogon_creds(
247         struct cli_state *cli,
248         enum dcerpc_transport_t transport,
249         struct netlogon_creds_cli_context *creds_ctx,
250         bool force_reauth,
251         struct cli_credentials *cli_creds)
252 {
253         TALLOC_CTX *frame = talloc_stackframe();
254         struct netlogon_creds_cli_lck *lck;
255         NTSTATUS status;
256
257         status = netlogon_creds_cli_lck(
258                 creds_ctx, NETLOGON_CREDS_CLI_LCK_EXCLUSIVE,
259                 frame, &lck);
260         if (!NT_STATUS_IS_OK(status)) {
261                 DBG_WARNING("netlogon_creds_cli_lck failed: %s\n",
262                             nt_errstr(status));
263                 TALLOC_FREE(frame);
264                 return status;
265         }
266
267         status = rpccli_setup_netlogon_creds_locked(
268                 cli, transport, creds_ctx, force_reauth, cli_creds, NULL);
269
270         TALLOC_FREE(frame);
271
272         return status;
273 }
274
275 NTSTATUS rpccli_connect_netlogon(
276         struct cli_state *cli,
277         enum dcerpc_transport_t transport,
278         struct netlogon_creds_cli_context *creds_ctx,
279         bool force_reauth,
280         struct cli_credentials *trust_creds,
281         struct rpc_pipe_client **_rpccli)
282 {
283         TALLOC_CTX *frame = talloc_stackframe();
284         struct netlogon_creds_CredentialState *creds = NULL;
285         enum netlogon_creds_cli_lck_type lck_type;
286         enum netr_SchannelType sec_chan_type;
287         struct netlogon_creds_cli_lck *lck = NULL;
288         uint32_t negotiate_flags;
289         uint8_t found_session_key[16] = {0};
290         bool found_existing_creds = false;
291         bool do_serverauth;
292         struct rpc_pipe_client *rpccli;
293         NTSTATUS status;
294         bool retry = false;
295
296         sec_chan_type = cli_credentials_get_secure_channel_type(trust_creds);
297         if (sec_chan_type == SEC_CHAN_NULL) {
298                 DBG_ERR("secure_channel_type gave SEC_CHAN_NULL\n");
299                 status = NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
300                 goto fail;
301         }
302
303 again:
304
305         /*
306          * See whether we can use existing netlogon_creds or
307          * whether we have to serverauthenticate.
308          */
309         status = netlogon_creds_cli_get(creds_ctx, frame, &creds);
310
311         if (NT_STATUS_IS_OK(status)) {
312                 int cmp = memcmp(found_session_key,
313                                  creds->session_key,
314                                  sizeof(found_session_key));
315                 found_existing_creds = (cmp != 0);
316
317                 memcpy(found_session_key,
318                        creds->session_key,
319                        sizeof(found_session_key));
320
321                 TALLOC_FREE(creds);
322         }
323
324         lck_type = (force_reauth || !found_existing_creds) ?
325                 NETLOGON_CREDS_CLI_LCK_EXCLUSIVE :
326                 NETLOGON_CREDS_CLI_LCK_SHARED;
327
328         status = netlogon_creds_cli_lck(creds_ctx, lck_type, frame, &lck);
329         if (!NT_STATUS_IS_OK(status)) {
330                 DBG_DEBUG("netlogon_creds_cli_lck failed: %s\n",
331                           nt_errstr(status));
332                 goto fail;
333         }
334
335         if (!found_existing_creds) {
336                 /*
337                  * Try to find creds under the lock again. Someone
338                  * else might have done it for us.
339                  */
340                 status = netlogon_creds_cli_get(creds_ctx, frame, &creds);
341
342                 if (NT_STATUS_IS_OK(status)) {
343                         int cmp = memcmp(found_session_key,
344                                          creds->session_key,
345                                          sizeof(found_session_key));
346                         found_existing_creds = (cmp != 0);
347
348                         memcpy(found_session_key, creds->session_key,
349                                sizeof(found_session_key));
350
351                         TALLOC_FREE(creds);
352                 }
353         }
354
355         do_serverauth = force_reauth || !found_existing_creds;
356
357         if (!do_serverauth) {
358                 /*
359                  * Do the quick schannel bind without a reauth
360                  */
361                 status = cli_rpc_pipe_open_bind_schannel(
362                         cli, &ndr_table_netlogon, transport, creds_ctx,
363                         &rpccli);
364                 if (!retry && NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_ACCESS_DENIED)) {
365                         DBG_DEBUG("Retrying with serverauthenticate\n");
366                         TALLOC_FREE(lck);
367                         retry = true;
368                         goto again;
369                 }
370                 if (!NT_STATUS_IS_OK(status)) {
371                         DBG_DEBUG("cli_rpc_pipe_open_bind_schannel "
372                                   "failed: %s\n", nt_errstr(status));
373                         goto fail;
374                 }
375                 goto done;
376         }
377
378         if (cli_credentials_is_anonymous(trust_creds)) {
379                 DBG_WARNING("get_trust_credential for %s only gave anonymous,"
380                             "unable to negotiate NETLOGON credentials\n",
381                             netlogon_creds_cli_debug_string(
382                                     creds_ctx, frame));
383                 status = NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
384                 goto fail;
385         }
386
387         status = rpccli_setup_netlogon_creds_locked(
388                 cli, transport, creds_ctx, true, trust_creds,
389                 &negotiate_flags);
390         if (!NT_STATUS_IS_OK(status)) {
391                 DBG_DEBUG("rpccli_setup_netlogon_creds failed for %s, "
392                           "unable to setup NETLOGON credentials: %s\n",
393                           netlogon_creds_cli_debug_string(
394                                   creds_ctx, frame),
395                           nt_errstr(status));
396                 goto fail;
397         }
398
399         if (!(negotiate_flags & NETLOGON_NEG_AUTHENTICATED_RPC)) {
400                 if (lp_winbind_sealed_pipes() || lp_require_strong_key()) {
401                         status = NT_STATUS_DOWNGRADE_DETECTED;
402                         DBG_WARNING("Unwilling to make connection to %s"
403                                     "without connection level security, "
404                                     "must set 'winbind sealed pipes = false'"
405                                     " and 'require strong key = false' "
406                                     "to proceed: %s\n",
407                                     netlogon_creds_cli_debug_string(
408                                             creds_ctx, frame),
409                                     nt_errstr(status));
410                         goto fail;
411                 }
412
413                 status = cli_rpc_pipe_open_noauth_transport(
414                         cli, transport, &ndr_table_netlogon, &rpccli);
415                 if (!NT_STATUS_IS_OK(status)) {
416                         DBG_DEBUG("cli_rpc_pipe_open_noauth_transport "
417                                   "failed: %s\n", nt_errstr(status));
418                         goto fail;
419                 }
420                 goto done;
421         }
422
423         status = cli_rpc_pipe_open_bind_schannel(
424                 cli, &ndr_table_netlogon, transport, creds_ctx, &rpccli);
425         if (!NT_STATUS_IS_OK(status)) {
426                 DBG_DEBUG("cli_rpc_pipe_open_bind_schannel "
427                           "failed: %s\n", nt_errstr(status));
428                 goto fail;
429         }
430
431         status = netlogon_creds_cli_check(creds_ctx, rpccli->binding_handle,
432                                           NULL);
433         if (!NT_STATUS_IS_OK(status)) {
434                 DBG_WARNING("netlogon_creds_cli_check failed: %s\n",
435                             nt_errstr(status));
436                 goto fail;
437         }
438
439 done:
440         *_rpccli = rpccli;
441         status = NT_STATUS_OK;
442 fail:
443         ZERO_STRUCT(found_session_key);
444         TALLOC_FREE(lck);
445         TALLOC_FREE(frame);
446         return status;
447 }
448
449 /* Logon domain user */
450
451 NTSTATUS rpccli_netlogon_password_logon(
452         struct netlogon_creds_cli_context *creds_ctx,
453         struct dcerpc_binding_handle *binding_handle,
454         TALLOC_CTX *mem_ctx,
455         uint32_t logon_parameters,
456         const char *domain,
457         const char *username,
458         const char *password,
459         const char *workstation,
460         const uint64_t logon_id,
461         enum netr_LogonInfoClass logon_type,
462         uint8_t *authoritative,
463         uint32_t *flags,
464         uint16_t *_validation_level,
465         union netr_Validation **_validation)
466 {
467         TALLOC_CTX *frame = talloc_stackframe();
468         NTSTATUS status;
469         union netr_LogonLevel *logon;
470         uint16_t validation_level = 0;
471         union netr_Validation *validation = NULL;
472         char *workstation_slash = NULL;
473
474         unsigned char local_nt_response[24];
475         unsigned char local_lm_response[24];
476         struct samr_Password lmpassword = {.hash = {0}};
477         struct samr_Password ntpassword = {.hash = {0}};
478         struct netr_ChallengeResponse lm = {0};
479         struct netr_ChallengeResponse nt = {0};
480
481         logon = talloc_zero(frame, union netr_LogonLevel);
482         if (logon == NULL) {
483                 TALLOC_FREE(frame);
484                 return NT_STATUS_NO_MEMORY;
485         }
486
487         if (workstation == NULL) {
488                 workstation = lp_netbios_name();
489         }
490
491         workstation_slash = talloc_asprintf(frame, "\\\\%s", workstation);
492         if (workstation_slash == NULL) {
493                 TALLOC_FREE(frame);
494                 return NT_STATUS_NO_MEMORY;
495         }
496
497         /* Initialise input parameters */
498
499         switch (logon_type) {
500         case NetlogonInteractiveInformation:
501         case NetlogonInteractiveTransitiveInformation: {
502
503                 struct netr_PasswordInfo *password_info;
504
505
506                 password_info = talloc_zero(frame, struct netr_PasswordInfo);
507                 if (password_info == NULL) {
508                         TALLOC_FREE(frame);
509                         return NT_STATUS_NO_MEMORY;
510                 }
511
512                 nt_lm_owf_gen(password, ntpassword.hash, lmpassword.hash);
513
514                 password_info->identity_info.domain_name.string         = domain;
515                 password_info->identity_info.parameter_control          = logon_parameters;
516                 password_info->identity_info.logon_id                   = logon_id;
517                 password_info->identity_info.account_name.string        = username;
518                 password_info->identity_info.workstation.string         = workstation_slash;
519
520                 password_info->lmpassword = lmpassword;
521                 password_info->ntpassword = ntpassword;
522
523                 logon->password = password_info;
524
525                 break;
526         }
527         case NetlogonNetworkInformation:
528         case NetlogonNetworkTransitiveInformation: {
529                 struct netr_NetworkInfo *network_info;
530                 uint8_t chal[8];
531
532                 ZERO_STRUCT(lm);
533                 ZERO_STRUCT(nt);
534
535                 network_info = talloc_zero(frame, struct netr_NetworkInfo);
536                 if (network_info == NULL) {
537                         TALLOC_FREE(frame);
538                         return NT_STATUS_NO_MEMORY;
539                 }
540
541                 generate_random_buffer(chal, 8);
542
543                 SMBencrypt(password, chal, local_lm_response);
544                 SMBNTencrypt(password, chal, local_nt_response);
545
546                 lm.length = 24;
547                 lm.data = local_lm_response;
548
549                 nt.length = 24;
550                 nt.data = local_nt_response;
551
552                 network_info->identity_info.domain_name.string          = domain;
553                 network_info->identity_info.parameter_control           = logon_parameters;
554                 network_info->identity_info.logon_id                    = logon_id;
555                 network_info->identity_info.account_name.string         = username;
556                 network_info->identity_info.workstation.string          = workstation_slash;
557
558                 memcpy(network_info->challenge, chal, 8);
559                 network_info->nt = nt;
560                 network_info->lm = lm;
561
562                 logon->network = network_info;
563
564                 break;
565         }
566         default:
567                 DEBUG(0, ("switch value %d not supported\n",
568                         logon_type));
569                 TALLOC_FREE(frame);
570                 return NT_STATUS_INVALID_INFO_CLASS;
571         }
572
573         status = netlogon_creds_cli_LogonSamLogon(creds_ctx,
574                                                   binding_handle,
575                                                   logon_type,
576                                                   logon,
577                                                   mem_ctx,
578                                                   &validation_level,
579                                                   &validation,
580                                                   authoritative,
581                                                   flags);
582         if (!NT_STATUS_IS_OK(status)) {
583                 TALLOC_FREE(frame);
584                 return status;
585         }
586
587         TALLOC_FREE(frame);
588         *_validation_level = validation_level;
589         *_validation = validation;
590
591         return NT_STATUS_OK;
592 }
593
594 /**
595  * Logon domain user with an 'network' SAM logon
596  *
597  * @param info3 Pointer to a NET_USER_INFO_3 already allocated by the caller.
598  **/
599
600
601 NTSTATUS rpccli_netlogon_network_logon(
602         struct netlogon_creds_cli_context *creds_ctx,
603         struct dcerpc_binding_handle *binding_handle,
604         TALLOC_CTX *mem_ctx,
605         uint32_t logon_parameters,
606         const char *username,
607         const char *domain,
608         const char *workstation,
609         const uint64_t logon_id,
610         const uint8_t chal[8],
611         DATA_BLOB lm_response,
612         DATA_BLOB nt_response,
613         enum netr_LogonInfoClass logon_type,
614         uint8_t *authoritative,
615         uint32_t *flags,
616         uint16_t *_validation_level,
617         union netr_Validation **_validation)
618 {
619         NTSTATUS status;
620         const char *workstation_name_slash;
621         union netr_LogonLevel *logon = NULL;
622         struct netr_NetworkInfo *network_info;
623         uint16_t validation_level = 0;
624         union netr_Validation *validation = NULL;
625         struct netr_ChallengeResponse lm;
626         struct netr_ChallengeResponse nt;
627
628         *_validation = NULL;
629
630         ZERO_STRUCT(lm);
631         ZERO_STRUCT(nt);
632
633         switch (logon_type) {
634         case NetlogonNetworkInformation:
635         case NetlogonNetworkTransitiveInformation:
636                 break;
637         default:
638                 DEBUG(0, ("switch value %d not supported\n",
639                         logon_type));
640                 return NT_STATUS_INVALID_INFO_CLASS;
641         }
642
643         logon = talloc_zero(mem_ctx, union netr_LogonLevel);
644         if (!logon) {
645                 return NT_STATUS_NO_MEMORY;
646         }
647
648         network_info = talloc_zero(mem_ctx, struct netr_NetworkInfo);
649         if (!network_info) {
650                 return NT_STATUS_NO_MEMORY;
651         }
652
653         if (workstation[0] != '\\' && workstation[1] != '\\') {
654                 workstation_name_slash = talloc_asprintf(mem_ctx, "\\\\%s", workstation);
655         } else {
656                 workstation_name_slash = workstation;
657         }
658
659         if (!workstation_name_slash) {
660                 DEBUG(0, ("talloc_asprintf failed!\n"));
661                 return NT_STATUS_NO_MEMORY;
662         }
663
664         /* Initialise input parameters */
665
666         lm.data = lm_response.data;
667         lm.length = lm_response.length;
668         nt.data = nt_response.data;
669         nt.length = nt_response.length;
670
671         network_info->identity_info.domain_name.string          = domain;
672         network_info->identity_info.parameter_control           = logon_parameters;
673         network_info->identity_info.logon_id                    = logon_id;
674         network_info->identity_info.account_name.string         = username;
675         network_info->identity_info.workstation.string          = workstation_name_slash;
676
677         memcpy(network_info->challenge, chal, 8);
678         network_info->nt = nt;
679         network_info->lm = lm;
680
681         logon->network = network_info;
682
683         /* Marshall data and send request */
684
685         status = netlogon_creds_cli_LogonSamLogon(creds_ctx,
686                                                   binding_handle,
687                                                   logon_type,
688                                                   logon,
689                                                   mem_ctx,
690                                                   &validation_level,
691                                                   &validation,
692                                                   authoritative,
693                                                   flags);
694         if (!NT_STATUS_IS_OK(status)) {
695                 return status;
696         }
697
698         *_validation_level = validation_level;
699         *_validation = validation;
700
701         return NT_STATUS_OK;
702 }
703
704 NTSTATUS rpccli_netlogon_interactive_logon(
705         struct netlogon_creds_cli_context *creds_ctx,
706         struct dcerpc_binding_handle *binding_handle,
707         TALLOC_CTX *mem_ctx,
708         uint32_t logon_parameters,
709         const char *username,
710         const char *domain,
711         const char *workstation,
712         const uint64_t logon_id,
713         DATA_BLOB lm_hash,
714         DATA_BLOB nt_hash,
715         enum netr_LogonInfoClass logon_type,
716         uint8_t *authoritative,
717         uint32_t *flags,
718         uint16_t *_validation_level,
719         union netr_Validation **_validation)
720 {
721         TALLOC_CTX *frame = talloc_stackframe();
722         NTSTATUS status;
723         const char *workstation_name_slash;
724         union netr_LogonLevel *logon = NULL;
725         struct netr_PasswordInfo *password_info = NULL;
726         uint16_t validation_level = 0;
727         union netr_Validation *validation = NULL;
728         struct netr_ChallengeResponse lm;
729         struct netr_ChallengeResponse nt;
730
731         *_validation = NULL;
732
733         ZERO_STRUCT(lm);
734         ZERO_STRUCT(nt);
735
736         switch (logon_type) {
737         case NetlogonInteractiveInformation:
738         case NetlogonInteractiveTransitiveInformation:
739                 break;
740         default:
741                 DEBUG(0, ("switch value %d not supported\n",
742                         logon_type));
743                 TALLOC_FREE(frame);
744                 return NT_STATUS_INVALID_INFO_CLASS;
745         }
746
747         logon = talloc_zero(mem_ctx, union netr_LogonLevel);
748         if (logon == NULL) {
749                 TALLOC_FREE(frame);
750                 return NT_STATUS_NO_MEMORY;
751         }
752
753         password_info = talloc_zero(logon, struct netr_PasswordInfo);
754         if (password_info == NULL) {
755                 TALLOC_FREE(frame);
756                 return NT_STATUS_NO_MEMORY;
757         }
758
759         if (workstation[0] != '\\' && workstation[1] != '\\') {
760                 workstation_name_slash = talloc_asprintf(frame, "\\\\%s", workstation);
761         } else {
762                 workstation_name_slash = workstation;
763         }
764
765         if (workstation_name_slash == NULL) {
766                 TALLOC_FREE(frame);
767                 return NT_STATUS_NO_MEMORY;
768         }
769
770         /* Initialise input parameters */
771
772         password_info->identity_info.domain_name.string         = domain;
773         password_info->identity_info.parameter_control          = logon_parameters;
774         password_info->identity_info.logon_id                   = logon_id;
775         password_info->identity_info.account_name.string        = username;
776         password_info->identity_info.workstation.string         = workstation_name_slash;
777
778         if (nt_hash.length != sizeof(password_info->ntpassword.hash)) {
779                 TALLOC_FREE(frame);
780                 return NT_STATUS_INVALID_PARAMETER;
781         }
782         memcpy(password_info->ntpassword.hash, nt_hash.data, nt_hash.length);
783         if (lm_hash.length != 0) {
784                 if (lm_hash.length != sizeof(password_info->lmpassword.hash)) {
785                         TALLOC_FREE(frame);
786                         return NT_STATUS_INVALID_PARAMETER;
787                 }
788                 memcpy(password_info->lmpassword.hash, lm_hash.data, lm_hash.length);
789         }
790
791         logon->password = password_info;
792
793         /* Marshall data and send request */
794
795         status = netlogon_creds_cli_LogonSamLogon(creds_ctx,
796                                                   binding_handle,
797                                                   logon_type,
798                                                   logon,
799                                                   mem_ctx,
800                                                   &validation_level,
801                                                   &validation,
802                                                   authoritative,
803                                                   flags);
804         if (!NT_STATUS_IS_OK(status)) {
805                 TALLOC_FREE(frame);
806                 return status;
807         }
808
809         *_validation_level = validation_level;
810         *_validation = validation;
811
812         TALLOC_FREE(frame);
813         return NT_STATUS_OK;
814 }