Coverage Report

Created: 2026-07-25 07:00

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/samba/auth/kerberos/kerberos_pac.c
Line
Count
Source
1
/*
2
   Unix SMB/CIFS implementation.
3
   kerberos authorization data (PAC) utility library
4
   Copyright (C) Jim McDonough <jmcd@us.ibm.com> 2003
5
   Copyright (C) Andrew Bartlett <abartlet@samba.org> 2004-2005
6
   Copyright (C) Andrew Tridgell 2001
7
   Copyright (C) Luke Howard 2002-2003
8
   Copyright (C) Stefan Metzmacher 2004-2005
9
   Copyright (C) Guenther Deschner 2005,2007,2008
10
11
   This program is free software; you can redistribute it and/or modify
12
   it under the terms of the GNU General Public License as published by
13
   the Free Software Foundation; either version 3 of the License, or
14
   (at your option) any later version.
15
16
   This program is distributed in the hope that it will be useful,
17
   but WITHOUT ANY WARRANTY; without even the implied warranty of
18
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19
   GNU General Public License for more details.
20
21
   You should have received a copy of the GNU General Public License
22
   along with this program.  If not, see <http://www.gnu.org/licenses/>.
23
*/
24
25
#include "includes.h"
26
27
#undef DBGC_CLASS
28
0
#define DBGC_CLASS DBGC_AUTH
29
30
#ifdef HAVE_KRB5
31
32
#include "librpc/gen_ndr/ndr_krb5pac.h"
33
#include "librpc/gen_ndr/auth.h"
34
#include "auth/common_auth.h"
35
#include "auth/kerberos/pac_utils.h"
36
#include "lib/krb5_wrap/krb5_samba.h"
37
38
krb5_error_code check_pac_checksum(DATA_BLOB pac_data,
39
            struct PAC_SIGNATURE_DATA *sig,
40
            krb5_context context,
41
            const krb5_keyblock *keyblock)
42
0
{
43
0
  krb5_error_code ret;
44
0
  krb5_checksum cksum;
45
0
  krb5_keyusage usage = 0;
46
0
  krb5_boolean checksum_valid = false;
47
0
  krb5_data input;
48
0
  size_t idx = 0;
49
0
  struct {
50
0
    krb5_cksumtype cksum_type;
51
0
    krb5_enctype enc_type;
52
0
  } supported_types[] = {
53
0
    {CKSUMTYPE_HMAC_SHA1_96_AES_256, ENCTYPE_AES256_CTS_HMAC_SHA1_96},
54
0
    {CKSUMTYPE_HMAC_SHA1_96_AES_128, ENCTYPE_AES128_CTS_HMAC_SHA1_96},
55
    /* RFC8009 types. Not supported by AD yet but used by FreeIPA and MIT Kerberos */
56
0
    {CKSUMTYPE_HMAC_SHA256_128_AES128, ENCTYPE_AES128_CTS_HMAC_SHA256_128},
57
0
    {CKSUMTYPE_HMAC_SHA384_192_AES256, ENCTYPE_AES256_CTS_HMAC_SHA384_192},
58
0
  };
59
0
  size_t num_supported_types = ARRAY_SIZE(supported_types);
60
61
0
  for (idx = 0; idx < num_supported_types; idx++) {
62
0
    if (sig->type == supported_types[idx].cksum_type) {
63
0
      if (KRB5_KEY_TYPE(keyblock) != supported_types[idx].enc_type) {
64
0
        return EINVAL;
65
0
      }
66
      /* ok */
67
0
      break;
68
0
    }
69
0
  }
70
71
  /* do not do key type check for HMAC-MD5 */
72
0
  if ((sig->type != CKSUMTYPE_HMAC_MD5) &&
73
0
      (idx == num_supported_types)) {
74
0
    DEBUG(2,("check_pac_checksum: Checksum Type %d is not supported\n",
75
0
      (int)sig->type));
76
0
    return EINVAL;
77
0
  }
78
79
0
#ifdef HAVE_CHECKSUM_IN_KRB5_CHECKSUM /* Heimdal */
80
0
  cksum.cksumtype = (krb5_cksumtype)sig->type;
81
0
  cksum.checksum.length = sig->signature.length;
82
0
  cksum.checksum.data = sig->signature.data;
83
#else /* MIT */
84
  cksum.checksum_type = (krb5_cksumtype)sig->type;
85
  cksum.length    = sig->signature.length;
86
  cksum.contents    = sig->signature.data;
87
#endif
88
89
0
#ifdef HAVE_KRB5_KU_OTHER_CKSUM /* Heimdal */
90
0
  usage = KRB5_KU_OTHER_CKSUM;
91
#elif defined(HAVE_KRB5_KEYUSAGE_APP_DATA_CKSUM) /* MIT */
92
  usage = KRB5_KEYUSAGE_APP_DATA_CKSUM;
93
#else
94
#error UNKNOWN_KRB5_KEYUSAGE
95
#endif
96
97
0
  input.data = (char *)pac_data.data;
98
0
  input.length = pac_data.length;
99
100
0
  ret = krb5_c_verify_checksum(context,
101
0
             keyblock,
102
0
             usage,
103
0
             &input,
104
0
             &cksum,
105
0
             &checksum_valid);
106
0
  if (!checksum_valid) {
107
0
    ret = KRB5KRB_AP_ERR_BAD_INTEGRITY;
108
0
  }
109
0
  if (ret){
110
0
    DEBUG(2,("check_pac_checksum: PAC Verification failed: %s (%d)\n",
111
0
      error_message(ret), ret));
112
0
    return ret;
113
0
  }
114
115
0
  return ret;
116
0
}
117
118
/**
119
* @brief Decode a blob containing a NDR encoded PAC structure
120
*
121
* @param mem_ctx    - The memory context
122
* @param pac_data_blob    - The data blob containing the NDR encoded data
123
* @param context    - The Kerberos Context
124
* @param service_keyblock - The Service Key used to verify the checksum
125
* @param client_principal - The client principal
126
* @param tgs_authtime     - The ticket timestamp
127
* @param pac_data_out   - [out] The decoded PAC
128
*
129
* @return - A NTSTATUS error code
130
*/
131
NTSTATUS kerberos_decode_pac(TALLOC_CTX *mem_ctx,
132
           DATA_BLOB pac_data_blob,
133
           krb5_context context,
134
           const krb5_keyblock *krbtgt_keyblock,
135
           const krb5_keyblock *service_keyblock,
136
           krb5_const_principal client_principal,
137
           time_t tgs_authtime,
138
           struct PAC_DATA **pac_data_out)
