Coverage Report

Created: 2025-07-23 07:04

/src/samba/source3/rpc_client/cli_netlogon.c
Line
Count
Source (jump to first uncovered line)
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 "rpc_client/rpc_client.h"
26
#include "rpc_client/cli_pipe.h"
27
#include "../libcli/auth/libcli_auth.h"
28
#include "../libcli/auth/netlogon_creds_cli.h"
29
#include "../librpc/gen_ndr/ndr_netlogon_c.h"
30
#include "../librpc/gen_ndr/schannel.h"
31
#include "rpc_client/cli_netlogon.h"
32
#include "rpc_client/util_netlogon.h"
33
#include "../libcli/security/security.h"
34
#include "lib/param/param.h"
35
#include "libcli/smb/smbXcli_base.h"
36
#include "dbwrap/dbwrap.h"
37
#include "dbwrap/dbwrap_open.h"
38
#include "util_tdb.h"
39
#include "lib/crypto/gnutls_helpers.h"
40
41
42
NTSTATUS rpccli_pre_open_netlogon_creds(void)
43
0
{
44
0
  static bool already_open = false;
45
0
  TALLOC_CTX *frame;
46
0
  struct loadparm_context *lp_ctx;
47
0
  char *fname;
48
0
  struct db_context *global_db;
49
0
  NTSTATUS status;
50
51
0
  if (already_open) {
52
0
    return NT_STATUS_OK;
53
0
  }
54
55
0
  frame = talloc_stackframe();
56
57
0
  lp_ctx = loadparm_init_s3(frame, loadparm_s3_helpers());
58
0
  if (lp_ctx == NULL) {
59
0
    TALLOC_FREE(frame);
60
0
    return NT_STATUS_NO_MEMORY;
61
0
  }
62
63
0
  fname = lpcfg_private_db_path(frame, lp_ctx, "netlogon_creds_cli");
64
0
  if (fname == NULL) {
65
0
    TALLOC_FREE(frame);
66
0
    return NT_STATUS_NO_MEMORY;
67
0
  }
68
69
0
  global_db = db_open(frame, fname,
70
0
          0, TDB_CLEAR_IF_FIRST|TDB_INCOMPATIBLE_HASH,
71
0
          O_RDWR|O_CREAT, 0600, DBWRAP_LOCK_ORDER_2,
72
0
          DBWRAP_FLAG_OPTIMIZE_READONLY_ACCESS);
73
0
  if (global_db == NULL) {
74
0
    TALLOC_FREE(frame);
75
0
    return NT_STATUS_NO_MEMORY;
76
0
  }
77
78
0
  status = netlogon_creds_cli_set_global_db(lp_ctx, &global_db);
79
0
  TALLOC_FREE(frame);
80
0
  if (!NT_STATUS_IS_OK(status)) {
81
0
    return status;
82
0
  }
83
84
0
  already_open = true;
85
0
  return NT_STATUS_OK;
86
0
}
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
0
{
98
0
  TALLOC_CTX *frame = talloc_stackframe();
99
0
  struct loadparm_context *lp_ctx;
100
0
  NTSTATUS status;
101
102
0
  status = rpccli_pre_open_netlogon_creds();
103
0
  if (!NT_STATUS_IS_OK(status)) {
104
0
    TALLOC_FREE(frame);
105
0
    return status;
106
0
  }
107
108
0
  lp_ctx = loadparm_init_s3(frame, loadparm_s3_helpers());
109
0
  if (lp_ctx == NULL) {
110
0
    TALLOC_FREE(frame);
111
0
    return NT_STATUS_NO_MEMORY;
112
0
  }
113
0
  status = netlogon_creds_cli_context_global(lp_ctx,
114
0
               msg_ctx,
115
0
               client_account,
116
0
               sec_chan_type,
117
0
               server_computer,
118
0
               server_netbios_domain,
119
0
               server_dns_domain,
120
0
               mem_ctx, netlogon_creds);
121
0
  TALLOC_FREE(frame);
122
0
  if (!NT_STATUS_IS_OK(status)) {
123
0
    return status;
124
0
  }
125
126
0
  return NT_STATUS_OK;
127
0
}
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
0
{
136
0
  enum netr_SchannelType sec_chan_type;
137
0
  const char *server_netbios_domain;
138
0
  const char *server_dns_domain;
139
0
  const char *client_account;
140
141
0
  sec_chan_type = cli_credentials_get_secure_channel_type(creds);
142
0
  client_account = cli_credentials_get_username(creds);
143
0
  server_netbios_domain = cli_credentials_get_domain(creds);
144
0
  server_dns_domain = cli_credentials_get_realm(creds);
145
146
0
  return rpccli_create_netlogon_creds(server_computer,
147
0
              server_netbios_domain,
148
0
              server_dns_domain,
149
0
              client_account,
150
0
              sec_chan_type,
151
0
              msg_ctx, mem_ctx,
152
0
              creds_ctx);
153
0
}
154
155
static NTSTATUS rpccli_setup_netlogon_creds_locked(
156
  struct cli_state *cli,
157
  enum dcerpc_transport_t transport,
158
  const char *remote_name,
159
  const struct sockaddr_storage *remote_sockaddr,
160
  struct netlogon_creds_cli_context *creds_ctx,
161
  bool force_reauth,
162
  struct cli_credentials *cli_creds,
163
  TALLOC_CTX *mem_ctx,
164
  struct rpc_pipe_client **_netlogon_pipe,
165
  uint32_t *negotiate_flags)
