Ignore:
Timestamp:
Nov 24, 2016, 1:14:11 PM (9 years ago)
Author:
Silvan Scherrer
Message:

Samba Server: update vendor to version 4.4.3

Location:
vendor/current/source4/auth/kerberos
Files:
1 added
5 deleted
8 edited

Legend:

Unmodified
Added
Removed
  • vendor/current/source4/auth/kerberos/kerberos-notes.txt

    r414 r988  
    77------------------------------------
    88
    9 This document should be read in conjuction with the Samba4 source code. 
     9This document should be read in conjunction with the Samba4 source code. 
    1010DAL and KDC requirements are expressed (as an implementation against Heimdal's
    1111HDB abstraction layer) in Samba4's source4/kdc/hdb-samba4.c in particular.
     
    160160correctly implement the GSSAPI specification, particularly on top of the
    161161(inflexible) MIT Kerberos API.  It did not seem possible to write a correct,
    162 seperate GSSAPI implementation on top of MIT Kerberos's public krb5lib API,
     162separate GSSAPI implementation on top of MIT Kerberos's public krb5lib API,
    163163and at the time, the effort did not need to extend beyond what Windows would
    164164require. 
     
    528528
    529529Traditional 'MIT' behaviour is to use a keytab, containing salted key
    530 data, extracted from the KDC.  (In this modal, there is no 'service
     530data, extracted from the KDC.  (In this model, there is no 'service
    531531password', instead the keys are often simply application of random
    532532bytes).  Heimdal also implements this behaviour.
    533533
    534 The windows modal is very different - instead of sharing a keytab with
     534The windows model is very different - instead of sharing a keytab with
    535535each member server, a random utf-16 pseudo-textual password is stored
    536536for the whole machine. 
  • vendor/current/source4/auth/kerberos/kerberos.h

    r740 r988  
    1919*/
    2020
     21#ifndef _AUTH_KERBEROS_H_
     22#define _AUTH_KERBEROS_H_
     23
    2124#if defined(HAVE_KRB5)
    2225
     26#include "system/kerberos.h"
    2327#include "auth/kerberos/krb5_init_context.h"
    2428#include "librpc/gen_ndr/krb5pac.h"
     29#include "lib/krb5_wrap/krb5_samba.h"
     30#include "lib/krb5_wrap/gss_samba.h"
    2531
    2632struct auth_user_info_dc;
     
    3541        struct smb_krb5_context *smb_krb5_context;
    3642        krb5_keytab keytab;
     43        bool password_based;
    3744};
    3845
     
    4451#define TOK_ID_GSS_WRAP         ((const uint8_t *)"\x02\x01")
    4552
    46 #ifdef HAVE_KRB5_KEYBLOCK_KEYVALUE
    47 #define KRB5_KEY_TYPE(k)        ((k)->keytype)
    48 #define KRB5_KEY_LENGTH(k)      ((k)->keyvalue.length)
    49 #define KRB5_KEY_DATA(k)        ((k)->keyvalue.data)
    50 #else
    51 #define KRB5_KEY_TYPE(k)        ((k)->enctype)
    52 #define KRB5_KEY_LENGTH(k)      ((k)->length)
    53 #define KRB5_KEY_DATA(k)        ((k)->contents)
    54 #endif /* HAVE_KRB5_KEYBLOCK_KEYVALUE */
    55 
    5653#define ENC_ALL_TYPES (ENC_CRC32 | ENC_RSA_MD5 | ENC_RC4_HMAC_MD5 |     \
    5754                       ENC_HMAC_SHA1_96_AES128 | ENC_HMAC_SHA1_96_AES256)
    58 
    59 #ifndef HAVE_KRB5_SET_REAL_TIME
    60 krb5_error_code krb5_set_real_time(krb5_context context, int32_t seconds, int32_t microseconds);
    61 #endif
    6255
    6356#ifndef HAVE_KRB5_SET_DEFAULT_TGS_KTYPES
     
    6962#endif
    7063
    71 #ifndef HAVE_KRB5_FREE_UNPARSED_NAME
    72 void krb5_free_unparsed_name(krb5_context ctx, char *val);
    73 #endif
    74 
    7564#if defined(HAVE_KRB5_PRINCIPAL_GET_COMP_STRING) && !defined(HAVE_KRB5_PRINC_COMPONENT)
    7665const krb5_data *krb5_princ_component(krb5_context context, krb5_principal principal, int i );
     
    7867
    7968/* Samba wrapper function for krb5 functionality. */
    80 void setup_kaddr( krb5_address *pkaddr, struct sockaddr *paddr);
    81 int create_kerberos_key_from_string(krb5_context context, krb5_principal host_princ, krb5_data *password, krb5_keyblock *key, krb5_enctype enctype);
    82 int create_kerberos_key_from_string_direct(krb5_context context, krb5_principal host_princ, krb5_data *password, krb5_keyblock *key, krb5_enctype enctype);
    83 krb5_const_principal get_principal_from_tkt(krb5_ticket *tkt);
    84 krb5_error_code get_kerberos_allowed_etypes(krb5_context context, krb5_enctype **enctypes);
    85 void free_kerberos_etypes(krb5_context context, krb5_enctype *enctypes);
    86 bool get_krb5_smb_session_key(krb5_context context, krb5_auth_context auth_context, DATA_BLOB *session_key, bool remote);
    87 krb5_error_code ads_krb5_mk_req(krb5_context context,
    88                                 krb5_auth_context *auth_context,
    89                                 const krb5_flags ap_req_options,
    90                                 const char *principal,
    91                                 krb5_ccache ccache,
    92                                 krb5_data *outbuf);
    93 bool get_auth_data_from_tkt(TALLOC_CTX *mem_ctx, DATA_BLOB *auth_data, krb5_ticket *tkt);
    94 krb5_error_code kerberos_kinit_password_cc(krb5_context ctx, krb5_ccache cc,
    95                                            krb5_principal principal, const char *password,
    96                                            krb5_principal impersonate_principal, const char *target_service,
    97                                            krb5_get_init_creds_opt *krb_options,
    98                                            time_t *expire_time, time_t *kdc_time);
    99 krb5_error_code kerberos_kinit_keyblock_cc(krb5_context ctx, krb5_ccache cc,
    100                                            krb5_principal principal, krb5_keyblock *keyblock,
    101                                            const char *target_service,
    102                                            krb5_get_init_creds_opt *krb_options,
    103                                            time_t *expire_time, time_t *kdc_time);
    104 krb5_principal kerberos_fetch_salt_princ_for_host_princ(krb5_context context,
    105                                                         krb5_principal host_princ,
    106                                                         int enctype);
    107 void kerberos_set_creds_enctype(krb5_creds *pcreds, int enctype);
    108 bool kerberos_compatible_enctypes(krb5_context context, krb5_enctype enctype1, krb5_enctype enctype2);
    109 void kerberos_free_data_contents(krb5_context context, krb5_data *pdata);
    110 krb5_error_code smb_krb5_kt_free_entry(krb5_context context, krb5_keytab_entry *kt_entry);
    111 char *smb_get_krb5_error_message(krb5_context context, krb5_error_code code, TALLOC_CTX *mem_ctx);
    112 NTSTATUS kerberos_decode_pac(TALLOC_CTX *mem_ctx,
    113                              struct PAC_DATA **pac_data_out,
    114                              DATA_BLOB blob,
    115                              krb5_context context,
    116                              const krb5_keyblock *krbtgt_keyblock,
    117                              const krb5_keyblock *service_keyblock,
    118                              krb5_const_principal client_principal,
    119                              time_t tgs_authtime,
    120                              krb5_error_code *k5ret);
    121  NTSTATUS kerberos_pac_logon_info(TALLOC_CTX *mem_ctx,
    122                                   struct PAC_LOGON_INFO **logon_info,
    123                                   DATA_BLOB blob,
    124                                   krb5_context context,
    125                                   const krb5_keyblock *krbtgt_keyblock,
    126                                   const krb5_keyblock *service_keyblock,
    127                                   krb5_const_principal client_principal,
    128                                   time_t tgs_authtime,
    129                                   krb5_error_code *k5ret);
    13069 krb5_error_code kerberos_encode_pac(TALLOC_CTX *mem_ctx,
    13170                                    struct PAC_DATA *pac_data,
     
    14281                                     time_t tgs_authtime,
    14382                                     DATA_BLOB *pac);
    144 struct loadparm_context;
    145 struct ldb_message;
    146 struct ldb_context;
    147 uint32_t kerberos_enctype_to_bitmap(krb5_enctype enc_type_enum);
    148 /* Translate between the Microsoft msDS-SupportedEncryptionTypes values and the IETF encryption type values */
    149 krb5_enctype kerberos_enctype_bitmap_to_enctype(uint32_t enctype_bitmap);
    150 krb5_error_code smb_krb5_update_keytab(TALLOC_CTX *parent_ctx,
    151                                        struct smb_krb5_context *smb_krb5_context,
    152                                        struct ldb_context *ldb,
    153                                        struct ldb_message *msg,
    154                                        bool delete_all_kvno,
    155                                        const char **error_string);
    15683
    15784#include "auth/kerberos/proto.h"
    15885
    15986#endif /* HAVE_KRB5 */
     87
     88#endif /* _AUTH_KERBEROS_H_ */
  • vendor/current/source4/auth/kerberos/kerberos_credentials.h

    r740 r988  
    2828                                enum credentials_obtained *obtained,
    2929                                const char **error_string);
     30
     31/* Manually prototyped here to avoid needing krb5 headers in most callers */
     32krb5_error_code principal_from_credentials(TALLOC_CTX *parent_ctx,
     33                                struct cli_credentials *credentials,
     34                                struct smb_krb5_context *smb_krb5_context,
     35                                krb5_principal *princ,
     36                                enum credentials_obtained *obtained,
     37                                const char **error_string);
  • vendor/current/source4/auth/kerberos/kerberos_pac.c

    r740 r988  
    3131#include <ldb.h>
    3232#include "auth/auth_sam_reply.h"
    33 
    34 krb5_error_code check_pac_checksum(TALLOC_CTX *mem_ctx,
    35                                    DATA_BLOB pac_data,
    36                                    struct PAC_SIGNATURE_DATA *sig,
    37                                    krb5_context context,
    38                                    const krb5_keyblock *keyblock)
    39 {
    40         krb5_error_code ret;
    41         krb5_crypto crypto;
    42         Checksum cksum;
    43 
    44         cksum.cksumtype         = (CKSUMTYPE)sig->type;
    45         cksum.checksum.length   = sig->signature.length;
    46         cksum.checksum.data     = sig->signature.data;
    47 
    48         ret = krb5_crypto_init(context,
    49                                keyblock,
    50                                0,
    51                                &crypto);
    52         if (ret) {
    53                 DEBUG(0,("krb5_crypto_init() failed: %s\n",
    54                           smb_get_krb5_error_message(context, ret, mem_ctx)));
    55                 return ret;
    56         }
    57         ret = krb5_verify_checksum(context,
    58                                    crypto,
    59                                    KRB5_KU_OTHER_CKSUM,
    60                                    pac_data.data,
    61                                    pac_data.length,
    62                                    &cksum);
    63         krb5_crypto_destroy(context, crypto);
    64 
    65         return ret;
    66 }
    67 
    68  NTSTATUS kerberos_decode_pac(TALLOC_CTX *mem_ctx,
    69                               struct PAC_DATA **pac_data_out,
    70                               DATA_BLOB blob,
    71                               krb5_context context,
    72                               const krb5_keyblock *krbtgt_keyblock,
    73                               const krb5_keyblock *service_keyblock,
    74                               krb5_const_principal client_principal,
    75                               time_t tgs_authtime,
    76                               krb5_error_code *k5ret)
    77 {
    78         krb5_error_code ret;
    79         NTSTATUS status;
    80         enum ndr_err_code ndr_err;
    81         struct PAC_SIGNATURE_DATA *srv_sig_ptr = NULL;
    82         struct PAC_SIGNATURE_DATA *kdc_sig_ptr = NULL;
    83         struct PAC_SIGNATURE_DATA *srv_sig_wipe = NULL;
    84         struct PAC_SIGNATURE_DATA *kdc_sig_wipe = NULL;
    85         struct PAC_LOGON_INFO *logon_info = NULL;
    86         struct PAC_LOGON_NAME *logon_name = NULL;
    87         struct PAC_DATA *pac_data;
    88         struct PAC_DATA_RAW *pac_data_raw;
    89 
    90         DATA_BLOB *srv_sig_blob = NULL;
    91         DATA_BLOB *kdc_sig_blob = NULL;
    92 
    93         DATA_BLOB modified_pac_blob;
    94         NTTIME tgs_authtime_nttime;
    95         krb5_principal client_principal_pac;
    96         uint32_t i;
    97 
    98         krb5_clear_error_message(context);
    99 
    100         if (k5ret) {
    101                 *k5ret = KRB5_PARSE_MALFORMED;
    102         }
    103 
    104         pac_data = talloc(mem_ctx, struct PAC_DATA);
    105         pac_data_raw = talloc(mem_ctx, struct PAC_DATA_RAW);
    106         kdc_sig_wipe = talloc(mem_ctx, struct PAC_SIGNATURE_DATA);
    107         srv_sig_wipe = talloc(mem_ctx, struct PAC_SIGNATURE_DATA);
    108         if (!pac_data_raw || !pac_data || !kdc_sig_wipe || !srv_sig_wipe) {
    109                 if (k5ret) {
    110                         *k5ret = ENOMEM;
    111                 }
    112                 return NT_STATUS_NO_MEMORY;
    113         }
    114 
    115         ndr_err = ndr_pull_struct_blob(&blob, pac_data,
    116                         pac_data, (ndr_pull_flags_fn_t)ndr_pull_PAC_DATA);
    117         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
    118                 status = ndr_map_error2ntstatus(ndr_err);
    119                 DEBUG(0,("can't parse the PAC: %s\n",
    120                         nt_errstr(status)));
    121                 return status;
    122         }
    123 
    124         if (pac_data->num_buffers < 4) {
    125                 /* we need logon_ingo, service_key and kdc_key */
    126                 DEBUG(0,("less than 4 PAC buffers\n"));
    127                 return NT_STATUS_INVALID_PARAMETER;
    128         }
    129 
    130         ndr_err = ndr_pull_struct_blob(&blob, pac_data_raw,
    131                                        pac_data_raw,
    132                                        (ndr_pull_flags_fn_t)ndr_pull_PAC_DATA_RAW);
    133         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
    134                 status = ndr_map_error2ntstatus(ndr_err);
    135                 DEBUG(0,("can't parse the PAC: %s\n",
    136                         nt_errstr(status)));
    137                 return status;
    138         }
    139 
    140         if (pac_data_raw->num_buffers < 4) {
    141                 /* we need logon_ingo, service_key and kdc_key */
    142                 DEBUG(0,("less than 4 PAC buffers\n"));
    143                 return NT_STATUS_INVALID_PARAMETER;
    144         }
    145 
    146         if (pac_data->num_buffers != pac_data_raw->num_buffers) {
    147                 /* we need logon_ingo, service_key and kdc_key */
    148                 DEBUG(0,("misparse!  PAC_DATA has %d buffers while PAC_DATA_RAW has %d\n",
    149                          pac_data->num_buffers, pac_data_raw->num_buffers));
    150                 return NT_STATUS_INVALID_PARAMETER;
    151         }
    152 
    153         for (i=0; i < pac_data->num_buffers; i++) {
    154                 if (pac_data->buffers[i].type != pac_data_raw->buffers[i].type) {
    155                         DEBUG(0,("misparse!  PAC_DATA buffer %d has type %d while PAC_DATA_RAW has %d\n",
    156                                  i, pac_data->buffers[i].type, pac_data->buffers[i].type));
    157                         return NT_STATUS_INVALID_PARAMETER;
    158                 }
    159                 switch (pac_data->buffers[i].type) {
    160                         case PAC_TYPE_LOGON_INFO:
    161                                 if (!pac_data->buffers[i].info) {
    162                                         break;
    163                                 }
    164                                 logon_info = pac_data->buffers[i].info->logon_info.info;
    165                                 break;
    166                         case PAC_TYPE_SRV_CHECKSUM:
    167                                 if (!pac_data->buffers[i].info) {
    168                                         break;
    169                                 }
    170                                 srv_sig_ptr = &pac_data->buffers[i].info->srv_cksum;
    171                                 srv_sig_blob = &pac_data_raw->buffers[i].info->remaining;
    172                                 break;
    173                         case PAC_TYPE_KDC_CHECKSUM:
    174                                 if (!pac_data->buffers[i].info) {
    175                                         break;
    176                                 }
    177                                 kdc_sig_ptr = &pac_data->buffers[i].info->kdc_cksum;
    178                                 kdc_sig_blob = &pac_data_raw->buffers[i].info->remaining;
    179                                 break;
    180                         case PAC_TYPE_LOGON_NAME:
    181                                 logon_name = &pac_data->buffers[i].info->logon_name;
    182                                 break;
    183                         default:
    184                                 break;
    185                 }
    186         }
    187 
    188         if (!logon_info) {
    189                 DEBUG(0,("PAC no logon_info\n"));
    190                 return NT_STATUS_INVALID_PARAMETER;
    191         }
    192 
    193         if (!logon_name) {
    194                 DEBUG(0,("PAC no logon_name\n"));
    195                 return NT_STATUS_INVALID_PARAMETER;
    196         }
    197 
    198         if (!srv_sig_ptr || !srv_sig_blob) {
    199                 DEBUG(0,("PAC no srv_key\n"));
    200                 return NT_STATUS_INVALID_PARAMETER;
    201         }
    202 
    203         if (!kdc_sig_ptr || !kdc_sig_blob) {
    204                 DEBUG(0,("PAC no kdc_key\n"));
    205                 return NT_STATUS_INVALID_PARAMETER;
    206         }
    207 
    208         /* Find and zero out the signatures, as required by the signing algorithm */
    209 
    210         /* We find the data blobs above, now we parse them to get at the exact portion we should zero */
    211         ndr_err = ndr_pull_struct_blob(kdc_sig_blob, kdc_sig_wipe,
    212                                        kdc_sig_wipe,
    213                                        (ndr_pull_flags_fn_t)ndr_pull_PAC_SIGNATURE_DATA);
    214         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
    215                 status = ndr_map_error2ntstatus(ndr_err);
    216                 DEBUG(0,("can't parse the KDC signature: %s\n",
    217                         nt_errstr(status)));
    218                 return status;
    219         }
    220 
    221         ndr_err = ndr_pull_struct_blob(srv_sig_blob, srv_sig_wipe,
    222                                        srv_sig_wipe,
    223                                        (ndr_pull_flags_fn_t)ndr_pull_PAC_SIGNATURE_DATA);
    224         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
    225                 status = ndr_map_error2ntstatus(ndr_err);
    226                 DEBUG(0,("can't parse the SRV signature: %s\n",
    227                         nt_errstr(status)));
    228                 return status;
    229         }
    230 
    231         /* Now zero the decoded structure */
    232         memset(kdc_sig_wipe->signature.data, '\0', kdc_sig_wipe->signature.length);
    233         memset(srv_sig_wipe->signature.data, '\0', srv_sig_wipe->signature.length);
    234 
    235         /* and reencode, back into the same place it came from */
    236         ndr_err = ndr_push_struct_blob(kdc_sig_blob, pac_data_raw,
    237                                        kdc_sig_wipe,
    238                                        (ndr_push_flags_fn_t)ndr_push_PAC_SIGNATURE_DATA);
    239         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
    240                 status = ndr_map_error2ntstatus(ndr_err);
    241                 DEBUG(0,("can't repack the KDC signature: %s\n",
    242                         nt_errstr(status)));
    243                 return status;
    244         }
    245         ndr_err = ndr_push_struct_blob(srv_sig_blob, pac_data_raw,
    246                                        srv_sig_wipe,
    247                                        (ndr_push_flags_fn_t)ndr_push_PAC_SIGNATURE_DATA);
    248         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
    249                 status = ndr_map_error2ntstatus(ndr_err);
    250                 DEBUG(0,("can't repack the SRV signature: %s\n",
    251                         nt_errstr(status)));
    252                 return status;
    253         }
    254 
    255         /* push out the whole structure, but now with zero'ed signatures */
    256         ndr_err = ndr_push_struct_blob(&modified_pac_blob, pac_data_raw,
    257                                        pac_data_raw,
    258                                        (ndr_push_flags_fn_t)ndr_push_PAC_DATA_RAW);
    259         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
    260                 status = ndr_map_error2ntstatus(ndr_err);
    261                 DEBUG(0,("can't repack the RAW PAC: %s\n",
    262                         nt_errstr(status)));
    263                 return status;
    264         }
    265 
    266         /* verify by service_key */
    267         ret = check_pac_checksum(mem_ctx,
    268                                  modified_pac_blob, srv_sig_ptr,
    269                                  context,
    270                                  service_keyblock);
    271         if (ret) {
    272                 DEBUG(1, ("PAC Decode: Failed to verify the service signature: %s\n",
    273                           smb_get_krb5_error_message(context, ret, mem_ctx)));
    274                 if (k5ret) {
    275                         *k5ret = ret;
    276                 }
    277                 return NT_STATUS_ACCESS_DENIED;
    278         }
    279 
    280         if (krbtgt_keyblock) {
    281                 ret = check_pac_checksum(mem_ctx,
    282                                             srv_sig_ptr->signature, kdc_sig_ptr,
    283                                             context, krbtgt_keyblock);
    284                 if (ret) {
    285                         DEBUG(1, ("PAC Decode: Failed to verify the KDC signature: %s\n",
    286                                   smb_get_krb5_error_message(context, ret, mem_ctx)));
    287                         if (k5ret) {
    288                                 *k5ret = ret;
    289                         }
    290                         return NT_STATUS_ACCESS_DENIED;
    291                 }
    292         }
    293 
    294         /* Convert to NT time, so as not to loose accuracy in comparison */
    295         unix_to_nt_time(&tgs_authtime_nttime, tgs_authtime);
    296 
    297         if (tgs_authtime_nttime != logon_name->logon_time) {
    298                 DEBUG(2, ("PAC Decode: Logon time mismatch between ticket and PAC!\n"));
    299                 DEBUG(2, ("PAC Decode: PAC: %s\n", nt_time_string(mem_ctx, logon_name->logon_time)));
    300                 DEBUG(2, ("PAC Decode: Ticket: %s\n", nt_time_string(mem_ctx, tgs_authtime_nttime)));
    301                 return NT_STATUS_ACCESS_DENIED;
    302         }
    303 
    304         ret = krb5_parse_name_flags(context, logon_name->account_name, KRB5_PRINCIPAL_PARSE_NO_REALM,
    305                                     &client_principal_pac);
    306         if (ret) {
    307                 DEBUG(2, ("Could not parse name from incoming PAC: [%s]: %s\n",
    308                           logon_name->account_name,
    309                           smb_get_krb5_error_message(context, ret, mem_ctx)));
    310                 if (k5ret) {
    311                         *k5ret = ret;
    312                 }
    313                 return NT_STATUS_INVALID_PARAMETER;
    314         }
    315 
    316         if (!krb5_principal_compare_any_realm(context, client_principal, client_principal_pac)) {
    317                 DEBUG(2, ("Name in PAC [%s] does not match principal name in ticket\n",
    318                           logon_name->account_name));
    319                 krb5_free_principal(context, client_principal_pac);
    320                 return NT_STATUS_ACCESS_DENIED;
    321         }
    322 
    323         krb5_free_principal(context, client_principal_pac);
    324 
    325 #if 0
    326         if (strcasecmp(logon_info->info3.base.account_name.string,
    327                        "Administrator")== 0) {
    328                 file_save("tmp_pac_data-admin.dat",blob.data,blob.length);
    329         }
    330 #endif
    331 
    332         DEBUG(3,("Found account name from PAC: %s [%s]\n",
    333                  logon_info->info3.base.account_name.string,
    334                  logon_info->info3.base.full_name.string));
    335         *pac_data_out = pac_data;
    336 
    337         return NT_STATUS_OK;
    338 }
    339 
    340 _PUBLIC_  NTSTATUS kerberos_pac_logon_info(TALLOC_CTX *mem_ctx,
    341                                   struct PAC_LOGON_INFO **logon_info,
    342                                   DATA_BLOB blob,
    343                                   krb5_context context,
    344                                   const krb5_keyblock *krbtgt_keyblock,
    345                                   const krb5_keyblock *service_keyblock,
    346                                   krb5_const_principal client_principal,
    347                                   time_t tgs_authtime,
    348                                   krb5_error_code *k5ret)
    349 {
    350         NTSTATUS nt_status;
    351         struct PAC_DATA *pac_data;
    352         int i;
    353         nt_status = kerberos_decode_pac(mem_ctx,
    354                                         &pac_data,
    355                                         blob,
    356                                         context,
    357                                         krbtgt_keyblock,
    358                                         service_keyblock,
    359                                         client_principal,
    360                                         tgs_authtime,
    361                                         k5ret);
    362         if (!NT_STATUS_IS_OK(nt_status)) {
    363                 return nt_status;
    364         }
    365 
    366         *logon_info = NULL;
    367         for (i=0; i < pac_data->num_buffers; i++) {
    368                 if (pac_data->buffers[i].type != PAC_TYPE_LOGON_INFO) {
    369                         continue;
    370                 }
    371                 *logon_info = pac_data->buffers[i].info->logon_info.info;
    372         }
    373         if (!*logon_info) {
    374                 return NT_STATUS_INVALID_PARAMETER;
    375         }
    376         return NT_STATUS_OK;
    377 }
    378 
    379 static krb5_error_code make_pac_checksum(TALLOC_CTX *mem_ctx,
    380                                          DATA_BLOB *pac_data,
    381                                          struct PAC_SIGNATURE_DATA *sig,
    382                                          krb5_context context,
    383                                          const krb5_keyblock *keyblock)
    384 {
    385         krb5_error_code ret;
    386         krb5_crypto crypto;
    387         Checksum cksum;
    388 
    389 
    390         ret = krb5_crypto_init(context,
    391                                keyblock,
    392                                0,
    393                                &crypto);
    394         if (ret) {
    395                 DEBUG(0,("krb5_crypto_init() failed: %s\n",
    396                           smb_get_krb5_error_message(context, ret, mem_ctx)));
    397                 return ret;
    398         }
    399         ret = krb5_create_checksum(context,
    400                                    crypto,
    401                                    KRB5_KU_OTHER_CKSUM,
    402                                    0,
    403                                    pac_data->data,
    404                                    pac_data->length,
    405                                    &cksum);
    406         if (ret) {
    407                 DEBUG(2, ("PAC Verification failed: %s\n",
    408                           smb_get_krb5_error_message(context, ret, mem_ctx)));
    409         }
    410 
    411         krb5_crypto_destroy(context, crypto);
    412 
    413         if (ret) {
    414                 return ret;
    415         }
    416 
    417         sig->type = cksum.cksumtype;
    418         sig->signature = data_blob_talloc(mem_ctx, cksum.checksum.data, cksum.checksum.length);
    419         free_Checksum(&cksum);
    420 
    421         return 0;
    422 }
     33#include "auth/credentials/credentials.h"
     34#include "auth/kerberos/kerberos_util.h"
     35#include "auth/kerberos/pac_utils.h"
    42336
    42437 krb5_error_code kerberos_encode_pac(TALLOC_CTX *mem_ctx,
     
    44457                }
    44558                kdc_checksum = &pac_data->buffers[i].info->kdc_cksum,
    446                 ret = make_pac_checksum(mem_ctx, &zero_blob,
    447                                         kdc_checksum,
    448                                         context, krbtgt_keyblock);
     59                ret = smb_krb5_make_pac_checksum(mem_ctx,
     60                                                 &zero_blob,
     61                                                 context,
     62                                                 krbtgt_keyblock,
     63                                                 &kdc_checksum->type,
     64                                                 &kdc_checksum->signature);
    44965                if (ret) {
    45066                        DEBUG(2, ("making krbtgt PAC checksum failed: %s\n",
     
    46076                }
    46177                srv_checksum = &pac_data->buffers[i].info->srv_cksum;
    462                 ret = make_pac_checksum(mem_ctx, &zero_blob,
    463                                         srv_checksum,
    464                                         context, service_keyblock);
     78                ret = smb_krb5_make_pac_checksum(mem_ctx,
     79                                                 &zero_blob,
     80                                                 context,
     81                                                 service_keyblock,
     82                                                 &srv_checksum->type,
     83                                                 &srv_checksum->signature);
    46584                if (ret) {
    46685                        DEBUG(2, ("making service PAC checksum failed: %s\n",
     
    495114
    496115        /* Then sign the result of the previous push, where the sig was zero'ed out */
    497         ret = make_pac_checksum(mem_ctx, &tmp_blob, srv_checksum,
    498                                 context, service_keyblock);
     116        ret = smb_krb5_make_pac_checksum(mem_ctx,
     117                                         &tmp_blob,
     118                                         context,
     119                                         service_keyblock,
     120                                         &srv_checksum->type,
     121                                         &srv_checksum->signature);
    499122
    500123        /* Then sign Server checksum */
    501         ret = make_pac_checksum(mem_ctx, &srv_checksum->signature, kdc_checksum, context, krbtgt_keyblock);
     124        ret = smb_krb5_make_pac_checksum(mem_ctx,
     125                                         &srv_checksum->signature,
     126                                         context,
     127                                         krbtgt_keyblock,
     128                                         &kdc_checksum->type,
     129                                         &kdc_checksum->signature);
    502130        if (ret) {
    503131                DEBUG(2, ("making krbtgt PAC checksum failed: %s\n",
     
    624252
    625253        ret = krb5_unparse_name_flags(context, client_principal,
    626                                       KRB5_PRINCIPAL_UNPARSE_NO_REALM, &name);
     254                                      KRB5_PRINCIPAL_UNPARSE_NO_REALM |
     255                                      KRB5_PRINCIPAL_UNPARSE_DISPLAY,
     256                                      &name);
    627257        if (ret) {
    628258                return ret;
     
    680310                                      PAC_TYPE_LOGON_INFO,
    681311                                      (ndr_pull_flags_fn_t)ndr_pull_PAC_INFO);
    682         krb5_data_free(&k5pac_logon_info_in);
     312        kerberos_free_data_contents(context, &k5pac_logon_info_in);
    683313        if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err) || !info.logon_info.info) {
    684314                nt_status = ndr_map_error2ntstatus(ndr_err);
     
    709339                                               pac_srv_sig,
    710340                                               (ndr_pull_flags_fn_t)ndr_pull_PAC_SIGNATURE_DATA);
    711                 krb5_data_free(&k5pac_srv_checksum_in);
     341                kerberos_free_data_contents(context, &k5pac_srv_checksum_in);
    712342                if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
    713343                        nt_status = ndr_map_error2ntstatus(ndr_err);
     
    730360                                               pac_kdc_sig,
    731361                                               (ndr_pull_flags_fn_t)ndr_pull_PAC_SIGNATURE_DATA);
    732                 krb5_data_free(&k5pac_kdc_checksum_in);
     362                kerberos_free_data_contents(context, &k5pac_kdc_checksum_in);
    733363                if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
    734364                        nt_status = ndr_map_error2ntstatus(ndr_err);
     
    757387                             &pac);
    758388        if (ret) {
    759                 return map_nt_error_from_unix(ret);
     389                return map_nt_error_from_unix_common(ret);
    760390        }
    761391
     
    764394        krb5_pac_free(context, pac);
    765395        if (ret) {
    766                 return map_nt_error_from_unix(ret);
     396                return map_nt_error_from_unix_common(ret);
    767397        }
    768398        return NT_STATUS_OK;
  • vendor/current/source4/auth/kerberos/kerberos_util.c

    r740 r988  
    2929#include "auth/kerberos/kerberos_credentials.h"
    3030#include "auth/kerberos/kerberos_util.h"
    31 #include <ldb.h>
    32 #include "param/secrets.h"
    3331
    3432struct principal_container {
     
    6462
    6563        if (ret) {
    66                 (*error_string) = smb_get_krb5_error_message(smb_krb5_context->krb5_context, ret, parent_ctx);
     64                (*error_string) = smb_get_krb5_error_message(
     65                                                smb_krb5_context->krb5_context,
     66                                                ret, parent_ctx);
    6767                return ret;
    6868        }
     
    7676        /* This song-and-dance effectivly puts the principal
    7777         * into talloc, so we can't loose it. */
    78         mem_ctx->smb_krb5_context = talloc_reference(mem_ctx, smb_krb5_context);
     78        mem_ctx->smb_krb5_context = talloc_reference(mem_ctx,
     79                                                     smb_krb5_context);
    7980        mem_ctx->principal = *princ;
    8081        talloc_set_destructor(mem_ctx, free_principal);
    8182        return 0;
    82 }
    83 
    84 static krb5_error_code principals_from_msg(TALLOC_CTX *parent_ctx,
    85                                            struct ldb_message *msg,
    86                                            struct smb_krb5_context *smb_krb5_context,
    87                                            struct principal_container ***principals_out,
    88                                            const char **error_string)
    89 {
    90         unsigned int i;
    91         krb5_error_code ret;
    92         char *upper_realm;
    93         const char *realm = ldb_msg_find_attr_as_string(msg, "realm", NULL);
    94         const char *samAccountName = ldb_msg_find_attr_as_string(msg, "samAccountName", NULL);
    95         struct ldb_message_element *spn_el = ldb_msg_find_element(msg, "servicePrincipalName");
    96         TALLOC_CTX *tmp_ctx;
    97         struct principal_container **principals;
    98         tmp_ctx = talloc_new(parent_ctx);
    99         if (!tmp_ctx) {
    100                 *error_string = "Cannot allocate tmp_ctx";
    101                 return ENOMEM;
    102         }
    103 
    104         if (!realm) {
    105                 *error_string = "Cannot have a kerberos secret in secrets.ldb without a realm";
    106                 return EINVAL;
    107         }
    108 
    109         upper_realm = strupper_talloc(tmp_ctx, realm);
    110         if (!upper_realm) {
    111                 talloc_free(tmp_ctx);
    112                 *error_string = "Cannot allocate full upper case realm";
    113                 return ENOMEM;
    114         }
    115 
    116         principals = talloc_array(tmp_ctx, struct principal_container *, spn_el ? (spn_el->num_values + 2) : 2);
    117 
    118         spn_el = ldb_msg_find_element(msg, "servicePrincipalName");
    119         for (i=0; spn_el && i < spn_el->num_values; i++) {
    120                 principals[i] = talloc(principals, struct principal_container);
    121                 if (!principals[i]) {
    122                         talloc_free(tmp_ctx);
    123                         *error_string = "Cannot allocate mem_ctx";
    124                         return ENOMEM;
    125                 }
    126 
    127                 principals[i]->smb_krb5_context = talloc_reference(principals[i], smb_krb5_context);
    128                 principals[i]->string_form = talloc_asprintf(principals[i], "%*.*s@%s",
    129                                                              (int)spn_el->values[i].length,
    130                                                              (int)spn_el->values[i].length,
    131                                                              (const char *)spn_el->values[i].data, upper_realm);
    132                 if (!principals[i]->string_form) {
    133                         talloc_free(tmp_ctx);
    134                         *error_string = "Cannot allocate full samAccountName";
    135                         return ENOMEM;
    136                 }
    137 
    138                 ret = krb5_parse_name(smb_krb5_context->krb5_context,
    139                                       principals[i]->string_form, &principals[i]->principal);
    140                
    141                 if (ret) {
    142                         talloc_free(tmp_ctx);
    143                         (*error_string) = smb_get_krb5_error_message(smb_krb5_context->krb5_context, ret, parent_ctx);
    144                         return ret;
    145                 }
    146 
    147                 /* This song-and-dance effectivly puts the principal
    148                  * into talloc, so we can't loose it. */
    149                 talloc_set_destructor(principals[i], free_principal);
    150         }
    151 
    152         if (samAccountName) {
    153                 principals[i] = talloc(principals, struct principal_container);
    154                 if (!principals[i]) {
    155                         talloc_free(tmp_ctx);
    156                         *error_string = "Cannot allocate mem_ctx";
    157                         return ENOMEM;
    158                 }
    159 
    160                 principals[i]->smb_krb5_context = talloc_reference(principals[i], smb_krb5_context);
    161                 principals[i]->string_form = talloc_asprintf(parent_ctx, "%s@%s", samAccountName, upper_realm);
    162                 if (!principals[i]->string_form) {
    163                         talloc_free(tmp_ctx);
    164                         *error_string = "Cannot allocate full samAccountName";
    165                         return ENOMEM;
    166                 }
    167                
    168                 ret = krb5_make_principal(smb_krb5_context->krb5_context, &principals[i]->principal, upper_realm, samAccountName,
    169                                           NULL);
    170                 if (ret) {
    171                         talloc_free(tmp_ctx);
    172                         (*error_string) = smb_get_krb5_error_message(smb_krb5_context->krb5_context, ret, parent_ctx);
    173                         return ret;
    174                 }
    175                
    176                 /* This song-and-dance effectivly puts the principal
    177                  * into talloc, so we can't loose it. */
    178                 talloc_set_destructor(principals[i], free_principal);
    179                 i++;
    180         }
    181 
    182         principals[i] = NULL;
    183         *principals_out = talloc_steal(parent_ctx, principals);
    184 
    185         talloc_free(tmp_ctx);
    186         return ret;
    187 }
    188 
    189 static krb5_error_code salt_principal_from_msg(TALLOC_CTX *parent_ctx,
    190                                                struct ldb_message *msg,
    191                                                struct smb_krb5_context *smb_krb5_context,
    192                                                krb5_principal *salt_princ,
    193                                                const char **error_string)
    194 {
    195         const char *salt_principal = ldb_msg_find_attr_as_string(msg, "saltPrincipal", NULL);
    196         const char *samAccountName = ldb_msg_find_attr_as_string(msg, "samAccountName", NULL);
    197         const char *realm = ldb_msg_find_attr_as_string(msg, "realm", NULL);
    198         if (salt_principal) {
    199                 return parse_principal(parent_ctx, salt_principal, smb_krb5_context, salt_princ, error_string);
    200         } else if (samAccountName) {
    201                 krb5_error_code ret;
    202                 char *machine_username;
    203                 char *salt_body;
    204                 char *lower_realm;
    205                 char *upper_realm;
    206 
    207                 TALLOC_CTX *tmp_ctx;
    208                 struct principal_container *mem_ctx = talloc(parent_ctx, struct principal_container);
    209                 if (!mem_ctx) {
    210                         *error_string = "Cannot allocate mem_ctx";
    211                         return ENOMEM;
    212                 }
    213 
    214                 tmp_ctx = talloc_new(mem_ctx);
    215                 if (!tmp_ctx) {
    216                         talloc_free(mem_ctx);
    217                         *error_string = "Cannot allocate tmp_ctx";
    218                         return ENOMEM;
    219                 }
    220 
    221                 if (!realm) {
    222                         *error_string = "Cannot have a kerberos secret in secrets.ldb without a realm";
    223                         return EINVAL;
    224                 }
    225                
    226                 machine_username = talloc_strdup(tmp_ctx, samAccountName);
    227                 if (!machine_username) {
    228                         talloc_free(mem_ctx);
    229                         *error_string = "Cannot duplicate samAccountName";
    230                         return ENOMEM;
    231                 }
    232                
    233                 if (machine_username[strlen(machine_username)-1] == '$') {
    234                         machine_username[strlen(machine_username)-1] = '\0';
    235                 }
    236 
    237                 lower_realm = strlower_talloc(tmp_ctx, realm);
    238                 if (!lower_realm) {
    239                         talloc_free(mem_ctx);
    240                         *error_string = "Cannot allocate to lower case realm";
    241                         return ENOMEM;
    242                 }
    243                
    244                 upper_realm = strupper_talloc(tmp_ctx, realm);
    245                 if (!upper_realm) {
    246                         talloc_free(mem_ctx);
    247                         *error_string = "Cannot allocate to upper case realm";
    248                         return ENOMEM;
    249                 }
    250                
    251                 salt_body = talloc_asprintf(tmp_ctx, "%s.%s", machine_username,
    252                                             lower_realm);
    253                 talloc_free(lower_realm);
    254                 talloc_free(machine_username);
    255                 if (!salt_body) {
    256                         talloc_free(mem_ctx);
    257                         *error_string = "Cannot form salt principal body";
    258                         return ENOMEM;
    259                 }
    260                
    261                 ret = krb5_make_principal(smb_krb5_context->krb5_context, salt_princ,
    262                                           upper_realm,
    263                                           "host", salt_body, NULL);
    264                 if (ret == 0) {
    265                         /* This song-and-dance effectivly puts the principal
    266                          * into talloc, so we can't loose it. */
    267                         mem_ctx->smb_krb5_context = talloc_reference(mem_ctx, smb_krb5_context);
    268                         mem_ctx->principal = *salt_princ;
    269                         talloc_set_destructor(mem_ctx, free_principal);
    270                 } else {
    271                         (*error_string) = smb_get_krb5_error_message(smb_krb5_context->krb5_context, ret, parent_ctx);
    272                 }
    273                 talloc_free(tmp_ctx);
    274                 return ret;
    275         } else {
    276                 (*error_string) = "Cannot determine salt principal, no saltPrincipal or samAccountName specified";
    277                 return EINVAL;
    278         }
    27983}
    28084
     
    28488 * system by means of a destructor (do *not* free). */
    28589
    286 krb5_error_code principal_from_credentials(TALLOC_CTX *parent_ctx, 
    287                                             struct cli_credentials *credentials,
    288                                             struct smb_krb5_context *smb_krb5_context,
    289                                             krb5_principal *princ,
    290                                             enum credentials_obtained *obtained,
    291                                             const char **error_string)
     90krb5_error_code principal_from_credentials(TALLOC_CTX *parent_ctx,
     91                                struct cli_credentials *credentials,
     92                                struct smb_krb5_context *smb_krb5_context,
     93                                krb5_principal *princ,
     94                                enum credentials_obtained *obtained,
     95                                const char **error_string)
    29296{
    29397        krb5_error_code ret;
    29498        const char *princ_string;
    29599        TALLOC_CTX *mem_ctx = talloc_new(parent_ctx);
     100        *obtained = CRED_UNINITIALISED;
     101
    296102        if (!mem_ctx) {
    297103                (*error_string) = error_message(ENOMEM);
    298104                return ENOMEM;
    299105        }
    300         princ_string = cli_credentials_get_principal_and_obtained(credentials, mem_ctx, obtained);
     106        princ_string = cli_credentials_get_principal_and_obtained(credentials,
     107                                                                  mem_ctx,
     108                                                                  obtained);
    301109        if (!princ_string) {
    302                 (*error_string) = error_message(ENOMEM);
    303                 return ENOMEM;
     110                *princ = NULL;
     111                return 0;
    304112        }
    305113
     
    315123 * system by means of a destructor (do *not* free). */
    316124
    317  krb5_error_code impersonate_principal_from_credentials(TALLOC_CTX *parent_ctx,
    318                                                         struct cli_credentials *credentials,
    319                                                         struct smb_krb5_context *smb_krb5_context,
    320                                                         krb5_principal *princ,
    321                                                         const char **error_string)
    322 {
    323         return parse_principal(parent_ctx, cli_credentials_get_impersonate_principal(credentials),
    324                                smb_krb5_context, princ, error_string);
     125static krb5_error_code impersonate_principal_from_credentials(
     126                                TALLOC_CTX *parent_ctx,
     127                                struct cli_credentials *credentials,
     128                                struct smb_krb5_context *smb_krb5_context,
     129                                krb5_principal *princ,
     130                                const char **error_string)
     131{
     132        return parse_principal(parent_ctx,
     133                        cli_credentials_get_impersonate_principal(credentials),
     134                        smb_krb5_context, princ, error_string);
     135}
     136
     137krb5_error_code smb_krb5_create_principals_array(TALLOC_CTX *mem_ctx,
     138                                                 krb5_context context,
     139                                                 const char *account_name,
     140                                                 const char *realm,
     141                                                 uint32_t num_spns,
     142                                                 const char *spns[],
     143                                                 uint32_t *pnum_principals,
     144                                                 krb5_principal **pprincipals,
     145                                                 const char **error_string)
     146{
     147        krb5_error_code code;
     148        TALLOC_CTX *tmp_ctx;
     149        uint32_t num_principals = 0;
     150        krb5_principal *principals;
     151        uint32_t i;
     152
     153        tmp_ctx = talloc_new(mem_ctx);
     154        if (tmp_ctx == NULL) {
     155                *error_string = "Cannot allocate tmp_ctx";
     156                return ENOMEM;
     157        }
     158
     159        if (realm == NULL) {
     160                *error_string = "Cannot create principal without a realm";
     161                code = EINVAL;
     162                goto done;
     163        }
     164
     165        if (account_name == NULL && (num_spns == 0 || spns == NULL)) {
     166                *error_string = "Cannot create principal without an account or SPN";
     167                code = EINVAL;
     168                goto done;
     169        }
     170
     171        if (account_name != NULL && account_name[0] != '\0') {
     172                num_principals++;
     173        }
     174        num_principals += num_spns;
     175
     176        principals = talloc_zero_array(tmp_ctx,
     177                                       krb5_principal,
     178                                       num_principals);
     179        if (principals == NULL) {
     180                *error_string = "Cannot allocate principals";
     181                code = ENOMEM;
     182                goto done;
     183        }
     184
     185        for (i = 0; i < num_spns; i++) {
     186                code = krb5_parse_name(context, spns[i], &(principals[i]));
     187                if (code != 0) {
     188                        *error_string = smb_get_krb5_error_message(context,
     189                                                                   code,
     190                                                                   mem_ctx);
     191                        goto done;
     192                }
     193        }
     194
     195        if (account_name != NULL && account_name[0] != '\0') {
     196                code = smb_krb5_make_principal(context,
     197                                               &(principals[i]),
     198                                               realm,
     199                                               account_name,
     200                                               NULL);
     201                if (code != 0) {
     202                        *error_string = smb_get_krb5_error_message(context,
     203                                                                   code,
     204                                                                   mem_ctx);
     205                        goto done;
     206                }
     207        }
     208
     209        if (pnum_principals != NULL) {
     210                *pnum_principals = num_principals;
     211
     212                if (pprincipals != NULL) {
     213                        *pprincipals = talloc_steal(mem_ctx, principals);
     214                }
     215        }
     216
     217        code = 0;
     218done:
     219        talloc_free(tmp_ctx);
     220        return code;
    325221}
    326222
     
    339235{
    340236        krb5_error_code ret;
    341         const char *password, *target_service;
     237        const char *password;
     238#ifdef SAMBA4_USES_HEIMDAL
     239        const char *self_service;
     240#endif
     241        const char *target_service;
    342242        time_t kdc_time = 0;
    343243        krb5_principal princ;
     
    358258        }
    359259
     260        if (princ == NULL) {
     261                (*error_string) = talloc_asprintf(credentials, "principal, username or realm was not specified in the credentials");
     262                talloc_free(mem_ctx);
     263                return KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN;
     264        }
     265
    360266        ret = impersonate_principal_from_credentials(mem_ctx, credentials, smb_krb5_context, &impersonate_principal, error_string);
    361267        if (ret) {
     
    364270        }
    365271
     272#ifdef SAMBA4_USES_HEIMDAL
     273        self_service = cli_credentials_get_self_service(credentials);
     274#endif
    366275        target_service = cli_credentials_get_target_service(credentials);
    367276
     
    377286        }
    378287
     288#ifdef SAMBA4_USES_HEIMDAL /* Disable for now MIT reads defaults when needed */
    379289        /* get the defaults */
    380290        krb5_get_init_creds_opt_set_default_flags(smb_krb5_context->krb5_context, NULL, NULL, krb_options);
    381 
     291#endif
    382292        /* set if we want a forwardable ticket */
    383293        switch (cli_credentials_get_krb_forwardable(credentials)) {
     
    392302        }
    393303
     304#ifdef SAMBA4_USES_HEIMDAL /* FIXME: MIT does not have this yet */
     305        /*
     306         * In order to work against windows KDCs even if we use
     307         * the netbios domain name as realm, we need to add the following
     308         * flags:
     309         * KRB5_INIT_CREDS_NO_C_CANON_CHECK;
     310         * KRB5_INIT_CREDS_NO_C_NO_EKU_CHECK;
     311         *
     312         * On MIT: Set pkinit_eku_checking to none
     313         */
     314        krb5_get_init_creds_opt_set_win2k(smb_krb5_context->krb5_context,
     315                                          krb_options, true);
     316#else /* MIT */
     317        krb5_get_init_creds_opt_set_canonicalize(krb_options, true);
     318#endif
     319
    394320        tries = 2;
    395321        while (tries--) {
     322#ifdef SAMBA4_USES_HEIMDAL
    396323                struct tevent_context *previous_ev;
    397324                /* Do this every time, in case we have weird recursive issues here */
     
    401328                        return ret;
    402329                }
     330#endif
    403331                if (password) {
    404                         ret = kerberos_kinit_password_cc(smb_krb5_context->krb5_context, ccache,
    405                                                          princ, password,
    406                                                          impersonate_principal, target_service,
    407                                                          krb_options,
    408                                                          NULL, &kdc_time);
     332                        if (impersonate_principal) {
     333#ifdef SAMBA4_USES_HEIMDAL
     334                                ret = kerberos_kinit_s4u2_cc(
     335                                                smb_krb5_context->krb5_context,
     336                                                ccache, princ, password,
     337                                                impersonate_principal,
     338                                                self_service, target_service,
     339                                                krb_options, NULL, &kdc_time);
     340#else
     341                                talloc_free(mem_ctx);
     342                                (*error_string) = "INTERNAL error: s4u2 ops "
     343                                        "are not supported with MIT build yet";
     344                                return EINVAL;
     345#endif
     346                        } else {
     347                                ret = kerberos_kinit_password_cc(
     348                                                smb_krb5_context->krb5_context,
     349                                                ccache, princ, password,
     350                                                target_service,
     351                                                krb_options, NULL, &kdc_time);
     352                        }
    409353                } else if (impersonate_principal) {
    410354                        talloc_free(mem_ctx);
     
    421365                                (*error_string) = "kinit_to_ccache: No password available for kinit\n";
    422366                                krb5_get_init_creds_opt_free(smb_krb5_context->krb5_context, krb_options);
     367#ifdef SAMBA4_USES_HEIMDAL
    423368                                smb_krb5_context_remove_event_ctx(smb_krb5_context, previous_ev, event_ctx);
     369#endif
    424370                                return EINVAL;
    425371                        }
    426                         ret = krb5_keyblock_init(smb_krb5_context->krb5_context,
     372                        ret = smb_krb5_keyblock_init_contents(smb_krb5_context->krb5_context,
    427373                                                 ENCTYPE_ARCFOUR_HMAC,
    428374                                                 mach_pwd->hash, sizeof(mach_pwd->hash),
     
    438384                }
    439385
     386#ifdef SAMBA4_USES_HEIMDAL
    440387                smb_krb5_context_remove_event_ctx(smb_krb5_context, previous_ev, event_ctx);
     388#endif
    441389
    442390                if (ret == KRB5KRB_AP_ERR_SKEW || ret == KRB5_KDCREP_SKEW) {
     
    485433                talloc_free(mem_ctx);
    486434                return ret;
    487         }
     435        }
     436
     437        DEBUG(10,("kinit for %s succeeded\n",
     438                cli_credentials_get_principal(credentials, mem_ctx)));
     439
     440
    488441        talloc_free(mem_ctx);
    489442        return 0;
    490443}
    491444
    492 static krb5_error_code free_keytab(struct keytab_container *ktc)
     445static krb5_error_code free_keytab_container(struct keytab_container *ktc)
    493446{
    494447        return krb5_kt_close(ktc->smb_krb5_context->krb5_context, ktc->keytab);
    495448}
    496449
    497 krb5_error_code smb_krb5_open_keytab(TALLOC_CTX *mem_ctx,
    498                          struct smb_krb5_context *smb_krb5_context,
    499                          const char *keytab_name, struct keytab_container **ktc)
     450krb5_error_code smb_krb5_get_keytab_container(TALLOC_CTX *mem_ctx,
     451                                struct smb_krb5_context *smb_krb5_context,
     452                                krb5_keytab opt_keytab,
     453                                const char *keytab_name,
     454                                struct keytab_container **ktc)
    500455{
    501456        krb5_keytab keytab;
    502457        krb5_error_code ret;
    503         ret = krb5_kt_resolve(smb_krb5_context->krb5_context, keytab_name, &keytab);
    504         if (ret) {
    505                 DEBUG(1,("failed to open krb5 keytab: %s\n",
    506                          smb_get_krb5_error_message(smb_krb5_context->krb5_context,
    507                                                     ret, mem_ctx)));
    508                 return ret;
     458
     459        if (opt_keytab) {
     460                keytab = opt_keytab;
     461        } else {
     462                ret = krb5_kt_resolve(smb_krb5_context->krb5_context,
     463                                                keytab_name, &keytab);
     464                if (ret) {
     465                        DEBUG(1,("failed to open krb5 keytab: %s\n",
     466                                 smb_get_krb5_error_message(
     467                                        smb_krb5_context->krb5_context,
     468                                        ret, mem_ctx)));
     469                        return ret;
     470                }
    509471        }
    510472
     
    516478        (*ktc)->smb_krb5_context = talloc_reference(*ktc, smb_krb5_context);
    517479        (*ktc)->keytab = keytab;
    518         talloc_set_destructor(*ktc, free_keytab);
     480        (*ktc)->password_based = false;
     481        talloc_set_destructor(*ktc, free_keytab_container);
    519482
    520483        return 0;
    521484}
    522485
    523 static krb5_error_code keytab_add_keys(TALLOC_CTX *parent_ctx,
    524                                        struct principal_container **principals,
    525                                        krb5_principal salt_princ,
    526                                        int kvno,
    527                                        const char *password_s,
    528                                        struct smb_krb5_context *smb_krb5_context,
    529                                        krb5_enctype *enctypes,
    530                                        krb5_keytab keytab,
    531                                        const char **error_string)
    532 {
    533         unsigned int i, p;
    534         krb5_error_code ret;
    535         krb5_data password;
    536 
    537         password.data = discard_const_p(char *, password_s);
    538         password.length = strlen(password_s);
    539 
    540         for (i=0; enctypes[i]; i++) {
    541                 krb5_keytab_entry entry;
    542 
    543                 ZERO_STRUCT(entry);
    544 
    545                 ret = create_kerberos_key_from_string(smb_krb5_context->krb5_context,
    546                                                       salt_princ, &password, &entry.keyblock, enctypes[i]);
    547                 if (ret != 0) {
    548                         return ret;
    549                 }
    550 
    551                 entry.vno = kvno;
    552 
    553                 for (p=0; principals[p]; p++) {
    554                         entry.principal = principals[p]->principal;
    555                         ret = krb5_kt_add_entry(smb_krb5_context->krb5_context, keytab, &entry);
    556                         if (ret != 0) {
    557                                 char *k5_error_string = smb_get_krb5_error_message(smb_krb5_context->krb5_context,
    558                                                                                    ret, NULL);
    559                                 *error_string = talloc_asprintf(parent_ctx, "Failed to add enctype %d entry for %s(kvno %d) to keytab: %s\n",
    560                                                                 (int)enctypes[i],
    561                                                                 principals[p]->string_form,
    562                                                                 kvno,
    563                                                                 k5_error_string);
    564                                 talloc_free(k5_error_string);
    565                                 krb5_free_keyblock_contents(smb_krb5_context->krb5_context, &entry.keyblock);
    566                                 return ret;
    567                         }
    568 
    569                         DEBUG(5, ("Added %s(kvno %d) to keytab (enctype %d)\n",
    570                                   principals[p]->string_form, kvno,
    571                                   (int)enctypes[i]));
    572                 }
    573                 krb5_free_keyblock_contents(smb_krb5_context->krb5_context, &entry.keyblock);
    574         }
    575         return 0;
    576 }
    577 
    578 static krb5_error_code create_keytab(TALLOC_CTX *parent_ctx,
    579                                      struct ldb_message *msg,
    580                                      struct principal_container **principals,
    581                                      struct smb_krb5_context *smb_krb5_context,
    582                                      krb5_keytab keytab,
    583                                      bool add_old,
    584                                      const char **error_string)
    585 {
    586         krb5_error_code ret;
    587         const char *password_s;
    588         const char *old_secret;
    589         int kvno;
    590         uint32_t enctype_bitmap;
    591         krb5_principal salt_princ;
    592         krb5_enctype *enctypes;
    593         TALLOC_CTX *mem_ctx = talloc_new(parent_ctx);
    594         if (!mem_ctx) {
    595                 *error_string = "unable to allocate tmp_ctx for create_keytab";
    596                 return ENOMEM;
    597         }
    598 
    599         /* The salt used to generate these entries may be different however, fetch that */
    600         ret = salt_principal_from_msg(mem_ctx, msg,
    601                                       smb_krb5_context,
    602                                       &salt_princ, error_string);
    603         if (ret) {
    604                 talloc_free(mem_ctx);
    605                 return ret;
    606         }
    607 
    608         kvno = ldb_msg_find_attr_as_int(msg, "msDS-KeyVersionNumber", 0);
    609 
    610         /* Finally, do the dance to get the password to put in the entry */
    611         password_s =  ldb_msg_find_attr_as_string(msg, "secret", NULL);
    612 
    613         if (!password_s) {
    614                 /* There is no password here, so nothing to do */
    615                 talloc_free(mem_ctx);
    616                 return 0;
    617         }
    618 
    619         if (add_old && kvno != 0) {
    620                 old_secret = ldb_msg_find_attr_as_string(msg, "priorSecret", NULL);
    621         } else {
    622                 old_secret = NULL;
    623         }
    624 
    625         enctype_bitmap = (uint32_t)ldb_msg_find_attr_as_int(msg, "msDS-SupportedEncryptionTypes", ENC_ALL_TYPES);
    626        
    627         ret = kerberos_enctype_bitmap_to_enctypes(mem_ctx, enctype_bitmap, &enctypes);
    628         if (ret) {
    629                 *error_string = talloc_asprintf(parent_ctx, "create_keytab: generating list of encryption types failed (%s)\n",
    630                                                 smb_get_krb5_error_message(smb_krb5_context->krb5_context,
    631                                                                            ret, mem_ctx));
    632                 talloc_free(mem_ctx);
    633                 return ret;
    634         }
    635 
    636         ret = keytab_add_keys(mem_ctx, principals,
    637                               salt_princ,
    638                               kvno, password_s, smb_krb5_context,
    639                               enctypes, keytab, error_string);
    640         if (ret) {
    641                 talloc_free(mem_ctx);
    642                 return ret;
    643         }
    644        
    645         if (old_secret) {
    646                 ret = keytab_add_keys(mem_ctx, principals,
    647                                       salt_princ,
    648                                       kvno - 1, old_secret, smb_krb5_context,
    649                                       enctypes, keytab, error_string);
    650                 if (ret) {
    651                         talloc_free(mem_ctx);
    652                         return ret;
    653                 }
    654         }
    655 
    656         talloc_free(mem_ctx);
    657         return ret;
    658 }
    659 
    660486/*
    661  * Walk the keytab, looking for entries of this principal name, with KVNO other than current kvno -1.
     487 * Walk the keytab, looking for entries of this principal name,
     488 * with KVNO other than current kvno -1.
    662489 *
    663  * These entries are now stale, we only keep the current, and previous entries around.
     490 * These entries are now stale,
     491 * we only keep the current and previous entries around.
    664492 *
    665493 * Inspired by the code in Samba3 for 'use kerberos keytab'.
    666  *
    667494 */
    668 
    669 static krb5_error_code remove_old_entries(TALLOC_CTX *parent_ctx,
    670                                           struct ldb_message *msg,
    671                                           struct principal_container **principals,
    672                                           bool delete_all_kvno,
    673                                           struct smb_krb5_context *smb_krb5_context,
    674                                           krb5_keytab keytab, bool *found_previous,
    675                                           const char **error_string)
    676 {
    677         krb5_error_code ret, ret2;
     495krb5_error_code smb_krb5_remove_obsolete_keytab_entries(TALLOC_CTX *mem_ctx,
     496                                                        krb5_context context,
     497                                                        krb5_keytab keytab,
     498                                                        uint32_t num_principals,
     499                                                        krb5_principal *principals,
     500                                                        krb5_kvno kvno,
     501                                                        bool *found_previous,
     502                                                        const char **error_string)
     503{
     504        TALLOC_CTX *tmp_ctx;
     505        krb5_error_code code;
    678506        krb5_kt_cursor cursor;
    679         int kvno;
    680         TALLOC_CTX *mem_ctx = talloc_new(parent_ctx);
    681 
    682         if (!mem_ctx) {
     507
     508        tmp_ctx = talloc_new(mem_ctx);
     509        if (tmp_ctx == NULL) {
     510                *error_string = "Cannot allocate tmp_ctx";
    683511                return ENOMEM;
    684512        }
    685513
    686         *found_previous = false;
    687 
    688         kvno = ldb_msg_find_attr_as_int(msg, "msDS-KeyVersionNumber", 0);
    689 
    690         /* for each entry in the keytab */
    691         ret = krb5_kt_start_seq_get(smb_krb5_context->krb5_context, keytab, &cursor);
    692         switch (ret) {
     514        *found_previous = true;
     515
     516        code = krb5_kt_start_seq_get(context, keytab, &cursor);
     517        switch (code) {
    693518        case 0:
    694519                break;
     520#ifdef HEIM_ERR_OPNOTSUPP
    695521        case HEIM_ERR_OPNOTSUPP:
     522#endif
    696523        case ENOENT:
    697524        case KRB5_KT_END:
    698525                /* no point enumerating if there isn't anything here */
    699                 talloc_free(mem_ctx);
    700                 return 0;
     526                code = 0;
     527                goto done;
    701528        default:
    702                 *error_string = talloc_asprintf(parent_ctx, "failed to open keytab for read of old entries: %s\n",
    703                                                 smb_get_krb5_error_message(smb_krb5_context->krb5_context,
    704                                                                            ret, mem_ctx));
    705                 talloc_free(mem_ctx);
    706                 return ret;
    707         }
    708 
    709         while (!ret) {
    710                 unsigned int i;
     529                *error_string = talloc_asprintf(mem_ctx,
     530                                                "failed to open keytab for read of old entries: %s\n",
     531                                                smb_get_krb5_error_message(context, code, mem_ctx));
     532                goto done;
     533        }
     534
     535        do {
     536                krb5_kvno old_kvno = kvno - 1;
     537                krb5_keytab_entry entry;
    711538                bool matched = false;
    712                 krb5_keytab_entry entry;
    713                 ret = krb5_kt_next_entry(smb_krb5_context->krb5_context, keytab, &entry, &cursor);
    714                 if (ret) {
     539                uint32_t i;
     540
     541                code = krb5_kt_next_entry(context, keytab, &entry, &cursor);
     542                if (code) {
    715543                        break;
    716544                }
    717                 for (i = 0; principals[i]; i++) {
    718                         /* if it matches our principal */
    719                         if (krb5_kt_compare(smb_krb5_context->krb5_context, &entry, principals[i]->principal, 0, 0)) {
     545
     546                for (i = 0; i < num_principals; i++) {
     547                        krb5_boolean ok;
     548
     549                        ok = smb_krb5_kt_compare(context,
     550                                                &entry,
     551                                                principals[i],
     552                                                0,
     553                                                0);
     554                        if (ok) {
    720555                                matched = true;
    721556                                break;
     
    724559
    725560                if (!matched) {
    726                         /* Free the entry, it wasn't the one we were looking for anyway */
    727                         krb5_kt_free_entry(smb_krb5_context->krb5_context, &entry);
     561                        /*
     562                         * Free the entry, it wasn't the one we were looking
     563                         * for anyway
     564                         */
     565                        krb5_kt_free_entry(context, &entry);
     566                        /* Make sure we do not double free */
     567                        ZERO_STRUCT(entry);
    728568                        continue;
    729569                }
    730570
    731                 /* delete it, if it is not kvno -1 */
    732                 if (entry.vno != (kvno - 1 )) {
     571                /*
     572                 * Delete it, if it is not kvno - 1.
     573                 *
     574                 * Some keytab files store the kvno only in 8bits. Limit the
     575                 * compare to 8bits, so that we don't miss old keys and delete
     576                 * them.
     577                 */
     578                if ((entry.vno & 0xff) != (old_kvno & 0xff)) {
     579                        krb5_error_code rc;
     580
    733581                        /* Release the enumeration.  We are going to
    734582                         * have to start this from the top again,
    735583                         * because deletes during enumeration may not
    736                          * always be consistant.
     584                         * always be consistent.
    737585                         *
    738586                         * Also, the enumeration locks a FILE: keytab
    739587                         */
    740                
    741                         krb5_kt_end_seq_get(smb_krb5_context->krb5_context, keytab, &cursor);
    742 
    743                         ret = krb5_kt_remove_entry(smb_krb5_context->krb5_context, keytab, &entry);
    744                         krb5_kt_free_entry(smb_krb5_context->krb5_context, &entry);
     588                        krb5_kt_end_seq_get(context, keytab, &cursor);
     589
     590                        code = krb5_kt_remove_entry(context, keytab, &entry);
     591                        krb5_kt_free_entry(context, &entry);
     592
     593                        /* Make sure we do not double free */
     594                        ZERO_STRUCT(entry);
    745595
    746596                        /* Deleted: Restart from the top */
    747                         ret2 = krb5_kt_start_seq_get(smb_krb5_context->krb5_context, keytab, &cursor);
    748                         if (ret2) {
    749                                 krb5_kt_free_entry(smb_krb5_context->krb5_context, &entry);
    750                                 DEBUG(1,("failed to restart enumeration of keytab: %s\n",
    751                                          smb_get_krb5_error_message(smb_krb5_context->krb5_context,
    752                                                                     ret, mem_ctx)));
    753                                
    754                                 talloc_free(mem_ctx);
    755                                 return ret2;
     597                        rc = krb5_kt_start_seq_get(context, keytab, &cursor);
     598                        if (rc != 0) {
     599                                krb5_kt_free_entry(context, &entry);
     600
     601                                /* Make sure we do not double free */
     602                                ZERO_STRUCT(entry);
     603
     604                                DEBUG(1, ("failed to restart enumeration of keytab: %s\n",
     605                                          smb_get_krb5_error_message(context,
     606                                                                     code,
     607                                                                     tmp_ctx)));
     608
     609                                talloc_free(tmp_ctx);
     610                                return rc;
    756611                        }
    757612
    758                         if (ret) {
     613                        if (code != 0) {
    759614                                break;
    760615                        }
    761                        
     616
    762617                } else {
    763618                        *found_previous = true;
    764619                }
    765                
     620
    766621                /* Free the entry, we don't need it any more */
    767                 krb5_kt_free_entry(smb_krb5_context->krb5_context, &entry);
    768                
    769                
    770         }
    771         krb5_kt_end_seq_get(smb_krb5_context->krb5_context, keytab, &cursor);
    772 
    773         switch (ret) {
     622                krb5_kt_free_entry(context, &entry);
     623                /* Make sure we do not double free */
     624                ZERO_STRUCT(entry);
     625        } while (code != 0);
     626
     627        krb5_kt_end_seq_get(context, keytab, &cursor);
     628
     629        switch (code) {
    774630        case 0:
    775631                break;
    776632        case ENOENT:
    777633        case KRB5_KT_END:
    778                 ret = 0;
     634                code = 0;
    779635                break;
    780636        default:
    781                 *error_string = talloc_asprintf(parent_ctx, "failed in deleting old entries for principal: %s\n",
    782                                                 smb_get_krb5_error_message(smb_krb5_context->krb5_context,
    783                                                                            ret, mem_ctx));
    784         }
    785         talloc_free(mem_ctx);
    786         return ret;
    787 }
    788 
    789 krb5_error_code smb_krb5_update_keytab(TALLOC_CTX *parent_ctx,
    790                                        struct smb_krb5_context *smb_krb5_context,
    791                                        struct ldb_context *ldb,
    792                                        struct ldb_message *msg,
    793                                        bool delete_all_kvno,
    794                                        const char **error_string)
    795 {
    796         krb5_error_code ret;
    797         bool found_previous;
    798         TALLOC_CTX *mem_ctx = talloc_new(NULL);
    799         struct keytab_container *keytab_container;
    800         struct principal_container **principals;
    801         const char *keytab_name;
    802 
    803         if (!mem_ctx) {
    804                 return ENOMEM;
    805         }
    806 
    807         keytab_name = keytab_name_from_msg(mem_ctx, ldb, msg);
    808         if (!keytab_name) {
    809                 return ENOENT;
    810         }
    811 
    812         ret = smb_krb5_open_keytab(mem_ctx, smb_krb5_context, keytab_name, &keytab_container);
    813 
    814         if (ret != 0) {
    815                 talloc_free(mem_ctx);
    816                 return ret;
    817         }
    818 
    819         DEBUG(5, ("Opened keytab %s\n", keytab_name));
    820 
    821         /* Get the principal we will store the new keytab entries under */
    822         ret = principals_from_msg(mem_ctx, msg, smb_krb5_context, &principals, error_string);
    823 
    824         if (ret != 0) {
    825                 *error_string = talloc_asprintf(parent_ctx, "Failed to load principals from ldb message: %s\n", *error_string);
    826                 talloc_free(mem_ctx);
    827                 return ret;
    828         }
    829 
    830         ret = remove_old_entries(mem_ctx, msg, principals, delete_all_kvno,
    831                                  smb_krb5_context, keytab_container->keytab, &found_previous, error_string);
    832         if (ret != 0) {
    833                 *error_string = talloc_asprintf(parent_ctx, "Failed to remove old principals from keytab: %s\n", *error_string);
    834                 talloc_free(mem_ctx);
    835                 return ret;
    836         }
    837        
    838         if (!delete_all_kvno) {
    839                 /* Create a new keytab.  If during the cleanout we found
    840                  * entires for kvno -1, then don't try and duplicate them.
    841                  * Otherwise, add kvno, and kvno -1 */
    842                
    843                 ret = create_keytab(mem_ctx, msg, principals,
    844                                     smb_krb5_context,
    845                                     keytab_container->keytab,
    846                                     found_previous ? false : true, error_string);
    847         }
    848         talloc_free(mem_ctx);
    849         return ret;
    850 }
    851 
    852 krb5_error_code smb_krb5_create_memory_keytab(TALLOC_CTX *parent_ctx,
    853                                            struct cli_credentials *machine_account,
    854                                            struct smb_krb5_context *smb_krb5_context,
    855                                            struct keytab_container **keytab_container)
    856 {
    857         krb5_error_code ret;
    858         TALLOC_CTX *mem_ctx = talloc_new(parent_ctx);
    859         const char *rand_string;
    860         const char *keytab_name;
    861         struct ldb_message *msg;
    862         const char *error_string;
    863         if (!mem_ctx) {
    864                 return ENOMEM;
    865         }
    866        
    867         *keytab_container = talloc(mem_ctx, struct keytab_container);
    868 
    869         rand_string = generate_random_str(mem_ctx, 16);
    870         if (!rand_string) {
    871                 talloc_free(mem_ctx);
    872                 return ENOMEM;
    873         }
    874 
    875         keytab_name = talloc_asprintf(mem_ctx, "MEMORY:%s",
    876                                       rand_string);
    877         if (!keytab_name) {
    878                 talloc_free(mem_ctx);
    879                 return ENOMEM;
    880         }
    881 
    882         ret = smb_krb5_open_keytab(mem_ctx, smb_krb5_context, keytab_name, keytab_container);
    883         if (ret) {
    884                 return ret;
    885         }
    886 
    887         msg = ldb_msg_new(mem_ctx);
    888         if (!msg) {
    889                 talloc_free(mem_ctx);
    890                 return ENOMEM;
    891         }
    892         ldb_msg_add_string(msg, "krb5Keytab", keytab_name);
    893         ldb_msg_add_string(msg, "secret", cli_credentials_get_password(machine_account));
    894         ldb_msg_add_string(msg, "samAccountName", cli_credentials_get_username(machine_account));
    895         ldb_msg_add_string(msg, "realm", cli_credentials_get_realm(machine_account));
    896         ldb_msg_add_fmt(msg, "msDS-KeyVersionNumber", "%d", (int)cli_credentials_get_kvno(machine_account));
    897 
    898         ret = smb_krb5_update_keytab(mem_ctx, smb_krb5_context, NULL, msg, false, &error_string);
    899         if (ret == 0) {
    900                 talloc_steal(parent_ctx, *keytab_container);
    901         } else {
    902                 DEBUG(0, ("Failed to create in-memory keytab: %s\n", error_string));
    903                 *keytab_container = NULL;
    904         }
    905         talloc_free(mem_ctx);
    906         return ret;
    907 }
    908 /* Translate between the IETF encryption type values and the Microsoft msDS-SupportedEncryptionTypes values */
    909 uint32_t kerberos_enctype_to_bitmap(krb5_enctype enc_type_enum)
    910 {
    911         switch (enc_type_enum) {
    912         case ENCTYPE_DES_CBC_CRC:
    913                 return ENC_CRC32;
    914         case ENCTYPE_DES_CBC_MD5:
    915                 return ENC_RSA_MD5;
    916         case ENCTYPE_ARCFOUR_HMAC_MD5:
    917                 return ENC_RC4_HMAC_MD5;
    918         case ENCTYPE_AES128_CTS_HMAC_SHA1_96:
    919                 return ENC_HMAC_SHA1_96_AES128;
    920         case ENCTYPE_AES256_CTS_HMAC_SHA1_96:
    921                 return ENC_HMAC_SHA1_96_AES256;
    922         default:
    923                 return 0;
    924         }
    925 }
    926 
    927 /* Translate between the Microsoft msDS-SupportedEncryptionTypes values and the IETF encryption type values */
    928 krb5_enctype kerberos_enctype_bitmap_to_enctype(uint32_t enctype_bitmap)
    929 {
    930         switch (enctype_bitmap) {
    931         case ENC_CRC32:
    932                 return ENCTYPE_DES_CBC_CRC;
    933         case ENC_RSA_MD5:
    934                 return ENCTYPE_DES_CBC_MD5;
    935         case ENC_RC4_HMAC_MD5:
    936                 return ENCTYPE_ARCFOUR_HMAC_MD5;
    937         case ENC_HMAC_SHA1_96_AES128:
    938                 return ENCTYPE_AES128_CTS_HMAC_SHA1_96;
    939         case ENC_HMAC_SHA1_96_AES256:
    940                 return ENCTYPE_AES256_CTS_HMAC_SHA1_96;
    941         default:
    942                 return 0;
    943         }
    944 }
    945 
    946 /* Return an array of krb5_enctype values */
    947 krb5_error_code kerberos_enctype_bitmap_to_enctypes(TALLOC_CTX *mem_ctx, uint32_t enctype_bitmap, krb5_enctype **enctypes)
    948 {
    949         unsigned int i, j = 0;
    950         *enctypes = talloc_zero_array(mem_ctx, krb5_enctype, (8*sizeof(enctype_bitmap))+1);
    951         if (!*enctypes) {
    952                 return ENOMEM;
    953         }
    954         for (i=0; i<(8*sizeof(enctype_bitmap)); i++) {
    955                 uint32_t bit_value = (1 << i) & enctype_bitmap;
    956                 if (bit_value & enctype_bitmap) {
    957                         (*enctypes)[j] = kerberos_enctype_bitmap_to_enctype(bit_value);
    958                         if (!(*enctypes)[j]) {
    959                                 continue;
    960                         }
    961                         j++;
    962                 }
    963         }
    964         (*enctypes)[j] = 0;
    965         return 0;
    966 }
     637                *error_string = talloc_asprintf(mem_ctx,
     638                                                "failed in deleting old entries for principal: %s\n",
     639                                                smb_get_krb5_error_message(context,
     640                                                                           code,
     641                                                                           mem_ctx));
     642        }
     643
     644        code = 0;
     645done:
     646        talloc_free(tmp_ctx);
     647        return code;
     648}
  • vendor/current/source4/auth/kerberos/krb5_init_context.c

    r740 r988  
    2323#include "includes.h"
    2424#include "system/kerberos.h"
     25#include "system/gssapi.h"
    2526#include <tevent.h>
    2627#include "auth/kerberos/kerberos.h"
     
    3132#include "libcli/resolve/resolve.h"
    3233#include "../lib/tsocket/tsocket.h"
    33 
     34#include "krb5_init_context.h"
    3435/*
    3536  context structure for operations on cldap packets
     
    4748
    4849        size_t partial_read;
    49 
     50#ifdef SAMBA4_USES_HEIMDAL
    5051        krb5_krbhst_info *hi;
     52#endif
    5153};
    5254
    5355static krb5_error_code smb_krb5_context_destroy(struct smb_krb5_context *ctx)
    5456{
    55         /* Otherwise krb5_free_context will try and close what we have already free()ed */
    56         krb5_set_warn_dest(ctx->krb5_context, NULL);
    57         krb5_closelog(ctx->krb5_context, ctx->logf);
     57#ifdef SAMBA4_USES_HEIMDAL
     58        if (ctx->pvt_log_data) {
     59                /* Otherwise krb5_free_context will try and close what we
     60                 * have already free()ed */
     61                krb5_set_warn_dest(ctx->krb5_context, NULL);
     62                krb5_closelog(ctx->krb5_context,
     63                                (krb5_log_facility *)ctx->pvt_log_data);
     64        }
     65#endif
    5866        krb5_free_context(ctx->krb5_context);
    5967        return 0;
    6068}
    6169
     70#ifdef SAMBA4_USES_HEIMDAL
    6271/* We never close down the DEBUG system, and no need to unreference the use */
    6372static void smb_krb5_debug_close(void *private_data) {
    6473        return;
    6574}
    66 
     75#endif
     76
     77#ifdef SAMBA4_USES_HEIMDAL
    6778static void smb_krb5_debug_wrapper(const char *timestr, const char *msg, void *private_data)
    6879{
    6980        DEBUG(3, ("Kerberos: %s\n", msg));
    7081}
    71 
     82#endif
     83
     84#ifdef SAMBA4_USES_HEIMDAL
    7285/*
    7386  handle recv events on a smb_krb5 socket
     
    105118        }
    106119
    107         DEBUG(2,("Received smb_krb5 packet of length %d\n",
     120        DEBUG(4,("Received smb_krb5 packet of length %d\n",
    108121                 (int)blob.length));
    109122
     
    198211}
    199212
    200 
    201 krb5_error_code smb_krb5_send_and_recv_func(krb5_context context,
    202                                             void *data,
    203                                             krb5_krbhst_info *hi,
    204                                             time_t timeout,
    205                                             const krb5_data *send_buf,
    206                                             krb5_data *recv_buf)
     213static krb5_error_code smb_krb5_send_and_recv_func_int(krb5_context context,
     214                                                       struct tevent_context *ev,
     215                                                       krb5_krbhst_info *hi,
     216                                                       struct addrinfo *ai,
     217                                                       krb5_send_to_kdc_func func,
     218                                                       void *data,
     219                                                       time_t timeout,
     220                                                       const krb5_data *send_buf,
     221                                                       krb5_data *recv_buf)
    207222{
    208223        krb5_error_code ret;
    209224        NTSTATUS status;
    210225        const char *name;
    211         struct addrinfo *ai, *a;
     226        struct addrinfo *a;
    212227        struct smb_krb5_socket *smb_krb5;
    213228
    214229        DATA_BLOB send_blob;
    215230
    216         struct tevent_context *ev;
    217         TALLOC_CTX *tmp_ctx = talloc_new(NULL);
    218         if (!tmp_ctx) {
     231        TALLOC_CTX *frame = talloc_stackframe();
     232        if (frame == NULL) {
    219233                return ENOMEM;
    220234        }
    221235
    222         if (!data) {
    223                 /* If no event context was available, then create one for this loop */
    224                 ev = tevent_context_init(tmp_ctx);
    225                 if (!ev) {
    226                         talloc_free(tmp_ctx);
    227                         return ENOMEM;
    228                 }
    229         } else {
    230                 ev = talloc_get_type_abort(data, struct tevent_context);
    231         }
    232 
    233236        send_blob = data_blob_const(send_buf->data, send_buf->length);
    234 
    235         ret = krb5_krbhst_get_addrinfo(context, hi, &ai);
    236         if (ret) {
    237                 talloc_free(tmp_ctx);
    238                 return ret;
    239         }
    240237
    241238        for (a = ai; a; a = a->ai_next) {
    242239                struct socket_address *remote_addr;
    243                 smb_krb5 = talloc(tmp_ctx, struct smb_krb5_socket);
     240                smb_krb5 = talloc(frame, struct smb_krb5_socket);
    244241                if (!smb_krb5) {
    245                         talloc_free(tmp_ctx);
     242                        TALLOC_FREE(frame);
    246243                        return ENOMEM;
    247244                }
     
    258255#endif
    259256                default:
    260                         talloc_free(tmp_ctx);
     257                        TALLOC_FREE(frame);
    261258                        return EINVAL;
    262259                }
     
    271268                        break;
    272269                case KRB5_KRBHST_HTTP:
    273                         talloc_free(tmp_ctx);
     270                        TALLOC_FREE(frame);
    274271                        return EINVAL;
    275272                }
     
    339336                        break;
    340337                case KRB5_KRBHST_HTTP:
    341                         talloc_free(tmp_ctx);
     338                        TALLOC_FREE(frame);
    342339                        return EINVAL;
    343340                }
    344341                while ((NT_STATUS_IS_OK(smb_krb5->status)) && !smb_krb5->reply.length) {
    345342                        if (tevent_loop_once(ev) != 0) {
    346                                 talloc_free(tmp_ctx);
     343                                TALLOC_FREE(frame);
    347344                                return EINVAL;
    348345                        }
    349346
    350                         /* After each and every event loop, reset the
    351                          * send_to_kdc pointers to what they were when
    352                          * we entered this loop.  That way, if a
    353                          * nested event has invalidated them, we put
    354                          * it back before we return to the heimdal
    355                          * code */
    356                         ret = krb5_set_send_to_kdc_func(context,
    357                                                         smb_krb5_send_and_recv_func,
    358                                                         data);
    359                         if (ret != 0) {
    360                                 talloc_free(tmp_ctx);
    361                                 return ret;
     347                        if (func) {
     348                                /* After each and every event loop, reset the
     349                                 * send_to_kdc pointers to what they were when
     350                                 * we entered this loop.  That way, if a
     351                                 * nested event has invalidated them, we put
     352                                 * it back before we return to the heimdal
     353                                 * code */
     354                                ret = krb5_set_send_to_kdc_func(context,
     355                                                                func,
     356                                                                data);
     357                                if (ret != 0) {
     358                                        TALLOC_FREE(frame);
     359                                        return ret;
     360                                }
    362361                        }
    363362                }
     
    383382                ret = krb5_data_copy(recv_buf, smb_krb5->reply.data, smb_krb5->reply.length);
    384383                if (ret) {
    385                         talloc_free(tmp_ctx);
     384                        TALLOC_FREE(frame);
    386385                        return ret;
    387386                }
     
    390389                break;
    391390        }
    392         talloc_free(tmp_ctx);
     391        TALLOC_FREE(frame);
    393392        if (a) {
    394393                return 0;
     
    396395        return KRB5_KDC_UNREACH;
    397396}
     397
     398krb5_error_code smb_krb5_send_and_recv_func(krb5_context context,
     399                                            void *data,
     400                                            krb5_krbhst_info *hi,
     401                                            time_t timeout,
     402                                            const krb5_data *send_buf,
     403                                            krb5_data *recv_buf)
     404{
     405        krb5_error_code ret;
     406        struct addrinfo *ai;
     407
     408        struct tevent_context *ev;
     409        TALLOC_CTX *frame = talloc_stackframe();
     410        if (frame == NULL) {
     411                return ENOMEM;
     412        }
     413
     414        if (data == NULL) {
     415                /* If no event context was available, then create one for this loop */
     416                ev = samba_tevent_context_init(frame);
     417                if (ev == NULL) {
     418                        TALLOC_FREE(frame);
     419                        return ENOMEM;
     420                }
     421        } else {
     422                ev = talloc_get_type_abort(data, struct tevent_context);
     423        }
     424
     425        ret = krb5_krbhst_get_addrinfo(context, hi, &ai);
     426        if (ret) {
     427                TALLOC_FREE(frame);
     428                return ret;
     429        }
     430
     431        ret = smb_krb5_send_and_recv_func_int(context, ev, hi, ai, smb_krb5_send_and_recv_func, data, timeout, send_buf, recv_buf);
     432        TALLOC_FREE(frame);
     433        return ret;
     434}
     435
     436krb5_error_code smb_krb5_send_and_recv_func_forced(krb5_context context,
     437                                                   void *data, /* struct addrinfo */
     438                                                   krb5_krbhst_info *hi,
     439                                                   time_t timeout,
     440                                                   const krb5_data *send_buf,
     441                                                   krb5_data *recv_buf)
     442{
     443        krb5_error_code k5ret;
     444        struct addrinfo *ai = data;
     445
     446        struct tevent_context *ev;
     447        TALLOC_CTX *frame = talloc_stackframe();
     448        if (frame == NULL) {
     449                return ENOMEM;
     450        }
     451
     452        /* no event context is passed in, create one for this loop */
     453        ev = samba_tevent_context_init(frame);
     454        if (ev == NULL) {
     455                TALLOC_FREE(frame);
     456                return ENOMEM;
     457        }
     458
     459        /* No need to pass in send_and_recv functions, we won't nest on this private event loop */
     460        k5ret = smb_krb5_send_and_recv_func_int(context, ev, hi, ai, NULL, NULL,
     461                                                timeout, send_buf, recv_buf);
     462        TALLOC_FREE(frame);
     463        return k5ret;
     464}
     465#endif
    398466
    399467krb5_error_code
     
    403471{
    404472        krb5_error_code ret;
     473#ifdef SAMBA4_USES_HEIMDAL
    405474        char **config_files;
    406475        const char *config_file, *realm;
     476#endif
    407477        krb5_context krb5_ctx;
    408478
     
    416486        }
    417487
    418         config_file = config_path(tmp_ctx, lp_ctx, "krb5.conf");
     488        /* The MIT Kerberos build relies on using the system krb5.conf file.
     489         * If you really want to use another file please set KRB5_CONFIG
     490         * accordingly. */
     491#ifdef SAMBA4_USES_HEIMDAL
     492        config_file = lpcfg_config_path(tmp_ctx, lp_ctx, "krb5.conf");
    419493        if (!config_file) {
    420494                krb5_free_context(krb5_ctx);
     
    423497
    424498        /* Use our local krb5.conf file by default */
    425         ret = krb5_prepend_config_files_default(config_file == NULL?"":config_file, &config_files);
     499        ret = krb5_prepend_config_files_default(config_file, &config_files);
    426500        if (ret) {
    427501                DEBUG(1,("krb5_prepend_config_files_default failed (%s)\n",
     
    450524                }
    451525        }
    452 
     526#endif
    453527        *_krb5_context = krb5_ctx;
    454528        return 0;
     
    456530
    457531krb5_error_code smb_krb5_init_context(void *parent_ctx,
    458                                       struct tevent_context *ev,
    459532                                      struct loadparm_context *lp_ctx,
    460533                                      struct smb_krb5_context **smb_krb5_context)
     
    462535        krb5_error_code ret;
    463536        TALLOC_CTX *tmp_ctx;
     537        krb5_context kctx;
     538#ifdef SAMBA4_USES_HEIMDAL
     539        krb5_log_facility *logf;
     540#endif
    464541
    465542        initialize_krb5_error_table();
     
    473550        }
    474551
    475         ret = smb_krb5_init_context_basic(tmp_ctx, lp_ctx,
    476                                           &(*smb_krb5_context)->krb5_context);
     552        ret = smb_krb5_init_context_basic(tmp_ctx, lp_ctx, &kctx);
    477553        if (ret) {
    478554                DEBUG(1,("smb_krb5_context_init_basic failed (%s)\n",
     
    481557                return ret;
    482558        }
    483 
     559        (*smb_krb5_context)->krb5_context = kctx;
     560
     561        talloc_set_destructor(*smb_krb5_context, smb_krb5_context_destroy);
     562
     563#ifdef SAMBA4_USES_HEIMDAL
    484564        /* TODO: Should we have a different name here? */
    485         ret = krb5_initlog((*smb_krb5_context)->krb5_context, "Samba", &(*smb_krb5_context)->logf);
     565        ret = krb5_initlog(kctx, "Samba", &logf);
    486566
    487567        if (ret) {
    488568                DEBUG(1,("krb5_initlog failed (%s)\n",
    489                          smb_get_krb5_error_message((*smb_krb5_context)->krb5_context, ret, tmp_ctx)));
    490                 krb5_free_context((*smb_krb5_context)->krb5_context);
    491                 talloc_free(tmp_ctx);
    492                 return ret;
    493         }
    494 
    495         talloc_set_destructor(*smb_krb5_context, smb_krb5_context_destroy);
    496 
    497         ret = krb5_addlog_func((*smb_krb5_context)->krb5_context, (*smb_krb5_context)->logf, 0 /* min */, -1 /* max */,
    498                                smb_krb5_debug_wrapper, smb_krb5_debug_close, NULL);
     569                         smb_get_krb5_error_message(kctx, ret, tmp_ctx)));
     570                talloc_free(tmp_ctx);
     571                return ret;
     572        }
     573        (*smb_krb5_context)->pvt_log_data = logf;
     574
     575        ret = krb5_addlog_func(kctx, logf, 0 /* min */, -1 /* max */,
     576                               smb_krb5_debug_wrapper,
     577                                smb_krb5_debug_close, NULL);
    499578        if (ret) {
    500579                DEBUG(1,("krb5_addlog_func failed (%s)\n",
    501                          smb_get_krb5_error_message((*smb_krb5_context)->krb5_context, ret, tmp_ctx)));
    502                 talloc_free(tmp_ctx);
    503                 return ret;
    504         }
    505         krb5_set_warn_dest((*smb_krb5_context)->krb5_context, (*smb_krb5_context)->logf);
    506 
    507         /* Set use of our socket lib */
    508         if (ev) {
    509                 struct tevent_context *previous_ev;
    510                 ret = smb_krb5_context_set_event_ctx(*smb_krb5_context,
    511                                                      ev, &previous_ev);
    512                 if (ret) {
    513                         talloc_free(tmp_ctx);
    514                         return ret;
    515                 }
    516         }
    517 
     580                         smb_get_krb5_error_message(kctx, ret, tmp_ctx)));
     581                talloc_free(tmp_ctx);
     582                return ret;
     583        }
     584        krb5_set_warn_dest(kctx, logf);
     585
     586        /* Set options in kerberos */
     587
     588        krb5_set_dns_canonicalize_hostname(kctx,
     589                        lpcfg_parm_bool(lp_ctx, NULL, "krb5",
     590                                        "set_dns_canonicalize", false));
     591#endif
    518592        talloc_steal(parent_ctx, *smb_krb5_context);
    519593        talloc_free(tmp_ctx);
    520594
    521         /* Set options in kerberos */
    522 
    523         krb5_set_dns_canonicalize_hostname((*smb_krb5_context)->krb5_context,
    524                                            lpcfg_parm_bool(lp_ctx, NULL, "krb5", "set_dns_canonicalize", false));
    525 
    526595        return 0;
    527596}
    528597
     598#ifdef SAMBA4_USES_HEIMDAL
    529599krb5_error_code smb_krb5_context_set_event_ctx(struct smb_krb5_context *smb_krb5_context,
    530600                                               struct tevent_context *ev,
     
    580650        return 0;
    581651}
     652#endif
  • vendor/current/source4/auth/kerberos/krb5_init_context.h

    r740 r988  
    1818*/
    1919
     20#ifndef _KRB5_INIT_CONTEXT_H_
     21#define _KRB5_INIT_CONTEXT_H_
     22
    2023struct smb_krb5_context {
    2124        krb5_context krb5_context;
    22         krb5_log_facility *logf;
     25        void *pvt_log_data;
    2326        struct tevent_context *current_ev;
    2427};
    25        
     28
    2629struct tevent_context;
    2730struct loadparm_context;
     
    3235                            krb5_context *_krb5_context);
    3336
    34 krb5_error_code smb_krb5_init_context(void *parent_ctx, struct tevent_context *ev,
     37krb5_error_code smb_krb5_init_context(void *parent_ctx,
    3538                                      struct loadparm_context *lp_ctx,
    3639                                      struct smb_krb5_context **smb_krb5_context);
    3740
     41#ifdef SAMBA4_USES_HEIMDAL
    3842krb5_error_code smb_krb5_send_and_recv_func(krb5_context context,
    3943                                            void *data,
     
    4246                                            const krb5_data *send_buf,
    4347                                            krb5_data *recv_buf);
     48krb5_error_code smb_krb5_send_and_recv_func_forced(krb5_context context,
     49                                                   void *data, /* struct addrinfo */
     50                                                   krb5_krbhst_info *hi,
     51                                                   time_t timeout,
     52                                                   const krb5_data *send_buf,
     53                                                   krb5_data *recv_buf);
     54krb5_error_code smb_krb5_context_set_event_ctx(struct smb_krb5_context *smb_krb5_context,
     55                                               struct tevent_context *ev,
     56                                               struct tevent_context **previous_ev);
     57krb5_error_code smb_krb5_context_remove_event_ctx(struct smb_krb5_context *smb_krb5_context,
     58                                                  struct tevent_context *previous_ev,
     59                                                  struct tevent_context *ev);
     60#endif
     61
     62#endif /* _KRB5_INIT_CONTEXT_H_ */
  • vendor/current/source4/auth/kerberos/wscript_build

    r740 r988  
    11#!/usr/bin/env python
    22
     3bld.SAMBA_SUBSYSTEM('KRB_INIT_CTX',
     4                    source='krb5_init_context.c',
     5                    deps='gssapi krb5samba'
     6                   )
     7
    38bld.SAMBA_LIBRARY('authkrb5',
    4                   source='kerberos.c clikrb5.c kerberos_heimdal.c kerberos_pac.c gssapi_parse.c krb5_init_context.c keytab_copy.c',
     9                  source='kerberos_pac.c',
    510                  autoproto='proto.h',
    6                   public_deps='krb5 ndr-krb5pac samba_socket LIBCLI_RESOLVE com_err asn1',
    7                   deps='ASN1_UTIL auth_sam_reply tevent LIBPACKET ndr ldb',
     11                  public_deps='ndr-krb5pac krb5samba samba_socket LIBCLI_RESOLVE asn1',
     12                  deps='auth_sam_reply tevent LIBPACKET ndr ldb krb5samba KRB_INIT_CTX KRB5_PAC samba-errors',
    813                  private_library=True
    914                  )
     
    1217        autoproto='kerberos_util.h',
    1318        source='kerberos_util.c',
    14         deps='authkrb5 com_err ldb CREDENTIALS_KRB5 SECRETS',
     19        deps='authkrb5 krb5samba com_err CREDENTIALS_KRB5',
    1520        )
    1621
     22bld.SAMBA_SUBSYSTEM('KERBEROS_SRV_KEYTAB',
     23        autoproto='kerberos_srv_keytab.h',
     24        source='srv_keytab.c',
     25        deps='authkrb5',
     26        )
Note: See TracChangeset for help on using the changeset viewer.