139
0
{
140
0
  NTSTATUS status = NT_STATUS_NO_MEMORY;
141
0
  enum ndr_err_code ndr_err;
142
0
  krb5_error_code ret;
143
0
  DATA_BLOB modified_pac_blob;
144
145
0
  NTTIME tgs_authtime_nttime;
146
0
  uint32_t i;
147
148
0
  struct PAC_SIGNATURE_DATA *srv_sig_ptr = NULL;
149
0
  struct PAC_SIGNATURE_DATA *kdc_sig_ptr = NULL;
150
0
  struct PAC_SIGNATURE_DATA *srv_sig_wipe = NULL;
151
0
  struct PAC_SIGNATURE_DATA *kdc_sig_wipe = NULL;
152
0
  struct PAC_LOGON_NAME *logon_name = NULL;
153
0
  struct PAC_LOGON_INFO *logon_info = NULL;
154
0
  struct PAC_DATA *pac_data = NULL;
155
0
  struct PAC_DATA_RAW *pac_data_raw = NULL;
156
157
0
  DATA_BLOB *srv_sig_blob = NULL;
158
0
  DATA_BLOB *kdc_sig_blob = NULL;
159
160
0
  bool bool_ret;
161
162
0
  TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
163
0
  if (!tmp_ctx) {
164
0
    return NT_STATUS_NO_MEMORY;
165
0
  }
166
167
0
  if (pac_data_out) {
168
0
    *pac_data_out = NULL;
169
0
  }
170
171
0
  pac_data = talloc(tmp_ctx, struct PAC_DATA);
172
0
  pac_data_raw = talloc(tmp_ctx, struct PAC_DATA_RAW);
173
0
  kdc_sig_wipe = talloc(tmp_ctx, struct PAC_SIGNATURE_DATA);
174
0
  srv_sig_wipe = talloc(tmp_ctx, struct PAC_SIGNATURE_DATA);
175
0
  if (!pac_data_raw || !pac_data || !kdc_sig_wipe || !srv_sig_wipe) {
176
0
    status = NT_STATUS_NO_MEMORY;
177
0
    goto out;
178
0
  }
179
180
0
  ndr_err = ndr_pull_struct_blob(&pac_data_blob, pac_data, pac_data,
181
0
           (ndr_pull_flags_fn_t)ndr_pull_PAC_DATA);
182
0
  if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
183
0
    status = ndr_map_error2ntstatus(ndr_err);
184
0
    DEBUG(0,("can't parse the PAC: %s\n",
185
0
      nt_errstr(status)));
186
0
    goto out;
187
0
  }