166
0
{
167
0
  TALLOC_CTX *frame = talloc_stackframe();
168
0
  struct rpc_pipe_client *netlogon_pipe = NULL;
169
0
  struct netlogon_creds_CredentialState *creds = NULL;
170
0
  uint8_t num_nt_hashes = 0;
171
0
  const struct samr_Password *nt_hashes[2] = { NULL, NULL };
172
0
  uint8_t idx_nt_hashes = 0;
173
0
  NTSTATUS status;
174
0
  bool client_use_krb5_netlogon = true;
175
0
  bool reject_aes_servers = true;
176
177
0
  netlogon_creds_cli_use_kerberos(creds_ctx,
178
0
          &client_use_krb5_netlogon,
179
0
          &reject_aes_servers);
180
181
0
  status = netlogon_creds_cli_get(creds_ctx, frame, &creds);
182
0
  if (NT_STATUS_IS_OK(status)) {
183
0
    const char *action = "using";
184
185
0
    if (force_reauth) {
186
0
      action = "overwrite";
187
0
    }
188
189
0
    DEBUG(5,("%s: %s cached netlogon_creds cli[%s/%s] to %s\n",
190
0
       __FUNCTION__, action,
191
0
       creds->account_name, creds->computer_name,
192
0
       remote_name));
193
0
    if (!force_reauth) {
194
0
      goto done;
195
0
    }
196
0
    TALLOC_FREE(creds);
197
0
  }
198
199
0
  nt_hashes[0] = cli_credentials_get_nt_hash(cli_creds, talloc_tos());
200
0
  if (nt_hashes[0] == NULL) {
201
0
    TALLOC_FREE(frame);
202
0
    return NT_STATUS_NO_MEMORY;
203
0
  }
204
0
  num_nt_hashes = 1;
205
206
0
  nt_hashes[1] = cli_credentials_get_old_nt_hash(cli_creds,
207
0
                   talloc_tos());
208
0
  if (nt_hashes[1] != NULL) {
209
0
    num_nt_hashes = 2;
210
0
  }
211
212
0
  if (client_use_krb5_netlogon) {
213
0
    status = cli_rpc_pipe_open_with_creds(cli,
214
0
                  &ndr_table_netlogon,
215
0
                  transport,
216
0
                  DCERPC_AUTH_TYPE_KRB5,
217
0
                  DCERPC_AUTH_LEVEL_PRIVACY,
218
0
                  "netlogon",
219
0
                  remote_name,
220
0
                  remote_sockaddr,
221
0
                  cli_creds,
222
0
                  &netlogon_pipe);
223
0
    if (NT_STATUS_IS_OK(status)) {
224
0
      goto do_auth;
225
0
    }
226
227
0
    if (reject_aes_servers) {
228
0
      DBG_ERR("failed to open krb5 netlogon connection to %s - %s\n",
229
0
         remote_name,
230
0
         nt_errstr(status));
231
0
      TALLOC_FREE(frame);
232
0
      return status;
233
0
    }
234
235
    /* Fall back to noauth */
236
0
  }
237
238
0
  status = cli_rpc_pipe_open_noauth_transport(cli,
239
0
                transport,
240
0
                &ndr_table_netlogon,
241
0
                remote_name,
242
0
                remote_sockaddr,
243
0
                &netlogon_pipe);
244
0
  if (!NT_STATUS_IS_OK(status)) {
245
0
    DEBUG(5,("%s: failed to open noauth netlogon connection to %s - %s\n",
246
0
       __FUNCTION__,
247
0
       remote_name,
248
0
       nt_errstr(status)));
249
0
    TALLOC_FREE(frame);
250
0
    return status;
251
0
  }
252
253
0
do_auth:
254
0
  talloc_steal(frame, netlogon_pipe);
255
256
0
  status = netlogon_creds_cli_auth(creds_ctx,
257
0
           netlogon_pipe->binding_handle,
258
0
           num_nt_hashes,
259
0
           nt_hashes,
260
0
           &idx_nt_hashes);
261
0
  if (!NT_STATUS_IS_OK(status)) {
262
0
    TALLOC_FREE(frame);
263
0
    return status;
264
0
  }
265
266
0
  status = netlogon_creds_cli_get(creds_ctx, frame, &creds);
267
0
  if (!NT_STATUS_IS_OK(status)) {
268
0
    TALLOC_FREE(frame);
269
0
    return NT_STATUS_INTERNAL_ERROR;
270
0
  }
271
272
0
  DEBUG(5,("%s: using new netlogon_creds cli[%s/%s] to %s\n",
273
0
     __FUNCTION__,
274
0
     creds->account_name, creds->computer_name,
275
0
     remote_name));
276
277
0
done:
278
0
  if (_netlogon_pipe != NULL) {
279
0
    *_netlogon_pipe = talloc_move(mem_ctx, &netlogon_pipe);
280
0
  }
281
282
0
  if (negotiate_flags != NULL) {
283
0
    *negotiate_flags = creds->negotiate_flags;
284
0
  }
285
286
0
  TALLOC_FREE(frame);
287
0
  return NT_STATUS_OK;
288
0
}
289
290
NTSTATUS rpccli_setup_netlogon_creds(
291
  struct cli_state *cli,
292
  enum dcerpc_transport_t transport,
293
  const char *remote_name,
294
  const struct sockaddr_storage *remote_sockaddr,
295
  struct netlogon_creds_cli_context *creds_ctx,
296
  bool force_reauth,
297
  struct cli_credentials *cli_creds)
