Ignore:
Timestamp:
Nov 27, 2012, 4:43:17 PM (13 years ago)
Author:
Silvan Scherrer
Message:

Samba Server: updated trunk to 3.6.0

Location:
trunk/server
Files:
2 deleted
7 edited
2 copied

Legend:

Unmodified
Added
Removed
  • trunk/server

  • trunk/server/source4/auth/kerberos/kerberos.c

    r414 r745  
    3434  This version is built to use a keyblock, rather than needing the
    3535  original password.
     36
     37  The impersonate_principal is the principal if NULL, or the principal to impersonate
     38
     39  The target_service defaults to the krbtgt if NULL, but could be kpasswd/realm or the local service (if we are doing s4u2self)
    3640*/
    3741 krb5_error_code kerberos_kinit_keyblock_cc(krb5_context ctx, krb5_ccache cc,
    38                                 krb5_principal principal, krb5_keyblock *keyblock,
    39                                 time_t *expire_time, time_t *kdc_time)
     42                                            krb5_principal principal, krb5_keyblock *keyblock,
     43                                            const char *target_service,
     44                                            krb5_get_init_creds_opt *krb_options,
     45                                            time_t *expire_time, time_t *kdc_time)
    4046{
    4147        krb5_error_code code = 0;
    4248        krb5_creds my_creds;
    43         krb5_get_init_creds_opt *options;
    44 
    45         if ((code = krb5_get_init_creds_opt_alloc(ctx, &options))) {
    46                 return code;
    47         }
    48 
    49         krb5_get_init_creds_opt_set_default_flags(ctx, NULL, NULL, options);
    5049
    5150        if ((code = krb5_get_init_creds_keyblock(ctx, &my_creds, principal, keyblock,
    52                                                  0, NULL, options))) {
     51                                                 0, target_service, krb_options))) {
    5352                return code;
    5453        }
    5554       
    5655        if ((code = krb5_cc_initialize(ctx, cc, principal))) {
    57                 krb5_get_init_creds_opt_free(ctx, options);
    5856                krb5_free_cred_contents(ctx, &my_creds);
    5957                return code;
     
    6159       
    6260        if ((code = krb5_cc_store_cred(ctx, cc, &my_creds))) {
    63                 krb5_get_init_creds_opt_free(ctx, options);
    6461                krb5_free_cred_contents(ctx, &my_creds);
    6562                return code;
     
    7471        }
    7572
    76         krb5_get_init_creds_opt_free(ctx, options);
    7773        krb5_free_cred_contents(ctx, &my_creds);
    7874       
     
    8379  simulate a kinit, putting the tgt in the given credentials cache.
    8480  Orignally by remus@snapserver.com
     81
     82  The impersonate_principal is the principal if NULL, or the principal to impersonate
     83
     84  The target_service defaults to the krbtgt if NULL, but could be kpasswd/realm or the local service (if we are doing s4u2self)
     85
    8586*/
    8687 krb5_error_code kerberos_kinit_password_cc(krb5_context ctx, krb5_ccache cc,
    87                                 krb5_principal principal, const char *password,
    88                                 time_t *expire_time, time_t *kdc_time)
     88                                            krb5_principal principal, const char *password,
     89                                            krb5_principal impersonate_principal, const char *target_service,
     90                                            krb5_get_init_creds_opt *krb_options,
     91                                            time_t *expire_time, time_t *kdc_time)
    8992{
    9093        krb5_error_code code = 0;
    9194        krb5_creds my_creds;
    92         krb5_get_init_creds_opt *options;
     95        krb5_creds *impersonate_creds;
     96        krb5_get_creds_opt options;
    9397
    94         if ((code = krb5_get_init_creds_opt_alloc(ctx, &options))) {
     98        /* If we are not impersonating, then get this ticket for the
     99         * target service, otherwise a krbtgt, and get the next ticket
     100         * for the target */
     101        if ((code = krb5_get_init_creds_password(ctx, &my_creds, principal, password,
     102                                                 NULL, NULL,
     103                                                 0,
     104                                                 impersonate_principal ? NULL : target_service,
     105                                                 krb_options))) {
    95106                return code;
    96107        }
    97108
    98         krb5_get_init_creds_opt_set_default_flags(ctx, NULL, NULL, options);
    99 
    100         if ((code = krb5_get_init_creds_password(ctx, &my_creds, principal, password,
    101                                                  NULL,
    102                                                  NULL, 0, NULL, options))) {
    103                 return code;
    104         }
    105        
    106109        if ((code = krb5_cc_initialize(ctx, cc, principal))) {
    107                 krb5_get_init_creds_opt_free(ctx, options);
    108110                krb5_free_cred_contents(ctx, &my_creds);
    109111                return code;
     
    111113       
    112114        if ((code = krb5_cc_store_cred(ctx, cc, &my_creds))) {
    113                 krb5_get_init_creds_opt_free(ctx, options);
    114115                krb5_free_cred_contents(ctx, &my_creds);
    115116                return code;
     
    124125        }
    125126
    126         krb5_get_init_creds_opt_free(ctx, options);
    127127        krb5_free_cred_contents(ctx, &my_creds);
    128128       
     129        if (code == 0 && impersonate_principal) {
     130                krb5_principal target_princ;
     131                if ((code = krb5_get_creds_opt_alloc(ctx, &options))) {
     132                        return code;
     133                }
     134
     135                if ((code = krb5_get_creds_opt_set_impersonate(ctx, options, impersonate_principal))) {
     136                        krb5_get_creds_opt_free(ctx, options);
     137                        return code;
     138                }
     139
     140                if ((code = krb5_parse_name(ctx, target_service, &target_princ))) {
     141                        krb5_get_creds_opt_free(ctx, options);
     142                        return code;
     143                }
     144
     145                if ((code = krb5_principal_set_realm(ctx, target_princ, krb5_principal_get_realm(ctx, principal)))) {
     146                        krb5_get_creds_opt_free(ctx, options);
     147                        krb5_free_principal(ctx, target_princ);
     148                        return code;
     149                }
     150
     151                if ((code = krb5_get_creds(ctx, options, cc, target_princ, &impersonate_creds))) {
     152                        krb5_free_principal(ctx, target_princ);
     153                        krb5_get_creds_opt_free(ctx, options);
     154                        return code;
     155                }
     156
     157                krb5_free_principal(ctx, target_princ);
     158
     159                code = krb5_cc_store_cred(ctx, cc, impersonate_creds);
     160                krb5_get_creds_opt_free(ctx, options);
     161                krb5_free_creds(ctx, impersonate_creds);
     162        }
     163
    129164        return 0;
    130165}
  • trunk/server/source4/auth/kerberos/kerberos.h

    r414 r745  
    2424#include "librpc/gen_ndr/krb5pac.h"
    2525
    26 struct auth_serversupplied_info;
     26struct auth_user_info_dc;
    2727struct cli_credentials;
    2828
     
    5353#define KRB5_KEY_DATA(k)        ((k)->contents)
    5454#endif /* HAVE_KRB5_KEYBLOCK_KEYVALUE */
     55
     56#define ENC_ALL_TYPES (ENC_CRC32 | ENC_RSA_MD5 | ENC_RC4_HMAC_MD5 |     \
     57                       ENC_HMAC_SHA1_96_AES128 | ENC_HMAC_SHA1_96_AES256)
    5558
    5659#ifndef HAVE_KRB5_SET_REAL_TIME
     
    8992                                krb5_data *outbuf);
    9093bool get_auth_data_from_tkt(TALLOC_CTX *mem_ctx, DATA_BLOB *auth_data, krb5_ticket *tkt);
    91 int kerberos_kinit_password_cc(krb5_context ctx, krb5_ccache cc,
    92                                krb5_principal principal, const char *password,
    93                                time_t *expire_time, time_t *kdc_time);
    94 int kerberos_kinit_keyblock_cc(krb5_context ctx, krb5_ccache cc,
    95                                krb5_principal principal, krb5_keyblock *keyblock,
    96                                time_t *expire_time, time_t *kdc_time);
     94krb5_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);
     99krb5_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);
    97104krb5_principal kerberos_fetch_salt_princ_for_host_princ(krb5_context context,
    98105                                                        krb5_principal host_princ,
     
    103110krb5_error_code smb_krb5_kt_free_entry(krb5_context context, krb5_keytab_entry *kt_entry);
    104111char *smb_get_krb5_error_message(krb5_context context, krb5_error_code code, TALLOC_CTX *mem_ctx);
    105  krb5_error_code kinit_to_ccache(TALLOC_CTX *parent_ctx,
    106                           struct cli_credentials *credentials,
    107                           struct smb_krb5_context *smb_krb5_context,
    108                                  krb5_ccache ccache);
    109 krb5_error_code principal_from_credentials(TALLOC_CTX *parent_ctx,
    110                                            struct cli_credentials *credentials,
    111                                            struct smb_krb5_context *smb_krb5_context,
    112                                            krb5_principal *princ);
    113112NTSTATUS kerberos_decode_pac(TALLOC_CTX *mem_ctx,
    114                              struct smb_iconv_convenience *iconv_convenience,
    115113                             struct PAC_DATA **pac_data_out,
    116114                             DATA_BLOB blob,
     
    122120                             krb5_error_code *k5ret);
    123121 NTSTATUS kerberos_pac_logon_info(TALLOC_CTX *mem_ctx,
    124                                   struct smb_iconv_convenience *iconv_convenience,
    125122                                  struct PAC_LOGON_INFO **logon_info,
    126123                                  DATA_BLOB blob,
     
    132129                                  krb5_error_code *k5ret);
    133130 krb5_error_code kerberos_encode_pac(TALLOC_CTX *mem_ctx,
    134                                      struct smb_iconv_convenience *iconv_convenience,
    135131                                    struct PAC_DATA *pac_data,
    136132                                    krb5_context context,
     
    139135                                    DATA_BLOB *pac);
    140136 krb5_error_code kerberos_create_pac(TALLOC_CTX *mem_ctx,
    141                                      struct smb_iconv_convenience *iconv_convenience,
    142                                      struct auth_serversupplied_info *server_info,
     137                                     struct auth_user_info_dc *user_info_dc,
    143138                                     krb5_context context,
    144139                                     const krb5_keyblock *krbtgt_keyblock,
     
    148143                                     DATA_BLOB *pac);
    149144struct loadparm_context;
     145struct ldb_message;
     146struct ldb_context;
     147uint32_t kerberos_enctype_to_bitmap(krb5_enctype enc_type_enum);
     148/* Translate between the Microsoft msDS-SupportedEncryptionTypes values and the IETF encryption type values */
     149krb5_enctype kerberos_enctype_bitmap_to_enctype(uint32_t enctype_bitmap);
     150krb5_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);
    150156
    151157#include "auth/kerberos/proto.h"
  • trunk/server/source4/auth/kerberos/kerberos_pac.c

    r414 r745  
    1 /* 
     1/*
    22   Unix SMB/CIFS implementation.
    33
    44   Create and parse the krb5 PAC
    5    
     5
    66   Copyright (C) Andrew Bartlett <abartlet@samba.org> 2004-2005,2008
    77   Copyright (C) Andrew Tridgell 2001
     
    1313   the Free Software Foundation; either version 3 of the License, or
    1414   (at your option) any later version.
    15    
     15
    1616   This program is distributed in the hope that it will be useful,
    1717   but WITHOUT ANY WARRANTY; without even the implied warranty of
     
    1919   GNU General Public License for more details.
    2020
    21    
     21
    2222   You should have received a copy of the GNU General Public License
    2323   along with this program.  If not, see <http://www.gnu.org/licenses/>.
     
    2929#include "auth/kerberos/kerberos.h"
    3030#include "librpc/gen_ndr/ndr_krb5pac.h"
    31 #include "lib/ldb/include/ldb.h"
     31#include <ldb.h>
    3232#include "auth/auth_sam_reply.h"
    3333
    34 krb5_error_code check_pac_checksum(TALLOC_CTX *mem_ctx, 
     34krb5_error_code check_pac_checksum(TALLOC_CTX *mem_ctx,
    3535                                   DATA_BLOB pac_data,
    3636                                   struct PAC_SIGNATURE_DATA *sig,
     
    5151                               &crypto);
    5252        if (ret) {
    53                 DEBUG(0,("krb5_crypto_init() failed: %s\n", 
     53                DEBUG(0,("krb5_crypto_init() failed: %s\n",
    5454                          smb_get_krb5_error_message(context, ret, mem_ctx)));
    5555                return ret;
     
    6767
    6868 NTSTATUS kerberos_decode_pac(TALLOC_CTX *mem_ctx,
    69                               struct smb_iconv_convenience *iconv_convenience,
    7069                              struct PAC_DATA **pac_data_out,
    7170                              DATA_BLOB blob,
     
    9594        NTTIME tgs_authtime_nttime;
    9695        krb5_principal client_principal_pac;
    97         int i;
     96        uint32_t i;
    9897
    9998        krb5_clear_error_message(context);
     
    114113        }
    115114
    116         ndr_err = ndr_pull_struct_blob(&blob, pac_data,
    117                         iconv_convenience, pac_data,
    118                        (ndr_pull_flags_fn_t)ndr_pull_PAC_DATA);
     115        ndr_err = ndr_pull_struct_blob(&blob, pac_data,
     116                        pac_data, (ndr_pull_flags_fn_t)ndr_pull_PAC_DATA);
    119117        if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
    120118                status = ndr_map_error2ntstatus(ndr_err);
     
    130128        }
    131129
    132         ndr_err = ndr_pull_struct_blob(&blob, pac_data_raw, 
    133                                        iconv_convenience, pac_data_raw,
     130        ndr_err = ndr_pull_struct_blob(&blob, pac_data_raw,
     131                                       pac_data_raw,
    134132                                       (ndr_pull_flags_fn_t)ndr_pull_PAC_DATA_RAW);
    135133        if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
     
    211209
    212210        /* We find the data blobs above, now we parse them to get at the exact portion we should zero */
    213         ndr_err = ndr_pull_struct_blob(kdc_sig_blob, kdc_sig_wipe, 
    214                                        iconv_convenience, kdc_sig_wipe,
     211        ndr_err = ndr_pull_struct_blob(kdc_sig_blob, kdc_sig_wipe,
     212                                       kdc_sig_wipe,
    215213                                       (ndr_pull_flags_fn_t)ndr_pull_PAC_SIGNATURE_DATA);
    216214        if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
     
    220218                return status;
    221219        }
    222        
    223         ndr_err = ndr_pull_struct_blob(srv_sig_blob, srv_sig_wipe, 
    224                                        iconv_convenience, srv_sig_wipe,
     220
     221        ndr_err = ndr_pull_struct_blob(srv_sig_blob, srv_sig_wipe,
     222                                       srv_sig_wipe,
    225223                                       (ndr_pull_flags_fn_t)ndr_pull_PAC_SIGNATURE_DATA);
    226224        if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
     
    234232        memset(kdc_sig_wipe->signature.data, '\0', kdc_sig_wipe->signature.length);
    235233        memset(srv_sig_wipe->signature.data, '\0', srv_sig_wipe->signature.length);
    236        
     234
    237235        /* and reencode, back into the same place it came from */
    238         ndr_err = ndr_push_struct_blob(kdc_sig_blob, pac_data_raw,
    239                                        iconv_convenience,
     236        ndr_err = ndr_push_struct_blob(kdc_sig_blob, pac_data_raw,
    240237                                       kdc_sig_wipe,
    241238                                       (ndr_push_flags_fn_t)ndr_push_PAC_SIGNATURE_DATA);
     
    246243                return status;
    247244        }
    248         ndr_err = ndr_push_struct_blob(srv_sig_blob, pac_data_raw,
    249                                        iconv_convenience,
     245        ndr_err = ndr_push_struct_blob(srv_sig_blob, pac_data_raw,
    250246                                       srv_sig_wipe,
    251247                                       (ndr_push_flags_fn_t)ndr_push_PAC_SIGNATURE_DATA);
     
    258254
    259255        /* push out the whole structure, but now with zero'ed signatures */
    260         ndr_err = ndr_push_struct_blob(&modified_pac_blob, pac_data_raw,
    261                                        iconv_convenience,
     256        ndr_err = ndr_push_struct_blob(&modified_pac_blob, pac_data_raw,
    262257                                       pac_data_raw,
    263258                                       (ndr_push_flags_fn_t)ndr_push_PAC_DATA_RAW);
     
    270265
    271266        /* verify by service_key */
    272         ret = check_pac_checksum(mem_ctx, 
    273                                  modified_pac_blob, srv_sig_ptr, 
    274                                  context, 
     267        ret = check_pac_checksum(mem_ctx,
     268                                 modified_pac_blob, srv_sig_ptr,
     269                                 context,
    275270                                 service_keyblock);
    276271        if (ret) {
     
    284279
    285280        if (krbtgt_keyblock) {
    286                 ret = check_pac_checksum(mem_ctx, 
    287                                             srv_sig_ptr->signature, kdc_sig_ptr, 
     281                ret = check_pac_checksum(mem_ctx,
     282                                            srv_sig_ptr->signature, kdc_sig_ptr,
    288283                                            context, krbtgt_keyblock);
    289284                if (ret) {
     
    307302        }
    308303
    309         ret = krb5_parse_name_flags(context, logon_name->account_name, KRB5_PRINCIPAL_PARSE_NO_REALM, 
     304        ret = krb5_parse_name_flags(context, logon_name->account_name, KRB5_PRINCIPAL_PARSE_NO_REALM,
    310305                                    &client_principal_pac);
    311306        if (ret) {
    312                 DEBUG(2, ("Could not parse name from incoming PAC: [%s]: %s\n", 
    313                           logon_name->account_name, 
     307                DEBUG(2, ("Could not parse name from incoming PAC: [%s]: %s\n",
     308                          logon_name->account_name,
    314309                          smb_get_krb5_error_message(context, ret, mem_ctx)));
    315310                if (k5ret) {
     
    320315
    321316        if (!krb5_principal_compare_any_realm(context, client_principal, client_principal_pac)) {
    322                 DEBUG(2, ("Name in PAC [%s] does not match principal name in ticket\n", 
     317                DEBUG(2, ("Name in PAC [%s] does not match principal name in ticket\n",
    323318                          logon_name->account_name));
     319                krb5_free_principal(context, client_principal_pac);
    324320                return NT_STATUS_ACCESS_DENIED;
    325321        }
    326        
     322
     323        krb5_free_principal(context, client_principal_pac);
     324
    327325#if 0
    328         if (strcasecmp(logon_info->info3.base.account_name.string, 
     326        if (strcasecmp(logon_info->info3.base.account_name.string,
    329327                       "Administrator")== 0) {
    330328                file_save("tmp_pac_data-admin.dat",blob.data,blob.length);
     
    333331
    334332        DEBUG(3,("Found account name from PAC: %s [%s]\n",
    335                  logon_info->info3.base.account_name.string, 
     333                 logon_info->info3.base.account_name.string,
    336334                 logon_info->info3.base.full_name.string));
    337335        *pac_data_out = pac_data;
     
    341339
    342340_PUBLIC_  NTSTATUS kerberos_pac_logon_info(TALLOC_CTX *mem_ctx,
    343                                   struct smb_iconv_convenience *iconv_convenience,
    344341                                  struct PAC_LOGON_INFO **logon_info,
    345342                                  DATA_BLOB blob,
     
    348345                                  const krb5_keyblock *service_keyblock,
    349346                                  krb5_const_principal client_principal,
    350                                   time_t tgs_authtime, 
     347                                  time_t tgs_authtime,
    351348                                  krb5_error_code *k5ret)
    352349{
     
    354351        struct PAC_DATA *pac_data;
    355352        int i;
    356         nt_status = kerberos_decode_pac(mem_ctx,
    357                                         iconv_convenience,
     353        nt_status = kerberos_decode_pac(mem_ctx,
    358354                                        &pac_data,
    359355                                        blob,
     
    361357                                        krbtgt_keyblock,
    362358                                        service_keyblock,
    363                                         client_principal, 
     359                                        client_principal,
    364360                                        tgs_authtime,
    365361                                        k5ret);
     
    373369                        continue;
    374370                }
    375                 *logon_info = pac_data->buffers[i].info->logon_info.info; 
     371                *logon_info = pac_data->buffers[i].info->logon_info.info;
    376372        }
    377373        if (!*logon_info) {
     
    381377}
    382378
    383 static krb5_error_code make_pac_checksum(TALLOC_CTX *mem_ctx, 
     379static krb5_error_code make_pac_checksum(TALLOC_CTX *mem_ctx,
    384380                                         DATA_BLOB *pac_data,
    385381                                         struct PAC_SIGNATURE_DATA *sig,
     
    409405                                   &cksum);
    410406        if (ret) {
    411                 DEBUG(2, ("PAC Verification failed: %s\n", 
     407                DEBUG(2, ("PAC Verification failed: %s\n",
    412408                          smb_get_krb5_error_message(context, ret, mem_ctx)));
    413409        }
     
    427423
    428424 krb5_error_code kerberos_encode_pac(TALLOC_CTX *mem_ctx,
    429                                      struct smb_iconv_convenience *iconv_convenience,
    430425                                    struct PAC_DATA *pac_data,
    431426                                    krb5_context context,
    432427                                    const krb5_keyblock *krbtgt_keyblock,
    433428                                    const krb5_keyblock *service_keyblock,
    434                                     DATA_BLOB *pac) 
     429                                    DATA_BLOB *pac)
    435430{
    436431        NTSTATUS nt_status;
     
    448443                        continue;
    449444                }
    450                 kdc_checksum = &pac_data->buffers[i].info->kdc_cksum, 
     445                kdc_checksum = &pac_data->buffers[i].info->kdc_cksum,
    451446                ret = make_pac_checksum(mem_ctx, &zero_blob,
    452                                         kdc_checksum, 
     447                                        kdc_checksum,
    453448                                        context, krbtgt_keyblock);
    454449                if (ret) {
    455                         DEBUG(2, ("making krbtgt PAC checksum failed: %s\n", 
     450                        DEBUG(2, ("making krbtgt PAC checksum failed: %s\n",
    456451                                  smb_get_krb5_error_message(context, ret, mem_ctx)));
    457452                        talloc_free(pac_data);
     
    459454                }
    460455        }
    461        
     456
    462457        for (i=0; i < pac_data->num_buffers; i++) {
    463458                if (pac_data->buffers[i].type != PAC_TYPE_SRV_CHECKSUM) {
    464459                        continue;
    465460                }
    466                 srv_checksum = &pac_data->buffers[i].info->srv_cksum; 
    467                 ret = make_pac_checksum(mem_ctx, &zero_blob, 
    468                                         srv_checksum, 
     461                srv_checksum = &pac_data->buffers[i].info->srv_cksum;
     462                ret = make_pac_checksum(mem_ctx, &zero_blob,
     463                                        srv_checksum,
    469464                                        context, service_keyblock);
    470465                if (ret) {
    471                         DEBUG(2, ("making service PAC checksum failed: %s\n", 
     466                        DEBUG(2, ("making service PAC checksum failed: %s\n",
    472467                                  smb_get_krb5_error_message(context, ret, mem_ctx)));
    473468                        talloc_free(pac_data);
     
    489484        memset(srv_checksum->signature.data, '\0', srv_checksum->signature.length);
    490485
    491         ndr_err = ndr_push_struct_blob(&tmp_blob, mem_ctx,
    492                                        iconv_convenience,
     486        ndr_err = ndr_push_struct_blob(&tmp_blob, mem_ctx,
    493487                                       pac_data,
    494488                                       (ndr_push_flags_fn_t)ndr_push_PAC_DATA);
     
    507501        ret = make_pac_checksum(mem_ctx, &srv_checksum->signature, kdc_checksum, context, krbtgt_keyblock);
    508502        if (ret) {
    509                 DEBUG(2, ("making krbtgt PAC checksum failed: %s\n", 
     503                DEBUG(2, ("making krbtgt PAC checksum failed: %s\n",
    510504                          smb_get_krb5_error_message(context, ret, mem_ctx)));
    511505                talloc_free(pac_data);
     
    514508
    515509        /* And push it out again, this time to the world.  This relies on determanistic pointer values */
    516         ndr_err = ndr_push_struct_blob(&tmp_blob, mem_ctx,
    517                                        iconv_convenience,
     510        ndr_err = ndr_push_struct_blob(&tmp_blob, mem_ctx,
    518511                                       pac_data,
    519512                                       (ndr_push_flags_fn_t)ndr_push_PAC_DATA);
     
    532525
    533526 krb5_error_code kerberos_create_pac(TALLOC_CTX *mem_ctx,
    534                                      struct smb_iconv_convenience *iconv_convenience,
    535                                      struct auth_serversupplied_info *server_info,
     527                                     struct auth_user_info_dc *user_info_dc,
    536528                                     krb5_context context,
    537529                                     const krb5_keyblock *krbtgt_keyblock,
     
    553545
    554546        char *name;
    555                
     547
    556548        enum {
    557549                PAC_BUF_LOGON_INFO = 0,
     
    569561        pac_data->version = 0;
    570562
    571         pac_data->buffers = talloc_array(pac_data, 
     563        pac_data->buffers = talloc_array(pac_data,
    572564                                         struct PAC_BUFFER,
    573565                                         pac_data->num_buffers);
     
    621613                return ENOMEM;
    622614        }
    623         nt_status = auth_convert_server_info_saminfo3(LOGON_INFO, server_info, &sam3);
     615        nt_status = auth_convert_user_info_dc_saminfo3(LOGON_INFO, user_info_dc, &sam3);
    624616        if (!NT_STATUS_IS_OK(nt_status)) {
    625617                DEBUG(1, ("Getting Samba info failed: %s\n", nt_errstr(nt_status)));
     
    631623        LOGON_INFO->info3 = *sam3;
    632624
    633         ret = krb5_unparse_name_flags(context, client_principal, 
     625        ret = krb5_unparse_name_flags(context, client_principal,
    634626                                      KRB5_PRINCIPAL_UNPARSE_NO_REALM, &name);
    635627        if (ret) {
     
    644636        unix_to_nt_time(&LOGON_NAME->logon_time, tgs_authtime);
    645637
    646         ret = kerberos_encode_pac(mem_ctx,
    647                                   iconv_convenience,
    648                                   pac_data,
     638        ret = kerberos_encode_pac(mem_ctx,
     639                                  pac_data,
    649640                                  context,
    650641                                  krbtgt_keyblock,
     
    655646}
    656647
    657 krb5_error_code kerberos_pac_to_server_info(TALLOC_CTX *mem_ctx,
    658                                                 struct smb_iconv_convenience *iconv_convenience,
    659                                                 krb5_pac pac,
    660                                                 krb5_context context,
    661                                                 struct auth_serversupplied_info **server_info)
     648krb5_error_code kerberos_pac_to_user_info_dc(TALLOC_CTX *mem_ctx,
     649                                             krb5_pac pac,
     650                                             krb5_context context,
     651                                             struct auth_user_info_dc **user_info_dc,
     652                                             struct PAC_SIGNATURE_DATA *pac_srv_sig,
     653                                             struct PAC_SIGNATURE_DATA *pac_kdc_sig)
    662654{
    663655        NTSTATUS nt_status;
     
    669661
    670662        union PAC_INFO info;
    671         union netr_Validation validation;
    672         struct auth_serversupplied_info *server_info_out;
     663        struct auth_user_info_dc *user_info_dc_out;
    673664
    674665        TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
     
    686677        pac_logon_info_in = data_blob_const(k5pac_logon_info_in.data, k5pac_logon_info_in.length);
    687678
    688         ndr_err = ndr_pull_union_blob(&pac_logon_info_in, tmp_ctx, iconv_convenience, &info,
     679        ndr_err = ndr_pull_union_blob(&pac_logon_info_in, tmp_ctx, &info,
    689680                                      PAC_TYPE_LOGON_INFO,
    690681                                      (ndr_pull_flags_fn_t)ndr_pull_PAC_INFO);
     
    698689
    699690        /* Pull this right into the normal auth sysstem structures */
    700         validation.sam3 = &info.logon_info.info->info3;
    701         nt_status = make_server_info_netlogon_validation(mem_ctx,
    702                                                          "",
    703                                                          3, &validation,
    704                                                          &server_info_out);
     691        nt_status = make_user_info_dc_pac(mem_ctx,
     692                                         info.logon_info.info,
     693                                         &user_info_dc_out);
    705694        if (!NT_STATUS_IS_OK(nt_status)) {
    706695                talloc_free(tmp_ctx);
    707696                return EINVAL;
    708697        }
    709        
    710         ret = krb5_pac_get_buffer(context, pac, PAC_TYPE_SRV_CHECKSUM, &k5pac_srv_checksum_in);
    711         if (ret != 0) {
    712                 talloc_free(tmp_ctx);
    713                 return ret;
    714         }
    715 
    716         pac_srv_checksum_in = data_blob_const(k5pac_srv_checksum_in.data, k5pac_srv_checksum_in.length);
    717                
    718         ndr_err = ndr_pull_struct_blob(&pac_srv_checksum_in, server_info_out,
    719                                        iconv_convenience, &server_info_out->pac_srv_sig,
    720                                        (ndr_pull_flags_fn_t)ndr_pull_PAC_SIGNATURE_DATA);
    721         krb5_data_free(&k5pac_srv_checksum_in);
    722         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
    723                 nt_status = ndr_map_error2ntstatus(ndr_err);
    724                 DEBUG(0,("can't parse the KDC signature: %s\n",
    725                         nt_errstr(nt_status)));
    726                 return EINVAL;
    727         }
    728 
    729         ret = krb5_pac_get_buffer(context, pac, PAC_TYPE_KDC_CHECKSUM, &k5pac_kdc_checksum_in);
    730         if (ret != 0) {
    731                 talloc_free(tmp_ctx);
    732                 return ret;
    733         }
    734 
    735         pac_kdc_checksum_in = data_blob_const(k5pac_kdc_checksum_in.data, k5pac_kdc_checksum_in.length);
    736                
    737         ndr_err = ndr_pull_struct_blob(&pac_kdc_checksum_in, server_info_out,
    738                                        iconv_convenience, &server_info_out->pac_kdc_sig,
    739                                        (ndr_pull_flags_fn_t)ndr_pull_PAC_SIGNATURE_DATA);
    740         krb5_data_free(&k5pac_kdc_checksum_in);
    741         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
    742                 nt_status = ndr_map_error2ntstatus(ndr_err);
    743                 DEBUG(0,("can't parse the KDC signature: %s\n",
    744                         nt_errstr(nt_status)));
    745                 return EINVAL;
    746         }
    747 
    748         *server_info = server_info_out;
    749        
     698
     699        if (pac_srv_sig) {
     700                ret = krb5_pac_get_buffer(context, pac, PAC_TYPE_SRV_CHECKSUM, &k5pac_srv_checksum_in);
     701                if (ret != 0) {
     702                        talloc_free(tmp_ctx);
     703                        return ret;
     704                }
     705
     706                pac_srv_checksum_in = data_blob_const(k5pac_srv_checksum_in.data, k5pac_srv_checksum_in.length);
     707
     708                ndr_err = ndr_pull_struct_blob(&pac_srv_checksum_in, pac_srv_sig,
     709                                               pac_srv_sig,
     710                                               (ndr_pull_flags_fn_t)ndr_pull_PAC_SIGNATURE_DATA);
     711                krb5_data_free(&k5pac_srv_checksum_in);
     712                if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
     713                        nt_status = ndr_map_error2ntstatus(ndr_err);
     714                        DEBUG(0,("can't parse the KDC signature: %s\n",
     715                                 nt_errstr(nt_status)));
     716                        return EINVAL;
     717                }
     718        }
     719
     720        if (pac_kdc_sig) {
     721                ret = krb5_pac_get_buffer(context, pac, PAC_TYPE_KDC_CHECKSUM, &k5pac_kdc_checksum_in);
     722                if (ret != 0) {
     723                        talloc_free(tmp_ctx);
     724                        return ret;
     725                }
     726
     727                pac_kdc_checksum_in = data_blob_const(k5pac_kdc_checksum_in.data, k5pac_kdc_checksum_in.length);
     728
     729                ndr_err = ndr_pull_struct_blob(&pac_kdc_checksum_in, pac_kdc_sig,
     730                                               pac_kdc_sig,
     731                                               (ndr_pull_flags_fn_t)ndr_pull_PAC_SIGNATURE_DATA);
     732                krb5_data_free(&k5pac_kdc_checksum_in);
     733                if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
     734                        nt_status = ndr_map_error2ntstatus(ndr_err);
     735                        DEBUG(0,("can't parse the KDC signature: %s\n",
     736                                 nt_errstr(nt_status)));
     737                        return EINVAL;
     738                }
     739        }
     740        *user_info_dc = user_info_dc_out;
     741
    750742        return 0;
    751743}
    752744
    753745
    754 NTSTATUS kerberos_pac_blob_to_server_info(TALLOC_CTX *mem_ctx,
    755                                                      struct smb_iconv_convenience *iconv_convenience,
    756                                                      DATA_BLOB pac_blob,
    757                                                      krb5_context context,
    758                                                      struct auth_serversupplied_info **server_info)
     746NTSTATUS kerberos_pac_blob_to_user_info_dc(TALLOC_CTX *mem_ctx,
     747                                           DATA_BLOB pac_blob,
     748                                           krb5_context context,
     749                                           struct auth_user_info_dc **user_info_dc,
     750                                           struct PAC_SIGNATURE_DATA *pac_srv_sig,
     751                                           struct PAC_SIGNATURE_DATA *pac_kdc_sig)
    759752{
    760753        krb5_error_code ret;
    761754        krb5_pac pac;
    762         ret = krb5_pac_parse(context, 
    763                              pac_blob.data, pac_blob.length, 
     755        ret = krb5_pac_parse(context,
     756                             pac_blob.data, pac_blob.length,
    764757                             &pac);
    765758        if (ret) {
     
    768761
    769762
    770         ret = kerberos_pac_to_server_info(mem_ctx, iconv_convenience, pac, context, server_info);
     763        ret = kerberos_pac_to_user_info_dc(mem_ctx, pac, context, user_info_dc, pac_srv_sig, pac_kdc_sig);
    771764        krb5_pac_free(context, pac);
    772765        if (ret) {
  • trunk/server/source4/auth/kerberos/kerberos_util.c

    r414 r745  
    2727#include "auth/credentials/credentials_proto.h"
    2828#include "auth/credentials/credentials_krb5.h"
     29#include "auth/kerberos/kerberos_credentials.h"
     30#include "auth/kerberos/kerberos_util.h"
     31#include <ldb.h>
     32#include "param/secrets.h"
    2933
    3034struct principal_container {
    3135        struct smb_krb5_context *smb_krb5_context;
    3236        krb5_principal principal;
     37        const char *string_form; /* Optional */
    3338};
    3439
     
    4146}
    4247
    43 static krb5_error_code salt_principal_from_credentials(TALLOC_CTX *parent_ctx,
    44                                                        struct cli_credentials *machine_account,
    45                                                        struct smb_krb5_context *smb_krb5_context,
    46                                                        krb5_principal *salt_princ)
    47 {
     48
     49static krb5_error_code parse_principal(TALLOC_CTX *parent_ctx,
     50                                       const char *princ_string,
     51                                       struct smb_krb5_context *smb_krb5_context,
     52                                       krb5_principal *princ,
     53                                       const char **error_string)
     54{
     55        int ret;
     56        struct principal_container *mem_ctx;
     57        if (princ_string == NULL) {
     58                 *princ = NULL;
     59                 return 0;
     60        }
     61
     62        ret = krb5_parse_name(smb_krb5_context->krb5_context,
     63                              princ_string, princ);
     64
     65        if (ret) {
     66                (*error_string) = smb_get_krb5_error_message(smb_krb5_context->krb5_context, ret, parent_ctx);
     67                return ret;
     68        }
     69
     70        mem_ctx = talloc(parent_ctx, struct principal_container);
     71        if (!mem_ctx) {
     72                (*error_string) = error_message(ENOMEM);
     73                return ENOMEM;
     74        }
     75
     76        /* This song-and-dance effectivly puts the principal
     77         * into talloc, so we can't loose it. */
     78        mem_ctx->smb_krb5_context = talloc_reference(mem_ctx, smb_krb5_context);
     79        mem_ctx->principal = *princ;
     80        talloc_set_destructor(mem_ctx, free_principal);
     81        return 0;
     82}
     83
     84static 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;
    4891        krb5_error_code ret;
    49         char *machine_username;
    50         char *salt_body;
    51         char *lower_realm;
    52         const char *salt_principal;
    53         struct principal_container *mem_ctx = talloc(parent_ctx, struct principal_container);
    54         if (!mem_ctx) {
    55                 return ENOMEM;
    56         }
    57 
    58         salt_principal = cli_credentials_get_salt_principal(machine_account);
     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
     189static 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);
    59198        if (salt_principal) {
    60                 ret = krb5_parse_name(smb_krb5_context->krb5_context, salt_principal, salt_princ);
    61         } else {
    62                 machine_username = talloc_strdup(mem_ctx, cli_credentials_get_username(machine_account));
    63                
     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);
    64227                if (!machine_username) {
    65228                        talloc_free(mem_ctx);
     229                        *error_string = "Cannot duplicate samAccountName";
    66230                        return ENOMEM;
    67231                }
     
    70234                        machine_username[strlen(machine_username)-1] = '\0';
    71235                }
    72                 lower_realm = strlower_talloc(mem_ctx, cli_credentials_get_realm(machine_account));
     236
     237                lower_realm = strlower_talloc(tmp_ctx, realm);
    73238                if (!lower_realm) {
    74239                        talloc_free(mem_ctx);
     240                        *error_string = "Cannot allocate to lower case realm";
    75241                        return ENOMEM;
    76242                }
    77243               
    78                 salt_body = talloc_asprintf(mem_ctx, "%s.%s", machine_username,
     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,
    79252                                            lower_realm);
     253                talloc_free(lower_realm);
     254                talloc_free(machine_username);
    80255                if (!salt_body) {
    81256                        talloc_free(mem_ctx);
    82                 return ENOMEM;
     257                        *error_string = "Cannot form salt principal body";
     258                        return ENOMEM;
    83259                }
    84260               
    85261                ret = krb5_make_principal(smb_krb5_context->krb5_context, salt_princ,
    86                                           cli_credentials_get_realm(machine_account),
     262                                          upper_realm,
    87263                                          "host", salt_body, NULL);
    88         }
    89 
    90         if (ret == 0) {
    91                 /* This song-and-dance effectivly puts the principal
    92                  * into talloc, so we can't loose it. */
    93                 mem_ctx->smb_krb5_context = talloc_reference(mem_ctx, smb_krb5_context);
    94                 mem_ctx->principal = *salt_princ;
    95                 talloc_set_destructor(mem_ctx, free_principal);
    96         }
    97         return ret;
     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        }
    98279}
    99280
     
    103284 * system by means of a destructor (do *not* free). */
    104285
    105  krb5_error_code principal_from_credentials(TALLOC_CTX *parent_ctx,
     286krb5_error_code principal_from_credentials(TALLOC_CTX *parent_ctx,
    106287                                            struct cli_credentials *credentials,
    107288                                            struct smb_krb5_context *smb_krb5_context,
    108                                             krb5_principal *princ)
     289                                            krb5_principal *princ,
     290                                            enum credentials_obtained *obtained,
     291                                            const char **error_string)
    109292{
    110293        krb5_error_code ret;
    111294        const char *princ_string;
    112         struct principal_container *mem_ctx = talloc(parent_ctx, struct principal_container);
     295        TALLOC_CTX *mem_ctx = talloc_new(parent_ctx);
    113296        if (!mem_ctx) {
    114                 return ENOMEM;
    115         }
    116        
    117         princ_string = cli_credentials_get_principal(credentials, mem_ctx);
    118 
    119         /* A NULL here has meaning, as the gssapi server case will
    120          * then use the principal from the client */
     297                (*error_string) = error_message(ENOMEM);
     298                return ENOMEM;
     299        }
     300        princ_string = cli_credentials_get_principal_and_obtained(credentials, mem_ctx, obtained);
    121301        if (!princ_string) {
    122                 talloc_free(mem_ctx);
    123                 princ = NULL;
    124                 return 0;
    125         }
    126 
    127         ret = krb5_parse_name(smb_krb5_context->krb5_context,
    128                               princ_string, princ);
    129 
    130         if (ret == 0) {
    131                 /* This song-and-dance effectivly puts the principal
    132                  * into talloc, so we can't loose it. */
    133                 mem_ctx->smb_krb5_context = talloc_reference(mem_ctx, smb_krb5_context);
    134                 mem_ctx->principal = *princ;
    135                 talloc_set_destructor(mem_ctx, free_principal);
    136         }
     302                (*error_string) = error_message(ENOMEM);
     303                return ENOMEM;
     304        }
     305
     306        ret = parse_principal(parent_ctx, princ_string,
     307                              smb_krb5_context, princ, error_string);
     308        talloc_free(mem_ctx);
    137309        return ret;
     310}
     311
     312/* Obtain the principal set on this context.  Requires a
     313 * smb_krb5_context because we are doing krb5 principal parsing with
     314 * the library routines.  The returned princ is placed in the talloc
     315 * system by means of a destructor (do *not* free). */
     316
     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);
    138325}
    139326
     
    146333                                 struct cli_credentials *credentials,
    147334                                 struct smb_krb5_context *smb_krb5_context,
    148                                  krb5_ccache ccache)
     335                                 struct tevent_context *event_ctx,
     336                                 krb5_ccache ccache,
     337                                 enum credentials_obtained *obtained,
     338                                 const char **error_string)
    149339{
    150340        krb5_error_code ret;
    151         const char *password;
     341        const char *password, *target_service;
    152342        time_t kdc_time = 0;
    153343        krb5_principal princ;
     344        krb5_principal impersonate_principal;
    154345        int tries;
    155346        TALLOC_CTX *mem_ctx = talloc_new(parent_ctx);
     347        krb5_get_init_creds_opt *krb_options;
    156348
    157349        if (!mem_ctx) {
    158                 return ENOMEM;
    159         }
    160 
    161         ret = principal_from_credentials(mem_ctx, credentials, smb_krb5_context, &princ);
     350                (*error_string) = strerror(ENOMEM);
     351                return ENOMEM;
     352        }
     353
     354        ret = principal_from_credentials(mem_ctx, credentials, smb_krb5_context, &princ, obtained, error_string);
    162355        if (ret) {
    163356                talloc_free(mem_ctx);
     
    165358        }
    166359
     360        ret = impersonate_principal_from_credentials(mem_ctx, credentials, smb_krb5_context, &impersonate_principal, error_string);
     361        if (ret) {
     362                talloc_free(mem_ctx);
     363                return ret;
     364        }
     365
     366        target_service = cli_credentials_get_target_service(credentials);
     367
    167368        password = cli_credentials_get_password(credentials);
     369
     370        /* setup the krb5 options we want */
     371        if ((ret = krb5_get_init_creds_opt_alloc(smb_krb5_context->krb5_context, &krb_options))) {
     372                (*error_string) = talloc_asprintf(credentials, "krb5_get_init_creds_opt_alloc failed (%s)\n",
     373                                                  smb_get_krb5_error_message(smb_krb5_context->krb5_context,
     374                                                                             ret, mem_ctx));
     375                talloc_free(mem_ctx);
     376                return ret;
     377        }
     378
     379        /* get the defaults */
     380        krb5_get_init_creds_opt_set_default_flags(smb_krb5_context->krb5_context, NULL, NULL, krb_options);
     381
     382        /* set if we want a forwardable ticket */
     383        switch (cli_credentials_get_krb_forwardable(credentials)) {
     384        case CRED_AUTO_KRB_FORWARDABLE:
     385                break;
     386        case CRED_NO_KRB_FORWARDABLE:
     387                krb5_get_init_creds_opt_set_forwardable(krb_options, FALSE);
     388                break;
     389        case CRED_FORCE_KRB_FORWARDABLE:
     390                krb5_get_init_creds_opt_set_forwardable(krb_options, TRUE);
     391                break;
     392        }
    168393
    169394        tries = 2;
    170395        while (tries--) {
     396                struct tevent_context *previous_ev;
     397                /* Do this every time, in case we have weird recursive issues here */
     398                ret = smb_krb5_context_set_event_ctx(smb_krb5_context, event_ctx, &previous_ev);
     399                if (ret) {
     400                        talloc_free(mem_ctx);
     401                        return ret;
     402                }
    171403                if (password) {
    172404                        ret = kerberos_kinit_password_cc(smb_krb5_context->krb5_context, ccache,
    173                                                          princ,
    174                                                          password, NULL, &kdc_time);
     405                                                         princ, password,
     406                                                         impersonate_principal, target_service,
     407                                                         krb_options,
     408                                                         NULL, &kdc_time);
     409                } else if (impersonate_principal) {
     410                        talloc_free(mem_ctx);
     411                        (*error_string) = "INTERNAL error: Cannot impersonate principal with just a keyblock.  A password must be specified in the credentials";
     412                        return EINVAL;
    175413                } else {
    176414                        /* No password available, try to use a keyblock instead */
     
    181419                        if (!mach_pwd) {
    182420                                talloc_free(mem_ctx);
    183                                 DEBUG(1, ("kinit_to_ccache: No password available for kinit\n"));
     421                                (*error_string) = "kinit_to_ccache: No password available for kinit\n";
     422                                krb5_get_init_creds_opt_free(smb_krb5_context->krb5_context, krb_options);
     423                                smb_krb5_context_remove_event_ctx(smb_krb5_context, previous_ev, event_ctx);
    184424                                return EINVAL;
    185425                        }
     
    191431                        if (ret == 0) {
    192432                                ret = kerberos_kinit_keyblock_cc(smb_krb5_context->krb5_context, ccache,
    193                                                                  princ,
    194                                                                  &keyblock, NULL, &kdc_time);
     433                                                                 princ, &keyblock,
     434                                                                 target_service, krb_options,
     435                                                                 NULL, &kdc_time);
    195436                                krb5_free_keyblock_contents(smb_krb5_context->krb5_context, &keyblock);
    196437                        }
    197438                }
     439
     440                smb_krb5_context_remove_event_ctx(smb_krb5_context, previous_ev, event_ctx);
    198441
    199442                if (ret == KRB5KRB_AP_ERR_SKEW || ret == KRB5_KDCREP_SKEW) {
     
    207450        }
    208451
     452        krb5_get_init_creds_opt_free(smb_krb5_context->krb5_context, krb_options);
     453
    209454        if (ret == KRB5KRB_AP_ERR_SKEW || ret == KRB5_KDCREP_SKEW) {
    210                 DEBUG(1,("kinit for %s failed (%s)\n",
    211                          cli_credentials_get_principal(credentials, mem_ctx),
    212                          smb_get_krb5_error_message(smb_krb5_context->krb5_context,
    213                                                     ret, mem_ctx)));
     455                (*error_string) = talloc_asprintf(credentials, "kinit for %s failed (%s)\n",
     456                                                  cli_credentials_get_principal(credentials, mem_ctx),
     457                                                  smb_get_krb5_error_message(smb_krb5_context->krb5_context,
     458                                                                             ret, mem_ctx));
    214459                talloc_free(mem_ctx);
    215460                return ret;
     
    228473                                      credentials,
    229474                                      smb_krb5_context,
    230                                       ccache);
    231         }
     475                                      event_ctx,
     476                                      ccache, obtained,
     477                                      error_string);
     478        }
     479
    232480        if (ret) {
    233                 DEBUG(1,("kinit for %s failed (%s)\n",
    234                          cli_credentials_get_principal(credentials, mem_ctx),
    235                          smb_get_krb5_error_message(smb_krb5_context->krb5_context,
    236                                                     ret, mem_ctx)));
     481                (*error_string) = talloc_asprintf(credentials, "kinit for %s failed (%s)\n",
     482                                                  cli_credentials_get_principal(credentials, mem_ctx),
     483                                                  smb_get_krb5_error_message(smb_krb5_context->krb5_context,
     484                                                                             ret, mem_ctx));
    237485                talloc_free(mem_ctx);
    238486                return ret;
     
    274522
    275523static krb5_error_code keytab_add_keys(TALLOC_CTX *parent_ctx,
    276                                        const char *princ_string,
    277                                        krb5_principal princ,
     524                                       struct principal_container **principals,
    278525                                       krb5_principal salt_princ,
    279526                                       int kvno,
    280527                                       const char *password_s,
    281528                                       struct smb_krb5_context *smb_krb5_context,
    282                                        const char **enctype_strings,
    283                                        krb5_keytab keytab)
    284 {
    285         int i;
     529                                       krb5_enctype *enctypes,
     530                                       krb5_keytab keytab,
     531                                       const char **error_string)
     532{
     533        unsigned int i, p;
    286534        krb5_error_code ret;
    287535        krb5_data password;
    288         TALLOC_CTX *mem_ctx = talloc_new(parent_ctx);
    289         if (!mem_ctx) {
    290                 return ENOMEM;
    291         }
    292536
    293537        password.data = discard_const_p(char *, password_s);
    294538        password.length = strlen(password_s);
    295539
    296         for (i=0; enctype_strings[i]; i++) {
     540        for (i=0; enctypes[i]; i++) {
    297541                krb5_keytab_entry entry;
    298                 krb5_enctype enctype;
    299                 ret = krb5_string_to_enctype(smb_krb5_context->krb5_context, enctype_strings[i], &enctype);
     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]);
    300547                if (ret != 0) {
    301                         DEBUG(1, ("Failed to interpret %s as a krb5 encryption type: %s\n",                               
    302                                   enctype_strings[i],
    303                                   smb_get_krb5_error_message(smb_krb5_context->krb5_context,
    304                                                              ret, mem_ctx)));
    305                         talloc_free(mem_ctx);
    306548                        return ret;
    307549                }
    308                 ret = create_kerberos_key_from_string(smb_krb5_context->krb5_context,
    309                                                       salt_princ, &password, &entry.keyblock, enctype);
    310                 if (ret != 0) {
    311                         talloc_free(mem_ctx);
    312                         return ret;
    313                 }
    314 
    315                 entry.principal = princ;
    316                 entry.vno       = kvno;
    317                 ret = krb5_kt_add_entry(smb_krb5_context->krb5_context, keytab, &entry);
    318                 if (ret != 0) {
    319                         DEBUG(1, ("Failed to add %s entry for %s(kvno %d) to keytab: %s\n",
    320                                   enctype_strings[i],
    321                                   princ_string,
    322                                   kvno,
    323                                   smb_get_krb5_error_message(smb_krb5_context->krb5_context,
    324                                                              ret, mem_ctx)));
    325                         talloc_free(mem_ctx);
    326                         krb5_free_keyblock_contents(smb_krb5_context->krb5_context, &entry.keyblock);
    327                         return ret;
    328                 }
    329 
    330                 DEBUG(5, ("Added %s(kvno %d) to keytab (%s)\n",
    331                           princ_string, kvno,
    332                           enctype_strings[i]));
    333                
     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                }
    334573                krb5_free_keyblock_contents(smb_krb5_context->krb5_context, &entry.keyblock);
    335574        }
    336         talloc_free(mem_ctx);
    337575        return 0;
    338576}
    339577
    340578static krb5_error_code create_keytab(TALLOC_CTX *parent_ctx,
    341                          struct cli_credentials *machine_account,
    342                          struct smb_krb5_context *smb_krb5_context,
    343                          const char **enctype_strings,
    344                          krb5_keytab keytab,
    345                          bool add_old)
     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)
    346585{
    347586        krb5_error_code ret;
     
    349588        const char *old_secret;
    350589        int kvno;
     590        uint32_t enctype_bitmap;
    351591        krb5_principal salt_princ;
    352         krb5_principal princ;
    353         const char *princ_string;
    354 
     592        krb5_enctype *enctypes;
    355593        TALLOC_CTX *mem_ctx = talloc_new(parent_ctx);
    356594        if (!mem_ctx) {
    357                 return ENOMEM;
    358         }
    359 
    360         princ_string = cli_credentials_get_principal(machine_account, mem_ctx);
    361         /* Get the principal we will store the new keytab entries under */
    362         ret = principal_from_credentials(mem_ctx, machine_account, smb_krb5_context, &princ);
     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);
    363603        if (ret) {
    364                 DEBUG(1,("create_keytab: makeing krb5 principal failed (%s)\n",
    365                          smb_get_krb5_error_message(smb_krb5_context->krb5_context,
    366                                                     ret, mem_ctx)));
    367                 talloc_free(mem_ctx);
    368                 return ret;
    369         }
    370 
    371         /* The salt used to generate these entries may be different however, fetch that */
    372         ret = salt_principal_from_credentials(mem_ctx, machine_account,
    373                                               smb_krb5_context,
    374                                               &salt_princ);
     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);
    375628        if (ret) {
    376                 DEBUG(1,("create_keytab: makeing salt principal failed (%s)\n",
    377                          smb_get_krb5_error_message(smb_krb5_context->krb5_context,
    378                                                     ret, mem_ctx)));
    379                 talloc_free(mem_ctx);
    380                 return ret;
    381         }
    382 
    383         /* Finally, do the dance to get the password to put in the entry */
    384         password_s = cli_credentials_get_password(machine_account);
    385         if (!password_s) {
    386                 krb5_keytab_entry entry;
    387                 const struct samr_Password *mach_pwd;
    388 
    389                 if (!str_list_check(enctype_strings, "arcfour-hmac-md5")) {
    390                         DEBUG(1, ("Asked to create keytab, but with only an NT hash supplied, "
    391                                   "but not listing arcfour-hmac-md5 as an enc type to include in the keytab!\n"));
    392                         talloc_free(mem_ctx);
    393                         return EINVAL;
    394                 }
    395 
    396                 /* If we don't have the plaintext password, try for
    397                  * the MD4 password hash */
    398                 mach_pwd = cli_credentials_get_nt_hash(machine_account, mem_ctx);
    399                 if (!mach_pwd) {
    400                         /* OK, nothing to do here */
    401                         talloc_free(mem_ctx);
    402                         return 0;
    403                 }
    404                 ret = krb5_keyblock_init(smb_krb5_context->krb5_context,
    405                                          ETYPE_ARCFOUR_HMAC_MD5,
    406                                          mach_pwd->hash, sizeof(mach_pwd->hash),
    407                                          &entry.keyblock);
     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);
    408650                if (ret) {
    409                         DEBUG(1, ("create_keytab: krb5_keyblock_init failed: %s\n",
    410                                   smb_get_krb5_error_message(smb_krb5_context->krb5_context,
    411                                                              ret, mem_ctx)));
    412651                        talloc_free(mem_ctx);
    413652                        return ret;
    414653                }
    415 
    416                 entry.principal = princ;
    417                 entry.vno       = cli_credentials_get_kvno(machine_account);
    418                 ret = krb5_kt_add_entry(smb_krb5_context->krb5_context, keytab, &entry);
    419                 if (ret) {
    420                         DEBUG(1, ("Failed to add ARCFOUR_HMAC (only) entry for %s to keytab: %s",
    421                                   cli_credentials_get_principal(machine_account, mem_ctx),
    422                                   smb_get_krb5_error_message(smb_krb5_context->krb5_context,
    423                                                              ret, mem_ctx)));
    424                         talloc_free(mem_ctx);
    425                         krb5_free_keyblock_contents(smb_krb5_context->krb5_context, &entry.keyblock);
    426                         return ret;
    427                 }
    428                
    429                 DEBUG(5, ("Added %s(kvno %d) to keytab (arcfour-hmac-md5)\n",
    430                           cli_credentials_get_principal(machine_account, mem_ctx),
    431                           cli_credentials_get_kvno(machine_account)));
    432 
    433                 krb5_free_keyblock_contents(smb_krb5_context->krb5_context, &entry.keyblock);
    434 
    435                 /* Can't go any further, we only have this one key */
    436                 talloc_free(mem_ctx);
    437                 return 0;
    438         }
    439        
    440         kvno = cli_credentials_get_kvno(machine_account);
    441         /* good, we actually have the real plaintext */
    442         ret = keytab_add_keys(mem_ctx, princ_string, princ, salt_princ,
    443                               kvno, password_s, smb_krb5_context,
    444                               enctype_strings, keytab);
    445         if (!ret) {
    446                 talloc_free(mem_ctx);
    447                 return ret;
    448         }
    449 
    450         if (!add_old || kvno == 0) {
    451                 talloc_free(mem_ctx);
    452                 return 0;
    453         }
    454 
    455         old_secret = cli_credentials_get_old_password(machine_account);
    456         if (!old_secret) {
    457                 talloc_free(mem_ctx);
    458                 return 0;
    459         }
    460        
    461         ret = keytab_add_keys(mem_ctx, princ_string, princ, salt_princ,
    462                               kvno - 1, old_secret, smb_krb5_context,
    463                               enctype_strings, keytab);
    464         if (!ret) {
    465                 talloc_free(mem_ctx);
    466                 return ret;
    467654        }
    468655
    469656        talloc_free(mem_ctx);
    470         return 0;
    471 }
    472 
     657        return ret;
     658}
    473659
    474660/*
     
    482668
    483669static krb5_error_code remove_old_entries(TALLOC_CTX *parent_ctx,
    484                                           struct cli_credentials *machine_account,
     670                                          struct ldb_message *msg,
     671                                          struct principal_container **principals,
     672                                          bool delete_all_kvno,
    485673                                          struct smb_krb5_context *smb_krb5_context,
    486                                           krb5_keytab keytab, bool *found_previous)
     674                                          krb5_keytab keytab, bool *found_previous,
     675                                          const char **error_string)
    487676{
    488677        krb5_error_code ret, ret2;
    489678        krb5_kt_cursor cursor;
    490         krb5_principal princ;
    491679        int kvno;
    492680        TALLOC_CTX *mem_ctx = talloc_new(parent_ctx);
    493         const char *princ_string;
     681
    494682        if (!mem_ctx) {
    495683                return ENOMEM;
     
    497685
    498686        *found_previous = false;
    499         princ_string = cli_credentials_get_principal(machine_account, mem_ctx);
    500 
    501         /* Get the principal we will store the new keytab entries under */
    502         ret = principal_from_credentials(mem_ctx, machine_account, smb_krb5_context, &princ);
    503         if (ret) {
    504                 DEBUG(1,("update_keytab: makeing krb5 principal failed (%s)\n",
    505                          smb_get_krb5_error_message(smb_krb5_context->krb5_context,
    506                                                     ret, mem_ctx)));
    507                 talloc_free(mem_ctx);
    508                 return ret;
    509         }
    510 
    511         kvno = cli_credentials_get_kvno(machine_account);
     687
     688        kvno = ldb_msg_find_attr_as_int(msg, "msDS-KeyVersionNumber", 0);
    512689
    513690        /* for each entry in the keytab */
     
    523700                return 0;
    524701        default:
    525                 DEBUG(1,("failed to open keytab for read of old entries: %s\n",
    526                          smb_get_krb5_error_message(smb_krb5_context->krb5_context,
    527                                                     ret, mem_ctx)));
     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));
    528705                talloc_free(mem_ctx);
    529706                return ret;
     
    531708
    532709        while (!ret) {
     710                unsigned int i;
     711                bool matched = false;
    533712                krb5_keytab_entry entry;
    534713                ret = krb5_kt_next_entry(smb_krb5_context->krb5_context, keytab, &entry, &cursor);
     
    536715                        break;
    537716                }
    538                 /* if it matches our principal */
    539                 if (!krb5_kt_compare(smb_krb5_context->krb5_context, &entry, princ, 0, 0)) {
     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)) {
     720                                matched = true;
     721                                break;
     722                        }
     723                }
     724
     725                if (!matched) {
    540726                        /* Free the entry, it wasn't the one we were looking for anyway */
    541727                        krb5_kt_free_entry(smb_krb5_context->krb5_context, &entry);
     
    593779                break;
    594780        default:
    595                 DEBUG(1,("failed in deleting old entries for principal: %s: %s\n",
    596                          princ_string,
    597                          smb_get_krb5_error_message(smb_krb5_context->krb5_context,
    598                                                     ret, mem_ctx)));
     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));
    599784        }
    600785        talloc_free(mem_ctx);
     
    603788
    604789krb5_error_code smb_krb5_update_keytab(TALLOC_CTX *parent_ctx,
    605                            struct cli_credentials *machine_account,
    606                            struct smb_krb5_context *smb_krb5_context,
    607                            const char **enctype_strings,
    608                            struct keytab_container *keytab_container)
     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)
    609795{
    610796        krb5_error_code ret;
    611797        bool found_previous;
    612         TALLOC_CTX *mem_ctx = talloc_new(parent_ctx);
     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
    613803        if (!mem_ctx) {
    614804                return ENOMEM;
    615805        }
    616806
    617         ret = remove_old_entries(mem_ctx, machine_account,
    618                                  smb_krb5_context, keytab_container->keytab, &found_previous);
     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
    619814        if (ret != 0) {
    620815                talloc_free(mem_ctx);
    621816                return ret;
    622817        }
     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        }
    623837       
    624         /* Create a new keytab.  If during the cleanout we found
    625          * entires for kvno -1, then don't try and duplicate them.
    626          * Otherwise, add kvno, and kvno -1 */
    627        
    628         ret = create_keytab(mem_ctx, machine_account, smb_krb5_context,
    629                             enctype_strings,
    630                             keytab_container->keytab,
    631                             found_previous ? false : true);
     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        }
    632848        talloc_free(mem_ctx);
    633849        return ret;
     
    637853                                           struct cli_credentials *machine_account,
    638854                                           struct smb_krb5_context *smb_krb5_context,
    639                                            const char **enctype_strings,
    640855                                           struct keytab_container **keytab_container)
    641856{
     
    644859        const char *rand_string;
    645860        const char *keytab_name;
     861        struct ldb_message *msg;
     862        const char *error_string;
    646863        if (!mem_ctx) {
    647864                return ENOMEM;
     
    668885        }
    669886
    670         ret = smb_krb5_update_keytab(mem_ctx, machine_account, smb_krb5_context, enctype_strings, *keytab_container);
     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);
    671899        if (ret == 0) {
    672900                talloc_steal(parent_ctx, *keytab_container);
    673901        } else {
     902                DEBUG(0, ("Failed to create in-memory keytab: %s\n", error_string));
    674903                *keytab_container = NULL;
    675904        }
     
    677906        return ret;
    678907}
    679 
     908/* Translate between the IETF encryption type values and the Microsoft msDS-SupportedEncryptionTypes values */
     909uint32_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 */
     928krb5_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 */
     947krb5_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}
  • trunk/server/source4/auth/kerberos/krb5_init_context.c

    r414 r745  
    1 /* 
     1/*
    22   Unix SMB/CIFS implementation.
    33   Wrapper for krb5_init_context
     
    1111   the Free Software Foundation; either version 3 of the License, or
    1212   (at your option) any later version.
    13    
     13
    1414   This program is distributed in the hope that it will be useful,
    1515   but WITHOUT ANY WARRANTY; without even the implied warranty of
    1616   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    1717   GNU General Public License for more details.
    18    
     18
    1919   You should have received a copy of the GNU General Public License
    2020   along with this program.  If not, see <http://www.gnu.org/licenses/>.
     
    3030#include "param/param.h"
    3131#include "libcli/resolve/resolve.h"
     32#include "../lib/tsocket/tsocket.h"
    3233
    3334/*
     
    4243        NTSTATUS status;
    4344        DATA_BLOB request, reply;
    44        
     45
    4546        struct packet_context *packet;
    4647
     
    5051};
    5152
    52 static krb5_error_code smb_krb5_context_destroy_1(struct smb_krb5_context *ctx)
    53 {
    54         krb5_free_context(ctx->krb5_context);
    55         return 0;
    56 }
    57 
    58 static krb5_error_code smb_krb5_context_destroy_2(struct smb_krb5_context *ctx)
     53static krb5_error_code smb_krb5_context_destroy(struct smb_krb5_context *ctx)
    5954{
    6055        /* Otherwise krb5_free_context will try and close what we have already free()ed */
    6156        krb5_set_warn_dest(ctx->krb5_context, NULL);
    6257        krb5_closelog(ctx->krb5_context, ctx->logf);
    63         smb_krb5_context_destroy_1(ctx);
     58        krb5_free_context(ctx->krb5_context);
    6459        return 0;
    6560}
     
    7267static void smb_krb5_debug_wrapper(const char *timestr, const char *msg, void *private_data)
    7368{
    74         DEBUG(2, ("Kerberos: %s\n", msg));
     69        DEBUG(3, ("Kerberos: %s\n", msg));
    7570}
    7671
     
    8984                return;
    9085        }
    91        
     86
    9287        blob = data_blob_talloc(tmp_ctx, NULL, dsize);
    9388        if (blob.data == NULL && dsize != 0) {
     
    9691                return;
    9792        }
    98        
     93
    9994        smb_krb5->status = socket_recv(smb_krb5->sock, blob.data, blob.length, &nread);
    10095        if (!NT_STATUS_IS_OK(smb_krb5->status)) {
     
    10398        }
    10499        blob.length = nread;
    105        
     100
    106101        if (nread == 0) {
    107102                smb_krb5->status = NT_STATUS_UNEXPECTED_NETWORK_ERROR;
     
    109104                return;
    110105        }
    111        
    112         DEBUG(2,("Received smb_krb5 packet of length %d\n", 
     106
     107        DEBUG(2,("Received smb_krb5 packet of length %d\n",
    113108                 (int)blob.length));
    114        
     109
    115110        talloc_steal(smb_krb5, blob.data);
    116111        smb_krb5->reply = blob;
     
    131126  handle request timeouts
    132127*/
    133 static void smb_krb5_request_timeout(struct tevent_context *event_ctx, 
     128static void smb_krb5_request_timeout(struct tevent_context *event_ctx,
    134129                                  struct tevent_timer *te, struct timeval t,
    135130                                  void *private_data)
     
    154149
    155150        size_t len;
    156        
     151
    157152        len = smb_krb5->request.length;
    158153        status = socket_send(smb_krb5->sock, &smb_krb5->request, &len);
    159154
    160155        if (!NT_STATUS_IS_OK(status)) return;
    161        
     156
    162157        TEVENT_FD_READABLE(smb_krb5->fde);
    163158
     
    213208        krb5_error_code ret;
    214209        NTSTATUS status;
    215         struct socket_address *remote_addr;
    216210        const char *name;
    217211        struct addrinfo *ai, *a;
    218212        struct smb_krb5_socket *smb_krb5;
    219213
    220         struct tevent_context *ev = talloc_get_type(data, struct tevent_context);
    221 
    222         DATA_BLOB send_blob = data_blob_const(send_buf->data, send_buf->length);
     214        DATA_BLOB send_blob;
     215
     216        struct tevent_context *ev;
     217        TALLOC_CTX *tmp_ctx = talloc_new(NULL);
     218        if (!tmp_ctx) {
     219                return ENOMEM;
     220        }
     221
     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
     233        send_blob = data_blob_const(send_buf->data, send_buf->length);
    223234
    224235        ret = krb5_krbhst_get_addrinfo(context, hi, &ai);
    225236        if (ret) {
    226                 return ret;
    227         }
    228 
    229         for (a = ai; a; a = ai->ai_next) {
    230                 smb_krb5 = talloc(NULL, struct smb_krb5_socket);
     237                talloc_free(tmp_ctx);
     238                return ret;
     239        }
     240
     241        for (a = ai; a; a = a->ai_next) {
     242                struct socket_address *remote_addr;
     243                smb_krb5 = talloc(tmp_ctx, struct smb_krb5_socket);
    231244                if (!smb_krb5) {
     245                        talloc_free(tmp_ctx);
    232246                        return ENOMEM;
    233247                }
    234248                smb_krb5->hi = hi;
    235                
     249
    236250                switch (a->ai_family) {
    237251                case PF_INET:
     
    244258#endif
    245259                default:
    246                         talloc_free(smb_krb5);
     260                        talloc_free(tmp_ctx);
    247261                        return EINVAL;
    248262                }
    249                
     263
    250264                status = NT_STATUS_INVALID_PARAMETER;
    251265                switch (hi->proto) {
     
    257271                        break;
    258272                case KRB5_KRBHST_HTTP:
    259                         talloc_free(smb_krb5);
     273                        talloc_free(tmp_ctx);
    260274                        return EINVAL;
    261275                }
     
    266280
    267281                talloc_steal(smb_krb5, smb_krb5->sock);
    268                
    269                 remote_addr = socket_address_from_sockaddr(smb_krb5, a->ai_addr, a->ai_addrlen); 
     282
     283                remote_addr = socket_address_from_sockaddr(smb_krb5, a->ai_addr, a->ai_addrlen);
    270284                if (!remote_addr) {
    271285                        talloc_free(smb_krb5);
     
    278292                        continue;
    279293                }
    280                 talloc_free(remote_addr);
    281294
    282295                /* Setup the FDE, start listening for read events
     
    326339                        break;
    327340                case KRB5_KRBHST_HTTP:
    328                         talloc_free(smb_krb5);
     341                        talloc_free(tmp_ctx);
    329342                        return EINVAL;
    330343                }
    331344                while ((NT_STATUS_IS_OK(smb_krb5->status)) && !smb_krb5->reply.length) {
    332345                        if (tevent_loop_once(ev) != 0) {
    333                                 talloc_free(smb_krb5);
     346                                talloc_free(tmp_ctx);
    334347                                return EINVAL;
     348                        }
     349
     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;
    335362                        }
    336363                }
     
    341368
    342369                if (!NT_STATUS_IS_OK(smb_krb5->status)) {
    343                         DEBUG(2,("Error reading smb_krb5 reply packet: %s\n", nt_errstr(smb_krb5->status)));
     370                        struct tsocket_address *addr = socket_address_to_tsocket_address(smb_krb5, remote_addr);
     371                        const char *addr_string = NULL;
     372                        if (addr) {
     373                                addr_string = tsocket_address_inet_addr_string(addr, smb_krb5);
     374                        } else {
     375                                addr_string = NULL;
     376                        }
     377                        DEBUG(2,("Error reading smb_krb5 reply packet: %s from %s\n", nt_errstr(smb_krb5->status),
     378                                 addr_string));
    344379                        talloc_free(smb_krb5);
    345380                        continue;
     
    348383                ret = krb5_data_copy(recv_buf, smb_krb5->reply.data, smb_krb5->reply.length);
    349384                if (ret) {
    350                         talloc_free(smb_krb5);
     385                        talloc_free(tmp_ctx);
    351386                        return ret;
    352387                }
    353388                talloc_free(smb_krb5);
    354                
     389
    355390                break;
    356391        }
     392        talloc_free(tmp_ctx);
    357393        if (a) {
    358394                return 0;
     
    361397}
    362398
    363 krb5_error_code smb_krb5_init_context(void *parent_ctx,
     399krb5_error_code
     400smb_krb5_init_context_basic(TALLOC_CTX *tmp_ctx,
     401                            struct loadparm_context *lp_ctx,
     402                            krb5_context *_krb5_context)
     403{
     404        krb5_error_code ret;
     405        char **config_files;
     406        const char *config_file, *realm;
     407        krb5_context krb5_ctx;
     408
     409        initialize_krb5_error_table();
     410
     411        ret = krb5_init_context(&krb5_ctx);
     412        if (ret) {
     413                DEBUG(1,("krb5_init_context failed (%s)\n",
     414                         error_message(ret)));
     415                return ret;
     416        }
     417
     418        config_file = config_path(tmp_ctx, lp_ctx, "krb5.conf");
     419        if (!config_file) {
     420                krb5_free_context(krb5_ctx);
     421                return ENOMEM;
     422        }
     423
     424        /* Use our local krb5.conf file by default */
     425        ret = krb5_prepend_config_files_default(config_file == NULL?"":config_file, &config_files);
     426        if (ret) {
     427                DEBUG(1,("krb5_prepend_config_files_default failed (%s)\n",
     428                         smb_get_krb5_error_message(krb5_ctx, ret, tmp_ctx)));
     429                krb5_free_context(krb5_ctx);
     430                return ret;
     431        }
     432
     433        ret = krb5_set_config_files(krb5_ctx, config_files);
     434        krb5_free_config_files(config_files);
     435        if (ret) {
     436                DEBUG(1,("krb5_set_config_files failed (%s)\n",
     437                         smb_get_krb5_error_message(krb5_ctx, ret, tmp_ctx)));
     438                krb5_free_context(krb5_ctx);
     439                return ret;
     440        }
     441
     442        realm = lpcfg_realm(lp_ctx);
     443        if (realm != NULL) {
     444                ret = krb5_set_default_realm(krb5_ctx, realm);
     445                if (ret) {
     446                        DEBUG(1,("krb5_set_default_realm failed (%s)\n",
     447                                 smb_get_krb5_error_message(krb5_ctx, ret, tmp_ctx)));
     448                        krb5_free_context(krb5_ctx);
     449                        return ret;
     450                }
     451        }
     452
     453        *_krb5_context = krb5_ctx;
     454        return 0;
     455}
     456
     457krb5_error_code smb_krb5_init_context(void *parent_ctx,
    364458                                      struct tevent_context *ev,
    365459                                      struct loadparm_context *lp_ctx,
    366                                        struct smb_krb5_context **smb_krb5_context)
     460                                      struct smb_krb5_context **smb_krb5_context)
    367461{
    368462        krb5_error_code ret;
    369463        TALLOC_CTX *tmp_ctx;
    370         char **config_files;
    371         const char *config_file;
    372        
     464
    373465        initialize_krb5_error_table();
    374        
     466
    375467        tmp_ctx = talloc_new(parent_ctx);
    376         *smb_krb5_context = talloc(tmp_ctx, struct smb_krb5_context);
     468        *smb_krb5_context = talloc_zero(tmp_ctx, struct smb_krb5_context);
    377469
    378470        if (!*smb_krb5_context || !tmp_ctx) {
     
    381473        }
    382474
    383         ret = krb5_init_context(&(*smb_krb5_context)->krb5_context);
    384         if (ret) {
    385                 DEBUG(1,("krb5_init_context failed (%s)\n",
     475        ret = smb_krb5_init_context_basic(tmp_ctx, lp_ctx,
     476                                          &(*smb_krb5_context)->krb5_context);
     477        if (ret) {
     478                DEBUG(1,("smb_krb5_context_init_basic failed (%s)\n",
    386479                         error_message(ret)));
    387480                talloc_free(tmp_ctx);
    388481                return ret;
    389         }
    390 
    391         talloc_set_destructor(*smb_krb5_context, smb_krb5_context_destroy_1);
    392 
    393         config_file = config_path(tmp_ctx, lp_ctx, "krb5.conf");
    394         if (!config_file) {
    395                 talloc_free(tmp_ctx);
    396                 return ENOMEM;
    397         }
    398                
    399         /* Use our local krb5.conf file by default */
    400         ret = krb5_prepend_config_files_default(config_file == NULL?"":config_file, &config_files);
    401         if (ret) {
    402                 DEBUG(1,("krb5_prepend_config_files_default failed (%s)\n",
    403                          smb_get_krb5_error_message((*smb_krb5_context)->krb5_context, ret, tmp_ctx)));
    404                 talloc_free(tmp_ctx);
    405                 return ret;
    406         }
    407 
    408         ret = krb5_set_config_files((*smb_krb5_context)->krb5_context,
    409                                     config_files);
    410         krb5_free_config_files(config_files);
    411         if (ret) {
    412                 DEBUG(1,("krb5_set_config_files failed (%s)\n",
    413                          smb_get_krb5_error_message((*smb_krb5_context)->krb5_context, ret, tmp_ctx)));
    414                 talloc_free(tmp_ctx);
    415                 return ret;
    416         }
    417                                                
    418         if (lp_realm(lp_ctx) && *lp_realm(lp_ctx)) {
    419                 char *upper_realm = strupper_talloc(tmp_ctx, lp_realm(lp_ctx));
    420                 if (!upper_realm) {
    421                         DEBUG(1,("gensec_krb5_start: could not uppercase realm: %s\n", lp_realm(lp_ctx)));
    422                         talloc_free(tmp_ctx);
    423                         return ENOMEM;
    424                 }
    425                 ret = krb5_set_default_realm((*smb_krb5_context)->krb5_context, upper_realm);
    426                 if (ret) {
    427                         DEBUG(1,("krb5_set_default_realm failed (%s)\n",
    428                                  smb_get_krb5_error_message((*smb_krb5_context)->krb5_context, ret, tmp_ctx)));
    429                         talloc_free(tmp_ctx);
    430                         return ret;
    431                 }
    432482        }
    433483
    434484        /* TODO: Should we have a different name here? */
    435485        ret = krb5_initlog((*smb_krb5_context)->krb5_context, "Samba", &(*smb_krb5_context)->logf);
    436        
    437         if (ret) {
    438                 DEBUG(1,("krb5_initlog failed (%s)\n", 
     486
     487        if (ret) {
     488                DEBUG(1,("krb5_initlog failed (%s)\n",
    439489                         smb_get_krb5_error_message((*smb_krb5_context)->krb5_context, ret, tmp_ctx)));
    440                 talloc_free(tmp_ctx);
    441                 return ret;
    442         }
    443 
    444         talloc_set_destructor(*smb_krb5_context, smb_krb5_context_destroy_2);
    445 
    446         ret = krb5_addlog_func((*smb_krb5_context)->krb5_context, (*smb_krb5_context)->logf, 0 /* min */, -1 /* max */,
     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 */,
    447498                               smb_krb5_debug_wrapper, smb_krb5_debug_close, NULL);
    448499        if (ret) {
    449                 DEBUG(1,("krb5_addlog_func failed (%s)\n", 
     500                DEBUG(1,("krb5_addlog_func failed (%s)\n",
    450501                         smb_get_krb5_error_message((*smb_krb5_context)->krb5_context, ret, tmp_ctx)));
    451502                talloc_free(tmp_ctx);
     
    455506
    456507        /* Set use of our socket lib */
    457         ret = krb5_set_send_to_kdc_func((*smb_krb5_context)->krb5_context,
    458                                         smb_krb5_send_and_recv_func,
    459                                         ev);
    460         if (ret) {
    461                 DEBUG(1,("krb5_set_send_recv_func failed (%s)\n",
    462                          smb_get_krb5_error_message((*smb_krb5_context)->krb5_context, ret, tmp_ctx)));
    463                 talloc_free(tmp_ctx);
    464                 return ret;
     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                }
    465516        }
    466517
     
    471522
    472523        krb5_set_dns_canonicalize_hostname((*smb_krb5_context)->krb5_context,
    473                                            lp_parm_bool(lp_ctx, NULL, "krb5", "set_dns_canonicalize", false));
     524                                           lpcfg_parm_bool(lp_ctx, NULL, "krb5", "set_dns_canonicalize", false));
    474525
    475526        return 0;
    476527}
    477528
     529krb5_error_code smb_krb5_context_set_event_ctx(struct smb_krb5_context *smb_krb5_context,
     530                                               struct tevent_context *ev,
     531                                               struct tevent_context **previous_ev)
     532{
     533        int ret;
     534        if (!ev) {
     535                return EINVAL;
     536        }
     537
     538        *previous_ev = smb_krb5_context->current_ev;
     539
     540        smb_krb5_context->current_ev = talloc_reference(smb_krb5_context, ev);
     541        if (!smb_krb5_context->current_ev) {
     542                return ENOMEM;
     543        }
     544
     545        /* Set use of our socket lib */
     546        ret = krb5_set_send_to_kdc_func(smb_krb5_context->krb5_context,
     547                                        smb_krb5_send_and_recv_func,
     548                                        ev);
     549        if (ret) {
     550                TALLOC_CTX *tmp_ctx = talloc_new(NULL);
     551                DEBUG(1,("krb5_set_send_recv_func failed (%s)\n",
     552                         smb_get_krb5_error_message(smb_krb5_context->krb5_context, ret, tmp_ctx)));
     553                talloc_free(tmp_ctx);
     554                talloc_unlink(smb_krb5_context, smb_krb5_context->current_ev);
     555                smb_krb5_context->current_ev = NULL;
     556                return ret;
     557        }
     558        return 0;
     559}
     560
     561krb5_error_code smb_krb5_context_remove_event_ctx(struct smb_krb5_context *smb_krb5_context,
     562                                                  struct tevent_context *previous_ev,
     563                                                  struct tevent_context *ev)
     564{
     565        int ret;
     566        talloc_unlink(smb_krb5_context, ev);
     567        /* If there was a mismatch with things happening on a stack, then don't wipe things */
     568        smb_krb5_context->current_ev = previous_ev;
     569        /* Set use of our socket lib */
     570        ret = krb5_set_send_to_kdc_func(smb_krb5_context->krb5_context,
     571                                        smb_krb5_send_and_recv_func,
     572                                        previous_ev);
     573        if (ret) {
     574                TALLOC_CTX *tmp_ctx = talloc_new(NULL);
     575                DEBUG(1,("krb5_set_send_recv_func failed (%s)\n",
     576                         smb_get_krb5_error_message(smb_krb5_context->krb5_context, ret, tmp_ctx)));
     577                talloc_free(tmp_ctx);
     578                return ret;
     579        }
     580        return 0;
     581}
  • trunk/server/source4/auth/kerberos/krb5_init_context.h

    r414 r745  
    2121        krb5_context krb5_context;
    2222        krb5_log_facility *logf;
     23        struct tevent_context *current_ev;
    2324};
    2425       
    2526struct tevent_context;
    2627struct loadparm_context;
     28
     29krb5_error_code
     30smb_krb5_init_context_basic(TALLOC_CTX *tmp_ctx,
     31                            struct loadparm_context *lp_ctx,
     32                            krb5_context *_krb5_context);
     33
    2734krb5_error_code smb_krb5_init_context(void *parent_ctx, struct tevent_context *ev,
    2835                                      struct loadparm_context *lp_ctx,
    2936                                      struct smb_krb5_context **smb_krb5_context);
    30 void smb_krb5_free_context(struct smb_krb5_context *smb_krb5_context);
    3137
    3238krb5_error_code smb_krb5_send_and_recv_func(krb5_context context,
Note: See TracChangeset for help on using the changeset viewer.