188
189
0
  if (pac_data->num_buffers < 4) {
190
    /* we need logon_info, service_key and kdc_key */
191
0
    DEBUG(0,("less than 4 PAC buffers\n"));
192
0
    status = NT_STATUS_INVALID_PARAMETER;
193
0
    goto out;
194
0
  }
195
196
0
  ndr_err = ndr_pull_struct_blob(
197
0
        &pac_data_blob, pac_data_raw, pac_data_raw,
198
0
        (ndr_pull_flags_fn_t)ndr_pull_PAC_DATA_RAW);
199
0
  if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
200
0
    status = ndr_map_error2ntstatus(ndr_err);
201
0
    DEBUG(0,("can't parse the PAC: %s\n",
202
0
      nt_errstr(status)));
203
0
    goto out;
204
0
  }
205
206
0
  if (pac_data_raw->num_buffers < 4) {
207
    /* we need logon_info, service_key and kdc_key */
208
0
    DEBUG(0,("less than 4 PAC buffers\n"));
209
0
    status = NT_STATUS_INVALID_PARAMETER;
210
0
    goto out;
211
0
  }
212
213
0
  if (pac_data->num_buffers != pac_data_raw->num_buffers) {
214
    /* we need logon_info, service_key and kdc_key */
215
0
    DEBUG(0, ("misparse! PAC_DATA has %d buffers while "
216
0
        "PAC_DATA_RAW has %d\n", pac_data->num_buffers,
217
0
        pac_data_raw->num_buffers));
218
0
    status = NT_STATUS_INVALID_PARAMETER;
219
0
    goto out;
220
0
  }
221
222
0
  for (i=0; i < pac_data->num_buffers; i++) {
223
0
    struct PAC_BUFFER *data_buf = &pac_data->buffers[i];
224
0
    struct PAC_BUFFER_RAW *raw_buf = &pac_data_raw->buffers[i];
225
226
0
    if (data_buf->type != raw_buf->type) {
227
0
      DEBUG(0, ("misparse! PAC_DATA buffer %d has type "
228
0
          "%d while PAC_DATA_RAW has %d\n", i,
229
0
          data_buf->type, raw_buf->type));
230
0
      status = NT_STATUS_INVALID_PARAMETER;
231
0
      goto out;
232
0
    }
233
0
    switch (data_buf->type) {
234
0
    case PAC_TYPE_LOGON_INFO:
235
0
      if (!data_buf->info) {
236
0
        break;
237
0
      }
238
0
      logon_info = data_buf->info->logon_info.info;
239
0
      break;
240
0
    case PAC_TYPE_SRV_CHECKSUM:
241
0
      if (!data_buf->info) {
242
0
        break;
243
0
      }
244
0
      srv_sig_ptr = &data_buf->info->srv_cksum;
245
0
      srv_sig_blob = &raw_buf->info->remaining;
246
0
      break;
247
0
    case PAC_TYPE_KDC_CHECKSUM:
248
0
      if (!data_buf->info) {
249
0
        break;
250
0
      }
251
0
      kdc_sig_ptr = &data_buf->info->kdc_cksum;
252
0
      kdc_sig_blob = &raw_buf->info->remaining;
253
0
      break;
254
0
    case PAC_TYPE_LOGON_NAME:
255
0
      logon_name = &data_buf->info->logon_name;
256
0
      break;
257
0
    default:
258
0
      break;
259
0
    }
260
0
  }
261
262
0
  if (!logon_info) {
263
0
    DEBUG(0,("PAC no logon_info\n"));
264
0
    status = NT_STATUS_INVALID_PARAMETER;
265
0
    goto out;
266
0
  }
267
268
0
  if (!logon_name) {
269
0
    DEBUG(0,("PAC no logon_name\n"));
270
0
    status = NT_STATUS_INVALID_PARAMETER;
271
0
    goto out;
272
0
  }