298
0
{
299
0
  TALLOC_CTX *frame = talloc_stackframe();
300
0
  struct netlogon_creds_cli_lck *lck;
301
0
  NTSTATUS status;
302
303
0
  status = netlogon_creds_cli_lck(
304
0
    creds_ctx, NETLOGON_CREDS_CLI_LCK_EXCLUSIVE,
305
0
    frame, &lck);
306
0
  if (!NT_STATUS_IS_OK(status)) {
307
0
    DBG_WARNING("netlogon_creds_cli_lck failed: %s\n",
308
0
          nt_errstr(status));
309
0
    TALLOC_FREE(frame);
310
0
    return status;
311
0
  }
312
313
0
  status = rpccli_setup_netlogon_creds_locked(cli,
314
0
                transport,
315
0
                remote_name,
316
0
                remote_sockaddr,
317
0
                creds_ctx,
318
0
                force_reauth,
319
0
                cli_creds,
320
0
                NULL,
321
0
                NULL,
322
0
                NULL);
323
324
0
  TALLOC_FREE(frame);
325
326
0
  return status;
327
0
}
328
329
NTSTATUS rpccli_connect_netlogon(
330
  struct cli_state *cli,
331
  enum dcerpc_transport_t transport,
332
  const char *remote_name,
333
  const struct sockaddr_storage *remote_sockaddr,
334
  struct netlogon_creds_cli_context *creds_ctx,
335
  bool force_reauth,
336
  struct cli_credentials *trust_creds,
337
  struct rpc_pipe_client **_rpccli)
