LCOV - code coverage report
Current view: top level - source4/kdc - pac-glue.c (source / functions) Hit Total Coverage
Test: coverage report for recycleplus df22b230 Lines: 472 864 54.6 %
Date: 2024-02-14 10:14:15 Functions: 18 20 90.0 %

          Line data    Source code
       1             : /*
       2             :    Unix SMB/CIFS implementation.
       3             : 
       4             :    PAC Glue between Samba and the KDC
       5             : 
       6             :    Copyright (C) Andrew Bartlett <abartlet@samba.org> 2005-2009
       7             :    Copyright (C) Simo Sorce <idra@samba.org> 2010
       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             : 
      20             :    You should have received a copy of the GNU General Public License
      21             :    along with this program.  If not, see <http://www.gnu.org/licenses/>.
      22             : */
      23             : 
      24             : #include "lib/replace/replace.h"
      25             : #include "lib/replace/system/kerberos.h"
      26             : #include "lib/util/debug.h"
      27             : #include "lib/util/samba_util.h"
      28             : #include "lib/util/talloc_stack.h"
      29             : 
      30             : #include "auth/auth_sam_reply.h"
      31             : #include "auth/kerberos/kerberos.h"
      32             : #include "auth/kerberos/pac_utils.h"
      33             : #include "libcli/security/security.h"
      34             : #include "libds/common/flags.h"
      35             : #include "librpc/gen_ndr/ndr_krb5pac.h"
      36             : #include "param/param.h"
      37             : #include "source4/auth/auth.h"
      38             : #include "source4/dsdb/common/util.h"
      39             : #include "source4/dsdb/samdb/samdb.h"
      40             : #include "source4/kdc/samba_kdc.h"
      41             : #include "source4/kdc/pac-glue.h"
      42             : 
      43             : #include <ldb.h>
      44             : 
      45             : #undef DBGC_CLASS
      46             : #define DBGC_CLASS DBGC_KERBEROS
      47             : 
      48             : static
      49       55161 : NTSTATUS samba_get_logon_info_pac_blob(TALLOC_CTX *mem_ctx,
      50             :                                        const struct auth_user_info_dc *info,
      51             :                                        DATA_BLOB *pac_data,
      52             :                                        DATA_BLOB *requester_sid_blob)
      53             : {
      54             :         struct netr_SamInfo3 *info3;
      55             :         union PAC_INFO pac_info;
      56             :         enum ndr_err_code ndr_err;
      57             :         NTSTATUS nt_status;
      58             : 
      59       55161 :         ZERO_STRUCT(pac_info);
      60             : 
      61       55161 :         *pac_data = data_blob_null;
      62       55161 :         if (requester_sid_blob != NULL) {
      63       17199 :                 *requester_sid_blob = data_blob_null;
      64             :         }
      65             : 
      66       55161 :         nt_status = auth_convert_user_info_dc_saminfo3(mem_ctx, info, &info3);
      67       55161 :         if (!NT_STATUS_IS_OK(nt_status)) {
      68           0 :                 DEBUG(1, ("Getting Samba info failed: %s\n",
      69             :                           nt_errstr(nt_status)));
      70           0 :                 return nt_status;
      71             :         }
      72             : 
      73       55161 :         pac_info.logon_info.info = talloc_zero(mem_ctx, struct PAC_LOGON_INFO);
      74       55161 :         if (!pac_info.logon_info.info) {
      75           0 :                 return NT_STATUS_NO_MEMORY;
      76             :         }
      77             : 
      78       55161 :         pac_info.logon_info.info->info3 = *info3;
      79             : 
      80       55161 :         ndr_err = ndr_push_union_blob(pac_data, mem_ctx, &pac_info,
      81             :                                       PAC_TYPE_LOGON_INFO,
      82             :                                       (ndr_push_flags_fn_t)ndr_push_PAC_INFO);
      83       55161 :         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
      84           0 :                 nt_status = ndr_map_error2ntstatus(ndr_err);
      85           0 :                 DEBUG(1, ("PAC_LOGON_INFO (presig) push failed: %s\n",
      86             :                           nt_errstr(nt_status)));
      87           0 :                 return nt_status;
      88             :         }
      89             : 
      90       55161 :         if (requester_sid_blob != NULL && info->num_sids > 0) {
      91             :                 union PAC_INFO pac_requester_sid;
      92             : 
      93       17199 :                 ZERO_STRUCT(pac_requester_sid);
      94             : 
      95       17199 :                 pac_requester_sid.requester_sid.sid = info->sids[0];
      96             : 
      97       17199 :                 ndr_err = ndr_push_union_blob(requester_sid_blob, mem_ctx,
      98             :                                               &pac_requester_sid,
      99             :                                               PAC_TYPE_REQUESTER_SID,
     100             :                                               (ndr_push_flags_fn_t)ndr_push_PAC_INFO);
     101       17199 :                 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
     102           0 :                         nt_status = ndr_map_error2ntstatus(ndr_err);
     103           0 :                         DEBUG(1, ("PAC_REQUESTER_SID (presig) push failed: %s\n",
     104             :                                   nt_errstr(nt_status)));
     105           0 :                         return nt_status;
     106             :                 }
     107             :         }
     108             : 
     109       55161 :         return NT_STATUS_OK;
     110             : }
     111             : 
     112             : static
     113       19021 : NTSTATUS samba_get_upn_info_pac_blob(TALLOC_CTX *mem_ctx,
     114             :                                      const struct auth_user_info_dc *info,
     115             :                                      DATA_BLOB *upn_data)
     116             : {
     117             :         union PAC_INFO pac_upn;
     118             :         enum ndr_err_code ndr_err;
     119             :         NTSTATUS nt_status;
     120             :         bool ok;
     121             : 
     122       19021 :         ZERO_STRUCT(pac_upn);
     123             : 
     124       19021 :         *upn_data = data_blob_null;
     125             : 
     126       19021 :         pac_upn.upn_dns_info.upn_name = info->info->user_principal_name;
     127       38042 :         pac_upn.upn_dns_info.dns_domain_name = strupper_talloc(mem_ctx,
     128       19021 :                                                 info->info->dns_domain_name);
     129       19021 :         if (pac_upn.upn_dns_info.dns_domain_name == NULL) {
     130           0 :                 return NT_STATUS_NO_MEMORY;
     131             :         }
     132       19021 :         if (info->info->user_principal_constructed) {
     133       17934 :                 pac_upn.upn_dns_info.flags |= PAC_UPN_DNS_FLAG_CONSTRUCTED;
     134             :         }
     135             : 
     136       19021 :         pac_upn.upn_dns_info.flags |= PAC_UPN_DNS_FLAG_HAS_SAM_NAME_AND_SID;
     137             : 
     138             :         pac_upn.upn_dns_info.ex.sam_name_and_sid.samaccountname
     139       19021 :                 = info->info->account_name;
     140             : 
     141             :         pac_upn.upn_dns_info.ex.sam_name_and_sid.objectsid
     142       19021 :                 = &info->sids[0];
     143             : 
     144       19021 :         ndr_err = ndr_push_union_blob(upn_data, mem_ctx, &pac_upn,
     145             :                                       PAC_TYPE_UPN_DNS_INFO,
     146             :                                       (ndr_push_flags_fn_t)ndr_push_PAC_INFO);
     147       19021 :         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
     148           0 :                 nt_status = ndr_map_error2ntstatus(ndr_err);
     149           0 :                 DEBUG(1, ("PAC UPN_DNS_INFO (presig) push failed: %s\n",
     150             :                           nt_errstr(nt_status)));
     151           0 :                 return nt_status;
     152             :         }
     153             : 
     154       19021 :         ok = data_blob_pad(mem_ctx, upn_data, 8);
     155       19021 :         if (!ok) {
     156           0 :                 return NT_STATUS_NO_MEMORY;
     157             :         }
     158             : 
     159       19021 :         return NT_STATUS_OK;
     160             : }
     161             : 
     162             : static
     163       17157 : NTSTATUS samba_get_pac_attrs_blob(TALLOC_CTX *mem_ctx,
     164             :                                   uint64_t pac_attributes,
     165             :                                   DATA_BLOB *pac_attrs_data)
     166             : {
     167             :         union PAC_INFO pac_attrs;
     168             :         enum ndr_err_code ndr_err;
     169             :         NTSTATUS nt_status;
     170             : 
     171       17157 :         ZERO_STRUCT(pac_attrs);
     172             : 
     173       17157 :         *pac_attrs_data = data_blob_null;
     174             : 
     175             :         /* Set the length of the flags in bits. */
     176       17157 :         pac_attrs.attributes_info.flags_length = 2;
     177       17157 :         pac_attrs.attributes_info.flags = pac_attributes;
     178             : 
     179       17157 :         ndr_err = ndr_push_union_blob(pac_attrs_data, mem_ctx, &pac_attrs,
     180             :                                       PAC_TYPE_ATTRIBUTES_INFO,
     181             :                                       (ndr_push_flags_fn_t)ndr_push_PAC_INFO);
     182       17157 :         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
     183           0 :                 nt_status = ndr_map_error2ntstatus(ndr_err);
     184           0 :                 DEBUG(1, ("PAC ATTRIBUTES_INFO (presig) push failed: %s\n",
     185             :                           nt_errstr(nt_status)));
     186           0 :                 return nt_status;
     187             :         }
     188             : 
     189       17157 :         return NT_STATUS_OK;
     190             : }
     191             : 
     192             : static
     193           0 : NTSTATUS samba_get_cred_info_ndr_blob(TALLOC_CTX *mem_ctx,
     194             :                                       const struct ldb_message *msg,
     195             :                                       DATA_BLOB *cred_blob)
     196             : {
     197             :         enum ndr_err_code ndr_err;
     198             :         NTSTATUS nt_status;
     199           0 :         struct samr_Password *lm_hash = NULL;
     200           0 :         struct samr_Password *nt_hash = NULL;
     201           0 :         struct PAC_CREDENTIAL_NTLM_SECPKG ntlm_secpkg = {
     202             :                 .version = 0,
     203             :         };
     204           0 :         DATA_BLOB ntlm_blob = data_blob_null;
     205           0 :         struct PAC_CREDENTIAL_SUPPLEMENTAL_SECPKG secpkgs[1] = {{
     206             :                 .credential_size = 0,
     207             :         }};
     208           0 :         struct PAC_CREDENTIAL_DATA cred_data = {
     209             :                 .credential_count = 0,
     210             :         };
     211             :         struct PAC_CREDENTIAL_DATA_NDR cred_ndr;
     212             : 
     213           0 :         ZERO_STRUCT(cred_ndr);
     214             : 
     215           0 :         *cred_blob = data_blob_null;
     216             : 
     217           0 :         lm_hash = samdb_result_hash(mem_ctx, msg, "dBCSPwd");
     218           0 :         if (lm_hash != NULL) {
     219           0 :                 bool zero = all_zero(lm_hash->hash, 16);
     220           0 :                 if (zero) {
     221           0 :                         lm_hash = NULL;
     222             :                 }
     223             :         }
     224           0 :         if (lm_hash != NULL) {
     225           0 :                 DEBUG(5, ("Passing LM password hash through credentials set\n"));
     226           0 :                 ntlm_secpkg.flags |= PAC_CREDENTIAL_NTLM_HAS_LM_HASH;
     227           0 :                 ntlm_secpkg.lm_password = *lm_hash;
     228           0 :                 ZERO_STRUCTP(lm_hash);
     229           0 :                 TALLOC_FREE(lm_hash);
     230             :         }
     231             : 
     232           0 :         nt_hash = samdb_result_hash(mem_ctx, msg, "unicodePwd");
     233           0 :         if (nt_hash != NULL) {
     234           0 :                 bool zero = all_zero(nt_hash->hash, 16);
     235           0 :                 if (zero) {
     236           0 :                         nt_hash = NULL;
     237             :                 }
     238             :         }
     239           0 :         if (nt_hash != NULL) {
     240           0 :                 DEBUG(5, ("Passing LM password hash through credentials set\n"));
     241           0 :                 ntlm_secpkg.flags |= PAC_CREDENTIAL_NTLM_HAS_NT_HASH;
     242           0 :                 ntlm_secpkg.nt_password = *nt_hash;
     243           0 :                 ZERO_STRUCTP(nt_hash);
     244           0 :                 TALLOC_FREE(nt_hash);
     245             :         }
     246             : 
     247           0 :         if (ntlm_secpkg.flags == 0) {
     248           0 :                 return NT_STATUS_OK;
     249             :         }
     250             : 
     251             : #ifdef DEBUG_PASSWORD
     252           0 :         if (DEBUGLVL(11)) {
     253           0 :                 NDR_PRINT_DEBUG(PAC_CREDENTIAL_NTLM_SECPKG, &ntlm_secpkg);
     254             :         }
     255             : #endif
     256             : 
     257           0 :         ndr_err = ndr_push_struct_blob(&ntlm_blob, mem_ctx, &ntlm_secpkg,
     258             :                         (ndr_push_flags_fn_t)ndr_push_PAC_CREDENTIAL_NTLM_SECPKG);
     259           0 :         ZERO_STRUCT(ntlm_secpkg);
     260           0 :         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
     261           0 :                 nt_status = ndr_map_error2ntstatus(ndr_err);
     262           0 :                 DEBUG(1, ("PAC_CREDENTIAL_NTLM_SECPKG (presig) push failed: %s\n",
     263             :                           nt_errstr(nt_status)));
     264           0 :                 return nt_status;
     265             :         }
     266             : 
     267           0 :         DEBUG(10, ("NTLM credential BLOB (len %zu) for user\n",
     268             :                   ntlm_blob.length));
     269           0 :         dump_data_pw("PAC_CREDENTIAL_NTLM_SECPKG",
     270           0 :                      ntlm_blob.data, ntlm_blob.length);
     271             : 
     272           0 :         secpkgs[0].package_name.string = discard_const_p(char, "NTLM");
     273           0 :         secpkgs[0].credential_size = ntlm_blob.length;
     274           0 :         secpkgs[0].credential = ntlm_blob.data;
     275             : 
     276           0 :         cred_data.credential_count = ARRAY_SIZE(secpkgs);
     277           0 :         cred_data.credentials = secpkgs;
     278             : 
     279             : #ifdef DEBUG_PASSWORD
     280           0 :         if (DEBUGLVL(11)) {
     281           0 :                 NDR_PRINT_DEBUG(PAC_CREDENTIAL_DATA, &cred_data);
     282             :         }
     283             : #endif
     284             : 
     285           0 :         cred_ndr.ctr.data = &cred_data;
     286             : 
     287             : #ifdef DEBUG_PASSWORD
     288           0 :         if (DEBUGLVL(11)) {
     289           0 :                 NDR_PRINT_DEBUG(PAC_CREDENTIAL_DATA_NDR, &cred_ndr);
     290             :         }
     291             : #endif
     292             : 
     293           0 :         ndr_err = ndr_push_struct_blob(cred_blob, mem_ctx, &cred_ndr,
     294             :                         (ndr_push_flags_fn_t)ndr_push_PAC_CREDENTIAL_DATA_NDR);
     295           0 :         data_blob_clear(&ntlm_blob);
     296           0 :         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
     297           0 :                 nt_status = ndr_map_error2ntstatus(ndr_err);
     298           0 :                 DEBUG(1, ("PAC_CREDENTIAL_DATA_NDR (presig) push failed: %s\n",
     299             :                           nt_errstr(nt_status)));
     300           0 :                 return nt_status;
     301             :         }
     302             : 
     303           0 :         DEBUG(10, ("Created credential BLOB (len %zu) for user\n",
     304             :                   cred_blob->length));
     305           0 :         dump_data_pw("PAC_CREDENTIAL_DATA_NDR",
     306           0 :                      cred_blob->data, cred_blob->length);
     307             : 
     308           0 :         return NT_STATUS_OK;
     309             : }
     310             : 
     311             : #ifdef SAMBA4_USES_HEIMDAL
     312           0 : krb5_error_code samba_kdc_encrypt_pac_credentials(krb5_context context,
     313             :                                                   const krb5_keyblock *pkreplykey,
     314             :                                                   const DATA_BLOB *cred_ndr_blob,
     315             :                                                   TALLOC_CTX *mem_ctx,
     316             :                                                   DATA_BLOB *cred_info_blob)
     317             : {
     318             :         krb5_crypto cred_crypto;
     319             :         krb5_enctype cred_enctype;
     320             :         krb5_data cred_ndr_crypt;
     321           0 :         struct PAC_CREDENTIAL_INFO pac_cred_info = { .version = 0, };
     322             :         krb5_error_code ret;
     323             :         const char *krb5err;
     324             :         enum ndr_err_code ndr_err;
     325             :         NTSTATUS nt_status;
     326             : 
     327           0 :         *cred_info_blob = data_blob_null;
     328             : 
     329           0 :         ret = krb5_crypto_init(context, pkreplykey, ETYPE_NULL,
     330             :                                &cred_crypto);
     331           0 :         if (ret != 0) {
     332           0 :                 krb5err = krb5_get_error_message(context, ret);
     333           0 :                 DEBUG(1, ("Failed initializing cred data crypto: %s\n", krb5err));
     334           0 :                 krb5_free_error_message(context, krb5err);
     335           0 :                 return ret;
     336             :         }
     337             : 
     338           0 :         ret = krb5_crypto_getenctype(context, cred_crypto, &cred_enctype);
     339           0 :         if (ret != 0) {
     340           0 :                 DEBUG(1, ("Failed getting crypto type for key\n"));
     341           0 :                 krb5_crypto_destroy(context, cred_crypto);
     342           0 :                 return ret;
     343             :         }
     344             : 
     345           0 :         DEBUG(10, ("Plain cred_ndr_blob (len %zu)\n",
     346             :                   cred_ndr_blob->length));
     347           0 :         dump_data_pw("PAC_CREDENTIAL_DATA_NDR",
     348           0 :                      cred_ndr_blob->data, cred_ndr_blob->length);
     349             : 
     350           0 :         ret = krb5_encrypt(context, cred_crypto,
     351             :                            KRB5_KU_OTHER_ENCRYPTED,
     352           0 :                            cred_ndr_blob->data, cred_ndr_blob->length,
     353             :                            &cred_ndr_crypt);
     354           0 :         krb5_crypto_destroy(context, cred_crypto);
     355           0 :         if (ret != 0) {
     356           0 :                 krb5err = krb5_get_error_message(context, ret);
     357           0 :                 DEBUG(1, ("Failed crypt of cred data: %s\n", krb5err));
     358           0 :                 krb5_free_error_message(context, krb5err);
     359           0 :                 return ret;
     360             :         }
     361             : 
     362           0 :         pac_cred_info.encryption_type = cred_enctype;
     363           0 :         pac_cred_info.encrypted_data.length = cred_ndr_crypt.length;
     364           0 :         pac_cred_info.encrypted_data.data = (uint8_t *)cred_ndr_crypt.data;
     365             : 
     366           0 :         if (DEBUGLVL(10)) {
     367           0 :                 NDR_PRINT_DEBUG(PAC_CREDENTIAL_INFO, &pac_cred_info);
     368             :         }
     369             : 
     370           0 :         ndr_err = ndr_push_struct_blob(cred_info_blob, mem_ctx, &pac_cred_info,
     371             :                         (ndr_push_flags_fn_t)ndr_push_PAC_CREDENTIAL_INFO);
     372           0 :         krb5_data_free(&cred_ndr_crypt);
     373           0 :         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
     374           0 :                 nt_status = ndr_map_error2ntstatus(ndr_err);
     375           0 :                 DEBUG(1, ("PAC_CREDENTIAL_INFO (presig) push failed: %s\n",
     376             :                           nt_errstr(nt_status)));
     377           0 :                 return KRB5KDC_ERR_SVC_UNAVAILABLE;
     378             :         }
     379             : 
     380           0 :         DEBUG(10, ("Encrypted credential BLOB (len %zu) with alg %d\n",
     381             :                   cred_info_blob->length, (int)pac_cred_info.encryption_type));
     382           0 :         dump_data_pw("PAC_CREDENTIAL_INFO",
     383           0 :                       cred_info_blob->data, cred_info_blob->length);
     384             : 
     385           0 :         return 0;
     386             : }
     387             : #else /* SAMBA4_USES_HEIMDAL */
     388           0 : krb5_error_code samba_kdc_encrypt_pac_credentials(krb5_context context,
     389             :                                                   const krb5_keyblock *pkreplykey,
     390             :                                                   const DATA_BLOB *cred_ndr_blob,
     391             :                                                   TALLOC_CTX *mem_ctx,
     392             :                                                   DATA_BLOB *cred_info_blob)
     393             : {
     394             :         krb5_key cred_key;
     395             :         krb5_enctype cred_enctype;
     396           0 :         struct PAC_CREDENTIAL_INFO pac_cred_info = { .version = 0, };
     397             :         krb5_error_code code;
     398             :         const char *krb5err;
     399             :         enum ndr_err_code ndr_err;
     400             :         NTSTATUS nt_status;
     401             :         krb5_data cred_ndr_data;
     402             :         krb5_enc_data cred_ndr_crypt;
     403           0 :         size_t enc_len = 0;
     404             : 
     405           0 :         *cred_info_blob = data_blob_null;
     406             : 
     407           0 :         code = krb5_k_create_key(context,
     408             :                                  pkreplykey,
     409             :                                  &cred_key);
     410           0 :         if (code != 0) {
     411           0 :                 krb5err = krb5_get_error_message(context, code);
     412           0 :                 DEBUG(1, ("Failed initializing cred data crypto: %s\n", krb5err));
     413           0 :                 krb5_free_error_message(context, krb5err);
     414           0 :                 return code;
     415             :         }
     416             : 
     417           0 :         cred_enctype = krb5_k_key_enctype(context, cred_key);
     418             : 
     419           0 :         DEBUG(10, ("Plain cred_ndr_blob (len %zu)\n",
     420             :                   cred_ndr_blob->length));
     421           0 :         dump_data_pw("PAC_CREDENTIAL_DATA_NDR",
     422           0 :                      cred_ndr_blob->data, cred_ndr_blob->length);
     423             : 
     424           0 :         pac_cred_info.encryption_type = cred_enctype;
     425             : 
     426           0 :         cred_ndr_data.magic = 0;
     427           0 :         cred_ndr_data.data = (char *)cred_ndr_blob->data;
     428           0 :         cred_ndr_data.length = cred_ndr_blob->length;
     429             : 
     430           0 :         code = krb5_c_encrypt_length(context,
     431             :                                      cred_enctype,
     432           0 :                                      cred_ndr_data.length,
     433             :                                      &enc_len);
     434           0 :         if (code != 0) {
     435           0 :                 krb5err = krb5_get_error_message(context, code);
     436           0 :                 DEBUG(1, ("Failed initializing cred data crypto: %s\n", krb5err));
     437           0 :                 krb5_free_error_message(context, krb5err);
     438           0 :                 return code;
     439             :         }
     440             : 
     441           0 :         pac_cred_info.encrypted_data = data_blob_talloc_zero(mem_ctx, enc_len);
     442           0 :         if (pac_cred_info.encrypted_data.data == NULL) {
     443           0 :                 DBG_ERR("Out of memory\n");
     444           0 :                 return ENOMEM;
     445             :         }
     446             : 
     447           0 :         cred_ndr_crypt.ciphertext.length = enc_len;
     448           0 :         cred_ndr_crypt.ciphertext.data = (char *)pac_cred_info.encrypted_data.data;
     449             : 
     450           0 :         code = krb5_k_encrypt(context,
     451             :                               cred_key,
     452             :                               KRB5_KU_OTHER_ENCRYPTED,
     453             :                               NULL,
     454             :                               &cred_ndr_data,
     455             :                               &cred_ndr_crypt);
     456           0 :         krb5_k_free_key(context, cred_key);
     457           0 :         if (code != 0) {
     458           0 :                 krb5err = krb5_get_error_message(context, code);
     459           0 :                 DEBUG(1, ("Failed crypt of cred data: %s\n", krb5err));
     460           0 :                 krb5_free_error_message(context, krb5err);
     461           0 :                 return code;
     462             :         }
     463             : 
     464           0 :         if (DEBUGLVL(10)) {
     465           0 :                 NDR_PRINT_DEBUG(PAC_CREDENTIAL_INFO, &pac_cred_info);
     466             :         }
     467             : 
     468           0 :         ndr_err = ndr_push_struct_blob(cred_info_blob, mem_ctx, &pac_cred_info,
     469             :                         (ndr_push_flags_fn_t)ndr_push_PAC_CREDENTIAL_INFO);
     470           0 :         TALLOC_FREE(pac_cred_info.encrypted_data.data);
     471           0 :         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
     472           0 :                 nt_status = ndr_map_error2ntstatus(ndr_err);
     473           0 :                 DEBUG(1, ("PAC_CREDENTIAL_INFO (presig) push failed: %s\n",
     474             :                           nt_errstr(nt_status)));
     475           0 :                 return KRB5KDC_ERR_SVC_UNAVAILABLE;
     476             :         }
     477             : 
     478           0 :         DEBUG(10, ("Encrypted credential BLOB (len %zu) with alg %d\n",
     479             :                   cred_info_blob->length, (int)pac_cred_info.encryption_type));
     480           0 :         dump_data_pw("PAC_CREDENTIAL_INFO",
     481           0 :                       cred_info_blob->data, cred_info_blob->length);
     482             : 
     483           0 :         return 0;
     484             : }
     485             : #endif /* SAMBA4_USES_HEIMDAL */
     486             : 
     487             : 
     488             : /**
     489             :  * @brief Create a PAC with the given blobs (logon, credentials, upn and
     490             :  * delegation).
     491             :  *
     492             :  * @param[in] context   The KRB5 context to use.
     493             :  *
     494             :  * @param[in] logon_blob Fill the logon info PAC buffer with the given blob,
     495             :  *                       use NULL to ignore it.
     496             :  *
     497             :  * @param[in] cred_blob  Fill the credentials info PAC buffer with the given
     498             :  *                       blob, use NULL to ignore it.
     499             :  *
     500             :  * @param[in] upn_blob  Fill the UPN info PAC buffer with the given blob, use
     501             :  *                      NULL to ignore it.
     502             :  *
     503             :  * @param[in] deleg_blob Fill the delegation info PAC buffer with the given
     504             :  *                       blob, use NULL to ignore it.
     505             :  *
     506             :  * @param[in] client_claims_blob Fill the client claims info PAC buffer with the
     507             :  *                               given blob, use NULL to ignore it.
     508             :  *
     509             :  * @param[in] device_info_blob Fill the device info PAC buffer with the given
     510             :  *                             blob, use NULL to ignore it.
     511             :  *
     512             :  * @param[in] device_claims_blob Fill the device claims info PAC buffer with the given
     513             :  *                               blob, use NULL to ignore it.
     514             :  *
     515             :  * @param[in] pac        The pac buffer to fill. This should be allocated with
     516             :  *                       krb5_pac_init() already.
     517             :  *
     518             :  * @returns 0 on success or a corresponding KRB5 error.
     519             :  */
     520       18979 : krb5_error_code samba_make_krb5_pac(krb5_context context,
     521             :                                     const DATA_BLOB *logon_blob,
     522             :                                     const DATA_BLOB *cred_blob,
     523             :                                     const DATA_BLOB *upn_blob,
     524             :                                     const DATA_BLOB *pac_attrs_blob,
     525             :                                     const DATA_BLOB *requester_sid_blob,
     526             :                                     const DATA_BLOB *deleg_blob,
     527             :                                     const DATA_BLOB *client_claims_blob,
     528             :                                     const DATA_BLOB *device_info_blob,
     529             :                                     const DATA_BLOB *device_claims_blob,
     530             :                                     krb5_pac pac)
     531             : {
     532             :         krb5_data logon_data;
     533             :         krb5_error_code ret;
     534             : #ifdef SAMBA4_USES_HEIMDAL
     535       18979 :         char null_byte = '\0';
     536       18979 :         krb5_data null_data = smb_krb5_make_data(&null_byte, 0);
     537             : #endif
     538             : 
     539             :         /* The user account may be set not to want the PAC */
     540       18979 :         if (logon_blob == NULL) {
     541           0 :                 return 0;
     542             :         }
     543             : 
     544       18979 :         logon_data = smb_krb5_data_from_blob(*logon_blob);
     545       18979 :         ret = krb5_pac_add_buffer(context, pac, PAC_TYPE_LOGON_INFO, &logon_data);
     546       18979 :         if (ret != 0) {
     547           0 :                 return ret;
     548             :         }
     549             : 
     550       18979 :         if (device_info_blob != NULL) {
     551           0 :                 krb5_data device_info_data = smb_krb5_data_from_blob(*device_info_blob);
     552           0 :                 ret = krb5_pac_add_buffer(context, pac,
     553             :                                           PAC_TYPE_DEVICE_INFO,
     554             :                                           &device_info_data);
     555           0 :                 if (ret != 0) {
     556           0 :                         return ret;
     557             :                 }
     558             :         }
     559             : 
     560       18979 :         if (client_claims_blob != NULL) {
     561           0 :                 krb5_data client_claims_data = smb_krb5_data_from_blob(*client_claims_blob);
     562           0 :                 ret = krb5_pac_add_buffer(context, pac,
     563             :                                           PAC_TYPE_CLIENT_CLAIMS_INFO,
     564             :                                           &client_claims_data);
     565           0 :                 if (ret != 0) {
     566           0 :                         return ret;
     567             :                 }
     568             :         }
     569             : 
     570       18979 :         if (device_claims_blob != NULL) {
     571           0 :                 krb5_data device_claims_data = smb_krb5_data_from_blob(*device_claims_blob);
     572           0 :                 ret = krb5_pac_add_buffer(context, pac,
     573             :                                           PAC_TYPE_DEVICE_CLAIMS_INFO,
     574             :                                           &device_claims_data);
     575           0 :                 if (ret != 0) {
     576           0 :                         return ret;
     577             :                 }
     578             :         }
     579             : 
     580       18979 :         if (cred_blob != NULL) {
     581           0 :                 krb5_data cred_data = smb_krb5_data_from_blob(*cred_blob);
     582           0 :                 ret = krb5_pac_add_buffer(context, pac,
     583             :                                           PAC_TYPE_CREDENTIAL_INFO,
     584             :                                           &cred_data);
     585           0 :                 if (ret != 0) {
     586           0 :                         return ret;
     587             :                 }
     588             :         }
     589             : 
     590             : #ifdef SAMBA4_USES_HEIMDAL
     591             :         /*
     592             :          * null_data will be filled by the generic KDC code in the caller
     593             :          * here we just add it in order to have it before
     594             :          * PAC_TYPE_UPN_DNS_INFO
     595             :          *
     596             :          * Not needed with MIT Kerberos - asn
     597             :          */
     598       18979 :         ret = krb5_pac_add_buffer(context, pac,
     599             :                                   PAC_TYPE_LOGON_NAME,
     600             :                                   &null_data);
     601       18979 :         if (ret != 0) {
     602           0 :                 return ret;
     603             :         }
     604             : #endif
     605             : 
     606       18979 :         if (upn_blob != NULL) {
     607       18979 :                 krb5_data upn_data = smb_krb5_data_from_blob(*upn_blob);
     608       18979 :                 ret = krb5_pac_add_buffer(context, pac,
     609             :                                           PAC_TYPE_UPN_DNS_INFO,
     610             :                                           &upn_data);
     611       18979 :                 if (ret != 0) {
     612           0 :                         return ret;
     613             :                 }
     614             :         }
     615             : 
     616       18979 :         if (pac_attrs_blob != NULL) {
     617       17157 :                 krb5_data pac_attrs_data = smb_krb5_data_from_blob(*pac_attrs_blob);
     618       17157 :                 ret = krb5_pac_add_buffer(context, pac,
     619             :                                           PAC_TYPE_ATTRIBUTES_INFO,
     620             :                                           &pac_attrs_data);
     621       17157 :                 if (ret != 0) {
     622           0 :                         return ret;
     623             :                 }
     624             :         }
     625             : 
     626       18979 :         if (requester_sid_blob != NULL) {
     627       17157 :                 krb5_data requester_sid_data = smb_krb5_data_from_blob(*requester_sid_blob);
     628       17157 :                 ret = krb5_pac_add_buffer(context, pac,
     629             :                                           PAC_TYPE_REQUESTER_SID,
     630             :                                           &requester_sid_data);
     631       17157 :                 if (ret != 0) {
     632           0 :                         return ret;
     633             :                 }
     634             :         }
     635             : 
     636       18979 :         if (deleg_blob != NULL) {
     637           0 :                 krb5_data deleg_data = smb_krb5_data_from_blob(*deleg_blob);
     638           0 :                 ret = krb5_pac_add_buffer(context, pac,
     639             :                                           PAC_TYPE_CONSTRAINED_DELEGATION,
     640             :                                           &deleg_data);
     641           0 :                 if (ret != 0) {
     642           0 :                         return ret;
     643             :                 }
     644             :         }
     645             : 
     646       18979 :         return ret;
     647             : }
     648             : 
     649       36182 : bool samba_princ_needs_pac(struct samba_kdc_entry *skdc_entry)
     650             : {
     651             : 
     652             :         uint32_t userAccountControl;
     653             : 
     654             :         /* The service account may be set not to want the PAC */
     655       36182 :         userAccountControl = ldb_msg_find_attr_as_uint(skdc_entry->msg, "userAccountControl", 0);
     656       36182 :         if (userAccountControl & UF_NO_AUTH_DATA_REQUIRED) {
     657           9 :                 return false;
     658             :         }
     659             : 
     660       36173 :         return true;
     661             : }
     662             : 
     663       14773 : int samba_client_requested_pac(krb5_context context,
     664             :                                const krb5_pac *pac,
     665             :                                TALLOC_CTX *mem_ctx,
     666             :                                bool *requested_pac)
     667             : {
     668             :         enum ndr_err_code ndr_err;
     669             :         krb5_data k5pac_attrs_in;
     670             :         DATA_BLOB pac_attrs_in;
     671             :         union PAC_INFO pac_attrs;
     672             :         int ret;
     673             : 
     674       14773 :         *requested_pac = true;
     675             : 
     676       14773 :         ret = krb5_pac_get_buffer(context, *pac, PAC_TYPE_ATTRIBUTES_INFO,
     677             :                                   &k5pac_attrs_in);
     678       14773 :         if (ret != 0) {
     679          51 :                 return ret == ENOENT ? 0 : ret;
     680             :         }
     681             : 
     682       14722 :         pac_attrs_in = data_blob_const(k5pac_attrs_in.data,
     683           0 :                                        k5pac_attrs_in.length);
     684             : 
     685       14722 :         ndr_err = ndr_pull_union_blob(&pac_attrs_in, mem_ctx, &pac_attrs,
     686             :                                       PAC_TYPE_ATTRIBUTES_INFO,
     687             :                                       (ndr_pull_flags_fn_t)ndr_pull_PAC_INFO);
     688       14722 :         smb_krb5_free_data_contents(context, &k5pac_attrs_in);
     689       14722 :         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
     690           0 :                 NTSTATUS nt_status = ndr_map_error2ntstatus(ndr_err);
     691           0 :                 DEBUG(0,("can't parse the PAC ATTRIBUTES_INFO: %s\n", nt_errstr(nt_status)));
     692           0 :                 return EINVAL;
     693             :         }
     694             : 
     695       14722 :         if (pac_attrs.attributes_info.flags & (PAC_ATTRIBUTE_FLAG_PAC_WAS_GIVEN_IMPLICITLY
     696             :                                                | PAC_ATTRIBUTE_FLAG_PAC_WAS_REQUESTED)) {
     697       14722 :                 *requested_pac = true;
     698             :         } else {
     699           0 :                 *requested_pac = false;
     700             :         }
     701             : 
     702       14722 :         return 0;
     703             : }
     704             : 
     705             : /* Was the krbtgt in this DB (ie, should we check the incoming signature) and was it an RODC */
     706       36207 : int samba_krbtgt_is_in_db(struct samba_kdc_entry *p,
     707             :                           bool *is_in_db,
     708             :                           bool *is_untrusted)
     709             : {
     710             :         NTSTATUS status;
     711             :         int rodc_krbtgt_number, trust_direction;
     712             :         uint32_t rid;
     713             : 
     714       36207 :         TALLOC_CTX *mem_ctx = talloc_new(NULL);
     715       36207 :         if (!mem_ctx) {
     716           0 :                 return ENOMEM;
     717             :         }
     718             : 
     719       36207 :         trust_direction = ldb_msg_find_attr_as_int(p->msg, "trustDirection", 0);
     720             : 
     721       36207 :         if (trust_direction != 0) {
     722             :                 /* Domain trust - we cannot check the sig, but we trust it for a correct PAC
     723             : 
     724             :                    This is exactly where we should flag for SID
     725             :                    validation when we do inter-foreest trusts
     726             :                  */
     727          48 :                 talloc_free(mem_ctx);
     728          48 :                 *is_untrusted = false;
     729          48 :                 *is_in_db = false;
     730          48 :                 return 0;
     731             :         }
     732             : 
     733             :         /* The lack of password controls etc applies to krbtgt by
     734             :          * virtue of being that particular RID */
     735       36159 :         status = dom_sid_split_rid(NULL, samdb_result_dom_sid(mem_ctx, p->msg, "objectSid"), NULL, &rid);
     736             : 
     737       36159 :         if (!NT_STATUS_IS_OK(status)) {
     738           0 :                 talloc_free(mem_ctx);
     739           0 :                 return EINVAL;
     740             :         }
     741             : 
     742       36159 :         rodc_krbtgt_number = ldb_msg_find_attr_as_int(p->msg, "msDS-SecondaryKrbTgtNumber", -1);
     743             : 
     744       36159 :         if (p->kdc_db_ctx->my_krbtgt_number == 0) {
     745       33766 :                 if (rid == DOMAIN_RID_KRBTGT) {
     746       33724 :                         *is_untrusted = false;
     747       33724 :                         *is_in_db = true;
     748       33724 :                         talloc_free(mem_ctx);
     749       33724 :                         return 0;
     750          42 :                 } else if (rodc_krbtgt_number != -1) {
     751          42 :                         *is_in_db = true;
     752          42 :                         *is_untrusted = true;
     753          42 :                         talloc_free(mem_ctx);
     754          42 :                         return 0;
     755             :                 }
     756        2393 :         } else if ((rid != DOMAIN_RID_KRBTGT) && (rodc_krbtgt_number == p->kdc_db_ctx->my_krbtgt_number)) {
     757        2393 :                 talloc_free(mem_ctx);
     758        2393 :                 *is_untrusted = false;
     759        2393 :                 *is_in_db = true;
     760        2393 :                 return 0;
     761           0 :         } else if (rid == DOMAIN_RID_KRBTGT) {
     762             :                 /* krbtgt viewed from an RODC */
     763           0 :                 talloc_free(mem_ctx);
     764           0 :                 *is_untrusted = false;
     765           0 :                 *is_in_db = false;
     766           0 :                 return 0;
     767             :         }
     768             : 
     769             :         /* Another RODC */
     770           0 :         talloc_free(mem_ctx);
     771           0 :         *is_untrusted = true;
     772           0 :         *is_in_db = false;
     773           0 :         return 0;
     774             : }
     775             : 
     776             : /*
     777             :  * Because the KDC does not limit protocol transition, two new well-known SIDs
     778             :  * were introduced to give this control to the resource administrator. These
     779             :  * SIDs identify whether protocol transition has occurred, and can be used with
     780             :  * standard access control lists to grant or limit access as needed.
     781             :  *
     782             :  * https://docs.microsoft.com/en-us/windows-server/security/kerberos/kerberos-constrained-delegation-overview
     783             :  */
     784       19021 : static NTSTATUS samba_add_asserted_identity(TALLOC_CTX *mem_ctx,
     785             :                                             enum samba_asserted_identity ai,
     786             :                                             struct auth_user_info_dc *user_info_dc)
     787             : {
     788             :         struct dom_sid ai_sid;
     789       19021 :         const char *sid_str = NULL;
     790             : 
     791       19021 :         switch (ai) {
     792         636 :         case SAMBA_ASSERTED_IDENTITY_SERVICE:
     793         636 :                 sid_str = SID_SERVICE_ASSERTED_IDENTITY;
     794       19021 :                 break;
     795       18385 :         case SAMBA_ASSERTED_IDENTITY_AUTHENTICATION_AUTHORITY:
     796       18385 :                 sid_str = SID_AUTHENTICATION_AUTHORITY_ASSERTED_IDENTITY;
     797       18385 :                 break;
     798           0 :         case SAMBA_ASSERTED_IDENTITY_IGNORE:
     799           0 :                 return NT_STATUS_OK;
     800             :         }
     801             : 
     802       19021 :         dom_sid_parse(sid_str, &ai_sid);
     803             : 
     804       19021 :         return add_sid_to_array_unique(user_info_dc,
     805             :                                        &ai_sid,
     806             :                                        &user_info_dc->sids,
     807             :                                        &user_info_dc->num_sids);
     808             : }
     809             : 
     810             : /*
     811             :  * Look up the user's info in the database and create a auth_user_info_dc
     812             :  * structure. If the resulting structure is not talloc_free()d, it will be
     813             :  * reused on future calls to this function.
     814             :  */
     815       50819 : NTSTATUS samba_kdc_get_user_info_from_db(struct samba_kdc_entry *skdc_entry,
     816             :                                          struct ldb_message *msg,
     817             :                                          struct auth_user_info_dc **user_info_dc)
     818             : {
     819       50819 :         if (skdc_entry->user_info_dc == NULL) {
     820             :                 NTSTATUS nt_status;
     821       32434 :                 struct loadparm_context *lp_ctx = skdc_entry->kdc_db_ctx->lp_ctx;
     822             : 
     823       32434 :                 nt_status = authsam_make_user_info_dc(skdc_entry,
     824       32434 :                                                       skdc_entry->kdc_db_ctx->samdb,
     825             :                                                       lpcfg_netbios_name(lp_ctx),
     826             :                                                       lpcfg_sam_name(lp_ctx),
     827             :                                                       lpcfg_sam_dnsname(lp_ctx),
     828             :                                                       skdc_entry->realm_dn,
     829             :                                                       msg,
     830             :                                                       data_blob_null,
     831             :                                                       data_blob_null,
     832             :                                                       &skdc_entry->user_info_dc);
     833       32434 :                 if (!NT_STATUS_IS_OK(nt_status)) {
     834           0 :                         return nt_status;
     835             :                 }
     836             :         }
     837             : 
     838       50819 :         *user_info_dc = skdc_entry->user_info_dc;
     839       50819 :         return NT_STATUS_OK;
     840             : }
     841             : 
     842       19021 : NTSTATUS samba_kdc_get_pac_blobs(TALLOC_CTX *mem_ctx,
     843             :                                  struct samba_kdc_entry *p,
     844             :                                  enum samba_asserted_identity asserted_identity,
     845             :                                  DATA_BLOB **_logon_info_blob,
     846             :                                  DATA_BLOB **_cred_ndr_blob,
     847             :                                  DATA_BLOB **_upn_info_blob,
     848             :                                  DATA_BLOB **_pac_attrs_blob,
     849             :                                  uint64_t pac_attributes,
     850             :                                  DATA_BLOB **_requester_sid_blob,
     851             :                                  DATA_BLOB **_client_claims_blob)
     852             : {
     853       19021 :         struct auth_user_info_dc *user_info_dc = NULL;
     854       19021 :         DATA_BLOB *logon_blob = NULL;
     855       19021 :         DATA_BLOB *cred_blob = NULL;
     856       19021 :         DATA_BLOB *upn_blob = NULL;
     857       19021 :         DATA_BLOB *pac_attrs_blob = NULL;
     858       19021 :         DATA_BLOB *requester_sid_blob = NULL;
     859       19021 :         DATA_BLOB *client_claims_blob = NULL;
     860             :         NTSTATUS nt_status;
     861             : 
     862       19021 :         *_logon_info_blob = NULL;
     863       19021 :         if (_cred_ndr_blob != NULL) {
     864           0 :                 *_cred_ndr_blob = NULL;
     865             :         }
     866       19021 :         *_upn_info_blob = NULL;
     867       19021 :         if (_pac_attrs_blob != NULL) {
     868       17157 :                 *_pac_attrs_blob = NULL;
     869             :         }
     870       19021 :         if (_requester_sid_blob != NULL) {
     871       17199 :                 *_requester_sid_blob = NULL;
     872             :         }
     873       19021 :         if (_client_claims_blob != NULL) {
     874          85 :                 *_client_claims_blob = NULL;
     875             :         }
     876             : 
     877       19021 :         logon_blob = talloc_zero(mem_ctx, DATA_BLOB);
     878       19021 :         if (logon_blob == NULL) {
     879           0 :                 return NT_STATUS_NO_MEMORY;
     880             :         }
     881             : 
     882       19021 :         if (_cred_ndr_blob != NULL) {
     883           0 :                 cred_blob = talloc_zero(mem_ctx, DATA_BLOB);
     884           0 :                 if (cred_blob == NULL) {
     885           0 :                         return NT_STATUS_NO_MEMORY;
     886             :                 }
     887             :         }
     888             : 
     889       19021 :         upn_blob = talloc_zero(mem_ctx, DATA_BLOB);
     890       19021 :         if (upn_blob == NULL) {
     891           0 :                 return NT_STATUS_NO_MEMORY;
     892             :         }
     893             : 
     894       19021 :         if (_pac_attrs_blob != NULL) {
     895       17157 :                 pac_attrs_blob = talloc_zero(mem_ctx, DATA_BLOB);
     896       17157 :                 if (pac_attrs_blob == NULL) {
     897           0 :                         return NT_STATUS_NO_MEMORY;
     898             :                 }
     899             :         }
     900             : 
     901       19021 :         if (_requester_sid_blob != NULL) {
     902       17199 :                 requester_sid_blob = talloc_zero(mem_ctx, DATA_BLOB);
     903       17199 :                 if (requester_sid_blob == NULL) {
     904           0 :                         return NT_STATUS_NO_MEMORY;
     905             :                 }
     906             :         }
     907             : 
     908       19021 :         if (_client_claims_blob != NULL) {
     909             :                 /*
     910             :                  * Until we support claims we just
     911             :                  * return an empty blob,
     912             :                  * that matches what Windows is doing
     913             :                  * without defined claims
     914             :                  */
     915          85 :                 client_claims_blob = talloc_zero(mem_ctx, DATA_BLOB);
     916          85 :                 if (client_claims_blob == NULL) {
     917           0 :                         return NT_STATUS_NO_MEMORY;
     918             :                 }
     919             :         }
     920             : 
     921       19021 :         nt_status = samba_kdc_get_user_info_from_db(p,
     922             :                                                     p->msg,
     923             :                                                     &user_info_dc);
     924       19021 :         if (!NT_STATUS_IS_OK(nt_status)) {
     925           0 :                 DEBUG(0, ("Getting user info for PAC failed: %s\n",
     926             :                           nt_errstr(nt_status)));
     927           0 :                 return nt_status;
     928             :         }
     929             : 
     930       19021 :         nt_status = samba_add_asserted_identity(mem_ctx,
     931             :                                                 asserted_identity,
     932             :                                                 user_info_dc);
     933       19021 :         if (!NT_STATUS_IS_OK(nt_status)) {
     934           0 :                 DBG_ERR("Failed to add assertied identity!\n");
     935           0 :                 return nt_status;
     936             :         }
     937             : 
     938       19021 :         nt_status = samba_get_logon_info_pac_blob(logon_blob,
     939             :                                                   user_info_dc,
     940             :                                                   logon_blob,
     941             :                                                   requester_sid_blob);
     942       19021 :         if (!NT_STATUS_IS_OK(nt_status)) {
     943           0 :                 DEBUG(0, ("Building PAC LOGON INFO failed: %s\n",
     944             :                           nt_errstr(nt_status)));
     945           0 :                 return nt_status;
     946             :         }
     947             : 
     948       19021 :         if (cred_blob != NULL) {
     949           0 :                 nt_status = samba_get_cred_info_ndr_blob(cred_blob,
     950           0 :                                                          p->msg,
     951             :                                                          cred_blob);
     952           0 :                 if (!NT_STATUS_IS_OK(nt_status)) {
     953           0 :                         DEBUG(0, ("Building PAC CRED INFO failed: %s\n",
     954             :                                   nt_errstr(nt_status)));
     955           0 :                         return nt_status;
     956             :                 }
     957             :         }
     958             : 
     959       19021 :         nt_status = samba_get_upn_info_pac_blob(upn_blob,
     960             :                                                 user_info_dc,
     961             :                                                 upn_blob);
     962       19021 :         if (!NT_STATUS_IS_OK(nt_status)) {
     963           0 :                 DEBUG(0, ("Building PAC UPN INFO failed: %s\n",
     964             :                           nt_errstr(nt_status)));
     965           0 :                 return nt_status;
     966             :         }
     967             : 
     968       19021 :         if (pac_attrs_blob != NULL) {
     969       17157 :                 nt_status = samba_get_pac_attrs_blob(pac_attrs_blob,
     970             :                                                      pac_attributes,
     971             :                                                      pac_attrs_blob);
     972             : 
     973       17157 :                 if (!NT_STATUS_IS_OK(nt_status)) {
     974           0 :                         DEBUG(0, ("Building PAC ATTRIBUTES failed: %s\n",
     975             :                                   nt_errstr(nt_status)));
     976           0 :                         return nt_status;
     977             :                 }
     978             :         }
     979             : 
     980       19021 :         *_logon_info_blob = logon_blob;
     981       19021 :         if (_cred_ndr_blob != NULL) {
     982           0 :                 *_cred_ndr_blob = cred_blob;
     983             :         }
     984       19021 :         *_upn_info_blob = upn_blob;
     985       19021 :         if (_pac_attrs_blob != NULL) {
     986       17157 :                 *_pac_attrs_blob = pac_attrs_blob;
     987             :         }
     988       19021 :         if (_requester_sid_blob != NULL) {
     989       17199 :                 *_requester_sid_blob = requester_sid_blob;
     990             :         }
     991       19021 :         if (_client_claims_blob != NULL) {
     992          85 :                 *_client_claims_blob = client_claims_blob;
     993             :         }
     994       19021 :         return NT_STATUS_OK;
     995             : }
     996             : 
     997       36140 : NTSTATUS samba_kdc_update_pac_blob(TALLOC_CTX *mem_ctx,
     998             :                                    krb5_context context,
     999             :                                    struct ldb_context *samdb,
    1000             :                                    const krb5_pac pac, DATA_BLOB *pac_blob,
    1001             :                                    struct PAC_SIGNATURE_DATA *pac_srv_sig,
    1002             :                                    struct PAC_SIGNATURE_DATA *pac_kdc_sig)
    1003             : {
    1004             :         struct auth_user_info_dc *user_info_dc;
    1005             :         krb5_error_code ret;
    1006             :         NTSTATUS nt_status;
    1007             : 
    1008       36140 :         ret = kerberos_pac_to_user_info_dc(mem_ctx, pac,
    1009             :                                            context, &user_info_dc, pac_srv_sig, pac_kdc_sig);
    1010       36140 :         if (ret) {
    1011           0 :                 return NT_STATUS_UNSUCCESSFUL;
    1012             :         }
    1013             : 
    1014             :         /*
    1015             :          * We need to expand group memberships within our local domain,
    1016             :          * as the token might be generated by a trusted domain.
    1017             :          */
    1018       36140 :         nt_status = authsam_update_user_info_dc(mem_ctx,
    1019             :                                                 samdb,
    1020             :                                                 user_info_dc);
    1021       36140 :         if (!NT_STATUS_IS_OK(nt_status)) {
    1022           0 :                 return nt_status;
    1023             :         }
    1024             : 
    1025       36140 :         nt_status = samba_get_logon_info_pac_blob(mem_ctx,
    1026             :                                                   user_info_dc, pac_blob, NULL);
    1027             : 
    1028       36140 :         return nt_status;
    1029             : }
    1030             : 
    1031          51 : NTSTATUS samba_kdc_update_delegation_info_blob(TALLOC_CTX *mem_ctx,
    1032             :                                 krb5_context context,
    1033             :                                 const krb5_pac pac,
    1034             :                                 const krb5_principal server_principal,
    1035             :                                 const krb5_principal proxy_principal,
    1036             :                                 DATA_BLOB *new_blob)
    1037             : {
    1038             :         krb5_data old_data;
    1039             :         DATA_BLOB old_blob;
    1040             :         krb5_error_code ret;
    1041             :         NTSTATUS nt_status;
    1042             :         enum ndr_err_code ndr_err;
    1043             :         union PAC_INFO info;
    1044             :         struct PAC_CONSTRAINED_DELEGATION _d;
    1045          51 :         struct PAC_CONSTRAINED_DELEGATION *d = NULL;
    1046          51 :         char *server = NULL;
    1047          51 :         char *proxy = NULL;
    1048             :         uint32_t i;
    1049          51 :         TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
    1050             : 
    1051          51 :         if (tmp_ctx == NULL) {
    1052           0 :                 return NT_STATUS_NO_MEMORY;
    1053             :         }
    1054             : 
    1055          51 :         ret = krb5_pac_get_buffer(context, pac, PAC_TYPE_CONSTRAINED_DELEGATION, &old_data);
    1056          51 :         if (ret == ENOENT) {
    1057          49 :                 ZERO_STRUCT(old_data);
    1058           2 :         } else if (ret) {
    1059           0 :                 talloc_free(tmp_ctx);
    1060           0 :                 return NT_STATUS_UNSUCCESSFUL;
    1061             :         }
    1062             : 
    1063          51 :         old_blob.length = old_data.length;
    1064          51 :         old_blob.data = (uint8_t *)old_data.data;
    1065             : 
    1066          51 :         ZERO_STRUCT(info);
    1067          51 :         if (old_blob.length > 0) {
    1068           2 :                 ndr_err = ndr_pull_union_blob(&old_blob, mem_ctx,
    1069             :                                 &info, PAC_TYPE_CONSTRAINED_DELEGATION,
    1070             :                                 (ndr_pull_flags_fn_t)ndr_pull_PAC_INFO);
    1071           2 :                 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
    1072           0 :                         smb_krb5_free_data_contents(context, &old_data);
    1073           0 :                         nt_status = ndr_map_error2ntstatus(ndr_err);
    1074           0 :                         DEBUG(0,("can't parse the PAC LOGON_INFO: %s\n", nt_errstr(nt_status)));
    1075           0 :                         talloc_free(tmp_ctx);
    1076           0 :                         return nt_status;
    1077             :                 }
    1078             :         } else {
    1079          49 :                 ZERO_STRUCT(_d);
    1080          49 :                 info.constrained_delegation.info = &_d;
    1081             :         }
    1082          51 :         smb_krb5_free_data_contents(context, &old_data);
    1083             : 
    1084          51 :         ret = krb5_unparse_name_flags(context, server_principal,
    1085             :                                       KRB5_PRINCIPAL_UNPARSE_NO_REALM, &server);
    1086          51 :         if (ret) {
    1087           0 :                 talloc_free(tmp_ctx);
    1088           0 :                 return NT_STATUS_INTERNAL_ERROR;
    1089             :         }
    1090             : 
    1091          51 :         ret = krb5_unparse_name(context, proxy_principal, &proxy);
    1092          51 :         if (ret) {
    1093           0 :                 SAFE_FREE(server);
    1094           0 :                 talloc_free(tmp_ctx);
    1095           0 :                 return NT_STATUS_INTERNAL_ERROR;
    1096             :         }
    1097             : 
    1098          51 :         d = info.constrained_delegation.info;
    1099          51 :         i = d->num_transited_services;
    1100          51 :         d->proxy_target.string = server;
    1101          51 :         d->transited_services = talloc_realloc(mem_ctx, d->transited_services,
    1102             :                                                struct lsa_String, i + 1);
    1103          51 :         d->transited_services[i].string = proxy;
    1104          51 :         d->num_transited_services = i + 1;
    1105             : 
    1106          51 :         ndr_err = ndr_push_union_blob(new_blob, mem_ctx,
    1107             :                                 &info, PAC_TYPE_CONSTRAINED_DELEGATION,
    1108             :                                 (ndr_push_flags_fn_t)ndr_push_PAC_INFO);
    1109          51 :         SAFE_FREE(server);
    1110          51 :         SAFE_FREE(proxy);
    1111          51 :         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
    1112           0 :                 smb_krb5_free_data_contents(context, &old_data);
    1113           0 :                 nt_status = ndr_map_error2ntstatus(ndr_err);
    1114           0 :                 DEBUG(0,("can't parse the PAC LOGON_INFO: %s\n", nt_errstr(nt_status)));
    1115           0 :                 talloc_free(tmp_ctx);
    1116           0 :                 return nt_status;
    1117             :         }
    1118             : 
    1119          51 :         talloc_free(tmp_ctx);
    1120          51 :         return NT_STATUS_OK;
    1121             : }
    1122             : 
    1123             : /* function to map policy errors */
    1124           4 : krb5_error_code samba_kdc_map_policy_err(NTSTATUS nt_status)
    1125             : {
    1126             :         krb5_error_code ret;
    1127             : 
    1128           4 :         if (NT_STATUS_EQUAL(nt_status, NT_STATUS_PASSWORD_MUST_CHANGE))
    1129           4 :                 ret = KRB5KDC_ERR_KEY_EXP;
    1130           0 :         else if (NT_STATUS_EQUAL(nt_status, NT_STATUS_PASSWORD_EXPIRED))
    1131           0 :                 ret = KRB5KDC_ERR_KEY_EXP;
    1132           0 :         else if (NT_STATUS_EQUAL(nt_status, NT_STATUS_ACCOUNT_EXPIRED))
    1133           0 :                 ret = KRB5KDC_ERR_CLIENT_REVOKED;
    1134           0 :         else if (NT_STATUS_EQUAL(nt_status, NT_STATUS_ACCOUNT_DISABLED))
    1135           0 :                 ret = KRB5KDC_ERR_CLIENT_REVOKED;
    1136           0 :         else if (NT_STATUS_EQUAL(nt_status, NT_STATUS_INVALID_LOGON_HOURS))
    1137           0 :                 ret = KRB5KDC_ERR_CLIENT_REVOKED;
    1138           0 :         else if (NT_STATUS_EQUAL(nt_status, NT_STATUS_ACCOUNT_LOCKED_OUT))
    1139           0 :                 ret = KRB5KDC_ERR_CLIENT_REVOKED;
    1140           0 :         else if (NT_STATUS_EQUAL(nt_status, NT_STATUS_INVALID_WORKSTATION))
    1141           0 :                 ret = KRB5KDC_ERR_POLICY;
    1142             :         else
    1143           0 :                 ret = KRB5KDC_ERR_POLICY;
    1144             : 
    1145           4 :         return ret;
    1146             : }
    1147             : 
    1148             : /* Given a kdc entry, consult the account_ok routine in auth/auth_sam.c
    1149             :  * for consistency */
    1150       18429 : NTSTATUS samba_kdc_check_client_access(struct samba_kdc_entry *kdc_entry,
    1151             :                                        const char *client_name,
    1152             :                                        const char *workstation,
    1153             :                                        bool password_change)
    1154             : {
    1155             :         TALLOC_CTX *tmp_ctx;
    1156             :         NTSTATUS nt_status;
    1157             : 
    1158       18429 :         tmp_ctx = talloc_named(NULL, 0, "samba_kdc_check_client_access");
    1159       18429 :         if (!tmp_ctx) {
    1160           0 :                 return NT_STATUS_NO_MEMORY;
    1161             :         }
    1162             : 
    1163             :         /* we allow all kinds of trusts here */
    1164       18429 :         nt_status = authsam_account_ok(tmp_ctx,
    1165       18429 :                                        kdc_entry->kdc_db_ctx->samdb,
    1166             :                                        MSV1_0_ALLOW_SERVER_TRUST_ACCOUNT |
    1167             :                                        MSV1_0_ALLOW_WORKSTATION_TRUST_ACCOUNT,
    1168             :                                        kdc_entry->realm_dn, kdc_entry->msg,
    1169             :                                        workstation, client_name,
    1170             :                                        true, password_change);
    1171             : 
    1172       18429 :         kdc_entry->reject_status = nt_status;
    1173       18429 :         talloc_free(tmp_ctx);
    1174       18429 :         return nt_status;
    1175             : }
    1176             : 
    1177       36133 : static krb5_error_code samba_get_requester_sid(TALLOC_CTX *mem_ctx,
    1178             :                                                krb5_const_pac pac,
    1179             :                                                krb5_context context,
    1180             :                                                struct dom_sid *sid)
    1181             : {
    1182             :         NTSTATUS nt_status;
    1183             :         enum ndr_err_code ndr_err;
    1184             :         krb5_error_code ret;
    1185             : 
    1186             :         DATA_BLOB pac_requester_sid_in;
    1187             :         krb5_data k5pac_requester_sid_in;
    1188             : 
    1189             :         union PAC_INFO info;
    1190             : 
    1191       36133 :         TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
    1192       36133 :         if (tmp_ctx == NULL) {
    1193           0 :                 return ENOMEM;
    1194             :         }
    1195             : 
    1196       36133 :         ret = krb5_pac_get_buffer(context, pac, PAC_TYPE_REQUESTER_SID,
    1197             :                                   &k5pac_requester_sid_in);
    1198       36133 :         if (ret != 0) {
    1199          50 :                 talloc_free(tmp_ctx);
    1200          50 :                 return ret;
    1201             :         }
    1202             : 
    1203       36083 :         pac_requester_sid_in = data_blob_const(k5pac_requester_sid_in.data,
    1204           0 :                                                k5pac_requester_sid_in.length);
    1205             : 
    1206       36083 :         ndr_err = ndr_pull_union_blob(&pac_requester_sid_in, tmp_ctx, &info,
    1207             :                                       PAC_TYPE_REQUESTER_SID,
    1208             :                                       (ndr_pull_flags_fn_t)ndr_pull_PAC_INFO);
    1209       36083 :         smb_krb5_free_data_contents(context, &k5pac_requester_sid_in);
    1210       36083 :         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
    1211           0 :                 nt_status = ndr_map_error2ntstatus(ndr_err);
    1212           0 :                 DEBUG(0,("can't parse the PAC REQUESTER_SID: %s\n", nt_errstr(nt_status)));
    1213           0 :                 talloc_free(tmp_ctx);
    1214           0 :                 return EINVAL;
    1215             :         }
    1216             : 
    1217       36083 :         *sid = info.requester_sid.sid;
    1218             : 
    1219       36083 :         talloc_free(tmp_ctx);
    1220       36083 :         return 0;
    1221             : }
    1222             : 
    1223             : /* Does a parse and SID check, but no crypto. */
    1224       36133 : krb5_error_code samba_kdc_validate_pac_blob(
    1225             :                 krb5_context context,
    1226             :                 const struct samba_kdc_entry *client_skdc_entry,
    1227             :                 const krb5_const_pac pac)
    1228             : {
    1229       36133 :         TALLOC_CTX *frame = talloc_stackframe();
    1230       36133 :         struct auth_user_info_dc *pac_user_info = NULL;
    1231       36133 :         struct dom_sid *client_sid = NULL;
    1232             :         struct dom_sid pac_sid;
    1233             :         krb5_error_code code;
    1234             :         bool ok;
    1235             : 
    1236             :         /*
    1237             :          * First, try to get the SID from the requester SID buffer in the PAC.
    1238             :          */
    1239       36133 :         code = samba_get_requester_sid(frame, pac, context, &pac_sid);
    1240             : 
    1241       36133 :         if (code == ENOENT) {
    1242             :                 /*
    1243             :                  * If the requester SID buffer isn't present, fall back to the
    1244             :                  * SID in the LOGON_INFO PAC buffer.
    1245             :                  */
    1246          50 :                 code = kerberos_pac_to_user_info_dc(frame,
    1247             :                                                     pac,
    1248             :                                                     context,
    1249             :                                                     &pac_user_info,
    1250             :                                                     NULL,
    1251             :                                                     NULL);
    1252          50 :                 if (code != 0) {
    1253           0 :                         goto out;
    1254             :                 }
    1255             : 
    1256          50 :                 if (pac_user_info->num_sids == 0) {
    1257           0 :                         code = EINVAL;
    1258           0 :                         goto out;
    1259             :                 }
    1260             : 
    1261          50 :                 pac_sid = pac_user_info->sids[0];
    1262       36083 :         } else if (code != 0) {
    1263           0 :                 goto out;
    1264             :         }
    1265             : 
    1266       36133 :         client_sid = samdb_result_dom_sid(frame,
    1267       36133 :                                           client_skdc_entry->msg,
    1268             :                                           "objectSid");
    1269             : 
    1270       36133 :         ok = dom_sid_equal(&pac_sid, client_sid);
    1271       36133 :         if (!ok) {
    1272             :                 struct dom_sid_buf buf1;
    1273             :                 struct dom_sid_buf buf2;
    1274             : 
    1275           0 :                 DBG_ERR("SID mismatch between PAC and looked up client: "
    1276             :                         "PAC[%s] != CLI[%s]\n",
    1277             :                         dom_sid_str_buf(&pac_sid, &buf1),
    1278             :                         dom_sid_str_buf(client_sid, &buf2));
    1279           0 :                         code = KRB5KDC_ERR_TGT_REVOKED;
    1280           0 :                 goto out;
    1281             :         }
    1282             : 
    1283       36133 :         code = 0;
    1284       36133 : out:
    1285       36133 :         TALLOC_FREE(frame);
    1286       36133 :         return code;
    1287             : }
    1288             : 
    1289             : 
    1290             : /*
    1291             :  * In the RODC case, to confirm that the returned user is permitted to
    1292             :  * be replicated to the KDC (krbgtgt_xxx user) represented by *rodc
    1293             :  */
    1294          42 : WERROR samba_rodc_confirm_user_is_allowed(uint32_t num_object_sids,
    1295             :                                           struct dom_sid *object_sids,
    1296             :                                           struct samba_kdc_entry *rodc,
    1297             :                                           struct samba_kdc_entry *object)
    1298             : {
    1299             :         int ret;
    1300             :         WERROR werr;
    1301          42 :         TALLOC_CTX *frame = talloc_stackframe();
    1302          42 :         const char *rodc_attrs[] = { "msDS-KrbTgtLink",
    1303             :                                      "msDS-NeverRevealGroup",
    1304             :                                      "msDS-RevealOnDemandGroup",
    1305             :                                      "userAccountControl",
    1306             :                                      "objectSid",
    1307             :                                      NULL };
    1308          42 :         struct ldb_result *rodc_machine_account = NULL;
    1309          42 :         struct ldb_dn *rodc_machine_account_dn = samdb_result_dn(rodc->kdc_db_ctx->samdb,
    1310             :                                                  frame,
    1311          42 :                                                  rodc->msg,
    1312             :                                                  "msDS-KrbTgtLinkBL",
    1313             :                                                  NULL);
    1314          42 :         const struct dom_sid *rodc_machine_account_sid = NULL;
    1315             : 
    1316          42 :         if (rodc_machine_account_dn == NULL) {
    1317           0 :                 DBG_ERR("krbtgt account %s has no msDS-KrbTgtLinkBL to find RODC machine account for allow/deny list\n",
    1318             :                         ldb_dn_get_linearized(rodc->msg->dn));
    1319           0 :                 TALLOC_FREE(frame);
    1320           0 :                 return WERR_DOMAIN_CONTROLLER_NOT_FOUND;
    1321             :         }
    1322             : 
    1323             :         /*
    1324             :          * Follow the link and get the RODC account (the krbtgt
    1325             :          * account is the krbtgt_XXX account, but the
    1326             :          * msDS-NeverRevealGroup and msDS-RevealOnDemandGroup is on
    1327             :          * the RODC$ account)
    1328             :          *
    1329             :          * We need DSDB_SEARCH_SHOW_EXTENDED_DN as we get a SID lists
    1330             :          * out of the extended DNs
    1331             :          */
    1332             : 
    1333          42 :         ret = dsdb_search_dn(rodc->kdc_db_ctx->samdb,
    1334             :                              frame,
    1335             :                              &rodc_machine_account,
    1336             :                              rodc_machine_account_dn,
    1337             :                              rodc_attrs,
    1338             :                              DSDB_SEARCH_SHOW_EXTENDED_DN);
    1339          42 :         if (ret != LDB_SUCCESS) {
    1340           0 :                 DBG_ERR("Failed to fetch RODC machine account %s pointed to by %s to check allow/deny list: %s\n",
    1341             :                         ldb_dn_get_linearized(rodc_machine_account_dn),
    1342             :                         ldb_dn_get_linearized(rodc->msg->dn),
    1343             :                         ldb_errstring(rodc->kdc_db_ctx->samdb));
    1344           0 :                 TALLOC_FREE(frame);
    1345           0 :                 return WERR_DOMAIN_CONTROLLER_NOT_FOUND;
    1346             :         }
    1347             : 
    1348          42 :         if (rodc_machine_account->count != 1) {
    1349           0 :                 DBG_ERR("Failed to fetch RODC machine account %s pointed to by %s to check allow/deny list: (%d)\n",
    1350             :                         ldb_dn_get_linearized(rodc_machine_account_dn),
    1351             :                         ldb_dn_get_linearized(rodc->msg->dn),
    1352             :                         rodc_machine_account->count);
    1353           0 :                 TALLOC_FREE(frame);
    1354           0 :                 return WERR_DS_DRA_BAD_DN;
    1355             :         }
    1356             : 
    1357             :         /* if the object SID is equal to the user_sid, allow */
    1358          42 :         rodc_machine_account_sid = samdb_result_dom_sid(frame,
    1359          42 :                                           rodc_machine_account->msgs[0],
    1360             :                                           "objectSid");
    1361          42 :         if (rodc_machine_account_sid == NULL) {
    1362           0 :                 return WERR_DS_DRA_BAD_DN;
    1363             :         }
    1364             : 
    1365          42 :         werr = samdb_confirm_rodc_allowed_to_repl_to_sid_list(rodc->kdc_db_ctx->samdb,
    1366             :                                                               rodc_machine_account_sid,
    1367          42 :                                                               rodc_machine_account->msgs[0],
    1368             :                                                               object->msg,
    1369             :                                                               num_object_sids,
    1370             :                                                               object_sids);
    1371             : 
    1372          42 :         TALLOC_FREE(frame);
    1373          42 :         return werr;
    1374             : }
    1375             : 
    1376             : /**
    1377             :  * @brief Update a PAC
    1378             :  *
    1379             :  * @param mem_ctx   A talloc memory context
    1380             :  *
    1381             :  * @param context   A krb5 context
    1382             :  *
    1383             :  * @param samdb     An open samdb connection.
    1384             :  *
    1385             :  * @param flags     Bitwise OR'ed flags
    1386             :  *
    1387             :  * @param client    The client samba kdc entry.
    1388             : 
    1389             :  * @param server_principal  The server principal
    1390             : 
    1391             :  * @param server    The server samba kdc entry.
    1392             : 
    1393             :  * @param krbtgt    The krbtgt samba kdc entry.
    1394             :  *
    1395             :  * @param delegated_proxy_principal The delegated proxy principal used for
    1396             :  *                                  updating the constrained delegation PAC
    1397             :  *                                  buffer.
    1398             : 
    1399             :  * @param old_pac                   The old PAC
    1400             : 
    1401             :  * @param new_pac                   The new already allocated PAC
    1402             : 
    1403             :  * @return A Kerberos error code. If no PAC should be returned, the code will be
    1404             :  * ENODATA!
    1405             :  */
    1406       36182 : krb5_error_code samba_kdc_update_pac(TALLOC_CTX *mem_ctx,
    1407             :                                      krb5_context context,
    1408             :                                      struct ldb_context *samdb,
    1409             :                                      uint32_t flags,
    1410             :                                      struct samba_kdc_entry *client,
    1411             :                                      const krb5_principal server_principal,
    1412             :                                      struct samba_kdc_entry *server,
    1413             :                                      struct samba_kdc_entry *krbtgt,
    1414             :                                      const krb5_principal delegated_proxy_principal,
    1415             :                                      const krb5_pac old_pac,
    1416             :                                      krb5_pac new_pac)
    1417             : {
    1418       36182 :         krb5_error_code code = EINVAL;
    1419             :         NTSTATUS nt_status;
    1420       36182 :         DATA_BLOB *pac_blob = NULL;
    1421       36182 :         DATA_BLOB *upn_blob = NULL;
    1422       36182 :         DATA_BLOB *deleg_blob = NULL;
    1423       36182 :         DATA_BLOB *requester_sid_blob = NULL;
    1424       36182 :         DATA_BLOB *client_claims_blob = NULL;
    1425       36182 :         bool is_untrusted = flags & SAMBA_KDC_FLAG_KRBTGT_IS_UNTRUSTED;
    1426       36182 :         int is_tgs = false;
    1427       36182 :         size_t num_types = 0;
    1428       36182 :         uint32_t *types = NULL;
    1429             :         /*
    1430             :          * FIXME: Do we really still need forced_next_type? With MIT Kerberos
    1431             :          * the PAC buffers do not get ordered and it works just fine. We are
    1432             :          * not aware of any issues in this regard. This might be just ancient
    1433             :          * code.
    1434             :          */
    1435       36182 :         uint32_t forced_next_type = 0;
    1436       36182 :         size_t i = 0;
    1437       36182 :         ssize_t logon_info_idx = -1;
    1438       36182 :         ssize_t delegation_idx = -1;
    1439       36182 :         ssize_t logon_name_idx = -1;
    1440       36182 :         ssize_t upn_dns_info_idx = -1;
    1441       36182 :         ssize_t srv_checksum_idx = -1;
    1442       36182 :         ssize_t kdc_checksum_idx = -1;
    1443       36182 :         ssize_t tkt_checksum_idx = -1;
    1444       36182 :         ssize_t attrs_info_idx = -1;
    1445       36182 :         ssize_t requester_sid_idx = -1;
    1446       36182 :         ssize_t full_checksum_idx = -1;
    1447             : 
    1448       36182 :         if (client != NULL) {
    1449             :                 /*
    1450             :                  * Check the objectSID of the client and pac data are the same.
    1451             :                  * Does a parse and SID check, but no crypto.
    1452             :                  */
    1453       36133 :                 code = samba_kdc_validate_pac_blob(context,
    1454             :                                                    client,
    1455             :                                                    old_pac);
    1456       36133 :                 if (code != 0) {
    1457           0 :                         goto done;
    1458             :                 }
    1459             :         }
    1460             : 
    1461       36182 :         if (delegated_proxy_principal != NULL) {
    1462          51 :                 deleg_blob = talloc_zero(mem_ctx, DATA_BLOB);
    1463          51 :                 if (deleg_blob == NULL) {
    1464           0 :                         code = ENOMEM;
    1465           0 :                         goto done;
    1466             :                 }
    1467             : 
    1468          51 :                 nt_status = samba_kdc_update_delegation_info_blob(
    1469             :                                 mem_ctx,
    1470             :                                 context,
    1471             :                                 old_pac,
    1472             :                                 server_principal,
    1473             :                                 delegated_proxy_principal,
    1474             :                                 deleg_blob);
    1475          51 :                 if (!NT_STATUS_IS_OK(nt_status)) {
    1476           0 :                         DBG_ERR("update delegation info blob failed: %s\n",
    1477             :                                 nt_errstr(nt_status));
    1478           0 :                         code = EINVAL;
    1479           0 :                         goto done;
    1480             :                 }
    1481             :         }
    1482             : 
    1483       36182 :         if (is_untrusted) {
    1484          42 :                 struct auth_user_info_dc *user_info_dc = NULL;
    1485             :                 WERROR werr;
    1486             :                 /*
    1487             :                  * In this case the RWDC discards the PAC an RODC generated.
    1488             :                  * Windows adds the asserted_identity in this case too.
    1489             :                  *
    1490             :                  * Note that SAMBA_KDC_FLAG_CONSTRAINED_DELEGATION
    1491             :                  * generates KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN.
    1492             :                  * So we can always use
    1493             :                  * SAMBA_ASSERTED_IDENTITY_AUTHENTICATION_AUTHORITY
    1494             :                  * here.
    1495             :                  */
    1496          42 :                 enum samba_asserted_identity asserted_identity =
    1497             :                         SAMBA_ASSERTED_IDENTITY_AUTHENTICATION_AUTHORITY;
    1498             : 
    1499          42 :                 if (client == NULL) {
    1500           0 :                         code = KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN;
    1501           0 :                         goto done;
    1502             :                 }
    1503             : 
    1504          42 :                 nt_status = samba_kdc_get_pac_blobs(mem_ctx,
    1505             :                                                     client,
    1506             :                                                     asserted_identity,
    1507             :                                                     &pac_blob,
    1508             :                                                     NULL,
    1509             :                                                     &upn_blob,
    1510             :                                                     NULL,
    1511             :                                                     PAC_ATTRIBUTE_FLAG_PAC_WAS_GIVEN_IMPLICITLY,
    1512             :                                                     &requester_sid_blob,
    1513             :                                                     &client_claims_blob);
    1514          42 :                 if (!NT_STATUS_IS_OK(nt_status)) {
    1515           0 :                         DBG_ERR("samba_kdc_get_pac_blobs failed: %s\n",
    1516             :                                 nt_errstr(nt_status));
    1517           0 :                         code = KRB5KDC_ERR_TGT_REVOKED;
    1518           0 :                         goto done;
    1519             :                 }
    1520             : 
    1521          42 :                 nt_status = samba_kdc_get_user_info_from_db(client,
    1522             :                                                             client->msg,
    1523             :                                                             &user_info_dc);
    1524          42 :                 if (!NT_STATUS_IS_OK(nt_status)) {
    1525           0 :                         DBG_ERR("samba_kdc_get_user_info_from_db failed: %s\n",
    1526             :                                 nt_errstr(nt_status));
    1527           0 :                         code = KRB5KDC_ERR_TGT_REVOKED;
    1528           0 :                         goto done;
    1529             :                 }
    1530             : 
    1531             :                 /*
    1532             :                  * Check if the SID list in the user_info_dc intersects
    1533             :                  * correctly with the RODC allow/deny lists.
    1534             :                  */
    1535          42 :                 werr = samba_rodc_confirm_user_is_allowed(user_info_dc->num_sids,
    1536          42 :                                                           user_info_dc->sids,
    1537             :                                                           krbtgt,
    1538             :                                                           client);
    1539          42 :                 TALLOC_FREE(user_info_dc);
    1540          42 :                 if (!W_ERROR_IS_OK(werr)) {
    1541           0 :                         code = KRB5KDC_ERR_TGT_REVOKED;
    1542           0 :                         if (W_ERROR_EQUAL(werr,
    1543             :                                           WERR_DOMAIN_CONTROLLER_NOT_FOUND)) {
    1544           0 :                                 code = KRB5KDC_ERR_POLICY;
    1545             :                         }
    1546           0 :                         goto done;
    1547             :                 }
    1548             : 
    1549             :                 /*
    1550             :                  * The RODC PAC data isn't trusted for authorization as it may
    1551             :                  * be stale. The only thing meaningful we can do with an RODC
    1552             :                  * account on a full DC is exchange the RODC TGT for a 'real'
    1553             :                  * TGT.
    1554             :                  *
    1555             :                  * So we match Windows (at least server 2022) and
    1556             :                  * don't allow S4U2Self.
    1557             :                  *
    1558             :                  * https://lists.samba.org/archive/cifs-protocol/2022-April/003673.html
    1559             :                  */
    1560          42 :                 if (flags & SAMBA_KDC_FLAG_PROTOCOL_TRANSITION) {
    1561           0 :                         code = KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN;
    1562           0 :                         goto done;
    1563             :                 }
    1564             :         } else {
    1565       36140 :                 pac_blob = talloc_zero(mem_ctx, DATA_BLOB);
    1566       36140 :                 if (pac_blob == NULL) {
    1567           0 :                         code = ENOMEM;
    1568           0 :                         goto done;
    1569             :                 }
    1570             : 
    1571       36140 :                 nt_status = samba_kdc_update_pac_blob(mem_ctx,
    1572             :                                                       context,
    1573             :                                                       samdb,
    1574             :                                                       old_pac,
    1575             :                                                       pac_blob,
    1576             :                                                       NULL,
    1577             :                                                       NULL);
    1578       36140 :                 if (!NT_STATUS_IS_OK(nt_status)) {
    1579           0 :                         DBG_ERR("samba_kdc_update_pac_blob failed: %s\n",
    1580             :                                  nt_errstr(nt_status));
    1581           0 :                         code = EINVAL;
    1582           0 :                         goto done;
    1583             :                 }
    1584             :         }
    1585             : 
    1586             :         /* Check the types of the given PAC */
    1587       36182 :         code = krb5_pac_get_types(context, old_pac, &num_types, &types);
    1588       36182 :         if (code != 0) {
    1589           0 :                 DBG_ERR("krb5_pac_get_types failed\n");
    1590           0 :                 goto done;
    1591             :         }
    1592             : 
    1593      289474 :         for (i = 0; i < num_types; i++) {
    1594      253292 :                 switch (types[i]) {
    1595       36182 :                 case PAC_TYPE_LOGON_INFO:
    1596       36182 :                         if (logon_info_idx != -1) {
    1597           0 :                                 DBG_WARNING("logon info type[%u] twice [%zd] "
    1598             :                                             "and [%zu]: \n",
    1599             :                                             types[i],
    1600             :                                             logon_info_idx,
    1601             :                                             i);
    1602           0 :                                 code = EINVAL;
    1603           0 :                                 goto done;
    1604             :                         }
    1605       36182 :                         logon_info_idx = i;
    1606       36182 :                         break;
    1607           2 :                 case PAC_TYPE_CONSTRAINED_DELEGATION:
    1608           2 :                         if (delegation_idx != -1) {
    1609           0 :                                 DBG_WARNING("constrained delegation type[%u] "
    1610             :                                             "twice [%zd] and [%zu]: \n",
    1611             :                                             types[i],
    1612             :                                             delegation_idx,
    1613             :                                             i);
    1614           0 :                                 code = EINVAL;
    1615           0 :                                 goto done;
    1616             :                         }
    1617           2 :                         delegation_idx = i;
    1618           2 :                         break;
    1619       36182 :                 case PAC_TYPE_LOGON_NAME:
    1620       36182 :                         if (logon_name_idx != -1) {
    1621           0 :                                 DBG_WARNING("logon name type[%u] twice [%zd] "
    1622             :                                             "and [%zu]: \n",
    1623             :                                             types[i],
    1624             :                                             logon_name_idx,
    1625             :                                             i);
    1626           0 :                                 code = EINVAL;
    1627           0 :                                 goto done;
    1628             :                         }
    1629       36182 :                         logon_name_idx = i;
    1630       36182 :                         break;
    1631       36182 :                 case PAC_TYPE_UPN_DNS_INFO:
    1632       36182 :                         if (upn_dns_info_idx != -1) {
    1633           0 :                                 DBG_WARNING("upn dns info type[%u] twice [%zd] "
    1634             :                                             "and [%zu]: \n",
    1635             :                                             types[i],
    1636             :                                             upn_dns_info_idx,
    1637             :                                             i);
    1638           0 :                                 code = EINVAL;
    1639           0 :                                 goto done;
    1640             :                         }
    1641       36182 :                         upn_dns_info_idx = i;
    1642       36182 :                         break;
    1643       36182 :                 case PAC_TYPE_SRV_CHECKSUM:
    1644       36182 :                         if (srv_checksum_idx != -1) {
    1645           0 :                                 DBG_WARNING("srv checksum type[%u] twice [%zd] "
    1646             :                                             "and [%zu]: \n",
    1647             :                                             types[i],
    1648             :                                             srv_checksum_idx,
    1649             :                                             i);
    1650           0 :                                 code = EINVAL;
    1651           0 :                                 goto done;
    1652             :                         }
    1653       36182 :                         srv_checksum_idx = i;
    1654       36182 :                         break;
    1655       36182 :                 case PAC_TYPE_KDC_CHECKSUM:
    1656       36182 :                         if (kdc_checksum_idx != -1) {
    1657           0 :                                 DBG_WARNING("kdc checksum type[%u] twice [%zd] "
    1658             :                                             "and [%zu]: \n",
    1659             :                                             types[i],
    1660             :                                             kdc_checksum_idx,
    1661             :                                             i);
    1662           0 :                                 code = EINVAL;
    1663           0 :                                 goto done;
    1664             :                         }
    1665       36182 :                         kdc_checksum_idx = i;
    1666       36182 :                         break;
    1667          59 :                 case PAC_TYPE_TICKET_CHECKSUM:
    1668          59 :                         if (tkt_checksum_idx != -1) {
    1669           0 :                                 DBG_WARNING("ticket checksum type[%u] twice "
    1670             :                                             "[%zd] and [%zu]: \n",
    1671             :                                             types[i],
    1672             :                                             tkt_checksum_idx,
    1673             :                                             i);
    1674           0 :                                 code = EINVAL;
    1675           0 :                                 goto done;
    1676             :                         }
    1677          59 :                         tkt_checksum_idx = i;
    1678          59 :                         break;
    1679       36131 :                 case PAC_TYPE_ATTRIBUTES_INFO:
    1680       36131 :                         if (attrs_info_idx != -1) {
    1681           0 :                                 DBG_WARNING("attributes info type[%u] twice "
    1682             :                                             "[%zd] and [%zu]: \n",
    1683             :                                             types[i],
    1684             :                                             attrs_info_idx,
    1685             :                                             i);
    1686           0 :                                 code = EINVAL;
    1687           0 :                                 goto done;
    1688             :                         }
    1689       36131 :                         attrs_info_idx = i;
    1690       36131 :                         break;
    1691       36131 :                 case PAC_TYPE_REQUESTER_SID:
    1692       36131 :                         if (requester_sid_idx != -1) {
    1693           0 :                                 DBG_WARNING("requester sid type[%u] twice"
    1694             :                                             "[%zd] and [%zu]: \n",
    1695             :                                             types[i],
    1696             :                                             requester_sid_idx,
    1697             :                                             i);
    1698           0 :                                 code = EINVAL;
    1699           0 :                                 goto done;
    1700             :                         }
    1701       36131 :                         requester_sid_idx = i;
    1702       36131 :                         break;
    1703          59 :                 case PAC_TYPE_FULL_CHECKSUM:
    1704          59 :                         if (full_checksum_idx != -1) {
    1705           0 :                                 DBG_WARNING("full checksum type[%u] twice "
    1706             :                                             "[%zd] and [%zu]: \n",
    1707             :                                             types[i],
    1708             :                                             full_checksum_idx,
    1709             :                                             i);
    1710           0 :                                 code = EINVAL;
    1711           0 :                                 goto done;
    1712             :                         }
    1713          59 :                         full_checksum_idx = i;
    1714          59 :                         break;
    1715           0 :                 default:
    1716           0 :                         continue;
    1717             :                 }
    1718             :         }
    1719             : 
    1720       36182 :         if (logon_info_idx == -1) {
    1721           0 :                 DBG_WARNING("PAC_TYPE_LOGON_INFO missing\n");
    1722           0 :                 code = EINVAL;
    1723           0 :                 goto done;
    1724             :         }
    1725       36182 :         if (logon_name_idx == -1) {
    1726           0 :                 DBG_WARNING("PAC_TYPE_LOGON_NAME missing\n");
    1727           0 :                 code = EINVAL;
    1728           0 :                 goto done;
    1729             :         }
    1730       36182 :         if (srv_checksum_idx == -1) {
    1731           0 :                 DBG_WARNING("PAC_TYPE_SRV_CHECKSUM missing\n");
    1732           0 :                 code = EINVAL;
    1733           0 :                 goto done;
    1734             :         }
    1735       36182 :         if (kdc_checksum_idx == -1) {
    1736           0 :                 DBG_WARNING("PAC_TYPE_KDC_CHECKSUM missing\n");
    1737           0 :                 code = EINVAL;
    1738           0 :                 goto done;
    1739             :         }
    1740       36182 :         if (!(flags & SAMBA_KDC_FLAG_CONSTRAINED_DELEGATION) &&
    1741             :             requester_sid_idx == -1) {
    1742           0 :                 DBG_WARNING("PAC_TYPE_REQUESTER_SID missing\n");
    1743           0 :                 code = KRB5KDC_ERR_TGT_REVOKED;
    1744           0 :                 goto done;
    1745             :         }
    1746             : 
    1747             :         /*
    1748             :          * The server account may be set not to want the PAC.
    1749             :          *
    1750             :          * While this is wasteful if the above cacluations were done
    1751             :          * and now thrown away, this is cleaner as we do any ticket
    1752             :          * signature checking etc always.
    1753             :          *
    1754             :          * UF_NO_AUTH_DATA_REQUIRED is the rare case and most of the
    1755             :          * time (eg not accepting a ticket from the RODC) we do not
    1756             :          * need to re-generate anything anyway.
    1757             :          */
    1758       36182 :         if (!samba_princ_needs_pac(server)) {
    1759           9 :                 code = ENODATA;
    1760           9 :                 goto done;
    1761             :         }
    1762             : 
    1763       36173 :         is_tgs = smb_krb5_principal_is_tgs(context, server_principal);
    1764       36173 :         if (is_tgs == -1) {
    1765           0 :                 code = ENOMEM;
    1766           0 :                 goto done;
    1767             :         }
    1768             : 
    1769       36173 :         if (!is_untrusted && !is_tgs) {
    1770             :                 /*
    1771             :                  * The client may have requested no PAC when obtaining the
    1772             :                  * TGT.
    1773             :                  */
    1774       14773 :                 bool requested_pac = false;
    1775             : 
    1776       14773 :                 code = samba_client_requested_pac(context,
    1777             :                                                   &old_pac,
    1778             :                                                   mem_ctx,
    1779             :                                                   &requested_pac);
    1780       14773 :                 if (code != 0 || !requested_pac) {
    1781           0 :                         if (!requested_pac) {
    1782           0 :                                 code = ENODATA;
    1783             :                         }
    1784           0 :                         goto done;
    1785             :                 }
    1786             :         }
    1787             : 
    1788             : #define MAX_PAC_BUFFERS 128 /* Avoid infinite loops */
    1789             : 
    1790      289451 :         for (i = 0; i < MAX_PAC_BUFFERS;) {
    1791      289451 :                 const uint8_t zero_byte = 0;
    1792             :                 krb5_data type_data;
    1793      289451 :                 DATA_BLOB type_blob = data_blob_null;
    1794             :                 uint32_t type;
    1795             : 
    1796             :                 static char null_byte = '\0';
    1797      289451 :                 const krb5_data null_data = smb_krb5_make_data(&null_byte, 0);
    1798             : 
    1799      289451 :                 if (forced_next_type != 0) {
    1800             :                         /*
    1801             :                          * We need to inject possible missing types
    1802             :                          */
    1803          49 :                         type = forced_next_type;
    1804          49 :                         forced_next_type = 0;
    1805      289402 :                 } else if (i < num_types) {
    1806      253229 :                         type = types[i];
    1807      253229 :                         i++;
    1808             :                 } else {
    1809       36173 :                         break;
    1810             :                 }
    1811             : 
    1812      253278 :                 switch (type) {
    1813       36173 :                 case PAC_TYPE_LOGON_INFO:
    1814       36173 :                         type_blob = *pac_blob;
    1815             : 
    1816       36173 :                         if (delegation_idx == -1 && deleg_blob != NULL) {
    1817             :                                 /* inject CONSTRAINED_DELEGATION behind */
    1818          49 :                                 forced_next_type =
    1819             :                                         PAC_TYPE_CONSTRAINED_DELEGATION;
    1820             :                         }
    1821       36173 :                         break;
    1822          51 :                 case PAC_TYPE_CONSTRAINED_DELEGATION:
    1823             :                         /*
    1824             :                          * This is generated in the main KDC code
    1825             :                          */
    1826          51 :                         if (flags & SAMBA_KDC_FLAG_SKIP_PAC_BUFFER) {
    1827       29528 :                                 continue;
    1828             :                         }
    1829             : 
    1830          51 :                         if (deleg_blob != NULL) {
    1831          51 :                                 type_blob = *deleg_blob;
    1832             :                         }
    1833          51 :                         break;
    1834           0 :                 case PAC_TYPE_CREDENTIAL_INFO:
    1835             :                         /*
    1836             :                          * Note that we copy the credential blob,
    1837             :                          * as it's only usable with the PKINIT based
    1838             :                          * AS-REP reply key, it's only available on the
    1839             :                          * host which did the AS-REQ/AS-REP exchange.
    1840             :                          *
    1841             :                          * This matches Windows 2008R2...
    1842             :                          */
    1843           0 :                         break;
    1844       36173 :                 case PAC_TYPE_LOGON_NAME:
    1845             :                         /*
    1846             :                          * This is generated in the main KDC code
    1847             :                          */
    1848       36173 :                         if (flags & SAMBA_KDC_FLAG_SKIP_PAC_BUFFER) {
    1849           0 :                                 continue;
    1850             :                         }
    1851             : 
    1852       36173 :                         type_blob = data_blob_const(&zero_byte, 1);
    1853             : 
    1854       36173 :                         if (upn_dns_info_idx == -1 && upn_blob != NULL) {
    1855             :                                 /* inject UPN_DNS_INFO behind */
    1856           0 :                                 forced_next_type = PAC_TYPE_UPN_DNS_INFO;
    1857             :                         }
    1858       36173 :                         break;
    1859       36173 :                 case PAC_TYPE_UPN_DNS_INFO:
    1860             :                         /*
    1861             :                          * Replace in the RODC case, otherwise
    1862             :                          * upn_blob is NULL and we just copy.
    1863             :                          */
    1864       36173 :                         if (upn_blob != NULL) {
    1865          42 :                                 type_blob = *upn_blob;
    1866             :                         }
    1867       36173 :                         break;
    1868       36173 :                 case PAC_TYPE_SRV_CHECKSUM:
    1869             :                         /*
    1870             :                          * This is generated in the main KDC code
    1871             :                          */
    1872       36173 :                         if (flags & SAMBA_KDC_FLAG_SKIP_PAC_BUFFER) {
    1873           0 :                                 continue;
    1874             :                         }
    1875             : 
    1876       36173 :                         type_blob = data_blob_const(&zero_byte, 1);
    1877             : 
    1878       36173 :                         if (requester_sid_idx == -1 && requester_sid_blob != NULL) {
    1879             :                                 /* inject REQUESTER_SID behind */
    1880           0 :                                 forced_next_type = PAC_TYPE_REQUESTER_SID;
    1881             :                         }
    1882       36173 :                         break;
    1883       36173 :                 case PAC_TYPE_KDC_CHECKSUM:
    1884             :                         /*
    1885             :                          * This is generated in the main KDC code
    1886             :                          */
    1887       36173 :                         if (flags & SAMBA_KDC_FLAG_SKIP_PAC_BUFFER) {
    1888           0 :                                 continue;
    1889             :                         }
    1890             : 
    1891       36173 :                         type_blob = data_blob_const(&zero_byte, 1);
    1892             : 
    1893       36173 :                         break;
    1894          59 :                 case PAC_TYPE_TICKET_CHECKSUM:
    1895             :                         /*
    1896             :                          * This is generated in the main KDC code
    1897             :                          */
    1898          59 :                         if (flags & SAMBA_KDC_FLAG_SKIP_PAC_BUFFER) {
    1899           0 :                                 continue;
    1900             :                         }
    1901             : 
    1902          59 :                         type_blob = data_blob_const(&zero_byte, 1);
    1903             : 
    1904          59 :                         break;
    1905       36122 :                 case PAC_TYPE_ATTRIBUTES_INFO:
    1906       36122 :                         if (!is_untrusted && is_tgs) {
    1907             :                                 /* just copy... */
    1908       21358 :                                 break;
    1909             :                         }
    1910             : 
    1911       14764 :                         continue;
    1912       36122 :                 case PAC_TYPE_REQUESTER_SID:
    1913       36122 :                         if (!is_tgs) {
    1914       14764 :                                 continue;
    1915             :                         }
    1916             : 
    1917             :                         /*
    1918             :                          * Replace in the RODC case, otherwise
    1919             :                          * requester_sid_blob is NULL and we just copy.
    1920             :                          */
    1921       21358 :                         if (requester_sid_blob != NULL) {
    1922           0 :                                 type_blob = *requester_sid_blob;
    1923             :                         }
    1924       21358 :                         break;
    1925          59 :                 case PAC_TYPE_FULL_CHECKSUM:
    1926             :                         /*
    1927             :                          * This is generated in the main KDC code
    1928             :                          */
    1929          59 :                         if (flags & SAMBA_KDC_FLAG_SKIP_PAC_BUFFER) {
    1930           0 :                                 continue;
    1931             :                         }
    1932             : 
    1933          59 :                         type_blob = data_blob_const(&zero_byte, 1);
    1934             : 
    1935          59 :                         break;
    1936           0 :                 default:
    1937             :                         /* just copy... */
    1938           0 :                         break;
    1939             :                 }
    1940             : 
    1941      223750 :                 if (type_blob.length != 0) {
    1942      144903 :                         type_data = smb_krb5_data_from_blob(type_blob);
    1943      144903 :                         code = krb5_pac_add_buffer(context, new_pac,
    1944             :                                                    type, &type_data);
    1945             :                 } else {
    1946       78847 :                         code = krb5_pac_get_buffer(context,
    1947             :                                                    old_pac,
    1948             :                                                    type,
    1949             :                                                    &type_data);
    1950       78847 :                         if (code != 0) {
    1951           0 :                                 goto done;
    1952             :                         }
    1953             :                         /*
    1954             :                          * Passing a NULL pointer into krb5_pac_add_buffer() is
    1955             :                          * not allowed, so pass null_data instead if needed.
    1956             :                          */
    1957       78847 :                         code = krb5_pac_add_buffer(context,
    1958             :                                                    new_pac,
    1959             :                                                    type,
    1960       78847 :                                                    (type_data.data != NULL) ? &type_data : &null_data);
    1961       78847 :                         smb_krb5_free_data_contents(context, &type_data);
    1962             :                 }
    1963             : 
    1964      223750 :                 if (code != 0) {
    1965           0 :                         goto done;
    1966             :                 }
    1967             :         }
    1968             : 
    1969       36173 :         code = 0;
    1970       36182 : done:
    1971       36182 :         TALLOC_FREE(pac_blob);
    1972       36182 :         TALLOC_FREE(upn_blob);
    1973       36182 :         TALLOC_FREE(deleg_blob);
    1974       36182 :         SAFE_FREE(types);
    1975       36182 :         return code;
    1976             : }

Generated by: LCOV version 1.14