273
274
0
  if (!srv_sig_ptr || !srv_sig_blob) {
275
0
    DEBUG(0,("PAC no srv_key\n"));
276
0
    status = NT_STATUS_INVALID_PARAMETER;
277
0
    goto out;
278
0
  }
279
280
0
  if (!kdc_sig_ptr || !kdc_sig_blob) {
281
0
    DEBUG(0,("PAC no kdc_key\n"));
282
0
    status = NT_STATUS_INVALID_PARAMETER;
283
0
    goto out;
284
0
  }
285
286
  /* Find and zero out the signatures,
287
   * as required by the signing algorithm */
288
289
  /* We find the data blobs above,
290
   * now we parse them to get at the exact portion we should zero */
291
0
  ndr_err = ndr_pull_struct_blob(
292
0
      kdc_sig_blob, kdc_sig_wipe, kdc_sig_wipe,
293
0
      (ndr_pull_flags_fn_t)ndr_pull_PAC_SIGNATURE_DATA);
294
0
  if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
295
0
    status = ndr_map_error2ntstatus(ndr_err);
296
0
    DEBUG(0,("can't parse the KDC signature: %s\n",
297
0
      nt_errstr(status)));
298
0
    goto out;
299
0
  }
300
301
0
  ndr_err = ndr_pull_struct_blob(
302
0
      srv_sig_blob, srv_sig_wipe, srv_sig_wipe,
303
0
      (ndr_pull_flags_fn_t)ndr_pull_PAC_SIGNATURE_DATA);
304
0
  if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
305
0
    status = ndr_map_error2ntstatus(ndr_err);
306
0
    DEBUG(0,("can't parse the SRV signature: %s\n",
307
0
      nt_errstr(status)));
308
0
    goto out;
309
0
  }
310
311
  /* Now zero the decoded structure */
312
0
  memset(kdc_sig_wipe->signature.data,
313
0
    '\0', kdc_sig_wipe->signature.length);
314
0
  memset(srv_sig_wipe->signature.data,
315
0
    '\0', srv_sig_wipe->signature.length);
316
317
  /* and re-encode, back into the same place it came from */
318
0
  ndr_err = ndr_push_struct_blob(
319
0
      kdc_sig_blob, pac_data_raw, kdc_sig_wipe,
320
0
      (ndr_push_flags_fn_t)ndr_push_PAC_SIGNATURE_DATA);
321
0
  if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
322
0
    status = ndr_map_error2ntstatus(ndr_err);
323
0
    DEBUG(0,("can't repack the KDC signature: %s\n",
324
0
      nt_errstr(status)));
325
0
    goto out;
326
0
  }
327
0
  ndr_err = ndr_push_struct_blob(
328
0
      srv_sig_blob, pac_data_raw, srv_sig_wipe,
329
0
      (ndr_push_flags_fn_t)ndr_push_PAC_SIGNATURE_DATA);
330
0
  if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
331
0
    status = ndr_map_error2ntstatus(ndr_err);
332
0
    DEBUG(0,("can't repack the SRV signature: %s\n",
333
0
      nt_errstr(status)));
334
0
    goto out;
335
0
  }
336
337
  /* push out the whole structure, but now with zero'ed signatures */
338
0
  ndr_err = ndr_push_struct_blob(
339
0
      &modified_pac_blob, pac_data_raw, pac_data_raw,
340
0
      (ndr_push_flags_fn_t)ndr_push_PAC_DATA_RAW);
341
0
  if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
342
0
    status = ndr_map_error2ntstatus(ndr_err);
343
0
    DEBUG(0,("can't repack the RAW PAC: %s\n",
344
0
      nt_errstr(status)));
345
0
    goto out;
346
0
  }