338
0
{
339
0
  TALLOC_CTX *frame = talloc_stackframe();
340
0
  struct netlogon_creds_CredentialState *creds = NULL;
341
0
  enum netlogon_creds_cli_lck_type lck_type;
342
0
  enum netr_SchannelType sec_chan_type;
343
0
  struct netlogon_creds_cli_lck *lck = NULL;
344
0
  uint32_t negotiate_flags;
345
0
  bool authenticate_kerberos = false;
346
0
  uint8_t found_session_key[16] = {0};
347
0
  bool found_existing_creds = false;
348
0
  bool do_serverauth;
349
0
  struct rpc_pipe_client *rpccli;
350
0
  NTSTATUS status;
351
0
  bool retry = false;
352
353
0
  sec_chan_type = cli_credentials_get_secure_channel_type(trust_creds);
354
0
  if (sec_chan_type == SEC_CHAN_NULL) {
355
0
    DBG_ERR("secure_channel_type gave SEC_CHAN_NULL\n");
356
0
    status = NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
357
0
    goto fail;
358
0
  }
359
360
0
again:
361
362
  /*
363
   * See whether we can use existing netlogon_creds or
364
   * whether we have to serverauthenticate.
365
   */
366
0
  status = netlogon_creds_cli_get(creds_ctx, frame, &creds);
367
368
0
  if (NT_STATUS_IS_OK(status)) {
369
0
    bool cmp = mem_equal_const_time(found_session_key,
370
0
            creds->session_key,
371
0
            sizeof(found_session_key));
372
0
    found_existing_creds = !cmp;
373
374
0
    memcpy(found_session_key,
375
0
           creds->session_key,
376
0
           sizeof(found_session_key));
377
378
0
    authenticate_kerberos = creds->authenticate_kerberos;
379
0
    TALLOC_FREE(creds);
380
0
  }
381
382
0
  lck_type = (force_reauth || !found_existing_creds) ?
383
0
    NETLOGON_CREDS_CLI_LCK_EXCLUSIVE :
384
0
    NETLOGON_CREDS_CLI_LCK_SHARED;
385
386
0
  status = netlogon_creds_cli_lck(creds_ctx, lck_type, frame, &lck);
387
0
  if (!NT_STATUS_IS_OK(status)) {
388
0
    DBG_DEBUG("netlogon_creds_cli_lck failed: %s\n",
389
0
        nt_errstr(status));
390
0
    goto fail;
391
0
  }
392
393
0
  if (!found_existing_creds) {
394
    /*
395
     * Try to find creds under the lock again. Someone
396
     * else might have done it for us.
397
     */
398
0
    status = netlogon_creds_cli_get(creds_ctx, frame, &creds);
399
400
0
    if (NT_STATUS_IS_OK(status)) {
401
0
      bool cmp = mem_equal_const_time(found_session_key,
402
0
              creds->session_key,
403
0
              sizeof(found_session_key));
404
0
      found_existing_creds = !cmp;
405
406
0
      memcpy(found_session_key, creds->session_key,
407
0
             sizeof(found_session_key));
408
409
0
      authenticate_kerberos = creds->authenticate_kerberos;
410
0
      TALLOC_FREE(creds);
411
0
    }
412
0
  }
413
414
0
  do_serverauth = force_reauth || !found_existing_creds;
415
416
0
  if (!do_serverauth) {
417
0
    if (authenticate_kerberos) {
418
      /*
419
       * Do the quick krb5 bind without a reauth
420
       */
421
0
      status = cli_rpc_pipe_open_with_creds(cli,
422
0
                    &ndr_table_netlogon,
423
0
                    transport,
424
0
                    DCERPC_AUTH_TYPE_KRB5,
425
0
                    DCERPC_AUTH_LEVEL_PRIVACY,
426
0
                    "netlogon",
427
0
                    remote_name,
428
0
                    remote_sockaddr,
429
0
                    trust_creds,
430
0
                    &rpccli);
431
0
      if (NT_STATUS_IS_OK(status)) {
432
0
        goto done;
433
0
      }
434
435
0
      if (!retry) {
436
0
        DBG_DEBUG("Retrying with serverauthenticate\n");
437
0
        TALLOC_FREE(lck);
438
0
        force_reauth = true;
439
0
        retry = true;
440
0
        goto again;
441
0
      }
442
0
      DBG_DEBUG("cli_rpc_pipe_open_with_creds(krb5) "
443
0
          "failed: %s\n", nt_errstr(status));
444
0
      goto fail;
445
0
    }
446
447
    /*
448
     * Do the quick schannel bind without a reauth
449
     */
450
0
    status = cli_rpc_pipe_open_bind_schannel(cli,
451
0
               &ndr_table_netlogon,
452
0
               transport,
453
0
               creds_ctx,
454
0
               remote_name,
455
0
               remote_sockaddr,
456
0
               &rpccli);
457
0
    if (!retry && NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_ACCESS_DENIED)) {
458
0
      DBG_DEBUG("Retrying with serverauthenticate\n");
459
0
      TALLOC_FREE(lck);
460
0
      force_reauth = true;
461
0
      retry = true;
462
0
      goto again;
463
0
    }
464
0
    if (!NT_STATUS_IS_OK(status)) {
465
0
      DBG_DEBUG("cli_rpc_pipe_open_bind_schannel "
466
0
          "failed: %s\n", nt_errstr(status));
467
0
      goto fail;
468
0
    }
469
0
    goto done;
470
0
  }
471
472
0
  if (cli_credentials_is_anonymous(trust_creds)) {
473
0
    DBG_WARNING("get_trust_credential for %s only gave anonymous,"
474
0
          "unable to negotiate NETLOGON credentials\n",
475
0
          netlogon_creds_cli_debug_string(
476
0
            creds_ctx, frame));
477
0
    status = NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
478
0
    goto fail;
479
0
  }
