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