347
348
0
  if (service_keyblock) {
349
    /* verify by service_key */
350
0
    ret = check_pac_checksum(modified_pac_blob, srv_sig_ptr,
351
0
           context,
352
0
           service_keyblock);
353
0
    if (ret) {
354
0
      DEBUG(5, ("PAC Decode: Failed to verify the service "
355
0
          "signature: %s\n", error_message(ret)));
356
0
      status = NT_STATUS_ACCESS_DENIED;
357
0
      goto out;
358
0
    }
359
360
0
    if (krbtgt_keyblock) {
361
      /* verify the service key checksum by krbtgt_key */
362
0
      ret = check_pac_checksum(srv_sig_ptr->signature, kdc_sig_ptr,
363
0
             context, krbtgt_keyblock);
364
0
      if (ret) {
365
0
        DEBUG(1, ("PAC Decode: Failed to verify the KDC signature: %s\n",
366
0
            smb_get_krb5_error_message(context, ret, tmp_ctx)));
367
0
        status = NT_STATUS_ACCESS_DENIED;
368
0
        goto out;
369
0
      }
370
0
    }
371
0
  }
372
373
0
  if (tgs_authtime) {
374
    /* Convert to NT time, so as not to lose accuracy in comparison */
375
0
    unix_to_nt_time(&tgs_authtime_nttime, tgs_authtime);
376
377
0
    if (tgs_authtime_nttime != logon_name->logon_time) {
378
0
      DEBUG(2, ("PAC Decode: "
379
0
          "Logon time mismatch between ticket and PAC!\n"));
380
0
      DEBUG(2, ("PAC Decode: PAC: %s\n",
381
0
          nt_time_string(tmp_ctx, logon_name->logon_time)));
382
0
      DEBUG(2, ("PAC Decode: Ticket: %s\n",
383
0
          nt_time_string(tmp_ctx, tgs_authtime_nttime)));
384
0
      status = NT_STATUS_ACCESS_DENIED;
385
0
      goto out;
386
0
    }
387
0
  }
388
389
0
  if (client_principal) {
390
0
    char *client_principal_string;
391
0
    ret = krb5_unparse_name_flags(context, client_principal,
392
0
                KRB5_PRINCIPAL_UNPARSE_NO_REALM|KRB5_PRINCIPAL_UNPARSE_DISPLAY,
393
0
                &client_principal_string);
394
0
    if (ret) {
395
0
      DEBUG(2, ("Could not unparse name from ticket to match with name from PAC: [%s]:%s\n",
396
0
          logon_name->account_name, error_message(ret)));
397
0
      status = NT_STATUS_INVALID_PARAMETER;
398
0
      goto out;
399
0
    }
400
401
0
    bool_ret = strcmp(client_principal_string, logon_name->account_name) == 0;
402
403
0
    if (!bool_ret) {
404
0
      DEBUG(2, ("Name in PAC [%s] does not match principal name "
405
0
          "in ticket [%s]\n",
406
0
          logon_name->account_name,
407
0
          client_principal_string));
408
0
    }
409
0
    SAFE_FREE(client_principal_string);
410
411
0
  }
412
413
0
  DEBUG(3,("Found account name from PAC: %s [%s]\n",
414
0
     logon_info->info3.base.account_name.string,
415
0
     logon_info->info3.base.full_name.string));
416
417
0
  if (DEBUGLEVEL >= 10) {
418
0
    const char *s = NDR_PRINT_STRUCT_STRING(
419
0
      tmp_ctx, PAC_DATA, pac_data);
420
421
0
    DEBUG(10,("Successfully validated Kerberos PAC\n%s%c",
422
0
        s != NULL ? s : "",
423
0
        s != NULL ? '\n' : '\0'));
424
0
  }
425
426
0
  if (pac_data_out) {
427
0
    *pac_data_out = talloc_move(mem_ctx, &pac_data);
428
0
  }
429
430
0
  status = NT_STATUS_OK;
431
432
0
    out:
433
434
0
  TALLOC_FREE(tmp_ctx);
435
0
  return status;
436
0
}
437
438
NTSTATUS kerberos_pac_logon_info(TALLOC_CTX *mem_ctx,
439
         DATA_BLOB blob,
440
         krb5_context context,
441
         const krb5_keyblock *krbtgt_keyblock,
442
         const krb5_keyblock *service_keyblock,
443
         krb5_const_principal client_principal,
444
         time_t tgs_authtime,
445
         struct PAC_LOGON_INFO **logon_info)