480
481
0
  status = rpccli_setup_netlogon_creds_locked(cli,
482
0
                transport,
483
0
                remote_name,
484
0
                remote_sockaddr,
485
0
                creds_ctx,
486
0
                true,
487
0
                trust_creds,
488
0
                NULL,
489
0
                &rpccli,
490
0
                &negotiate_flags);
491
0
  if (!NT_STATUS_IS_OK(status)) {
492
0
    DBG_DEBUG("rpccli_setup_netlogon_creds failed for %s, "
493
0
        "unable to setup NETLOGON credentials: %s\n",
494
0
        netlogon_creds_cli_debug_string(
495
0
          creds_ctx, frame),
496
0
        nt_errstr(status));
497
0
    goto fail;
498
0
  }
499
0
  talloc_steal(frame, rpccli);
500
501
0
  if (!(negotiate_flags & NETLOGON_NEG_AUTHENTICATED_RPC)) {
502
0
    if (lp_winbind_sealed_pipes() || lp_require_strong_key()) {
503
0
      status = NT_STATUS_DOWNGRADE_DETECTED;
504
0
      DBG_WARNING("Unwilling to make connection to %s"
505
0
            "without connection level security, "
506
0
            "must set 'winbind sealed pipes = false'"
507
0
            " and 'require strong key = false' "
508
0
            "to proceed: %s\n",
509
0
            netlogon_creds_cli_debug_string(
510
0
              creds_ctx, frame),
511
0
            nt_errstr(status));
512
0
      goto fail;
513
0
    }
514
515
    /*
516
     * we keep the AUTH_TYPE_NONE rpccli for the
517
     * caller...
518
     */
519
0
    goto done;
520
0
  }
521
522
0
  if (negotiate_flags & NETLOGON_NEG_SUPPORTS_KERBEROS_AUTH) {
523
    /*
524
     * we keep the AUTH_TYPE_KRB5 rpccli for the
525
     * caller...
526
     */
527
0
    goto check;
528
0
  }
529
530
0
  status = cli_rpc_pipe_client_prepare_alter(rpccli,
531
0
               true, /* new_auth_context */
532
0
               &ndr_table_netlogon,
533
0
               false); /* new_pres_context */
534
0
  if (!NT_STATUS_IS_OK(status)) {
535
0
    DBG_WARNING("cli_rpc_pipe_client_prepare_alter "
536
0
          "failed: %s\n", nt_errstr(status));
537
0
    goto fail;
538
0
  }
539
540
0
  status = cli_rpc_pipe_client_auth_schannel(rpccli,
541
0
               &ndr_table_netlogon,
542
0
               creds_ctx);
543
0
  if (!NT_STATUS_IS_OK(status)) {
544
0
    DBG_DEBUG("cli_rpc_pipe_client_auth_schannel "
545
0
        "failed: %s\n", nt_errstr(status));
546
0
    goto fail;
547
0
  }
548
549
0
check:
550
0
  status = netlogon_creds_cli_check(creds_ctx, rpccli->binding_handle,
551
0
            NULL);
552
0
  if (!NT_STATUS_IS_OK(status)) {
553
0
    DBG_WARNING("netlogon_creds_cli_check failed: %s\n",
554
0
          nt_errstr(status));
555
0
    goto fail;
556
0
  }
557
558
0
done:
559
0
  *_rpccli = talloc_move(NULL, &rpccli);
560
0
  status = NT_STATUS_OK;
561
0
fail:
562
0
  ZERO_STRUCT(found_session_key);
563
0
  TALLOC_FREE(lck);
564
0
  TALLOC_FREE(frame);
565
0
  return status;
566
0
}
567
568
/* Logon domain user */
569
570
NTSTATUS rpccli_netlogon_password_logon(
571
  struct netlogon_creds_cli_context *creds_ctx,
572
  struct dcerpc_binding_handle *binding_handle,
573
  TALLOC_CTX *mem_ctx,
574
  uint32_t logon_parameters,
575
  const char *domain,
576
  const char *username,
577
  const char *password,
578
  const char *workstation,
579
  const uint64_t logon_id,
580
  enum netr_LogonInfoClass logon_type,
581
  uint8_t *authoritative,
582
  uint32_t *flags,
583
  uint16_t *_validation_level,
584
  union netr_Validation **_validation)
