LCOV - code coverage report
Current view: top level - source4/kdc - pac-glue.c (source / functions) Hit Total Coverage
Test: coverage report for v4-17-test 1498b464 Lines: 481 913 52.7 %
Date: 2024-06-13 04:01:37 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       54978 : 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       54978 :         ZERO_STRUCT(pac_info);
      60             : 
      61       54978 :         *pac_data = data_blob_null;
      62       54978 :         if (requester_sid_blob != NULL) {
      63       17188 :                 *requester_sid_blob = data_blob_null;
      64             :         }
      65             : 
      66       54978 :         nt_status = auth_convert_user_info_dc_saminfo3(mem_ctx, info, &info3);
      67       54978 :         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       54978 :         pac_info.logon_info.info = talloc_zero(mem_ctx, struct PAC_LOGON_INFO);
      74       54978 :         if (!pac_info.logon_info.info) {
      75           0 :                 return NT_STATUS_NO_MEMORY;
      76             :         }
      77             : 
      78       54978 :         pac_info.logon_info.info->info3 = *info3;
      79             : 
      80       54978 :         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       54978 :         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       54978 :         if (requester_sid_blob != NULL && info->num_sids > 0) {
      91             :                 union PAC_INFO pac_requester_sid;
      92             : 
      93       17188 :                 ZERO_STRUCT(pac_requester_sid);
      94             : 
      95       17188 :                 pac_requester_sid.requester_sid.sid = info->sids[0];
      96             : 
      97       17188 :                 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       17188 :                 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       54978 :         return NT_STATUS_OK;
     110             : }
     111             : 
     112             : static
     113       19010 : 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       19010 :         ZERO_STRUCT(pac_upn);
     123             : 
     124       19010 :         *upn_data = data_blob_null;
     125             : 
     126       19010 :         pac_upn.upn_dns_info.upn_name = info->info->user_principal_name;
     127       19010 :         pac_upn.upn_dns_info.dns_domain_name = strupper_talloc(mem_ctx,
     128       19010 :                                                 info->info->dns_domain_name);
     129       19010 :         if (pac_upn.upn_dns_info.dns_domain_name == NULL) {
     130           0 :                 return NT_STATUS_NO_MEMORY;
     131             :         }
     132       19010 :         if (info->info->user_principal_constructed) {
     133       17923 :                 pac_upn.upn_dns_info.flags |= PAC_UPN_DNS_FLAG_CONSTRUCTED;
     134             :         }
     135             : 
     136       19010 :         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       19010 :                 = info->info->account_name;
     140             : 
     141             :         pac_upn.upn_dns_info.ex.sam_name_and_sid.objectsid
     142       19010 :                 = &info->sids[0];
     143             : 
     144       19010 :         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       19010 :         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       19010 :         ok = data_blob_pad(mem_ctx, upn_data, 8);
     155       19010 :         if (!ok) {
     156           0 :                 return NT_STATUS_NO_MEMORY;
     157             :         }
     158             : 
     159       19010 :         return NT_STATUS_OK;
     160             : }
     161             : 
     162             : static
     163       17141 : 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       17141 :         ZERO_STRUCT(pac_attrs);
     172             : 
     173       17141 :         *pac_attrs_data = data_blob_null;
     174             : 
     175             :         /* Set the length of the flags in bits. */
     176       17141 :         pac_attrs.attributes_info.flags_length = 2;
     177       17141 :         pac_attrs.attributes_info.flags = pac_attributes;
     178             : 
     179       17141 :         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       17141 :         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       17141 :         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] pac        The pac buffer to fill. This should be allocated with
     507             :  *                       krb5_pac_init() already.
     508             :  *
     509             :  * @returns 0 on success or a corresponding KRB5 error.
     510             :  */
     511       18963 : krb5_error_code samba_make_krb5_pac(krb5_context context,
     512             :                                     const DATA_BLOB *logon_blob,
     513             :                                     const DATA_BLOB *cred_blob,
     514             :                                     const DATA_BLOB *upn_blob,
     515             :                                     const DATA_BLOB *pac_attrs_blob,
     516             :                                     const DATA_BLOB *requester_sid_blob,
     517             :                                     const DATA_BLOB *deleg_blob,
     518             :                                     krb5_pac pac)
     519             : {
     520             :         krb5_data logon_data;
     521             :         krb5_data cred_data;
     522             :         krb5_data upn_data;
     523             :         krb5_data pac_attrs_data;
     524             :         krb5_data requester_sid_data;
     525             :         krb5_data deleg_data;
     526             :         krb5_error_code ret;
     527             : #ifdef SAMBA4_USES_HEIMDAL
     528       18963 :         char null_byte = '\0';
     529       18963 :         krb5_data null_data = {
     530             :                 .length = 1,
     531             :                 .data = &null_byte,
     532             :         };
     533             : #endif
     534             : 
     535             :         /* The user account may be set not to want the PAC */
     536       18963 :         if (logon_blob == NULL) {
     537           0 :                 return 0;
     538             :         }
     539             : 
     540       37926 :         ret = smb_krb5_copy_data_contents(&logon_data,
     541       18963 :                                           logon_blob->data,
     542           0 :                                           logon_blob->length);
     543       18963 :         if (ret != 0) {
     544           0 :                 return ret;
     545             :         }
     546             : 
     547       18963 :         ZERO_STRUCT(cred_data);
     548       18963 :         if (cred_blob != NULL) {
     549           0 :                 ret = smb_krb5_copy_data_contents(&cred_data,
     550           0 :                                                   cred_blob->data,
     551           0 :                                                   cred_blob->length);
     552           0 :                 if (ret != 0) {
     553           0 :                         smb_krb5_free_data_contents(context, &logon_data);
     554           0 :                         return ret;
     555             :                 }
     556             :         }
     557             : 
     558       18963 :         ZERO_STRUCT(upn_data);
     559       18963 :         if (upn_blob != NULL) {
     560       37926 :                 ret = smb_krb5_copy_data_contents(&upn_data,
     561       18963 :                                                   upn_blob->data,
     562           0 :                                                   upn_blob->length);
     563       18963 :                 if (ret != 0) {
     564           0 :                         smb_krb5_free_data_contents(context, &logon_data);
     565           0 :                         smb_krb5_free_data_contents(context, &cred_data);
     566           0 :                         return ret;
     567             :                 }
     568             :         }
     569             : 
     570       18963 :         ZERO_STRUCT(pac_attrs_data);
     571       18963 :         if (pac_attrs_blob != NULL) {
     572       34282 :                 ret = smb_krb5_copy_data_contents(&pac_attrs_data,
     573       17141 :                                                   pac_attrs_blob->data,
     574           0 :                                                   pac_attrs_blob->length);
     575       17141 :                 if (ret != 0) {
     576           0 :                         smb_krb5_free_data_contents(context, &logon_data);
     577           0 :                         smb_krb5_free_data_contents(context, &cred_data);
     578           0 :                         smb_krb5_free_data_contents(context, &upn_data);
     579           0 :                         return ret;
     580             :                 }
     581             :         }
     582             : 
     583       18963 :         ZERO_STRUCT(requester_sid_data);
     584       18963 :         if (requester_sid_blob != NULL) {
     585       34282 :                 ret = smb_krb5_copy_data_contents(&requester_sid_data,
     586       17141 :                                                   requester_sid_blob->data,
     587           0 :                                                   requester_sid_blob->length);
     588       17141 :                 if (ret != 0) {
     589           0 :                         smb_krb5_free_data_contents(context, &logon_data);
     590           0 :                         smb_krb5_free_data_contents(context, &cred_data);
     591           0 :                         smb_krb5_free_data_contents(context, &upn_data);
     592           0 :                         smb_krb5_free_data_contents(context, &pac_attrs_data);
     593           0 :                         return ret;
     594             :                 }
     595             :         }
     596             : 
     597       18963 :         ZERO_STRUCT(deleg_data);
     598       18963 :         if (deleg_blob != NULL) {
     599           0 :                 ret = smb_krb5_copy_data_contents(&deleg_data,
     600           0 :                                                   deleg_blob->data,
     601           0 :                                                   deleg_blob->length);
     602           0 :                 if (ret != 0) {
     603           0 :                         smb_krb5_free_data_contents(context, &logon_data);
     604           0 :                         smb_krb5_free_data_contents(context, &cred_data);
     605           0 :                         smb_krb5_free_data_contents(context, &upn_data);
     606           0 :                         smb_krb5_free_data_contents(context, &pac_attrs_data);
     607           0 :                         smb_krb5_free_data_contents(context, &requester_sid_data);
     608           0 :                         return ret;
     609             :                 }
     610             :         }
     611             : 
     612       18963 :         ret = krb5_pac_add_buffer(context, pac, PAC_TYPE_LOGON_INFO, &logon_data);
     613       18963 :         smb_krb5_free_data_contents(context, &logon_data);
     614       18963 :         if (ret != 0) {
     615           0 :                 smb_krb5_free_data_contents(context, &cred_data);
     616           0 :                 smb_krb5_free_data_contents(context, &upn_data);
     617           0 :                 smb_krb5_free_data_contents(context, &pac_attrs_data);
     618           0 :                 smb_krb5_free_data_contents(context, &requester_sid_data);
     619           0 :                 smb_krb5_free_data_contents(context, &deleg_data);
     620           0 :                 return ret;
     621             :         }
     622             : 
     623       18963 :         if (cred_blob != NULL) {
     624           0 :                 ret = krb5_pac_add_buffer(context, pac,
     625             :                                           PAC_TYPE_CREDENTIAL_INFO,
     626             :                                           &cred_data);
     627           0 :                 smb_krb5_free_data_contents(context, &cred_data);
     628           0 :                 if (ret != 0) {
     629           0 :                         smb_krb5_free_data_contents(context, &upn_data);
     630           0 :                         smb_krb5_free_data_contents(context, &pac_attrs_data);
     631           0 :                         smb_krb5_free_data_contents(context, &requester_sid_data);
     632           0 :                         smb_krb5_free_data_contents(context, &deleg_data);
     633           0 :                         return ret;
     634             :                 }
     635             :         }
     636             : 
     637             : #ifdef SAMBA4_USES_HEIMDAL
     638             :         /*
     639             :          * null_data will be filled by the generic KDC code in the caller
     640             :          * here we just add it in order to have it before
     641             :          * PAC_TYPE_UPN_DNS_INFO
     642             :          *
     643             :          * Not needed with MIT Kerberos - asn
     644             :          */
     645       18963 :         ret = krb5_pac_add_buffer(context, pac,
     646             :                                   PAC_TYPE_LOGON_NAME,
     647             :                                   &null_data);
     648       18963 :         if (ret != 0) {
     649           0 :                 smb_krb5_free_data_contents(context, &upn_data);
     650           0 :                 smb_krb5_free_data_contents(context, &pac_attrs_data);
     651           0 :                 smb_krb5_free_data_contents(context, &requester_sid_data);
     652           0 :                 smb_krb5_free_data_contents(context, &deleg_data);
     653           0 :                 return ret;
     654             :         }
     655             : #endif
     656             : 
     657       18963 :         if (upn_blob != NULL) {
     658       18963 :                 ret = krb5_pac_add_buffer(context, pac,
     659             :                                           PAC_TYPE_UPN_DNS_INFO,
     660             :                                           &upn_data);
     661       18963 :                 smb_krb5_free_data_contents(context, &upn_data);
     662       18963 :                 if (ret != 0) {
     663           0 :                         smb_krb5_free_data_contents(context, &pac_attrs_data);
     664           0 :                         smb_krb5_free_data_contents(context, &requester_sid_data);
     665           0 :                         smb_krb5_free_data_contents(context, &deleg_data);
     666           0 :                         return ret;
     667             :                 }
     668             :         }
     669             : 
     670       18963 :         if (pac_attrs_blob != NULL) {
     671       17141 :                 ret = krb5_pac_add_buffer(context, pac,
     672             :                                           PAC_TYPE_ATTRIBUTES_INFO,
     673             :                                           &pac_attrs_data);
     674       17141 :                 smb_krb5_free_data_contents(context, &pac_attrs_data);
     675       17141 :                 if (ret != 0) {
     676           0 :                         smb_krb5_free_data_contents(context, &requester_sid_data);
     677           0 :                         smb_krb5_free_data_contents(context, &deleg_data);
     678           0 :                         return ret;
     679             :                 }
     680             :         }
     681             : 
     682       18963 :         if (requester_sid_blob != NULL) {
     683       17141 :                 ret = krb5_pac_add_buffer(context, pac,
     684             :                                           PAC_TYPE_REQUESTER_SID,
     685             :                                           &requester_sid_data);
     686       17141 :                 smb_krb5_free_data_contents(context, &requester_sid_data);
     687       17141 :                 if (ret != 0) {
     688           0 :                         smb_krb5_free_data_contents(context, &deleg_data);
     689           0 :                         return ret;
     690             :                 }
     691             :         }
     692             : 
     693       18963 :         if (deleg_blob != NULL) {
     694           0 :                 ret = krb5_pac_add_buffer(context, pac,
     695             :                                           PAC_TYPE_CONSTRAINED_DELEGATION,
     696             :                                           &deleg_data);
     697           0 :                 smb_krb5_free_data_contents(context, &deleg_data);
     698           0 :                 if (ret != 0) {
     699           0 :                         return ret;
     700             :                 }
     701             :         }
     702             : 
     703       18963 :         return ret;
     704             : }
     705             : 
     706       36015 : bool samba_princ_needs_pac(struct samba_kdc_entry *skdc_entry)
     707             : {
     708             : 
     709             :         uint32_t userAccountControl;
     710             : 
     711             :         /* The service account may be set not to want the PAC */
     712       36015 :         userAccountControl = ldb_msg_find_attr_as_uint(skdc_entry->msg, "userAccountControl", 0);
     713       36015 :         if (userAccountControl & UF_NO_AUTH_DATA_REQUIRED) {
     714           9 :                 return false;
     715             :         }
     716             : 
     717       36006 :         return true;
     718             : }
     719             : 
     720       14760 : int samba_client_requested_pac(krb5_context context,
     721             :                                const krb5_pac *pac,
     722             :                                TALLOC_CTX *mem_ctx,
     723             :                                bool *requested_pac)
     724             : {
     725             :         enum ndr_err_code ndr_err;
     726             :         krb5_data k5pac_attrs_in;
     727             :         DATA_BLOB pac_attrs_in;
     728             :         union PAC_INFO pac_attrs;
     729             :         int ret;
     730             : 
     731       14760 :         *requested_pac = true;
     732             : 
     733       14760 :         ret = krb5_pac_get_buffer(context, *pac, PAC_TYPE_ATTRIBUTES_INFO,
     734             :                                   &k5pac_attrs_in);
     735       14760 :         if (ret != 0) {
     736          51 :                 return ret == ENOENT ? 0 : ret;
     737             :         }
     738             : 
     739       14709 :         pac_attrs_in = data_blob_const(k5pac_attrs_in.data,
     740           0 :                                        k5pac_attrs_in.length);
     741             : 
     742       14709 :         ndr_err = ndr_pull_union_blob(&pac_attrs_in, mem_ctx, &pac_attrs,
     743             :                                       PAC_TYPE_ATTRIBUTES_INFO,
     744             :                                       (ndr_pull_flags_fn_t)ndr_pull_PAC_INFO);
     745       14709 :         smb_krb5_free_data_contents(context, &k5pac_attrs_in);
     746       14709 :         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
     747           0 :                 NTSTATUS nt_status = ndr_map_error2ntstatus(ndr_err);
     748           0 :                 DEBUG(0,("can't parse the PAC ATTRIBUTES_INFO: %s\n", nt_errstr(nt_status)));
     749           0 :                 return EINVAL;
     750             :         }
     751             : 
     752       14709 :         if (pac_attrs.attributes_info.flags & (PAC_ATTRIBUTE_FLAG_PAC_WAS_GIVEN_IMPLICITLY
     753             :                                                | PAC_ATTRIBUTE_FLAG_PAC_WAS_REQUESTED)) {
     754       14709 :                 *requested_pac = true;
     755             :         } else {
     756           0 :                 *requested_pac = false;
     757             :         }
     758             : 
     759       14709 :         return 0;
     760             : }
     761             : 
     762             : /* Was the krbtgt in this DB (ie, should we check the incoming signature) and was it an RODC */
     763       36040 : int samba_krbtgt_is_in_db(struct samba_kdc_entry *p,
     764             :                           bool *is_in_db,
     765             :                           bool *is_untrusted)
     766             : {
     767             :         NTSTATUS status;
     768             :         int rodc_krbtgt_number, trust_direction;
     769             :         uint32_t rid;
     770             : 
     771       36040 :         TALLOC_CTX *mem_ctx = talloc_new(NULL);
     772       36040 :         if (!mem_ctx) {
     773           0 :                 return ENOMEM;
     774             :         }
     775             : 
     776       36040 :         trust_direction = ldb_msg_find_attr_as_int(p->msg, "trustDirection", 0);
     777             : 
     778       36040 :         if (trust_direction != 0) {
     779             :                 /* Domain trust - we cannot check the sig, but we trust it for a correct PAC
     780             : 
     781             :                    This is exactly where we should flag for SID
     782             :                    validation when we do inter-foreest trusts
     783             :                  */
     784          48 :                 talloc_free(mem_ctx);
     785          48 :                 *is_untrusted = false;
     786          48 :                 *is_in_db = false;
     787          48 :                 return 0;
     788             :         }
     789             : 
     790             :         /* The lack of password controls etc applies to krbtgt by
     791             :          * virtue of being that particular RID */
     792       35992 :         status = dom_sid_split_rid(NULL, samdb_result_dom_sid(mem_ctx, p->msg, "objectSid"), NULL, &rid);
     793             : 
     794       35992 :         if (!NT_STATUS_IS_OK(status)) {
     795           0 :                 talloc_free(mem_ctx);
     796           0 :                 return EINVAL;
     797             :         }
     798             : 
     799       35992 :         rodc_krbtgt_number = ldb_msg_find_attr_as_int(p->msg, "msDS-SecondaryKrbTgtNumber", -1);
     800             : 
     801       35992 :         if (p->kdc_db_ctx->my_krbtgt_number == 0) {
     802       33594 :                 if (rid == DOMAIN_RID_KRBTGT) {
     803       33547 :                         *is_untrusted = false;
     804       33547 :                         *is_in_db = true;
     805       33547 :                         talloc_free(mem_ctx);
     806       33547 :                         return 0;
     807          47 :                 } else if (rodc_krbtgt_number != -1) {
     808          47 :                         *is_in_db = true;
     809          47 :                         *is_untrusted = true;
     810          47 :                         talloc_free(mem_ctx);
     811          47 :                         return 0;
     812             :                 }
     813        2398 :         } else if ((rid != DOMAIN_RID_KRBTGT) && (rodc_krbtgt_number == p->kdc_db_ctx->my_krbtgt_number)) {
     814        2398 :                 talloc_free(mem_ctx);
     815        2398 :                 *is_untrusted = false;
     816        2398 :                 *is_in_db = true;
     817        2398 :                 return 0;
     818           0 :         } else if (rid == DOMAIN_RID_KRBTGT) {
     819             :                 /* krbtgt viewed from an RODC */
     820           0 :                 talloc_free(mem_ctx);
     821           0 :                 *is_untrusted = false;
     822           0 :                 *is_in_db = false;
     823           0 :                 return 0;
     824             :         }
     825             : 
     826             :         /* Another RODC */
     827           0 :         talloc_free(mem_ctx);
     828           0 :         *is_untrusted = true;
     829           0 :         *is_in_db = false;
     830           0 :         return 0;
     831             : }
     832             : 
     833             : /*
     834             :  * Because the KDC does not limit protocol transition, two new well-known SIDs
     835             :  * were introduced to give this control to the resource administrator. These
     836             :  * SIDs identify whether protocol transition has occurred, and can be used with
     837             :  * standard access control lists to grant or limit access as needed.
     838             :  *
     839             :  * https://docs.microsoft.com/en-us/windows-server/security/kerberos/kerberos-constrained-delegation-overview
     840             :  */
     841       19010 : static NTSTATUS samba_add_asserted_identity(TALLOC_CTX *mem_ctx,
     842             :                                             enum samba_asserted_identity ai,
     843             :                                             struct auth_user_info_dc *user_info_dc)
     844             : {
     845             :         struct dom_sid ai_sid;
     846       19010 :         const char *sid_str = NULL;
     847             : 
     848       19010 :         switch (ai) {
     849         636 :         case SAMBA_ASSERTED_IDENTITY_SERVICE:
     850         636 :                 sid_str = SID_SERVICE_ASSERTED_IDENTITY;
     851         636 :                 break;
     852       18374 :         case SAMBA_ASSERTED_IDENTITY_AUTHENTICATION_AUTHORITY:
     853       18374 :                 sid_str = SID_AUTHENTICATION_AUTHORITY_ASSERTED_IDENTITY;
     854       18374 :                 break;
     855           0 :         case SAMBA_ASSERTED_IDENTITY_IGNORE:
     856           0 :                 return NT_STATUS_OK;
     857             :         }
     858             : 
     859       19010 :         dom_sid_parse(sid_str, &ai_sid);
     860             : 
     861       19010 :         return add_sid_to_array_unique(user_info_dc,
     862             :                                        &ai_sid,
     863             :                                        &user_info_dc->sids,
     864             :                                        &user_info_dc->num_sids);
     865             : }
     866             : 
     867             : /*
     868             :  * Look up the user's info in the database and create a auth_user_info_dc
     869             :  * structure. If the resulting structure is not talloc_free()d, it will be
     870             :  * reused on future calls to this function.
     871             :  */
     872       50789 : NTSTATUS samba_kdc_get_user_info_from_db(struct samba_kdc_entry *skdc_entry,
     873             :                                          struct ldb_message *msg,
     874             :                                          struct auth_user_info_dc **user_info_dc)
     875             : {
     876       50789 :         if (skdc_entry->user_info_dc == NULL) {
     877             :                 NTSTATUS nt_status;
     878       32415 :                 struct loadparm_context *lp_ctx = skdc_entry->kdc_db_ctx->lp_ctx;
     879             : 
     880       64830 :                 nt_status = authsam_make_user_info_dc(skdc_entry,
     881       32415 :                                                       skdc_entry->kdc_db_ctx->samdb,
     882             :                                                       lpcfg_netbios_name(lp_ctx),
     883             :                                                       lpcfg_sam_name(lp_ctx),
     884             :                                                       lpcfg_sam_dnsname(lp_ctx),
     885             :                                                       skdc_entry->realm_dn,
     886             :                                                       msg,
     887             :                                                       data_blob_null,
     888             :                                                       data_blob_null,
     889             :                                                       &skdc_entry->user_info_dc);
     890       32415 :                 if (!NT_STATUS_IS_OK(nt_status)) {
     891           0 :                         return nt_status;
     892             :                 }
     893             :         }
     894             : 
     895       50789 :         *user_info_dc = skdc_entry->user_info_dc;
     896       50789 :         return NT_STATUS_OK;
     897             : }
     898             : 
     899       19010 : NTSTATUS samba_kdc_get_pac_blobs(TALLOC_CTX *mem_ctx,
     900             :                                  struct samba_kdc_entry *p,
     901             :                                  enum samba_asserted_identity asserted_identity,
     902             :                                  DATA_BLOB **_logon_info_blob,
     903             :                                  DATA_BLOB **_cred_ndr_blob,
     904             :                                  DATA_BLOB **_upn_info_blob,
     905             :                                  DATA_BLOB **_pac_attrs_blob,
     906             :                                  uint64_t pac_attributes,
     907             :                                  DATA_BLOB **_requester_sid_blob)
     908             : {
     909       19010 :         struct auth_user_info_dc *user_info_dc = NULL;
     910       19010 :         DATA_BLOB *logon_blob = NULL;
     911       19010 :         DATA_BLOB *cred_blob = NULL;
     912       19010 :         DATA_BLOB *upn_blob = NULL;
     913       19010 :         DATA_BLOB *pac_attrs_blob = NULL;
     914       19010 :         DATA_BLOB *requester_sid_blob = NULL;
     915             :         NTSTATUS nt_status;
     916             : 
     917       19010 :         *_logon_info_blob = NULL;
     918       19010 :         if (_cred_ndr_blob != NULL) {
     919           0 :                 *_cred_ndr_blob = NULL;
     920             :         }
     921       19010 :         *_upn_info_blob = NULL;
     922       19010 :         if (_pac_attrs_blob != NULL) {
     923       17141 :                 *_pac_attrs_blob = NULL;
     924             :         }
     925       19010 :         if (_requester_sid_blob != NULL) {
     926       17188 :                 *_requester_sid_blob = NULL;
     927             :         }
     928             : 
     929       19010 :         logon_blob = talloc_zero(mem_ctx, DATA_BLOB);
     930       19010 :         if (logon_blob == NULL) {
     931           0 :                 return NT_STATUS_NO_MEMORY;
     932             :         }
     933             : 
     934       19010 :         if (_cred_ndr_blob != NULL) {
     935           0 :                 cred_blob = talloc_zero(mem_ctx, DATA_BLOB);
     936           0 :                 if (cred_blob == NULL) {
     937           0 :                         return NT_STATUS_NO_MEMORY;
     938             :                 }
     939             :         }
     940             : 
     941       19010 :         upn_blob = talloc_zero(mem_ctx, DATA_BLOB);
     942       19010 :         if (upn_blob == NULL) {
     943           0 :                 return NT_STATUS_NO_MEMORY;
     944             :         }
     945             : 
     946       19010 :         if (_pac_attrs_blob != NULL) {
     947       17141 :                 pac_attrs_blob = talloc_zero(mem_ctx, DATA_BLOB);
     948       17141 :                 if (pac_attrs_blob == NULL) {
     949           0 :                         return NT_STATUS_NO_MEMORY;
     950             :                 }
     951             :         }
     952             : 
     953       19010 :         if (_requester_sid_blob != NULL) {
     954       17188 :                 requester_sid_blob = talloc_zero(mem_ctx, DATA_BLOB);
     955       17188 :                 if (requester_sid_blob == NULL) {
     956           0 :                         return NT_STATUS_NO_MEMORY;
     957             :                 }
     958             :         }
     959             : 
     960       19010 :         nt_status = samba_kdc_get_user_info_from_db(p,
     961             :                                                     p->msg,
     962             :                                                     &user_info_dc);
     963       19010 :         if (!NT_STATUS_IS_OK(nt_status)) {
     964           0 :                 DEBUG(0, ("Getting user info for PAC failed: %s\n",
     965             :                           nt_errstr(nt_status)));
     966           0 :                 return nt_status;
     967             :         }
     968             : 
     969       19010 :         nt_status = samba_add_asserted_identity(mem_ctx,
     970             :                                                 asserted_identity,
     971             :                                                 user_info_dc);
     972       19010 :         if (!NT_STATUS_IS_OK(nt_status)) {
     973           0 :                 DBG_ERR("Failed to add assertied identity!\n");
     974           0 :                 return nt_status;
     975             :         }
     976             : 
     977       19010 :         nt_status = samba_get_logon_info_pac_blob(logon_blob,
     978             :                                                   user_info_dc,
     979             :                                                   logon_blob,
     980             :                                                   requester_sid_blob);
     981       19010 :         if (!NT_STATUS_IS_OK(nt_status)) {
     982           0 :                 DEBUG(0, ("Building PAC LOGON INFO failed: %s\n",
     983             :                           nt_errstr(nt_status)));
     984           0 :                 return nt_status;
     985             :         }
     986             : 
     987       19010 :         if (cred_blob != NULL) {
     988           0 :                 nt_status = samba_get_cred_info_ndr_blob(cred_blob,
     989           0 :                                                          p->msg,
     990             :                                                          cred_blob);
     991           0 :                 if (!NT_STATUS_IS_OK(nt_status)) {
     992           0 :                         DEBUG(0, ("Building PAC CRED INFO failed: %s\n",
     993             :                                   nt_errstr(nt_status)));
     994           0 :                         return nt_status;
     995             :                 }
     996             :         }
     997             : 
     998       19010 :         nt_status = samba_get_upn_info_pac_blob(upn_blob,
     999             :                                                 user_info_dc,
    1000             :                                                 upn_blob);
    1001       19010 :         if (!NT_STATUS_IS_OK(nt_status)) {
    1002           0 :                 DEBUG(0, ("Building PAC UPN INFO failed: %s\n",
    1003             :                           nt_errstr(nt_status)));
    1004           0 :                 return nt_status;
    1005             :         }
    1006             : 
    1007       19010 :         if (pac_attrs_blob != NULL) {
    1008       17141 :                 nt_status = samba_get_pac_attrs_blob(pac_attrs_blob,
    1009             :                                                      pac_attributes,
    1010             :                                                      pac_attrs_blob);
    1011             : 
    1012       17141 :                 if (!NT_STATUS_IS_OK(nt_status)) {
    1013           0 :                         DEBUG(0, ("Building PAC ATTRIBUTES failed: %s\n",
    1014             :                                   nt_errstr(nt_status)));
    1015           0 :                         return nt_status;
    1016             :                 }
    1017             :         }
    1018             : 
    1019       19010 :         *_logon_info_blob = logon_blob;
    1020       19010 :         if (_cred_ndr_blob != NULL) {
    1021           0 :                 *_cred_ndr_blob = cred_blob;
    1022             :         }
    1023       19010 :         *_upn_info_blob = upn_blob;
    1024       19010 :         if (_pac_attrs_blob != NULL) {
    1025       17141 :                 *_pac_attrs_blob = pac_attrs_blob;
    1026             :         }
    1027       19010 :         if (_requester_sid_blob != NULL) {
    1028       17188 :                 *_requester_sid_blob = requester_sid_blob;
    1029             :         }
    1030       19010 :         return NT_STATUS_OK;
    1031             : }
    1032             : 
    1033       35968 : NTSTATUS samba_kdc_update_pac_blob(TALLOC_CTX *mem_ctx,
    1034             :                                    krb5_context context,
    1035             :                                    struct ldb_context *samdb,
    1036             :                                    const krb5_pac pac, DATA_BLOB *pac_blob,
    1037             :                                    struct PAC_SIGNATURE_DATA *pac_srv_sig,
    1038             :                                    struct PAC_SIGNATURE_DATA *pac_kdc_sig)
    1039             : {
    1040             :         struct auth_user_info_dc *user_info_dc;
    1041             :         krb5_error_code ret;
    1042             :         NTSTATUS nt_status;
    1043             : 
    1044       35968 :         ret = kerberos_pac_to_user_info_dc(mem_ctx, pac,
    1045             :                                            context, &user_info_dc, pac_srv_sig, pac_kdc_sig);
    1046       35968 :         if (ret) {
    1047           0 :                 return NT_STATUS_UNSUCCESSFUL;
    1048             :         }
    1049             : 
    1050             :         /*
    1051             :          * We need to expand group memberships within our local domain,
    1052             :          * as the token might be generated by a trusted domain.
    1053             :          */
    1054       35968 :         nt_status = authsam_update_user_info_dc(mem_ctx,
    1055             :                                                 samdb,
    1056             :                                                 user_info_dc);
    1057       35968 :         if (!NT_STATUS_IS_OK(nt_status)) {
    1058           0 :                 return nt_status;
    1059             :         }
    1060             : 
    1061       35968 :         nt_status = samba_get_logon_info_pac_blob(mem_ctx,
    1062             :                                                   user_info_dc, pac_blob, NULL);
    1063             : 
    1064       35968 :         return nt_status;
    1065             : }
    1066             : 
    1067          51 : NTSTATUS samba_kdc_update_delegation_info_blob(TALLOC_CTX *mem_ctx,
    1068             :                                 krb5_context context,
    1069             :                                 const krb5_pac pac,
    1070             :                                 const krb5_principal server_principal,
    1071             :                                 const krb5_principal proxy_principal,
    1072             :                                 DATA_BLOB *new_blob)
    1073             : {
    1074             :         krb5_data old_data;
    1075             :         DATA_BLOB old_blob;
    1076             :         krb5_error_code ret;
    1077             :         NTSTATUS nt_status;
    1078             :         enum ndr_err_code ndr_err;
    1079             :         union PAC_INFO info;
    1080             :         struct PAC_CONSTRAINED_DELEGATION _d;
    1081          51 :         struct PAC_CONSTRAINED_DELEGATION *d = NULL;
    1082          51 :         char *server = NULL;
    1083          51 :         char *proxy = NULL;
    1084             :         uint32_t i;
    1085          51 :         TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
    1086             : 
    1087          51 :         if (tmp_ctx == NULL) {
    1088           0 :                 return NT_STATUS_NO_MEMORY;
    1089             :         }
    1090             : 
    1091          51 :         ret = krb5_pac_get_buffer(context, pac, PAC_TYPE_CONSTRAINED_DELEGATION, &old_data);
    1092          51 :         if (ret == ENOENT) {
    1093          49 :                 ZERO_STRUCT(old_data);
    1094           2 :         } else if (ret) {
    1095           0 :                 talloc_free(tmp_ctx);
    1096           0 :                 return NT_STATUS_UNSUCCESSFUL;
    1097             :         }
    1098             : 
    1099          51 :         old_blob.length = old_data.length;
    1100          51 :         old_blob.data = (uint8_t *)old_data.data;
    1101             : 
    1102          51 :         ZERO_STRUCT(info);
    1103          51 :         if (old_blob.length > 0) {
    1104           2 :                 ndr_err = ndr_pull_union_blob(&old_blob, mem_ctx,
    1105             :                                 &info, PAC_TYPE_CONSTRAINED_DELEGATION,
    1106             :                                 (ndr_pull_flags_fn_t)ndr_pull_PAC_INFO);
    1107           2 :                 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
    1108           0 :                         smb_krb5_free_data_contents(context, &old_data);
    1109           0 :                         nt_status = ndr_map_error2ntstatus(ndr_err);
    1110           0 :                         DEBUG(0,("can't parse the PAC LOGON_INFO: %s\n", nt_errstr(nt_status)));
    1111           0 :                         talloc_free(tmp_ctx);
    1112           0 :                         return nt_status;
    1113             :                 }
    1114             :         } else {
    1115          49 :                 ZERO_STRUCT(_d);
    1116          49 :                 info.constrained_delegation.info = &_d;
    1117             :         }
    1118          51 :         smb_krb5_free_data_contents(context, &old_data);
    1119             : 
    1120          51 :         ret = krb5_unparse_name_flags(context, server_principal,
    1121             :                                       KRB5_PRINCIPAL_UNPARSE_NO_REALM, &server);
    1122          51 :         if (ret) {
    1123           0 :                 talloc_free(tmp_ctx);
    1124           0 :                 return NT_STATUS_INTERNAL_ERROR;
    1125             :         }
    1126             : 
    1127          51 :         ret = krb5_unparse_name(context, proxy_principal, &proxy);
    1128          51 :         if (ret) {
    1129           0 :                 SAFE_FREE(server);
    1130           0 :                 talloc_free(tmp_ctx);
    1131           0 :                 return NT_STATUS_INTERNAL_ERROR;
    1132             :         }
    1133             : 
    1134          51 :         d = info.constrained_delegation.info;
    1135          51 :         i = d->num_transited_services;
    1136          51 :         d->proxy_target.string = server;
    1137          51 :         d->transited_services = talloc_realloc(mem_ctx, d->transited_services,
    1138             :                                                struct lsa_String, i + 1);
    1139          51 :         d->transited_services[i].string = proxy;
    1140          51 :         d->num_transited_services = i + 1;
    1141             : 
    1142          51 :         ndr_err = ndr_push_union_blob(new_blob, mem_ctx,
    1143             :                                 &info, PAC_TYPE_CONSTRAINED_DELEGATION,
    1144             :                                 (ndr_push_flags_fn_t)ndr_push_PAC_INFO);
    1145          51 :         SAFE_FREE(server);
    1146          51 :         SAFE_FREE(proxy);
    1147          51 :         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
    1148           0 :                 smb_krb5_free_data_contents(context, &old_data);
    1149           0 :                 nt_status = ndr_map_error2ntstatus(ndr_err);
    1150           0 :                 DEBUG(0,("can't parse the PAC LOGON_INFO: %s\n", nt_errstr(nt_status)));
    1151           0 :                 talloc_free(tmp_ctx);
    1152           0 :                 return nt_status;
    1153             :         }
    1154             : 
    1155          51 :         talloc_free(tmp_ctx);
    1156          51 :         return NT_STATUS_OK;
    1157             : }
    1158             : 
    1159             : /* function to map policy errors */
    1160           4 : krb5_error_code samba_kdc_map_policy_err(NTSTATUS nt_status)
    1161             : {
    1162             :         krb5_error_code ret;
    1163             : 
    1164           4 :         if (NT_STATUS_EQUAL(nt_status, NT_STATUS_PASSWORD_MUST_CHANGE))
    1165           4 :                 ret = KRB5KDC_ERR_KEY_EXP;
    1166           0 :         else if (NT_STATUS_EQUAL(nt_status, NT_STATUS_PASSWORD_EXPIRED))
    1167           0 :                 ret = KRB5KDC_ERR_KEY_EXP;
    1168           0 :         else if (NT_STATUS_EQUAL(nt_status, NT_STATUS_ACCOUNT_EXPIRED))
    1169           0 :                 ret = KRB5KDC_ERR_CLIENT_REVOKED;
    1170           0 :         else if (NT_STATUS_EQUAL(nt_status, NT_STATUS_ACCOUNT_DISABLED))
    1171           0 :                 ret = KRB5KDC_ERR_CLIENT_REVOKED;
    1172           0 :         else if (NT_STATUS_EQUAL(nt_status, NT_STATUS_INVALID_LOGON_HOURS))
    1173           0 :                 ret = KRB5KDC_ERR_CLIENT_REVOKED;
    1174           0 :         else if (NT_STATUS_EQUAL(nt_status, NT_STATUS_ACCOUNT_LOCKED_OUT))
    1175           0 :                 ret = KRB5KDC_ERR_CLIENT_REVOKED;
    1176           0 :         else if (NT_STATUS_EQUAL(nt_status, NT_STATUS_INVALID_WORKSTATION))
    1177           0 :                 ret = KRB5KDC_ERR_POLICY;
    1178             :         else
    1179           0 :                 ret = KRB5KDC_ERR_POLICY;
    1180             : 
    1181           4 :         return ret;
    1182             : }
    1183             : 
    1184             : /* Given a kdc entry, consult the account_ok routine in auth/auth_sam.c
    1185             :  * for consistency */
    1186       18413 : NTSTATUS samba_kdc_check_client_access(struct samba_kdc_entry *kdc_entry,
    1187             :                                        const char *client_name,
    1188             :                                        const char *workstation,
    1189             :                                        bool password_change)
    1190             : {
    1191             :         TALLOC_CTX *tmp_ctx;
    1192             :         NTSTATUS nt_status;
    1193             : 
    1194       18413 :         tmp_ctx = talloc_named(NULL, 0, "samba_kdc_check_client_access");
    1195       18413 :         if (!tmp_ctx) {
    1196           0 :                 return NT_STATUS_NO_MEMORY;
    1197             :         }
    1198             : 
    1199             :         /* we allow all kinds of trusts here */
    1200       36826 :         nt_status = authsam_account_ok(tmp_ctx,
    1201       18413 :                                        kdc_entry->kdc_db_ctx->samdb,
    1202             :                                        MSV1_0_ALLOW_SERVER_TRUST_ACCOUNT |
    1203             :                                        MSV1_0_ALLOW_WORKSTATION_TRUST_ACCOUNT,
    1204             :                                        kdc_entry->realm_dn, kdc_entry->msg,
    1205             :                                        workstation, client_name,
    1206             :                                        true, password_change);
    1207             : 
    1208       18413 :         kdc_entry->reject_status = nt_status;
    1209       18413 :         talloc_free(tmp_ctx);
    1210       18413 :         return nt_status;
    1211             : }
    1212             : 
    1213       35966 : static krb5_error_code samba_get_requester_sid(TALLOC_CTX *mem_ctx,
    1214             :                                                krb5_pac pac,
    1215             :                                                krb5_context context,
    1216             :                                                struct dom_sid *sid)
    1217             : {
    1218             :         NTSTATUS nt_status;
    1219             :         enum ndr_err_code ndr_err;
    1220             :         krb5_error_code ret;
    1221             : 
    1222             :         DATA_BLOB pac_requester_sid_in;
    1223             :         krb5_data k5pac_requester_sid_in;
    1224             : 
    1225             :         union PAC_INFO info;
    1226             : 
    1227       35966 :         TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
    1228       35966 :         if (tmp_ctx == NULL) {
    1229           0 :                 return ENOMEM;
    1230             :         }
    1231             : 
    1232       35966 :         ret = krb5_pac_get_buffer(context, pac, PAC_TYPE_REQUESTER_SID,
    1233             :                                   &k5pac_requester_sid_in);
    1234       35966 :         if (ret != 0) {
    1235          50 :                 talloc_free(tmp_ctx);
    1236          50 :                 return ret;
    1237             :         }
    1238             : 
    1239       35916 :         pac_requester_sid_in = data_blob_const(k5pac_requester_sid_in.data,
    1240           0 :                                                k5pac_requester_sid_in.length);
    1241             : 
    1242       35916 :         ndr_err = ndr_pull_union_blob(&pac_requester_sid_in, tmp_ctx, &info,
    1243             :                                       PAC_TYPE_REQUESTER_SID,
    1244             :                                       (ndr_pull_flags_fn_t)ndr_pull_PAC_INFO);
    1245       35916 :         smb_krb5_free_data_contents(context, &k5pac_requester_sid_in);
    1246       35916 :         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
    1247           0 :                 nt_status = ndr_map_error2ntstatus(ndr_err);
    1248           0 :                 DEBUG(0,("can't parse the PAC REQUESTER_SID: %s\n", nt_errstr(nt_status)));
    1249           0 :                 talloc_free(tmp_ctx);
    1250           0 :                 return EINVAL;
    1251             :         }
    1252             : 
    1253       35916 :         *sid = info.requester_sid.sid;
    1254             : 
    1255       35916 :         talloc_free(tmp_ctx);
    1256       35916 :         return 0;
    1257             : }
    1258             : 
    1259             : /* Does a parse and SID check, but no crypto. */
    1260       35966 : krb5_error_code samba_kdc_validate_pac_blob(
    1261             :                 krb5_context context,
    1262             :                 struct samba_kdc_entry *client_skdc_entry,
    1263             :                 const krb5_pac pac)
    1264             : {
    1265       35966 :         TALLOC_CTX *frame = talloc_stackframe();
    1266       35966 :         struct auth_user_info_dc *pac_user_info = NULL;
    1267       35966 :         struct dom_sid *client_sid = NULL;
    1268             :         struct dom_sid pac_sid;
    1269             :         krb5_error_code code;
    1270             :         bool ok;
    1271             : 
    1272             :         /*
    1273             :          * First, try to get the SID from the requester SID buffer in the PAC.
    1274             :          */
    1275       35966 :         code = samba_get_requester_sid(frame, pac, context, &pac_sid);
    1276             : 
    1277       35966 :         if (code == ENOENT) {
    1278             :                 /*
    1279             :                  * If the requester SID buffer isn't present, fall back to the
    1280             :                  * SID in the LOGON_INFO PAC buffer.
    1281             :                  */
    1282          50 :                 code = kerberos_pac_to_user_info_dc(frame,
    1283             :                                                     pac,
    1284             :                                                     context,
    1285             :                                                     &pac_user_info,
    1286             :                                                     NULL,
    1287             :                                                     NULL);
    1288          50 :                 if (code != 0) {
    1289           0 :                         goto out;
    1290             :                 }
    1291             : 
    1292          50 :                 if (pac_user_info->num_sids == 0) {
    1293           0 :                         code = EINVAL;
    1294           0 :                         goto out;
    1295             :                 }
    1296             : 
    1297          50 :                 pac_sid = pac_user_info->sids[0];
    1298       35916 :         } else if (code != 0) {
    1299           0 :                 goto out;
    1300             :         }
    1301             : 
    1302       35966 :         client_sid = samdb_result_dom_sid(frame,
    1303       35966 :                                           client_skdc_entry->msg,
    1304             :                                           "objectSid");
    1305             : 
    1306       35966 :         ok = dom_sid_equal(&pac_sid, client_sid);
    1307       35966 :         if (!ok) {
    1308             :                 struct dom_sid_buf buf1;
    1309             :                 struct dom_sid_buf buf2;
    1310             : 
    1311           0 :                 DBG_ERR("SID mismatch between PAC and looked up client: "
    1312             :                         "PAC[%s] != CLI[%s]\n",
    1313             :                         dom_sid_str_buf(&pac_sid, &buf1),
    1314             :                         dom_sid_str_buf(client_sid, &buf2));
    1315           0 :                         code = KRB5KDC_ERR_TGT_REVOKED;
    1316           0 :                 goto out;
    1317             :         }
    1318             : 
    1319       35966 :         code = 0;
    1320       35966 : out:
    1321       35966 :         TALLOC_FREE(frame);
    1322       35966 :         return code;
    1323             : }
    1324             : 
    1325             : 
    1326             : /*
    1327             :  * In the RODC case, to confirm that the returned user is permitted to
    1328             :  * be replicated to the KDC (krbgtgt_xxx user) represented by *rodc
    1329             :  */
    1330          47 : WERROR samba_rodc_confirm_user_is_allowed(uint32_t num_object_sids,
    1331             :                                           struct dom_sid *object_sids,
    1332             :                                           struct samba_kdc_entry *rodc,
    1333             :                                           struct samba_kdc_entry *object)
    1334             : {
    1335             :         int ret;
    1336             :         WERROR werr;
    1337          47 :         TALLOC_CTX *frame = talloc_stackframe();
    1338          47 :         const char *rodc_attrs[] = { "msDS-KrbTgtLink",
    1339             :                                      "msDS-NeverRevealGroup",
    1340             :                                      "msDS-RevealOnDemandGroup",
    1341             :                                      "userAccountControl",
    1342             :                                      "objectSid",
    1343             :                                      NULL };
    1344          47 :         struct ldb_result *rodc_machine_account = NULL;
    1345          47 :         struct ldb_dn *rodc_machine_account_dn = samdb_result_dn(rodc->kdc_db_ctx->samdb,
    1346             :                                                  frame,
    1347          47 :                                                  rodc->msg,
    1348             :                                                  "msDS-KrbTgtLinkBL",
    1349             :                                                  NULL);
    1350          47 :         const struct dom_sid *rodc_machine_account_sid = NULL;
    1351             : 
    1352          47 :         if (rodc_machine_account_dn == NULL) {
    1353           0 :                 DBG_ERR("krbtgt account %s has no msDS-KrbTgtLinkBL to find RODC machine account for allow/deny list\n",
    1354             :                         ldb_dn_get_linearized(rodc->msg->dn));
    1355           0 :                 TALLOC_FREE(frame);
    1356           0 :                 return WERR_DOMAIN_CONTROLLER_NOT_FOUND;
    1357             :         }
    1358             : 
    1359             :         /*
    1360             :          * Follow the link and get the RODC account (the krbtgt
    1361             :          * account is the krbtgt_XXX account, but the
    1362             :          * msDS-NeverRevealGroup and msDS-RevealOnDemandGroup is on
    1363             :          * the RODC$ account)
    1364             :          *
    1365             :          * We need DSDB_SEARCH_SHOW_EXTENDED_DN as we get a SID lists
    1366             :          * out of the extended DNs
    1367             :          */
    1368             : 
    1369          47 :         ret = dsdb_search_dn(rodc->kdc_db_ctx->samdb,
    1370             :                              frame,
    1371             :                              &rodc_machine_account,
    1372             :                              rodc_machine_account_dn,
    1373             :                              rodc_attrs,
    1374             :                              DSDB_SEARCH_SHOW_EXTENDED_DN);
    1375          47 :         if (ret != LDB_SUCCESS) {
    1376           0 :                 DBG_ERR("Failed to fetch RODC machine account %s pointed to by %s to check allow/deny list: %s\n",
    1377             :                         ldb_dn_get_linearized(rodc_machine_account_dn),
    1378             :                         ldb_dn_get_linearized(rodc->msg->dn),
    1379             :                         ldb_errstring(rodc->kdc_db_ctx->samdb));
    1380           0 :                 TALLOC_FREE(frame);
    1381           0 :                 return WERR_DOMAIN_CONTROLLER_NOT_FOUND;
    1382             :         }
    1383             : 
    1384          47 :         if (rodc_machine_account->count != 1) {
    1385           0 :                 DBG_ERR("Failed to fetch RODC machine account %s pointed to by %s to check allow/deny list: (%d)\n",
    1386             :                         ldb_dn_get_linearized(rodc_machine_account_dn),
    1387             :                         ldb_dn_get_linearized(rodc->msg->dn),
    1388             :                         rodc_machine_account->count);
    1389           0 :                 TALLOC_FREE(frame);
    1390           0 :                 return WERR_DS_DRA_BAD_DN;
    1391             :         }
    1392             : 
    1393             :         /* if the object SID is equal to the user_sid, allow */
    1394          47 :         rodc_machine_account_sid = samdb_result_dom_sid(frame,
    1395          47 :                                           rodc_machine_account->msgs[0],
    1396             :                                           "objectSid");
    1397          47 :         if (rodc_machine_account_sid == NULL) {
    1398           0 :                 return WERR_DS_DRA_BAD_DN;
    1399             :         }
    1400             : 
    1401          94 :         werr = samdb_confirm_rodc_allowed_to_repl_to_sid_list(rodc->kdc_db_ctx->samdb,
    1402             :                                                               rodc_machine_account_sid,
    1403          47 :                                                               rodc_machine_account->msgs[0],
    1404             :                                                               object->msg,
    1405             :                                                               num_object_sids,
    1406             :                                                               object_sids);
    1407             : 
    1408          47 :         TALLOC_FREE(frame);
    1409          47 :         return werr;
    1410             : }
    1411             : 
    1412             : /**
    1413             :  * @brief Update a PAC
    1414             :  *
    1415             :  * @param mem_ctx   A talloc memory context
    1416             :  *
    1417             :  * @param context   A krb5 context
    1418             :  *
    1419             :  * @param samdb     An open samdb connection.
    1420             :  *
    1421             :  * @param flags     Bitwise OR'ed flags
    1422             :  *
    1423             :  * @param client    The client samba kdc entry.
    1424             : 
    1425             :  * @param server_principal  The server principal
    1426             : 
    1427             :  * @param server    The server samba kdc entry.
    1428             : 
    1429             :  * @param krbtgt    The krbtgt samba kdc entry.
    1430             :  *
    1431             :  * @param delegated_proxy_principal The delegated proxy principal used for
    1432             :  *                                  updating the constrained delegation PAC
    1433             :  *                                  buffer.
    1434             : 
    1435             :  * @param old_pac                   The old PAC
    1436             : 
    1437             :  * @param new_pac                   The new already allocated PAC
    1438             : 
    1439             :  * @return A Kerberos error code. If no PAC should be returned, the code will be
    1440             :  * ENODATA!
    1441             :  */
    1442       36015 : krb5_error_code samba_kdc_update_pac(TALLOC_CTX *mem_ctx,
    1443             :                                      krb5_context context,
    1444             :                                      struct ldb_context *samdb,
    1445             :                                      uint32_t flags,
    1446             :                                      struct samba_kdc_entry *client,
    1447             :                                      const krb5_principal server_principal,
    1448             :                                      struct samba_kdc_entry *server,
    1449             :                                      struct samba_kdc_entry *krbtgt,
    1450             :                                      const krb5_principal delegated_proxy_principal,
    1451             :                                      const krb5_pac old_pac,
    1452             :                                      krb5_pac new_pac)
    1453             : {
    1454       36015 :         krb5_error_code code = EINVAL;
    1455             :         NTSTATUS nt_status;
    1456       36015 :         DATA_BLOB *pac_blob = NULL;
    1457       36015 :         DATA_BLOB *upn_blob = NULL;
    1458       36015 :         DATA_BLOB *deleg_blob = NULL;
    1459       36015 :         DATA_BLOB *requester_sid_blob = NULL;
    1460       36015 :         bool is_untrusted = flags & SAMBA_KDC_FLAG_KRBTGT_IS_UNTRUSTED;
    1461       36015 :         int is_tgs = false;
    1462       36015 :         size_t num_types = 0;
    1463       36015 :         uint32_t *types = NULL;
    1464             :         /*
    1465             :          * FIXME: Do we really still need forced_next_type? With MIT Kerberos
    1466             :          * the PAC buffers do not get ordered and it works just fine. We are
    1467             :          * not aware of any issues in this regard. This might be just ancient
    1468             :          * code.
    1469             :          */
    1470       36015 :         uint32_t forced_next_type = 0;
    1471       36015 :         size_t i = 0;
    1472       36015 :         ssize_t logon_info_idx = -1;
    1473       36015 :         ssize_t delegation_idx = -1;
    1474       36015 :         ssize_t logon_name_idx = -1;
    1475       36015 :         ssize_t upn_dns_info_idx = -1;
    1476       36015 :         ssize_t srv_checksum_idx = -1;
    1477       36015 :         ssize_t kdc_checksum_idx = -1;
    1478       36015 :         ssize_t tkt_checksum_idx = -1;
    1479       36015 :         ssize_t attrs_info_idx = -1;
    1480       36015 :         ssize_t requester_sid_idx = -1;
    1481       36015 :         ssize_t full_checksum_idx = -1;
    1482             : 
    1483       36015 :         if (client != NULL) {
    1484             :                 /*
    1485             :                  * Check the objectSID of the client and pac data are the same.
    1486             :                  * Does a parse and SID check, but no crypto.
    1487             :                  */
    1488       35966 :                 code = samba_kdc_validate_pac_blob(context,
    1489             :                                                    client,
    1490             :                                                    old_pac);
    1491       35966 :                 if (code != 0) {
    1492           0 :                         goto done;
    1493             :                 }
    1494             :         }
    1495             : 
    1496       36015 :         if (delegated_proxy_principal != NULL) {
    1497          51 :                 deleg_blob = talloc_zero(mem_ctx, DATA_BLOB);
    1498          51 :                 if (deleg_blob == NULL) {
    1499           0 :                         code = ENOMEM;
    1500           0 :                         goto done;
    1501             :                 }
    1502             : 
    1503          51 :                 nt_status = samba_kdc_update_delegation_info_blob(
    1504             :                                 mem_ctx,
    1505             :                                 context,
    1506             :                                 old_pac,
    1507             :                                 server_principal,
    1508             :                                 delegated_proxy_principal,
    1509             :                                 deleg_blob);
    1510          51 :                 if (!NT_STATUS_IS_OK(nt_status)) {
    1511           0 :                         DBG_ERR("update delegation info blob failed: %s\n",
    1512             :                                 nt_errstr(nt_status));
    1513           0 :                         code = EINVAL;
    1514           0 :                         goto done;
    1515             :                 }
    1516             :         }
    1517             : 
    1518       36015 :         if (is_untrusted) {
    1519          47 :                 struct auth_user_info_dc *user_info_dc = NULL;
    1520             :                 WERROR werr;
    1521             :                 /*
    1522             :                  * In this case the RWDC discards the PAC an RODC generated.
    1523             :                  * Windows adds the asserted_identity in this case too.
    1524             :                  *
    1525             :                  * Note that SAMBA_KDC_FLAG_CONSTRAINED_DELEGATION
    1526             :                  * generates KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN.
    1527             :                  * So we can always use
    1528             :                  * SAMBA_ASSERTED_IDENTITY_AUTHENTICATION_AUTHORITY
    1529             :                  * here.
    1530             :                  */
    1531          47 :                 enum samba_asserted_identity asserted_identity =
    1532             :                         SAMBA_ASSERTED_IDENTITY_AUTHENTICATION_AUTHORITY;
    1533             : 
    1534          47 :                 if (client == NULL) {
    1535           0 :                         code = KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN;
    1536           0 :                         goto done;
    1537             :                 }
    1538             : 
    1539          47 :                 nt_status = samba_kdc_get_pac_blobs(mem_ctx,
    1540             :                                                     client,
    1541             :                                                     asserted_identity,
    1542             :                                                     &pac_blob,
    1543             :                                                     NULL,
    1544             :                                                     &upn_blob,
    1545             :                                                     NULL,
    1546             :                                                     PAC_ATTRIBUTE_FLAG_PAC_WAS_GIVEN_IMPLICITLY,
    1547             :                                                     &requester_sid_blob);
    1548          47 :                 if (!NT_STATUS_IS_OK(nt_status)) {
    1549           0 :                         DBG_ERR("samba_kdc_get_pac_blobs failed: %s\n",
    1550             :                                 nt_errstr(nt_status));
    1551           0 :                         code = KRB5KDC_ERR_TGT_REVOKED;
    1552           0 :                         goto done;
    1553             :                 }
    1554             : 
    1555          47 :                 nt_status = samba_kdc_get_user_info_from_db(client,
    1556             :                                                             client->msg,
    1557             :                                                             &user_info_dc);
    1558          47 :                 if (!NT_STATUS_IS_OK(nt_status)) {
    1559           0 :                         DBG_ERR("samba_kdc_get_user_info_from_db failed: %s\n",
    1560             :                                 nt_errstr(nt_status));
    1561           0 :                         code = KRB5KDC_ERR_TGT_REVOKED;
    1562           0 :                         goto done;
    1563             :                 }
    1564             : 
    1565             :                 /*
    1566             :                  * Check if the SID list in the user_info_dc intersects
    1567             :                  * correctly with the RODC allow/deny lists.
    1568             :                  */
    1569          47 :                 werr = samba_rodc_confirm_user_is_allowed(user_info_dc->num_sids,
    1570          47 :                                                           user_info_dc->sids,
    1571             :                                                           krbtgt,
    1572             :                                                           client);
    1573          47 :                 TALLOC_FREE(user_info_dc);
    1574          47 :                 if (!W_ERROR_IS_OK(werr)) {
    1575           0 :                         code = KRB5KDC_ERR_TGT_REVOKED;
    1576           0 :                         if (W_ERROR_EQUAL(werr,
    1577             :                                           WERR_DOMAIN_CONTROLLER_NOT_FOUND)) {
    1578           0 :                                 code = KRB5KDC_ERR_POLICY;
    1579             :                         }
    1580           0 :                         goto done;
    1581             :                 }
    1582             : 
    1583             :                 /*
    1584             :                  * The RODC PAC data isn't trusted for authorization as it may
    1585             :                  * be stale. The only thing meaningful we can do with an RODC
    1586             :                  * account on a full DC is exchange the RODC TGT for a 'real'
    1587             :                  * TGT.
    1588             :                  *
    1589             :                  * So we match Windows (at least server 2022) and
    1590             :                  * don't allow S4U2Self.
    1591             :                  *
    1592             :                  * https://lists.samba.org/archive/cifs-protocol/2022-April/003673.html
    1593             :                  */
    1594          47 :                 if (flags & SAMBA_KDC_FLAG_PROTOCOL_TRANSITION) {
    1595           0 :                         code = KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN;
    1596           0 :                         goto done;
    1597             :                 }
    1598             :         } else {
    1599       35968 :                 pac_blob = talloc_zero(mem_ctx, DATA_BLOB);
    1600       35968 :                 if (pac_blob == NULL) {
    1601           0 :                         code = ENOMEM;
    1602           0 :                         goto done;
    1603             :                 }
    1604             : 
    1605       35968 :                 nt_status = samba_kdc_update_pac_blob(mem_ctx,
    1606             :                                                       context,
    1607             :                                                       samdb,
    1608             :                                                       old_pac,
    1609             :                                                       pac_blob,
    1610             :                                                       NULL,
    1611             :                                                       NULL);
    1612       35968 :                 if (!NT_STATUS_IS_OK(nt_status)) {
    1613           0 :                         DBG_ERR("samba_kdc_update_pac_blob failed: %s\n",
    1614             :                                  nt_errstr(nt_status));
    1615           0 :                         code = EINVAL;
    1616           0 :                         goto done;
    1617             :                 }
    1618             :         }
    1619             : 
    1620             :         /* Check the types of the given PAC */
    1621       36015 :         code = krb5_pac_get_types(context, old_pac, &num_types, &types);
    1622       36015 :         if (code != 0) {
    1623           0 :                 DBG_ERR("krb5_pac_get_types failed\n");
    1624           0 :                 goto done;
    1625             :         }
    1626             : 
    1627      288138 :         for (i = 0; i < num_types; i++) {
    1628      252123 :                 switch (types[i]) {
    1629       36015 :                 case PAC_TYPE_LOGON_INFO:
    1630       36015 :                         if (logon_info_idx != -1) {
    1631           0 :                                 DBG_WARNING("logon info type[%u] twice [%zd] "
    1632             :                                             "and [%zu]: \n",
    1633             :                                             types[i],
    1634             :                                             logon_info_idx,
    1635             :                                             i);
    1636           0 :                                 code = EINVAL;
    1637           0 :                                 goto done;
    1638             :                         }
    1639       36015 :                         logon_info_idx = i;
    1640       36015 :                         break;
    1641           2 :                 case PAC_TYPE_CONSTRAINED_DELEGATION:
    1642           2 :                         if (delegation_idx != -1) {
    1643           0 :                                 DBG_WARNING("constrained delegation type[%u] "
    1644             :                                             "twice [%zd] and [%zu]: \n",
    1645             :                                             types[i],
    1646             :                                             delegation_idx,
    1647             :                                             i);
    1648           0 :                                 code = EINVAL;
    1649           0 :                                 goto done;
    1650             :                         }
    1651           2 :                         delegation_idx = i;
    1652           2 :                         break;
    1653       36015 :                 case PAC_TYPE_LOGON_NAME:
    1654       36015 :                         if (logon_name_idx != -1) {
    1655           0 :                                 DBG_WARNING("logon name type[%u] twice [%zd] "
    1656             :                                             "and [%zu]: \n",
    1657             :                                             types[i],
    1658             :                                             logon_name_idx,
    1659             :                                             i);
    1660           0 :                                 code = EINVAL;
    1661           0 :                                 goto done;
    1662             :                         }
    1663       36015 :                         logon_name_idx = i;
    1664       36015 :                         break;
    1665       36015 :                 case PAC_TYPE_UPN_DNS_INFO:
    1666       36015 :                         if (upn_dns_info_idx != -1) {
    1667           0 :                                 DBG_WARNING("upn dns info type[%u] twice [%zd] "
    1668             :                                             "and [%zu]: \n",
    1669             :                                             types[i],
    1670             :                                             upn_dns_info_idx,
    1671             :                                             i);
    1672           0 :                                 code = EINVAL;
    1673           0 :                                 goto done;
    1674             :                         }
    1675       36015 :                         upn_dns_info_idx = i;
    1676       36015 :                         break;
    1677       36015 :                 case PAC_TYPE_SRV_CHECKSUM:
    1678       36015 :                         if (srv_checksum_idx != -1) {
    1679           0 :                                 DBG_WARNING("srv checksum type[%u] twice [%zd] "
    1680             :                                             "and [%zu]: \n",
    1681             :                                             types[i],
    1682             :                                             srv_checksum_idx,
    1683             :                                             i);
    1684           0 :                                 code = EINVAL;
    1685           0 :                                 goto done;
    1686             :                         }
    1687       36015 :                         srv_checksum_idx = i;
    1688       36015 :                         break;
    1689       36015 :                 case PAC_TYPE_KDC_CHECKSUM:
    1690       36015 :                         if (kdc_checksum_idx != -1) {
    1691           0 :                                 DBG_WARNING("kdc checksum type[%u] twice [%zd] "
    1692             :                                             "and [%zu]: \n",
    1693             :                                             types[i],
    1694             :                                             kdc_checksum_idx,
    1695             :                                             i);
    1696           0 :                                 code = EINVAL;
    1697           0 :                                 goto done;
    1698             :                         }
    1699       36015 :                         kdc_checksum_idx = i;
    1700       36015 :                         break;
    1701          59 :                 case PAC_TYPE_TICKET_CHECKSUM:
    1702          59 :                         if (tkt_checksum_idx != -1) {
    1703           0 :                                 DBG_WARNING("ticket checksum type[%u] twice "
    1704             :                                             "[%zd] and [%zu]: \n",
    1705             :                                             types[i],
    1706             :                                             tkt_checksum_idx,
    1707             :                                             i);
    1708           0 :                                 code = EINVAL;
    1709           0 :                                 goto done;
    1710             :                         }
    1711          59 :                         tkt_checksum_idx = i;
    1712          59 :                         break;
    1713       35964 :                 case PAC_TYPE_ATTRIBUTES_INFO:
    1714       35964 :                         if (attrs_info_idx != -1) {
    1715           0 :                                 DBG_WARNING("attributes info type[%u] twice "
    1716             :                                             "[%zd] and [%zu]: \n",
    1717             :                                             types[i],
    1718             :                                             attrs_info_idx,
    1719             :                                             i);
    1720           0 :                                 code = EINVAL;
    1721           0 :                                 goto done;
    1722             :                         }
    1723       35964 :                         attrs_info_idx = i;
    1724       35964 :                         break;
    1725       35964 :                 case PAC_TYPE_REQUESTER_SID:
    1726       35964 :                         if (requester_sid_idx != -1) {
    1727           0 :                                 DBG_WARNING("requester sid type[%u] twice"
    1728             :                                             "[%zd] and [%zu]: \n",
    1729             :                                             types[i],
    1730             :                                             requester_sid_idx,
    1731             :                                             i);
    1732           0 :                                 code = EINVAL;
    1733           0 :                                 goto done;
    1734             :                         }
    1735       35964 :                         requester_sid_idx = i;
    1736       35964 :                         break;
    1737          59 :                 case PAC_TYPE_FULL_CHECKSUM:
    1738          59 :                         if (full_checksum_idx != -1) {
    1739           0 :                                 DBG_WARNING("full checksum type[%u] twice "
    1740             :                                             "[%zd] and [%zu]: \n",
    1741             :                                             types[i],
    1742             :                                             full_checksum_idx,
    1743             :                                             i);
    1744           0 :                                 code = EINVAL;
    1745           0 :                                 goto done;
    1746             :                         }
    1747          59 :                         full_checksum_idx = i;
    1748          59 :                         break;
    1749           0 :                 default:
    1750           0 :                         continue;
    1751             :                 }
    1752             :         }
    1753             : 
    1754       36015 :         if (logon_info_idx == -1) {
    1755           0 :                 DBG_WARNING("PAC_TYPE_LOGON_INFO missing\n");
    1756           0 :                 code = EINVAL;
    1757           0 :                 goto done;
    1758             :         }
    1759       36015 :         if (logon_name_idx == -1) {
    1760           0 :                 DBG_WARNING("PAC_TYPE_LOGON_NAME missing\n");
    1761           0 :                 code = EINVAL;
    1762           0 :                 goto done;
    1763             :         }
    1764       36015 :         if (srv_checksum_idx == -1) {
    1765           0 :                 DBG_WARNING("PAC_TYPE_SRV_CHECKSUM missing\n");
    1766           0 :                 code = EINVAL;
    1767           0 :                 goto done;
    1768             :         }
    1769       36015 :         if (kdc_checksum_idx == -1) {
    1770           0 :                 DBG_WARNING("PAC_TYPE_KDC_CHECKSUM missing\n");
    1771           0 :                 code = EINVAL;
    1772           0 :                 goto done;
    1773             :         }
    1774       36015 :         if (!(flags & SAMBA_KDC_FLAG_CONSTRAINED_DELEGATION) &&
    1775             :             requester_sid_idx == -1) {
    1776           0 :                 DBG_WARNING("PAC_TYPE_REQUESTER_SID missing\n");
    1777           0 :                 code = KRB5KDC_ERR_TGT_REVOKED;
    1778           0 :                 goto done;
    1779             :         }
    1780             : 
    1781             :         /*
    1782             :          * The server account may be set not to want the PAC.
    1783             :          *
    1784             :          * While this is wasteful if the above cacluations were done
    1785             :          * and now thrown away, this is cleaner as we do any ticket
    1786             :          * signature checking etc always.
    1787             :          *
    1788             :          * UF_NO_AUTH_DATA_REQUIRED is the rare case and most of the
    1789             :          * time (eg not accepting a ticket from the RODC) we do not
    1790             :          * need to re-generate anything anyway.
    1791             :          */
    1792       36015 :         if (!samba_princ_needs_pac(server)) {
    1793           9 :                 code = ENODATA;
    1794           9 :                 goto done;
    1795             :         }
    1796             : 
    1797       36006 :         is_tgs = smb_krb5_principal_is_tgs(context, server_principal);
    1798       36006 :         if (is_tgs == -1) {
    1799           0 :                 code = ENOMEM;
    1800           0 :                 goto done;
    1801             :         }
    1802             : 
    1803       36006 :         if (!is_untrusted && !is_tgs) {
    1804             :                 /*
    1805             :                  * The client may have requested no PAC when obtaining the
    1806             :                  * TGT.
    1807             :                  */
    1808       14760 :                 bool requested_pac = false;
    1809             : 
    1810       14760 :                 code = samba_client_requested_pac(context,
    1811             :                                                   &old_pac,
    1812             :                                                   mem_ctx,
    1813             :                                                   &requested_pac);
    1814       14760 :                 if (code != 0 || !requested_pac) {
    1815           0 :                         if (!requested_pac) {
    1816           0 :                                 code = ENODATA;
    1817             :                         }
    1818           0 :                         goto done;
    1819             :                 }
    1820             :         }
    1821             : 
    1822             : #define MAX_PAC_BUFFERS 128 /* Avoid infinite loops */
    1823             : 
    1824      324121 :         for (i = 0; i < MAX_PAC_BUFFERS;) {
    1825      288115 :                 const uint8_t zero_byte = 0;
    1826             :                 krb5_data type_data;
    1827      288115 :                 DATA_BLOB type_blob = data_blob_null;
    1828             :                 uint32_t type;
    1829             : 
    1830      288115 :                 if (forced_next_type != 0) {
    1831             :                         /*
    1832             :                          * We need to inject possible missing types
    1833             :                          */
    1834          49 :                         type = forced_next_type;
    1835          49 :                         forced_next_type = 0;
    1836      288066 :                 } else if (i < num_types) {
    1837      252060 :                         type = types[i];
    1838      252060 :                         i++;
    1839             :                 } else {
    1840       36006 :                         break;
    1841             :                 }
    1842             : 
    1843      252109 :                 switch (type) {
    1844       36006 :                 case PAC_TYPE_LOGON_INFO:
    1845       36006 :                         type_blob = *pac_blob;
    1846             : 
    1847       36006 :                         if (delegation_idx == -1 && deleg_blob != NULL) {
    1848             :                                 /* inject CONSTRAINED_DELEGATION behind */
    1849          49 :                                 forced_next_type =
    1850             :                                         PAC_TYPE_CONSTRAINED_DELEGATION;
    1851             :                         }
    1852       36006 :                         break;
    1853          51 :                 case PAC_TYPE_CONSTRAINED_DELEGATION:
    1854             :                         /*
    1855             :                          * This is generated in the main KDC code
    1856             :                          */
    1857          51 :                         if (flags & SAMBA_KDC_FLAG_SKIP_PAC_BUFFER) {
    1858       29512 :                                 continue;
    1859             :                         }
    1860             : 
    1861          51 :                         if (deleg_blob != NULL) {
    1862          51 :                                 type_blob = *deleg_blob;
    1863             :                         }
    1864          51 :                         break;
    1865           0 :                 case PAC_TYPE_CREDENTIAL_INFO:
    1866             :                         /*
    1867             :                          * Note that we copy the credential blob,
    1868             :                          * as it's only usable with the PKINIT based
    1869             :                          * AS-REP reply key, it's only available on the
    1870             :                          * host which did the AS-REQ/AS-REP exchange.
    1871             :                          *
    1872             :                          * This matches Windows 2008R2...
    1873             :                          */
    1874           0 :                         break;
    1875       36006 :                 case PAC_TYPE_LOGON_NAME:
    1876             :                         /*
    1877             :                          * This is generated in the main KDC code
    1878             :                          */
    1879       36006 :                         if (flags & SAMBA_KDC_FLAG_SKIP_PAC_BUFFER) {
    1880           0 :                                 continue;
    1881             :                         }
    1882             : 
    1883       36006 :                         type_blob = data_blob_const(&zero_byte, 1);
    1884             : 
    1885       36006 :                         if (upn_dns_info_idx == -1 && upn_blob != NULL) {
    1886             :                                 /* inject UPN_DNS_INFO behind */
    1887           0 :                                 forced_next_type = PAC_TYPE_UPN_DNS_INFO;
    1888             :                         }
    1889       36006 :                         break;
    1890       36006 :                 case PAC_TYPE_UPN_DNS_INFO:
    1891             :                         /*
    1892             :                          * Replace in the RODC case, otherwise
    1893             :                          * upn_blob is NULL and we just copy.
    1894             :                          */
    1895       36006 :                         if (upn_blob != NULL) {
    1896          47 :                                 type_blob = *upn_blob;
    1897             :                         }
    1898       36006 :                         break;
    1899       36006 :                 case PAC_TYPE_SRV_CHECKSUM:
    1900             :                         /*
    1901             :                          * This is generated in the main KDC code
    1902             :                          */
    1903       36006 :                         if (flags & SAMBA_KDC_FLAG_SKIP_PAC_BUFFER) {
    1904           0 :                                 continue;
    1905             :                         }
    1906             : 
    1907       36006 :                         type_blob = data_blob_const(&zero_byte, 1);
    1908             : 
    1909       36006 :                         if (requester_sid_idx == -1 && requester_sid_blob != NULL) {
    1910             :                                 /* inject REQUESTER_SID behind */
    1911           0 :                                 forced_next_type = PAC_TYPE_REQUESTER_SID;
    1912             :                         }
    1913       36006 :                         break;
    1914       36006 :                 case PAC_TYPE_KDC_CHECKSUM:
    1915             :                         /*
    1916             :                          * This is generated in the main KDC code
    1917             :                          */
    1918       36006 :                         if (flags & SAMBA_KDC_FLAG_SKIP_PAC_BUFFER) {
    1919           0 :                                 continue;
    1920             :                         }
    1921             : 
    1922       36006 :                         type_blob = data_blob_const(&zero_byte, 1);
    1923             : 
    1924       36006 :                         break;
    1925          59 :                 case PAC_TYPE_TICKET_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       35955 :                 case PAC_TYPE_ATTRIBUTES_INFO:
    1937       35955 :                         if (!is_untrusted && is_tgs) {
    1938             :                                 /* just copy... */
    1939       21199 :                                 break;
    1940             :                         }
    1941             : 
    1942       14756 :                         continue;
    1943       35955 :                 case PAC_TYPE_REQUESTER_SID:
    1944       35955 :                         if (!is_tgs) {
    1945       14756 :                                 continue;
    1946             :                         }
    1947             : 
    1948             :                         /*
    1949             :                          * Replace in the RODC case, otherwise
    1950             :                          * requester_sid_blob is NULL and we just copy.
    1951             :                          */
    1952       21199 :                         if (requester_sid_blob != NULL) {
    1953           0 :                                 type_blob = *requester_sid_blob;
    1954             :                         }
    1955       21199 :                         break;
    1956          59 :                 case PAC_TYPE_FULL_CHECKSUM:
    1957             :                         /*
    1958             :                          * This is generated in the main KDC code
    1959             :                          */
    1960          59 :                         if (flags & SAMBA_KDC_FLAG_SKIP_PAC_BUFFER) {
    1961           0 :                                 continue;
    1962             :                         }
    1963             : 
    1964          59 :                         type_blob = data_blob_const(&zero_byte, 1);
    1965             : 
    1966          59 :                         break;
    1967           0 :                 default:
    1968             :                         /* just copy... */
    1969           0 :                         break;
    1970             :                 }
    1971             : 
    1972      222597 :                 if (type_blob.length != 0) {
    1973      288480 :                         code = smb_krb5_copy_data_contents(&type_data,
    1974      144240 :                                                            type_blob.data,
    1975             :                                                            type_blob.length);
    1976      144240 :                         if (code != 0) {
    1977           0 :                                 goto done;
    1978             :                         }
    1979             :                 } else {
    1980       78357 :                         code = krb5_pac_get_buffer(context,
    1981             :                                                    old_pac,
    1982             :                                                    type,
    1983             :                                                    &type_data);
    1984       78357 :                         if (code != 0) {
    1985           0 :                                 goto done;
    1986             :                         }
    1987             :                 }
    1988             : 
    1989      222597 :                 code = krb5_pac_add_buffer(context,
    1990             :                                            new_pac,
    1991             :                                            type,
    1992             :                                            &type_data);
    1993      222597 :                 smb_krb5_free_data_contents(context, &type_data);
    1994      222597 :                 if (code != 0) {
    1995           0 :                         goto done;
    1996             :                 }
    1997             :         }
    1998             : 
    1999       36006 :         code = 0;
    2000       36015 : done:
    2001       36015 :         TALLOC_FREE(pac_blob);
    2002       36015 :         TALLOC_FREE(upn_blob);
    2003       36015 :         TALLOC_FREE(deleg_blob);
    2004       36015 :         SAFE_FREE(types);
    2005       36015 :         return code;
    2006             : }

Generated by: LCOV version 1.13