cli_netlogon: Rename rpccli_create_netlogon_creds_with_creds
[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/init_netlogon.h"
34 #include "rpc_client/util_netlogon.h"
35 #include "../libcli/security/security.h"
36 #include "lib/param/param.h"
37 #include "libcli/smb/smbXcli_base.h"
38 #include "dbwrap/dbwrap.h"
39 #include "dbwrap/dbwrap_open.h"
40 #include "util_tdb.h"
41
42
43 NTSTATUS rpccli_pre_open_netlogon_creds(void)
44 {
45         static bool already_open = false;
46         TALLOC_CTX *frame;
47         struct loadparm_context *lp_ctx;
48         char *fname;
49         struct db_context *global_db;
50         NTSTATUS status;
51
52         if (already_open) {
53                 return NT_STATUS_OK;
54         }
55
56         frame = talloc_stackframe();
57
58         lp_ctx = loadparm_init_s3(frame, loadparm_s3_helpers());
59         if (lp_ctx == NULL) {
60                 TALLOC_FREE(frame);
61                 return NT_STATUS_NO_MEMORY;
62         }
63
64         fname = lpcfg_private_db_path(frame, lp_ctx, "netlogon_creds_cli");
65         if (fname == NULL) {
66                 TALLOC_FREE(frame);
67                 return NT_STATUS_NO_MEMORY;
68         }
69
70         global_db = db_open(frame, fname,
71                             0, TDB_CLEAR_IF_FIRST|TDB_INCOMPATIBLE_HASH,
72                             O_RDWR|O_CREAT, 0600, DBWRAP_LOCK_ORDER_2,
73                             DBWRAP_FLAG_OPTIMIZE_READONLY_ACCESS);
74         if (global_db == NULL) {
75                 TALLOC_FREE(frame);
76                 return NT_STATUS_NO_MEMORY;
77         }
78
79         status = netlogon_creds_cli_set_global_db(&global_db);
80         TALLOC_FREE(frame);
81         if (!NT_STATUS_IS_OK(status)) {
82                 return status;
83         }
84
85         already_open = true;
86         return NT_STATUS_OK;
87 }
88
89 static NTSTATUS rpccli_create_netlogon_creds(
90         const char *server_computer,
91         const char *server_netbios_domain,
92         const char *server_dns_domain,
93         const char *client_account,
94         enum netr_SchannelType sec_chan_type,
95         struct messaging_context *msg_ctx,
96         TALLOC_CTX *mem_ctx,
97         struct netlogon_creds_cli_context **netlogon_creds)
98 {
99         TALLOC_CTX *frame = talloc_stackframe();
100         struct loadparm_context *lp_ctx;
101         NTSTATUS status;
102
103         status = rpccli_pre_open_netlogon_creds();
104         if (!NT_STATUS_IS_OK(status)) {
105                 TALLOC_FREE(frame);
106                 return status;
107         }
108
109         lp_ctx = loadparm_init_s3(frame, loadparm_s3_helpers());
110         if (lp_ctx == NULL) {
111                 TALLOC_FREE(frame);
112                 return NT_STATUS_NO_MEMORY;
113         }
114         status = netlogon_creds_cli_context_global(lp_ctx,
115                                                    msg_ctx,
116                                                    client_account,
117                                                    sec_chan_type,
118                                                    server_computer,
119                                                    server_netbios_domain,
120                                                    server_dns_domain,
121                                                    mem_ctx, netlogon_creds);
122         TALLOC_FREE(frame);
123         if (!NT_STATUS_IS_OK(status)) {
124                 return status;
125         }
126
127         return NT_STATUS_OK;
128 }
129
130 NTSTATUS rpccli_create_netlogon_creds_ctx(
131         struct cli_credentials *creds,
132         const char *server_computer,
133         struct messaging_context *msg_ctx,
134         TALLOC_CTX *mem_ctx,
135         struct netlogon_creds_cli_context **netlogon_creds)
136 {
137         enum netr_SchannelType sec_chan_type;
138         const char *server_netbios_domain;
139         const char *server_dns_domain;
140         const char *client_account;
141
142         sec_chan_type = cli_credentials_get_secure_channel_type(creds);
143         if (sec_chan_type == SEC_CHAN_NULL) {
144                 return NT_STATUS_INVALID_PARAMETER_MIX;
145         }
146
147         client_account = cli_credentials_get_username(creds);
148         server_netbios_domain = cli_credentials_get_domain(creds);
149         server_dns_domain = cli_credentials_get_realm(creds);
150
151         return rpccli_create_netlogon_creds(server_computer,
152                                             server_netbios_domain,
153                                             server_dns_domain,
154                                             client_account,
155                                             sec_chan_type,
156                                             msg_ctx, mem_ctx,
157                                             netlogon_creds);
158 }
159
160 static NTSTATUS rpccli_setup_netlogon_creds(
161         struct cli_state *cli,
162         enum dcerpc_transport_t transport,
163         struct netlogon_creds_cli_context *netlogon_creds,
164         bool force_reauth,
165         struct samr_Password current_nt_hash,
166         const struct samr_Password *previous_nt_hash)
167 {
168         TALLOC_CTX *frame = talloc_stackframe();
169         struct rpc_pipe_client *netlogon_pipe = NULL;
170         struct netlogon_creds_CredentialState *creds = NULL;
171         uint8_t num_nt_hashes = 0;
172         const struct samr_Password *nt_hashes[2] = { NULL, NULL };
173         uint8_t idx_nt_hashes = 0;
174         NTSTATUS status;
175
176         status = netlogon_creds_cli_get(netlogon_creds,
177                                         frame, &creds);
178         if (NT_STATUS_IS_OK(status)) {
179                 const char *action = "using";
180
181                 if (force_reauth) {
182                         action = "overwrite";
183                 }
184
185                 DEBUG(5,("%s: %s cached netlogon_creds cli[%s/%s] to %s\n",
186                          __FUNCTION__, action,
187                          creds->account_name, creds->computer_name,
188                          smbXcli_conn_remote_name(cli->conn)));
189                 if (!force_reauth) {
190                         TALLOC_FREE(frame);
191                         return NT_STATUS_OK;
192                 }
193                 TALLOC_FREE(creds);
194         }
195
196         status = cli_rpc_pipe_open_noauth_transport(cli,
197                                                     transport,
198                                                     &ndr_table_netlogon,
199                                                     &netlogon_pipe);
200         if (!NT_STATUS_IS_OK(status)) {
201                 DEBUG(5,("%s: failed to open noauth netlogon connection to %s - %s\n",
202                          __FUNCTION__,
203                          smbXcli_conn_remote_name(cli->conn),
204                          nt_errstr(status)));
205                 TALLOC_FREE(frame);
206                 return status;
207         }
208         talloc_steal(frame, netlogon_pipe);
209
210         nt_hashes[0] = &current_nt_hash;
211         num_nt_hashes = 1;
212         if (previous_nt_hash != NULL) {
213                 nt_hashes[1] = previous_nt_hash;
214                 num_nt_hashes = 2;
215         }
216
217         status = netlogon_creds_cli_auth(netlogon_creds,
218                                          netlogon_pipe->binding_handle,
219                                          num_nt_hashes,
220                                          nt_hashes,
221                                          &idx_nt_hashes);
222         if (!NT_STATUS_IS_OK(status)) {
223                 TALLOC_FREE(frame);
224                 return status;
225         }
226
227         status = netlogon_creds_cli_get(netlogon_creds,
228                                         frame, &creds);
229         if (!NT_STATUS_IS_OK(status)) {
230                 TALLOC_FREE(frame);
231                 return NT_STATUS_INTERNAL_ERROR;
232         }
233
234         DEBUG(5,("%s: using new netlogon_creds cli[%s/%s] to %s\n",
235                  __FUNCTION__,
236                  creds->account_name, creds->computer_name,
237                  smbXcli_conn_remote_name(cli->conn)));
238
239         TALLOC_FREE(frame);
240         return NT_STATUS_OK;
241 }
242
243 NTSTATUS rpccli_setup_netlogon_creds_with_creds(struct cli_state *cli,
244                                                 enum dcerpc_transport_t transport,
245                                                 struct netlogon_creds_cli_context *netlogon_creds,
246                                                 bool force_reauth,
247                                                 struct cli_credentials *creds)
248 {
249         struct samr_Password *current_nt_hash = NULL;
250         struct samr_Password *previous_nt_hash = NULL;
251         NTSTATUS status;
252
253         current_nt_hash = cli_credentials_get_nt_hash(creds, talloc_tos());
254         if (current_nt_hash == NULL) {
255                 return NT_STATUS_NO_MEMORY;
256         }
257
258         previous_nt_hash = cli_credentials_get_old_nt_hash(creds, talloc_tos());
259
260         status = rpccli_setup_netlogon_creds(cli, transport,
261                                              netlogon_creds,
262                                              force_reauth,
263                                              *current_nt_hash,
264                                              previous_nt_hash);
265         TALLOC_FREE(current_nt_hash);
266         TALLOC_FREE(previous_nt_hash);
267         if (!NT_STATUS_IS_OK(status)) {
268                 return status;
269         }
270
271         return NT_STATUS_OK;
272 }
273
274 static NTSTATUS map_validation_to_info3(TALLOC_CTX *mem_ctx,
275                                         uint16_t validation_level,
276                                         union netr_Validation *validation,
277                                         struct netr_SamInfo3 **info3_p)
278 {
279         struct netr_SamInfo3 *info3;
280         NTSTATUS status;
281
282         if (validation == NULL) {
283                 return NT_STATUS_INVALID_PARAMETER;
284         }
285
286         switch (validation_level) {
287         case 3:
288                 if (validation->sam3 == NULL) {
289                         return NT_STATUS_INVALID_PARAMETER;
290                 }
291
292                 info3 = talloc_move(mem_ctx, &validation->sam3);
293                 break;
294         case 6:
295                 if (validation->sam6 == NULL) {
296                         return NT_STATUS_INVALID_PARAMETER;
297                 }
298
299                 info3 = talloc_zero(mem_ctx, struct netr_SamInfo3);
300                 if (info3 == NULL) {
301                         return NT_STATUS_NO_MEMORY;
302                 }
303                 status = copy_netr_SamBaseInfo(info3, &validation->sam6->base, &info3->base);
304                 if (!NT_STATUS_IS_OK(status)) {
305                         TALLOC_FREE(info3);
306                         return status;
307                 }
308
309                 info3->sidcount = validation->sam6->sidcount;
310                 info3->sids = talloc_move(info3, &validation->sam6->sids);
311                 break;
312         default:
313                 return NT_STATUS_BAD_VALIDATION_CLASS;
314         }
315
316         *info3_p = info3;
317
318         return NT_STATUS_OK;
319 }
320
321 /* Logon domain user */
322
323 NTSTATUS rpccli_netlogon_password_logon(struct netlogon_creds_cli_context *creds,
324                                         struct dcerpc_binding_handle *binding_handle,
325                                         TALLOC_CTX *mem_ctx,
326                                         uint32_t logon_parameters,
327                                         const char *domain,
328                                         const char *username,
329                                         const char *password,
330                                         const char *workstation,
331                                         enum netr_LogonInfoClass logon_type,
332                                         uint8_t *authoritative,
333                                         uint32_t *flags,
334                                         struct netr_SamInfo3 **info3)
335 {
336         TALLOC_CTX *frame = talloc_stackframe();
337         NTSTATUS status;
338         union netr_LogonLevel *logon;
339         uint16_t validation_level = 0;
340         union netr_Validation *validation = NULL;
341         char *workstation_slash = NULL;
342
343         logon = talloc_zero(frame, union netr_LogonLevel);
344         if (logon == NULL) {
345                 TALLOC_FREE(frame);
346                 return NT_STATUS_NO_MEMORY;
347         }
348
349         if (workstation == NULL) {
350                 workstation = lp_netbios_name();
351         }
352
353         workstation_slash = talloc_asprintf(frame, "\\\\%s", workstation);
354         if (workstation_slash == NULL) {
355                 TALLOC_FREE(frame);
356                 return NT_STATUS_NO_MEMORY;
357         }
358
359         /* Initialise input parameters */
360
361         switch (logon_type) {
362         case NetlogonInteractiveInformation: {
363
364                 struct netr_PasswordInfo *password_info;
365
366                 struct samr_Password lmpassword;
367                 struct samr_Password ntpassword;
368
369                 password_info = talloc_zero(frame, struct netr_PasswordInfo);
370                 if (password_info == NULL) {
371                         TALLOC_FREE(frame);
372                         return NT_STATUS_NO_MEMORY;
373                 }
374
375                 nt_lm_owf_gen(password, ntpassword.hash, lmpassword.hash);
376
377                 password_info->identity_info.domain_name.string         = domain;
378                 password_info->identity_info.parameter_control          = logon_parameters;
379                 password_info->identity_info.logon_id_low               = 0xdead;
380                 password_info->identity_info.logon_id_high              = 0xbeef;
381                 password_info->identity_info.account_name.string        = username;
382                 password_info->identity_info.workstation.string         = workstation_slash;
383
384                 password_info->lmpassword = lmpassword;
385                 password_info->ntpassword = ntpassword;
386
387                 logon->password = password_info;
388
389                 break;
390         }
391         case NetlogonNetworkInformation: {
392                 struct netr_NetworkInfo *network_info;
393                 uint8_t chal[8];
394                 unsigned char local_lm_response[24];
395                 unsigned char local_nt_response[24];
396                 struct netr_ChallengeResponse lm;
397                 struct netr_ChallengeResponse nt;
398
399                 ZERO_STRUCT(lm);
400                 ZERO_STRUCT(nt);
401
402                 network_info = talloc_zero(frame, struct netr_NetworkInfo);
403                 if (network_info == NULL) {
404                         TALLOC_FREE(frame);
405                         return NT_STATUS_NO_MEMORY;
406                 }
407
408                 generate_random_buffer(chal, 8);
409
410                 SMBencrypt(password, chal, local_lm_response);
411                 SMBNTencrypt(password, chal, local_nt_response);
412
413                 lm.length = 24;
414                 lm.data = local_lm_response;
415
416                 nt.length = 24;
417                 nt.data = local_nt_response;
418
419                 network_info->identity_info.domain_name.string          = domain;
420                 network_info->identity_info.parameter_control           = logon_parameters;
421                 network_info->identity_info.logon_id_low                = 0xdead;
422                 network_info->identity_info.logon_id_high               = 0xbeef;
423                 network_info->identity_info.account_name.string         = username;
424                 network_info->identity_info.workstation.string          = workstation_slash;
425
426                 memcpy(network_info->challenge, chal, 8);
427                 network_info->nt = nt;
428                 network_info->lm = lm;
429
430                 logon->network = network_info;
431
432                 break;
433         }
434         default:
435                 DEBUG(0, ("switch value %d not supported\n",
436                         logon_type));
437                 TALLOC_FREE(frame);
438                 return NT_STATUS_INVALID_INFO_CLASS;
439         }
440
441         status = netlogon_creds_cli_LogonSamLogon(creds,
442                                                   binding_handle,
443                                                   logon_type,
444                                                   logon,
445                                                   frame,
446                                                   &validation_level,
447                                                   &validation,
448                                                   authoritative,
449                                                   flags);
450         if (!NT_STATUS_IS_OK(status)) {
451                 TALLOC_FREE(frame);
452                 return status;
453         }
454
455         status = map_validation_to_info3(mem_ctx,
456                                          validation_level, validation,
457                                          info3);
458         TALLOC_FREE(frame);
459         if (!NT_STATUS_IS_OK(status)) {
460                 return status;
461         }
462
463
464         return NT_STATUS_OK;
465 }
466
467 /**
468  * Logon domain user with an 'network' SAM logon
469  *
470  * @param info3 Pointer to a NET_USER_INFO_3 already allocated by the caller.
471  **/
472
473
474 NTSTATUS rpccli_netlogon_network_logon(struct netlogon_creds_cli_context *creds,
475                                        struct dcerpc_binding_handle *binding_handle,
476                                        TALLOC_CTX *mem_ctx,
477                                        uint32_t logon_parameters,
478                                        const char *username,
479                                        const char *domain,
480                                        const char *workstation,
481                                        const uint8_t chal[8],
482                                        DATA_BLOB lm_response,
483                                        DATA_BLOB nt_response,
484                                        uint8_t *authoritative,
485                                        uint32_t *flags,
486                                        struct netr_SamInfo3 **info3)
487 {
488         NTSTATUS status;
489         const char *workstation_name_slash;
490         union netr_LogonLevel *logon = NULL;
491         struct netr_NetworkInfo *network_info;
492         uint16_t validation_level = 0;
493         union netr_Validation *validation = NULL;
494         struct netr_ChallengeResponse lm;
495         struct netr_ChallengeResponse nt;
496
497         *info3 = NULL;
498
499         ZERO_STRUCT(lm);
500         ZERO_STRUCT(nt);
501
502         logon = talloc_zero(mem_ctx, union netr_LogonLevel);
503         if (!logon) {
504                 return NT_STATUS_NO_MEMORY;
505         }
506
507         network_info = talloc_zero(mem_ctx, struct netr_NetworkInfo);
508         if (!network_info) {
509                 return NT_STATUS_NO_MEMORY;
510         }
511
512         if (workstation[0] != '\\' && workstation[1] != '\\') {
513                 workstation_name_slash = talloc_asprintf(mem_ctx, "\\\\%s", workstation);
514         } else {
515                 workstation_name_slash = workstation;
516         }
517
518         if (!workstation_name_slash) {
519                 DEBUG(0, ("talloc_asprintf failed!\n"));
520                 return NT_STATUS_NO_MEMORY;
521         }
522
523         /* Initialise input parameters */
524
525         lm.data = lm_response.data;
526         lm.length = lm_response.length;
527         nt.data = nt_response.data;
528         nt.length = nt_response.length;
529
530         network_info->identity_info.domain_name.string          = domain;
531         network_info->identity_info.parameter_control           = logon_parameters;
532         network_info->identity_info.logon_id_low                = 0xdead;
533         network_info->identity_info.logon_id_high               = 0xbeef;
534         network_info->identity_info.account_name.string         = username;
535         network_info->identity_info.workstation.string          = workstation_name_slash;
536
537         memcpy(network_info->challenge, chal, 8);
538         network_info->nt = nt;
539         network_info->lm = lm;
540
541         logon->network = network_info;
542
543         /* Marshall data and send request */
544
545         status = netlogon_creds_cli_LogonSamLogon(creds,
546                                                   binding_handle,
547                                                   NetlogonNetworkInformation,
548                                                   logon,
549                                                   mem_ctx,
550                                                   &validation_level,
551                                                   &validation,
552                                                   authoritative,
553                                                   flags);
554         if (!NT_STATUS_IS_OK(status)) {
555                 return status;
556         }
557
558         status = map_validation_to_info3(mem_ctx,
559                                          validation_level, validation,
560                                          info3);
561         if (!NT_STATUS_IS_OK(status)) {
562                 return status;
563         }
564
565         return NT_STATUS_OK;
566 }