585
0
{
586
0
  TALLOC_CTX *frame = talloc_stackframe();
587
0
  NTSTATUS status;
588
0
  union netr_LogonLevel *logon;
589
0
  uint16_t validation_level = 0;
590
0
  union netr_Validation *validation = NULL;
591
0
  char *workstation_slash = NULL;
592
593
0
  unsigned char local_nt_response[24];
594
0
  unsigned char local_lm_response[24];
595
0
  struct samr_Password lmpassword = {.hash = {0}};
596
0
  struct samr_Password ntpassword = {.hash = {0}};
597
0
  struct netr_ChallengeResponse lm = {0};
598
0
  struct netr_ChallengeResponse nt = {0};
599
600
0
  logon = talloc_zero(frame, union netr_LogonLevel);
601
0
  if (logon == NULL) {
602
0
    TALLOC_FREE(frame);
603
0
    return NT_STATUS_NO_MEMORY;
604
0
  }
605
606
0
  if (workstation == NULL) {
607
0
    workstation = lp_netbios_name();
608
0
  }
609
610
0
  workstation_slash = talloc_asprintf(frame, "\\\\%s", workstation);
611
0
  if (workstation_slash == NULL) {
612
0
    TALLOC_FREE(frame);
613
0
    return NT_STATUS_NO_MEMORY;
614
0
  }
615
616
  /* Initialise input parameters */
617
618
0
  switch (logon_type) {
619
0
  case NetlogonInteractiveInformation:
620
0
  case NetlogonInteractiveTransitiveInformation: {
621
622
0
    struct netr_PasswordInfo *password_info;
623
624
625
0
    password_info = talloc_zero(frame, struct netr_PasswordInfo);
626
0
    if (password_info == NULL) {
627
0
      TALLOC_FREE(frame);
628
0
      return NT_STATUS_NO_MEMORY;
629
0
    }
630
631
0
    nt_lm_owf_gen(password, ntpassword.hash, lmpassword.hash);
632
633
0
    password_info->identity_info.domain_name.string   = domain;
634
0
    password_info->identity_info.parameter_control    = logon_parameters;
635
0
    password_info->identity_info.logon_id     = logon_id;
636
0
    password_info->identity_info.account_name.string  = username;
637
0
    password_info->identity_info.workstation.string   = workstation_slash;
638
639
0
    password_info->lmpassword = lmpassword;
640
0
    password_info->ntpassword = ntpassword;
641
642
0
    logon->password = password_info;
643
644
0
    break;
645
0
  }
646
0
  case NetlogonNetworkInformation:
647
0
  case NetlogonNetworkTransitiveInformation: {
648
0
    struct netr_NetworkInfo *network_info;
649
0
    uint8_t chal[8];
650
0
    int rc;
651
652
0
    ZERO_STRUCT(lm);
653
0
    ZERO_STRUCT(nt);
654
655
0
    network_info = talloc_zero(frame, struct netr_NetworkInfo);
656
0
    if (network_info == NULL) {
657
0
      TALLOC_FREE(frame);
658
0
      return NT_STATUS_NO_MEMORY;
659
0
    }
660
661
0
    generate_random_buffer(chal, 8);
662
663
0
    SMBencrypt(password, chal, local_lm_response);
664
0
    rc = SMBNTencrypt(password, chal, local_nt_response);
665
0
    if (rc != 0) {
666
0
      TALLOC_FREE(frame);
667
0
      return gnutls_error_to_ntstatus(rc, NT_STATUS_ACCESS_DISABLED_BY_POLICY_OTHER);
668
0
    }
669
670
0
    lm.length = 24;
671
0
    lm.data = local_lm_response;
672
673
0
    nt.length = 24;
674
0
    nt.data = local_nt_response;
675
676
0
    network_info->identity_info.domain_name.string    = domain;
677
0
    network_info->identity_info.parameter_control   = logon_parameters;
678
0
    network_info->identity_info.logon_id      = logon_id;
679
0
    network_info->identity_info.account_name.string   = username;
680
0
    network_info->identity_info.workstation.string    = workstation_slash;
681
682
0
    memcpy(network_info->challenge, chal, 8);
683
0
    network_info->nt = nt;
684
0
    network_info->lm = lm;
685
686
0
    logon->network = network_info;
687
688
0
    break;
689
0
  }
690
0
  default:
691
0
    DEBUG(0, ("switch value %d not supported\n",
692
0
      logon_type));
693
0
    TALLOC_FREE(frame);
694
0
    return NT_STATUS_INVALID_INFO_CLASS;
695
0
  }
696
697
0
  status = netlogon_creds_cli_LogonSamLogon(creds_ctx,
698
0
              binding_handle,
699
0
              logon_type,
700
0
              logon,
701
0
              mem_ctx,
702
0
              &validation_level,
703
0
              &validation,
704
0
              authoritative,
705
0
              flags);
706
0
  if (!NT_STATUS_IS_OK(status)) {
707
0
    TALLOC_FREE(frame);
708
0
    return status;
709
0
  }
710
711
0
  TALLOC_FREE(frame);
712
0
  *_validation_level = validation_level;
713
0
  *_validation = validation;
714
715
0
  return NT_STATUS_OK;
716
0
}
717
718
/**
719
 * Logon domain user with an 'network' SAM logon
720
 *
721
 * @param info3 Pointer to a NET_USER_INFO_3 already allocated by the caller.
722
 **/