446
0
{
447
0
  NTSTATUS nt_status;
448
0
  struct PAC_DATA *pac_data;
449
0
  uint32_t i;
450
0
  nt_status = kerberos_decode_pac(mem_ctx,
451
0
          blob,
452
0
          context,
453
0
          krbtgt_keyblock,
454
0
          service_keyblock,
455
0
          client_principal,
456
0
          tgs_authtime,
457
0
          &pac_data);
458
0
  if (!NT_STATUS_IS_OK(nt_status)) {
459
0
    return nt_status;
460
0
  }
461
462
0
  *logon_info = NULL;
463
0
  for (i=0; i < pac_data->num_buffers; i++) {
464
0
    if (pac_data->buffers[i].type != PAC_TYPE_LOGON_INFO) {
465
0
      continue;
466
0
    }
467
0
    *logon_info = pac_data->buffers[i].info->logon_info.info;
468
0
  }
469
0
  if (!*logon_info) {
470
0
    return NT_STATUS_INVALID_PARAMETER;
471
0
  }
472
0
  return NT_STATUS_OK;
473
0
}
474
475
static NTSTATUS auth4_context_fetch_PAC_DATA_CTR(
476
        struct auth4_context *auth_ctx,
477
        TALLOC_CTX *mem_ctx,
478
        struct smb_krb5_context *smb_krb5_context,
479
        DATA_BLOB *pac_blob,
480
        const char *princ_name,
481
        const struct tsocket_address *remote_address,
482
        uint32_t session_info_flags,
483
        struct auth_session_info **session_info)
484
0
{
485
0
  struct PAC_DATA_CTR *pac_data_ctr = NULL;
486
0
  NTSTATUS status;
487
488
0
  if (pac_blob == NULL) {
489
0
    return NT_STATUS_NO_IMPERSONATION_TOKEN;
490
0
  }
491
492
0
  pac_data_ctr = talloc_zero(mem_ctx, struct PAC_DATA_CTR);
493
0
  if (pac_data_ctr == NULL) {
494
0
    status = NT_STATUS_NO_MEMORY;
495
0
    goto fail;
496
0
  }
497
498
0
  status = kerberos_decode_pac(pac_data_ctr,
499
0
             *pac_blob,
500
0
             NULL,
501
0
             NULL,
502
0
             NULL,
503
0
             NULL,
504
0
             0,
505
0
             &pac_data_ctr->pac_data);
506
0
  if (!NT_STATUS_IS_OK(status)) {
507
0
    goto fail;
508
0
  }
509
510
0
  pac_data_ctr->pac_blob = data_blob_talloc(pac_data_ctr,
511
0
              pac_blob->data,
512
0
              pac_blob->length);
513
0
  if (pac_data_ctr->pac_blob.length != pac_blob->length) {
514
0
    status = NT_STATUS_NO_MEMORY;
515
0
    goto fail;
516
0
  }
517
518
0
  *session_info = talloc_zero(mem_ctx, struct auth_session_info);
519
0
  if (*session_info == NULL) {
520
0
    status = NT_STATUS_NO_MEMORY;
521
0
    goto fail;
522
0
  }
523
524
0
  TALLOC_FREE(auth_ctx->private_data);
525
0
  auth_ctx->private_data = talloc_move(auth_ctx, &pac_data_ctr);
526
527
0
  return NT_STATUS_OK;
528
529
0
fail:
530
0
  TALLOC_FREE(pac_data_ctr);
531
532
0
  return status;
533
0
}
534
535
struct auth4_context *auth4_context_for_PAC_DATA_CTR(TALLOC_CTX *mem_ctx)
536
0
{
537
0
  struct auth4_context *auth_ctx = NULL;
538
539
0
  auth_ctx = talloc_zero(mem_ctx, struct auth4_context);
540
0
  if (auth_ctx == NULL) {
541
0
    return NULL;
542
0
  }
543
0
  auth_ctx->generate_session_info_pac = auth4_context_fetch_PAC_DATA_CTR;
544
545
0
  return auth_ctx;
546
0
}
547
548
struct PAC_DATA_CTR *auth4_context_get_PAC_DATA_CTR(struct auth4_context *auth_ctx,
549
                TALLOC_CTX *mem_ctx)
550
0
{
551
0
  struct PAC_DATA_CTR *p = NULL;
552
0
  SMB_ASSERT(auth_ctx->generate_session_info_pac == auth4_context_fetch_PAC_DATA_CTR);
553
0
  p = talloc_get_type_abort(auth_ctx->private_data, struct PAC_DATA_CTR);
554
0
  auth_ctx->private_data = NULL;
555
0
  return talloc_move(mem_ctx, &p);
556
0
}
557
558
#endif