723
724
725
NTSTATUS rpccli_netlogon_network_logon(
726
  struct netlogon_creds_cli_context *creds_ctx,
727
  struct dcerpc_binding_handle *binding_handle,
728
  TALLOC_CTX *mem_ctx,
729
  uint32_t logon_parameters,
730
  const char *username,
731
  const char *domain,
732
  const char *workstation,
733
  const uint64_t logon_id,
734
  DATA_BLOB chal,
735
  DATA_BLOB lm_response,
736
  DATA_BLOB nt_response,
737
  enum netr_LogonInfoClass logon_type,
738
  uint8_t *authoritative,
739
  uint32_t *flags,
740
  uint16_t *_validation_level,
741
  union netr_Validation **_validation)
742
0
{
743
0
  NTSTATUS status;
744
0
  const char *workstation_name_slash;
745
0
  union netr_LogonLevel *logon = NULL;
746
0
  struct netr_NetworkInfo *network_info;
747
0
  uint16_t validation_level = 0;
748
0
  union netr_Validation *validation = NULL;
749
0
  struct netr_ChallengeResponse lm;
750
0
  struct netr_ChallengeResponse nt;
751
752
0
  *_validation = NULL;
753
754
0
  ZERO_STRUCT(lm);
755
0
  ZERO_STRUCT(nt);
756
757
0
  switch (logon_type) {
758
0
  case NetlogonNetworkInformation:
759
0
  case NetlogonNetworkTransitiveInformation:
760
0
    break;
761
0
  default:
762
0
    DEBUG(0, ("switch value %d not supported\n",
763
0
      logon_type));
764
0
    return NT_STATUS_INVALID_INFO_CLASS;
765
0
  }
766
767
0
  logon = talloc_zero(mem_ctx, union netr_LogonLevel);
768
0
  if (!logon) {
769
0
    return NT_STATUS_NO_MEMORY;
770
0
  }
771
772
0
  network_info = talloc_zero(mem_ctx, struct netr_NetworkInfo);
773
0
  if (!network_info) {
774
0
    return NT_STATUS_NO_MEMORY;
775
0
  }
776
777
0
  if (workstation == NULL) {
778
0
    workstation = lp_netbios_name();
779
0
  }
780
781
0
  if (workstation[0] != '\\' && workstation[1] != '\\') {
782
0
    workstation_name_slash = talloc_asprintf(mem_ctx, "\\\\%s", workstation);
783
0
  } else {
784
0
    workstation_name_slash = workstation;
785
0
  }
786
787
0
  if (!workstation_name_slash) {
788
0
    DEBUG(0, ("talloc_asprintf failed!\n"));
789
0
    return NT_STATUS_NO_MEMORY;
790
0
  }
791
792
  /* Initialise input parameters */
793
794
0
  lm.data = lm_response.data;
795
0
  lm.length = lm_response.length;
796
0
  nt.data = nt_response.data;
797
0
  nt.length = nt_response.length;
798
799
0
  network_info->identity_info.domain_name.string    = domain;
800
0
  network_info->identity_info.parameter_control   = logon_parameters;
801
0
  network_info->identity_info.logon_id      = logon_id;
802
0
  network_info->identity_info.account_name.string   = username;
803
0
  network_info->identity_info.workstation.string    = workstation_name_slash;
804
805
0
  if (chal.length != 8) {
806
0
    DBG_WARNING("Invalid challenge length %zd\n", chal.length);
807
0
    return NT_STATUS_INVALID_PARAMETER;
808
0
  }
809
810
0
  memcpy(network_info->challenge, chal.data, chal.length);
811
0
  network_info->nt = nt;
812
0
  network_info->lm = lm;
813
814
0
  logon->network = network_info;
815
816
  /* Marshall data and send request */
817
818
0
  status = netlogon_creds_cli_LogonSamLogon(creds_ctx,
819
0
              binding_handle,
820
0
              logon_type,
821
0
              logon,
822
0
              mem_ctx,
823
0
              &validation_level,
824
0
              &validation,
825
0
              authoritative,
826
0
              flags);
827
0
  if (!NT_STATUS_IS_OK(status)) {
828
0
    return status;
829
0
  }
830
831
0
  *_validation_level = validation_level;
832
0
  *_validation = validation;
833
834
0
  return NT_STATUS_OK;
835
0
}
836
837
NTSTATUS rpccli_netlogon_interactive_logon(
838
  struct netlogon_creds_cli_context *creds_ctx,
839
  struct dcerpc_binding_handle *binding_handle,
840
  TALLOC_CTX *mem_ctx,
841
  uint32_t logon_parameters,
842
  const char *username,
843
  const char *domain,
844
  const char *workstation,
845
  const uint64_t logon_id,
846
  DATA_BLOB lm_hash,
847
  DATA_BLOB nt_hash,
848
  enum netr_LogonInfoClass logon_type,
849
  uint8_t *authoritative,
850
  uint32_t *flags,
851
  uint16_t *_validation_level,
852
  union netr_Validation **_validation)
853
0
{
854
0
  TALLOC_CTX *frame = talloc_stackframe();
855
0
  NTSTATUS status;
856
0
  const char *workstation_name_slash;
857
0
  union netr_LogonLevel *logon = NULL;
858
0
  struct netr_PasswordInfo *password_info = NULL;
859
0
  uint16_t validation_level = 0;
860
0
  union netr_Validation *validation = NULL;
861
0
  struct netr_ChallengeResponse lm;
862
0
  struct netr_ChallengeResponse nt;
863
864
0
  *_validation = NULL;
865
866
0
  ZERO_STRUCT(lm);
867
0
  ZERO_STRUCT(nt);
868
869
0
  switch (logon_type) {
870
0
  case NetlogonInteractiveInformation:
871
0
  case NetlogonInteractiveTransitiveInformation:
872
0
    break;
873
0
  default:
874
0
    DEBUG(0, ("switch value %d not supported\n",
875
0
      logon_type));
876
0
    TALLOC_FREE(frame);
877
0
    return NT_STATUS_INVALID_INFO_CLASS;
878
0
  }
879
880
0
  logon = talloc_zero(mem_ctx, union netr_LogonLevel);
881
0
  if (logon == NULL) {
882
0
    TALLOC_FREE(frame);
883
0
    return NT_STATUS_NO_MEMORY;
884
0
  }
885
886
0
  password_info = talloc_zero(logon, struct netr_PasswordInfo);
887
0
  if (password_info == NULL) {
888
0
    TALLOC_FREE(frame);
889
0
    return NT_STATUS_NO_MEMORY;
890
0
  }
891
892
0
  if (workstation[0] != '\\' && workstation[1] != '\\') {
893
0
    workstation_name_slash = talloc_asprintf(frame, "\\\\%s", workstation);
894
0
  } else {
895
0
    workstation_name_slash = workstation;
896
0
  }
897
898
0
  if (workstation_name_slash == NULL) {
899
0
    TALLOC_FREE(frame);
900
0
    return NT_STATUS_NO_MEMORY;
901
0
  }
902
903
  /* Initialise input parameters */
904
905
0
  password_info->identity_info.domain_name.string   = domain;
906
0
  password_info->identity_info.parameter_control    = logon_parameters;
907
0
  password_info->identity_info.logon_id     = logon_id;
908
0
  password_info->identity_info.account_name.string  = username;
909
0
  password_info->identity_info.workstation.string   = workstation_name_slash;
910
911
0
  if (nt_hash.length != sizeof(password_info->ntpassword.hash)) {
912
0
    TALLOC_FREE(frame);
913
0
    return NT_STATUS_INVALID_PARAMETER;
914
0
  }
915
0
  memcpy(password_info->ntpassword.hash, nt_hash.data, nt_hash.length);
916
0
  if (lm_hash.length != 0) {
917
0
    if (lm_hash.length != sizeof(password_info->lmpassword.hash)) {
918
0
      TALLOC_FREE(frame);
919
0
      return NT_STATUS_INVALID_PARAMETER;
920
0
    }
921
0
    memcpy(password_info->lmpassword.hash, lm_hash.data, lm_hash.length);
922
0
  }
923
924
0
  logon->password = password_info;
925
926
  /* Marshall data and send request */
927
928
0
  status = netlogon_creds_cli_LogonSamLogon(creds_ctx,
929
0
              binding_handle,
930
0
              logon_type,
931
0
              logon,
932
0
              mem_ctx,
933
0
              &validation_level,
934
0
              &validation,
935
0
              authoritative,
936
0
              flags);
937
0
  if (!NT_STATUS_IS_OK(status)) {
938
0
    TALLOC_FREE(frame);
939
0
    return status;
940
0
  }
941
942
0
  *_validation_level = validation_level;
943
0
  *_validation = validation;
944
945
0
  TALLOC_FREE(frame);
946
0
  return NT_STATUS_OK;
947
0
}