Changeset 988 for vendor/current/source4/auth/kerberos
- Timestamp:
- Nov 24, 2016, 1:14:11 PM (9 years ago)
- Location:
- vendor/current/source4/auth/kerberos
- Files:
-
- 1 added
- 5 deleted
- 8 edited
Legend:
- Unmodified
- Added
- Removed
-
vendor/current/source4/auth/kerberos/kerberos-notes.txt
r414 r988 7 7 ------------------------------------ 8 8 9 This document should be read in conju ction with the Samba4 source code.9 This document should be read in conjunction with the Samba4 source code. 10 10 DAL and KDC requirements are expressed (as an implementation against Heimdal's 11 11 HDB abstraction layer) in Samba4's source4/kdc/hdb-samba4.c in particular. … … 160 160 correctly implement the GSSAPI specification, particularly on top of the 161 161 (inflexible) MIT Kerberos API. It did not seem possible to write a correct, 162 sep erate GSSAPI implementation on top of MIT Kerberos's public krb5lib API,162 separate GSSAPI implementation on top of MIT Kerberos's public krb5lib API, 163 163 and at the time, the effort did not need to extend beyond what Windows would 164 164 require. … … 528 528 529 529 Traditional 'MIT' behaviour is to use a keytab, containing salted key 530 data, extracted from the KDC. (In this mod al, there is no 'service530 data, extracted from the KDC. (In this model, there is no 'service 531 531 password', instead the keys are often simply application of random 532 532 bytes). Heimdal also implements this behaviour. 533 533 534 The windows mod al is very different - instead of sharing a keytab with534 The windows model is very different - instead of sharing a keytab with 535 535 each member server, a random utf-16 pseudo-textual password is stored 536 536 for the whole machine. -
vendor/current/source4/auth/kerberos/kerberos.h
r740 r988 19 19 */ 20 20 21 #ifndef _AUTH_KERBEROS_H_ 22 #define _AUTH_KERBEROS_H_ 23 21 24 #if defined(HAVE_KRB5) 22 25 26 #include "system/kerberos.h" 23 27 #include "auth/kerberos/krb5_init_context.h" 24 28 #include "librpc/gen_ndr/krb5pac.h" 29 #include "lib/krb5_wrap/krb5_samba.h" 30 #include "lib/krb5_wrap/gss_samba.h" 25 31 26 32 struct auth_user_info_dc; … … 35 41 struct smb_krb5_context *smb_krb5_context; 36 42 krb5_keytab keytab; 43 bool password_based; 37 44 }; 38 45 … … 44 51 #define TOK_ID_GSS_WRAP ((const uint8_t *)"\x02\x01") 45 52 46 #ifdef HAVE_KRB5_KEYBLOCK_KEYVALUE47 #define KRB5_KEY_TYPE(k) ((k)->keytype)48 #define KRB5_KEY_LENGTH(k) ((k)->keyvalue.length)49 #define KRB5_KEY_DATA(k) ((k)->keyvalue.data)50 #else51 #define KRB5_KEY_TYPE(k) ((k)->enctype)52 #define KRB5_KEY_LENGTH(k) ((k)->length)53 #define KRB5_KEY_DATA(k) ((k)->contents)54 #endif /* HAVE_KRB5_KEYBLOCK_KEYVALUE */55 56 53 #define ENC_ALL_TYPES (ENC_CRC32 | ENC_RSA_MD5 | ENC_RC4_HMAC_MD5 | \ 57 54 ENC_HMAC_SHA1_96_AES128 | ENC_HMAC_SHA1_96_AES256) 58 59 #ifndef HAVE_KRB5_SET_REAL_TIME60 krb5_error_code krb5_set_real_time(krb5_context context, int32_t seconds, int32_t microseconds);61 #endif62 55 63 56 #ifndef HAVE_KRB5_SET_DEFAULT_TGS_KTYPES … … 69 62 #endif 70 63 71 #ifndef HAVE_KRB5_FREE_UNPARSED_NAME72 void krb5_free_unparsed_name(krb5_context ctx, char *val);73 #endif74 75 64 #if defined(HAVE_KRB5_PRINCIPAL_GET_COMP_STRING) && !defined(HAVE_KRB5_PRINC_COMPONENT) 76 65 const krb5_data *krb5_princ_component(krb5_context context, krb5_principal principal, int i ); … … 78 67 79 68 /* Samba wrapper function for krb5 functionality. */ 80 void setup_kaddr( krb5_address *pkaddr, struct sockaddr *paddr);81 int create_kerberos_key_from_string(krb5_context context, krb5_principal host_princ, krb5_data *password, krb5_keyblock *key, krb5_enctype enctype);82 int create_kerberos_key_from_string_direct(krb5_context context, krb5_principal host_princ, krb5_data *password, krb5_keyblock *key, krb5_enctype enctype);83 krb5_const_principal get_principal_from_tkt(krb5_ticket *tkt);84 krb5_error_code get_kerberos_allowed_etypes(krb5_context context, krb5_enctype **enctypes);85 void free_kerberos_etypes(krb5_context context, krb5_enctype *enctypes);86 bool get_krb5_smb_session_key(krb5_context context, krb5_auth_context auth_context, DATA_BLOB *session_key, bool remote);87 krb5_error_code ads_krb5_mk_req(krb5_context context,88 krb5_auth_context *auth_context,89 const krb5_flags ap_req_options,90 const char *principal,91 krb5_ccache ccache,92 krb5_data *outbuf);93 bool get_auth_data_from_tkt(TALLOC_CTX *mem_ctx, DATA_BLOB *auth_data, krb5_ticket *tkt);94 krb5_error_code kerberos_kinit_password_cc(krb5_context ctx, krb5_ccache cc,95 krb5_principal principal, const char *password,96 krb5_principal impersonate_principal, const char *target_service,97 krb5_get_init_creds_opt *krb_options,98 time_t *expire_time, time_t *kdc_time);99 krb5_error_code kerberos_kinit_keyblock_cc(krb5_context ctx, krb5_ccache cc,100 krb5_principal principal, krb5_keyblock *keyblock,101 const char *target_service,102 krb5_get_init_creds_opt *krb_options,103 time_t *expire_time, time_t *kdc_time);104 krb5_principal kerberos_fetch_salt_princ_for_host_princ(krb5_context context,105 krb5_principal host_princ,106 int enctype);107 void kerberos_set_creds_enctype(krb5_creds *pcreds, int enctype);108 bool kerberos_compatible_enctypes(krb5_context context, krb5_enctype enctype1, krb5_enctype enctype2);109 void kerberos_free_data_contents(krb5_context context, krb5_data *pdata);110 krb5_error_code smb_krb5_kt_free_entry(krb5_context context, krb5_keytab_entry *kt_entry);111 char *smb_get_krb5_error_message(krb5_context context, krb5_error_code code, TALLOC_CTX *mem_ctx);112 NTSTATUS kerberos_decode_pac(TALLOC_CTX *mem_ctx,113 struct PAC_DATA **pac_data_out,114 DATA_BLOB blob,115 krb5_context context,116 const krb5_keyblock *krbtgt_keyblock,117 const krb5_keyblock *service_keyblock,118 krb5_const_principal client_principal,119 time_t tgs_authtime,120 krb5_error_code *k5ret);121 NTSTATUS kerberos_pac_logon_info(TALLOC_CTX *mem_ctx,122 struct PAC_LOGON_INFO **logon_info,123 DATA_BLOB blob,124 krb5_context context,125 const krb5_keyblock *krbtgt_keyblock,126 const krb5_keyblock *service_keyblock,127 krb5_const_principal client_principal,128 time_t tgs_authtime,129 krb5_error_code *k5ret);130 69 krb5_error_code kerberos_encode_pac(TALLOC_CTX *mem_ctx, 131 70 struct PAC_DATA *pac_data, … … 142 81 time_t tgs_authtime, 143 82 DATA_BLOB *pac); 144 struct loadparm_context;145 struct ldb_message;146 struct ldb_context;147 uint32_t kerberos_enctype_to_bitmap(krb5_enctype enc_type_enum);148 /* Translate between the Microsoft msDS-SupportedEncryptionTypes values and the IETF encryption type values */149 krb5_enctype kerberos_enctype_bitmap_to_enctype(uint32_t enctype_bitmap);150 krb5_error_code smb_krb5_update_keytab(TALLOC_CTX *parent_ctx,151 struct smb_krb5_context *smb_krb5_context,152 struct ldb_context *ldb,153 struct ldb_message *msg,154 bool delete_all_kvno,155 const char **error_string);156 83 157 84 #include "auth/kerberos/proto.h" 158 85 159 86 #endif /* HAVE_KRB5 */ 87 88 #endif /* _AUTH_KERBEROS_H_ */ -
vendor/current/source4/auth/kerberos/kerberos_credentials.h
r740 r988 28 28 enum credentials_obtained *obtained, 29 29 const char **error_string); 30 31 /* Manually prototyped here to avoid needing krb5 headers in most callers */ 32 krb5_error_code principal_from_credentials(TALLOC_CTX *parent_ctx, 33 struct cli_credentials *credentials, 34 struct smb_krb5_context *smb_krb5_context, 35 krb5_principal *princ, 36 enum credentials_obtained *obtained, 37 const char **error_string); -
vendor/current/source4/auth/kerberos/kerberos_pac.c
r740 r988 31 31 #include <ldb.h> 32 32 #include "auth/auth_sam_reply.h" 33 34 krb5_error_code check_pac_checksum(TALLOC_CTX *mem_ctx, 35 DATA_BLOB pac_data, 36 struct PAC_SIGNATURE_DATA *sig, 37 krb5_context context, 38 const krb5_keyblock *keyblock) 39 { 40 krb5_error_code ret; 41 krb5_crypto crypto; 42 Checksum cksum; 43 44 cksum.cksumtype = (CKSUMTYPE)sig->type; 45 cksum.checksum.length = sig->signature.length; 46 cksum.checksum.data = sig->signature.data; 47 48 ret = krb5_crypto_init(context, 49 keyblock, 50 0, 51 &crypto); 52 if (ret) { 53 DEBUG(0,("krb5_crypto_init() failed: %s\n", 54 smb_get_krb5_error_message(context, ret, mem_ctx))); 55 return ret; 56 } 57 ret = krb5_verify_checksum(context, 58 crypto, 59 KRB5_KU_OTHER_CKSUM, 60 pac_data.data, 61 pac_data.length, 62 &cksum); 63 krb5_crypto_destroy(context, crypto); 64 65 return ret; 66 } 67 68 NTSTATUS kerberos_decode_pac(TALLOC_CTX *mem_ctx, 69 struct PAC_DATA **pac_data_out, 70 DATA_BLOB blob, 71 krb5_context context, 72 const krb5_keyblock *krbtgt_keyblock, 73 const krb5_keyblock *service_keyblock, 74 krb5_const_principal client_principal, 75 time_t tgs_authtime, 76 krb5_error_code *k5ret) 77 { 78 krb5_error_code ret; 79 NTSTATUS status; 80 enum ndr_err_code ndr_err; 81 struct PAC_SIGNATURE_DATA *srv_sig_ptr = NULL; 82 struct PAC_SIGNATURE_DATA *kdc_sig_ptr = NULL; 83 struct PAC_SIGNATURE_DATA *srv_sig_wipe = NULL; 84 struct PAC_SIGNATURE_DATA *kdc_sig_wipe = NULL; 85 struct PAC_LOGON_INFO *logon_info = NULL; 86 struct PAC_LOGON_NAME *logon_name = NULL; 87 struct PAC_DATA *pac_data; 88 struct PAC_DATA_RAW *pac_data_raw; 89 90 DATA_BLOB *srv_sig_blob = NULL; 91 DATA_BLOB *kdc_sig_blob = NULL; 92 93 DATA_BLOB modified_pac_blob; 94 NTTIME tgs_authtime_nttime; 95 krb5_principal client_principal_pac; 96 uint32_t i; 97 98 krb5_clear_error_message(context); 99 100 if (k5ret) { 101 *k5ret = KRB5_PARSE_MALFORMED; 102 } 103 104 pac_data = talloc(mem_ctx, struct PAC_DATA); 105 pac_data_raw = talloc(mem_ctx, struct PAC_DATA_RAW); 106 kdc_sig_wipe = talloc(mem_ctx, struct PAC_SIGNATURE_DATA); 107 srv_sig_wipe = talloc(mem_ctx, struct PAC_SIGNATURE_DATA); 108 if (!pac_data_raw || !pac_data || !kdc_sig_wipe || !srv_sig_wipe) { 109 if (k5ret) { 110 *k5ret = ENOMEM; 111 } 112 return NT_STATUS_NO_MEMORY; 113 } 114 115 ndr_err = ndr_pull_struct_blob(&blob, pac_data, 116 pac_data, (ndr_pull_flags_fn_t)ndr_pull_PAC_DATA); 117 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { 118 status = ndr_map_error2ntstatus(ndr_err); 119 DEBUG(0,("can't parse the PAC: %s\n", 120 nt_errstr(status))); 121 return status; 122 } 123 124 if (pac_data->num_buffers < 4) { 125 /* we need logon_ingo, service_key and kdc_key */ 126 DEBUG(0,("less than 4 PAC buffers\n")); 127 return NT_STATUS_INVALID_PARAMETER; 128 } 129 130 ndr_err = ndr_pull_struct_blob(&blob, pac_data_raw, 131 pac_data_raw, 132 (ndr_pull_flags_fn_t)ndr_pull_PAC_DATA_RAW); 133 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { 134 status = ndr_map_error2ntstatus(ndr_err); 135 DEBUG(0,("can't parse the PAC: %s\n", 136 nt_errstr(status))); 137 return status; 138 } 139 140 if (pac_data_raw->num_buffers < 4) { 141 /* we need logon_ingo, service_key and kdc_key */ 142 DEBUG(0,("less than 4 PAC buffers\n")); 143 return NT_STATUS_INVALID_PARAMETER; 144 } 145 146 if (pac_data->num_buffers != pac_data_raw->num_buffers) { 147 /* we need logon_ingo, service_key and kdc_key */ 148 DEBUG(0,("misparse! PAC_DATA has %d buffers while PAC_DATA_RAW has %d\n", 149 pac_data->num_buffers, pac_data_raw->num_buffers)); 150 return NT_STATUS_INVALID_PARAMETER; 151 } 152 153 for (i=0; i < pac_data->num_buffers; i++) { 154 if (pac_data->buffers[i].type != pac_data_raw->buffers[i].type) { 155 DEBUG(0,("misparse! PAC_DATA buffer %d has type %d while PAC_DATA_RAW has %d\n", 156 i, pac_data->buffers[i].type, pac_data->buffers[i].type)); 157 return NT_STATUS_INVALID_PARAMETER; 158 } 159 switch (pac_data->buffers[i].type) { 160 case PAC_TYPE_LOGON_INFO: 161 if (!pac_data->buffers[i].info) { 162 break; 163 } 164 logon_info = pac_data->buffers[i].info->logon_info.info; 165 break; 166 case PAC_TYPE_SRV_CHECKSUM: 167 if (!pac_data->buffers[i].info) { 168 break; 169 } 170 srv_sig_ptr = &pac_data->buffers[i].info->srv_cksum; 171 srv_sig_blob = &pac_data_raw->buffers[i].info->remaining; 172 break; 173 case PAC_TYPE_KDC_CHECKSUM: 174 if (!pac_data->buffers[i].info) { 175 break; 176 } 177 kdc_sig_ptr = &pac_data->buffers[i].info->kdc_cksum; 178 kdc_sig_blob = &pac_data_raw->buffers[i].info->remaining; 179 break; 180 case PAC_TYPE_LOGON_NAME: 181 logon_name = &pac_data->buffers[i].info->logon_name; 182 break; 183 default: 184 break; 185 } 186 } 187 188 if (!logon_info) { 189 DEBUG(0,("PAC no logon_info\n")); 190 return NT_STATUS_INVALID_PARAMETER; 191 } 192 193 if (!logon_name) { 194 DEBUG(0,("PAC no logon_name\n")); 195 return NT_STATUS_INVALID_PARAMETER; 196 } 197 198 if (!srv_sig_ptr || !srv_sig_blob) { 199 DEBUG(0,("PAC no srv_key\n")); 200 return NT_STATUS_INVALID_PARAMETER; 201 } 202 203 if (!kdc_sig_ptr || !kdc_sig_blob) { 204 DEBUG(0,("PAC no kdc_key\n")); 205 return NT_STATUS_INVALID_PARAMETER; 206 } 207 208 /* Find and zero out the signatures, as required by the signing algorithm */ 209 210 /* We find the data blobs above, now we parse them to get at the exact portion we should zero */ 211 ndr_err = ndr_pull_struct_blob(kdc_sig_blob, kdc_sig_wipe, 212 kdc_sig_wipe, 213 (ndr_pull_flags_fn_t)ndr_pull_PAC_SIGNATURE_DATA); 214 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { 215 status = ndr_map_error2ntstatus(ndr_err); 216 DEBUG(0,("can't parse the KDC signature: %s\n", 217 nt_errstr(status))); 218 return status; 219 } 220 221 ndr_err = ndr_pull_struct_blob(srv_sig_blob, srv_sig_wipe, 222 srv_sig_wipe, 223 (ndr_pull_flags_fn_t)ndr_pull_PAC_SIGNATURE_DATA); 224 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { 225 status = ndr_map_error2ntstatus(ndr_err); 226 DEBUG(0,("can't parse the SRV signature: %s\n", 227 nt_errstr(status))); 228 return status; 229 } 230 231 /* Now zero the decoded structure */ 232 memset(kdc_sig_wipe->signature.data, '\0', kdc_sig_wipe->signature.length); 233 memset(srv_sig_wipe->signature.data, '\0', srv_sig_wipe->signature.length); 234 235 /* and reencode, back into the same place it came from */ 236 ndr_err = ndr_push_struct_blob(kdc_sig_blob, pac_data_raw, 237 kdc_sig_wipe, 238 (ndr_push_flags_fn_t)ndr_push_PAC_SIGNATURE_DATA); 239 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { 240 status = ndr_map_error2ntstatus(ndr_err); 241 DEBUG(0,("can't repack the KDC signature: %s\n", 242 nt_errstr(status))); 243 return status; 244 } 245 ndr_err = ndr_push_struct_blob(srv_sig_blob, pac_data_raw, 246 srv_sig_wipe, 247 (ndr_push_flags_fn_t)ndr_push_PAC_SIGNATURE_DATA); 248 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { 249 status = ndr_map_error2ntstatus(ndr_err); 250 DEBUG(0,("can't repack the SRV signature: %s\n", 251 nt_errstr(status))); 252 return status; 253 } 254 255 /* push out the whole structure, but now with zero'ed signatures */ 256 ndr_err = ndr_push_struct_blob(&modified_pac_blob, pac_data_raw, 257 pac_data_raw, 258 (ndr_push_flags_fn_t)ndr_push_PAC_DATA_RAW); 259 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { 260 status = ndr_map_error2ntstatus(ndr_err); 261 DEBUG(0,("can't repack the RAW PAC: %s\n", 262 nt_errstr(status))); 263 return status; 264 } 265 266 /* verify by service_key */ 267 ret = check_pac_checksum(mem_ctx, 268 modified_pac_blob, srv_sig_ptr, 269 context, 270 service_keyblock); 271 if (ret) { 272 DEBUG(1, ("PAC Decode: Failed to verify the service signature: %s\n", 273 smb_get_krb5_error_message(context, ret, mem_ctx))); 274 if (k5ret) { 275 *k5ret = ret; 276 } 277 return NT_STATUS_ACCESS_DENIED; 278 } 279 280 if (krbtgt_keyblock) { 281 ret = check_pac_checksum(mem_ctx, 282 srv_sig_ptr->signature, kdc_sig_ptr, 283 context, krbtgt_keyblock); 284 if (ret) { 285 DEBUG(1, ("PAC Decode: Failed to verify the KDC signature: %s\n", 286 smb_get_krb5_error_message(context, ret, mem_ctx))); 287 if (k5ret) { 288 *k5ret = ret; 289 } 290 return NT_STATUS_ACCESS_DENIED; 291 } 292 } 293 294 /* Convert to NT time, so as not to loose accuracy in comparison */ 295 unix_to_nt_time(&tgs_authtime_nttime, tgs_authtime); 296 297 if (tgs_authtime_nttime != logon_name->logon_time) { 298 DEBUG(2, ("PAC Decode: Logon time mismatch between ticket and PAC!\n")); 299 DEBUG(2, ("PAC Decode: PAC: %s\n", nt_time_string(mem_ctx, logon_name->logon_time))); 300 DEBUG(2, ("PAC Decode: Ticket: %s\n", nt_time_string(mem_ctx, tgs_authtime_nttime))); 301 return NT_STATUS_ACCESS_DENIED; 302 } 303 304 ret = krb5_parse_name_flags(context, logon_name->account_name, KRB5_PRINCIPAL_PARSE_NO_REALM, 305 &client_principal_pac); 306 if (ret) { 307 DEBUG(2, ("Could not parse name from incoming PAC: [%s]: %s\n", 308 logon_name->account_name, 309 smb_get_krb5_error_message(context, ret, mem_ctx))); 310 if (k5ret) { 311 *k5ret = ret; 312 } 313 return NT_STATUS_INVALID_PARAMETER; 314 } 315 316 if (!krb5_principal_compare_any_realm(context, client_principal, client_principal_pac)) { 317 DEBUG(2, ("Name in PAC [%s] does not match principal name in ticket\n", 318 logon_name->account_name)); 319 krb5_free_principal(context, client_principal_pac); 320 return NT_STATUS_ACCESS_DENIED; 321 } 322 323 krb5_free_principal(context, client_principal_pac); 324 325 #if 0 326 if (strcasecmp(logon_info->info3.base.account_name.string, 327 "Administrator")== 0) { 328 file_save("tmp_pac_data-admin.dat",blob.data,blob.length); 329 } 330 #endif 331 332 DEBUG(3,("Found account name from PAC: %s [%s]\n", 333 logon_info->info3.base.account_name.string, 334 logon_info->info3.base.full_name.string)); 335 *pac_data_out = pac_data; 336 337 return NT_STATUS_OK; 338 } 339 340 _PUBLIC_ NTSTATUS kerberos_pac_logon_info(TALLOC_CTX *mem_ctx, 341 struct PAC_LOGON_INFO **logon_info, 342 DATA_BLOB blob, 343 krb5_context context, 344 const krb5_keyblock *krbtgt_keyblock, 345 const krb5_keyblock *service_keyblock, 346 krb5_const_principal client_principal, 347 time_t tgs_authtime, 348 krb5_error_code *k5ret) 349 { 350 NTSTATUS nt_status; 351 struct PAC_DATA *pac_data; 352 int i; 353 nt_status = kerberos_decode_pac(mem_ctx, 354 &pac_data, 355 blob, 356 context, 357 krbtgt_keyblock, 358 service_keyblock, 359 client_principal, 360 tgs_authtime, 361 k5ret); 362 if (!NT_STATUS_IS_OK(nt_status)) { 363 return nt_status; 364 } 365 366 *logon_info = NULL; 367 for (i=0; i < pac_data->num_buffers; i++) { 368 if (pac_data->buffers[i].type != PAC_TYPE_LOGON_INFO) { 369 continue; 370 } 371 *logon_info = pac_data->buffers[i].info->logon_info.info; 372 } 373 if (!*logon_info) { 374 return NT_STATUS_INVALID_PARAMETER; 375 } 376 return NT_STATUS_OK; 377 } 378 379 static krb5_error_code make_pac_checksum(TALLOC_CTX *mem_ctx, 380 DATA_BLOB *pac_data, 381 struct PAC_SIGNATURE_DATA *sig, 382 krb5_context context, 383 const krb5_keyblock *keyblock) 384 { 385 krb5_error_code ret; 386 krb5_crypto crypto; 387 Checksum cksum; 388 389 390 ret = krb5_crypto_init(context, 391 keyblock, 392 0, 393 &crypto); 394 if (ret) { 395 DEBUG(0,("krb5_crypto_init() failed: %s\n", 396 smb_get_krb5_error_message(context, ret, mem_ctx))); 397 return ret; 398 } 399 ret = krb5_create_checksum(context, 400 crypto, 401 KRB5_KU_OTHER_CKSUM, 402 0, 403 pac_data->data, 404 pac_data->length, 405 &cksum); 406 if (ret) { 407 DEBUG(2, ("PAC Verification failed: %s\n", 408 smb_get_krb5_error_message(context, ret, mem_ctx))); 409 } 410 411 krb5_crypto_destroy(context, crypto); 412 413 if (ret) { 414 return ret; 415 } 416 417 sig->type = cksum.cksumtype; 418 sig->signature = data_blob_talloc(mem_ctx, cksum.checksum.data, cksum.checksum.length); 419 free_Checksum(&cksum); 420 421 return 0; 422 } 33 #include "auth/credentials/credentials.h" 34 #include "auth/kerberos/kerberos_util.h" 35 #include "auth/kerberos/pac_utils.h" 423 36 424 37 krb5_error_code kerberos_encode_pac(TALLOC_CTX *mem_ctx, … … 444 57 } 445 58 kdc_checksum = &pac_data->buffers[i].info->kdc_cksum, 446 ret = make_pac_checksum(mem_ctx, &zero_blob, 447 kdc_checksum, 448 context, krbtgt_keyblock); 59 ret = smb_krb5_make_pac_checksum(mem_ctx, 60 &zero_blob, 61 context, 62 krbtgt_keyblock, 63 &kdc_checksum->type, 64 &kdc_checksum->signature); 449 65 if (ret) { 450 66 DEBUG(2, ("making krbtgt PAC checksum failed: %s\n", … … 460 76 } 461 77 srv_checksum = &pac_data->buffers[i].info->srv_cksum; 462 ret = make_pac_checksum(mem_ctx, &zero_blob, 463 srv_checksum, 464 context, service_keyblock); 78 ret = smb_krb5_make_pac_checksum(mem_ctx, 79 &zero_blob, 80 context, 81 service_keyblock, 82 &srv_checksum->type, 83 &srv_checksum->signature); 465 84 if (ret) { 466 85 DEBUG(2, ("making service PAC checksum failed: %s\n", … … 495 114 496 115 /* Then sign the result of the previous push, where the sig was zero'ed out */ 497 ret = make_pac_checksum(mem_ctx, &tmp_blob, srv_checksum, 498 context, service_keyblock); 116 ret = smb_krb5_make_pac_checksum(mem_ctx, 117 &tmp_blob, 118 context, 119 service_keyblock, 120 &srv_checksum->type, 121 &srv_checksum->signature); 499 122 500 123 /* Then sign Server checksum */ 501 ret = make_pac_checksum(mem_ctx, &srv_checksum->signature, kdc_checksum, context, krbtgt_keyblock); 124 ret = smb_krb5_make_pac_checksum(mem_ctx, 125 &srv_checksum->signature, 126 context, 127 krbtgt_keyblock, 128 &kdc_checksum->type, 129 &kdc_checksum->signature); 502 130 if (ret) { 503 131 DEBUG(2, ("making krbtgt PAC checksum failed: %s\n", … … 624 252 625 253 ret = krb5_unparse_name_flags(context, client_principal, 626 KRB5_PRINCIPAL_UNPARSE_NO_REALM, &name); 254 KRB5_PRINCIPAL_UNPARSE_NO_REALM | 255 KRB5_PRINCIPAL_UNPARSE_DISPLAY, 256 &name); 627 257 if (ret) { 628 258 return ret; … … 680 310 PAC_TYPE_LOGON_INFO, 681 311 (ndr_pull_flags_fn_t)ndr_pull_PAC_INFO); 682 k rb5_data_free(&k5pac_logon_info_in);312 kerberos_free_data_contents(context, &k5pac_logon_info_in); 683 313 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err) || !info.logon_info.info) { 684 314 nt_status = ndr_map_error2ntstatus(ndr_err); … … 709 339 pac_srv_sig, 710 340 (ndr_pull_flags_fn_t)ndr_pull_PAC_SIGNATURE_DATA); 711 k rb5_data_free(&k5pac_srv_checksum_in);341 kerberos_free_data_contents(context, &k5pac_srv_checksum_in); 712 342 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { 713 343 nt_status = ndr_map_error2ntstatus(ndr_err); … … 730 360 pac_kdc_sig, 731 361 (ndr_pull_flags_fn_t)ndr_pull_PAC_SIGNATURE_DATA); 732 k rb5_data_free(&k5pac_kdc_checksum_in);362 kerberos_free_data_contents(context, &k5pac_kdc_checksum_in); 733 363 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { 734 364 nt_status = ndr_map_error2ntstatus(ndr_err); … … 757 387 &pac); 758 388 if (ret) { 759 return map_nt_error_from_unix (ret);389 return map_nt_error_from_unix_common(ret); 760 390 } 761 391 … … 764 394 krb5_pac_free(context, pac); 765 395 if (ret) { 766 return map_nt_error_from_unix (ret);396 return map_nt_error_from_unix_common(ret); 767 397 } 768 398 return NT_STATUS_OK; -
vendor/current/source4/auth/kerberos/kerberos_util.c
r740 r988 29 29 #include "auth/kerberos/kerberos_credentials.h" 30 30 #include "auth/kerberos/kerberos_util.h" 31 #include <ldb.h>32 #include "param/secrets.h"33 31 34 32 struct principal_container { … … 64 62 65 63 if (ret) { 66 (*error_string) = smb_get_krb5_error_message(smb_krb5_context->krb5_context, ret, parent_ctx); 64 (*error_string) = smb_get_krb5_error_message( 65 smb_krb5_context->krb5_context, 66 ret, parent_ctx); 67 67 return ret; 68 68 } … … 76 76 /* This song-and-dance effectivly puts the principal 77 77 * into talloc, so we can't loose it. */ 78 mem_ctx->smb_krb5_context = talloc_reference(mem_ctx, smb_krb5_context); 78 mem_ctx->smb_krb5_context = talloc_reference(mem_ctx, 79 smb_krb5_context); 79 80 mem_ctx->principal = *princ; 80 81 talloc_set_destructor(mem_ctx, free_principal); 81 82 return 0; 82 }83 84 static krb5_error_code principals_from_msg(TALLOC_CTX *parent_ctx,85 struct ldb_message *msg,86 struct smb_krb5_context *smb_krb5_context,87 struct principal_container ***principals_out,88 const char **error_string)89 {90 unsigned int i;91 krb5_error_code ret;92 char *upper_realm;93 const char *realm = ldb_msg_find_attr_as_string(msg, "realm", NULL);94 const char *samAccountName = ldb_msg_find_attr_as_string(msg, "samAccountName", NULL);95 struct ldb_message_element *spn_el = ldb_msg_find_element(msg, "servicePrincipalName");96 TALLOC_CTX *tmp_ctx;97 struct principal_container **principals;98 tmp_ctx = talloc_new(parent_ctx);99 if (!tmp_ctx) {100 *error_string = "Cannot allocate tmp_ctx";101 return ENOMEM;102 }103 104 if (!realm) {105 *error_string = "Cannot have a kerberos secret in secrets.ldb without a realm";106 return EINVAL;107 }108 109 upper_realm = strupper_talloc(tmp_ctx, realm);110 if (!upper_realm) {111 talloc_free(tmp_ctx);112 *error_string = "Cannot allocate full upper case realm";113 return ENOMEM;114 }115 116 principals = talloc_array(tmp_ctx, struct principal_container *, spn_el ? (spn_el->num_values + 2) : 2);117 118 spn_el = ldb_msg_find_element(msg, "servicePrincipalName");119 for (i=0; spn_el && i < spn_el->num_values; i++) {120 principals[i] = talloc(principals, struct principal_container);121 if (!principals[i]) {122 talloc_free(tmp_ctx);123 *error_string = "Cannot allocate mem_ctx";124 return ENOMEM;125 }126 127 principals[i]->smb_krb5_context = talloc_reference(principals[i], smb_krb5_context);128 principals[i]->string_form = talloc_asprintf(principals[i], "%*.*s@%s",129 (int)spn_el->values[i].length,130 (int)spn_el->values[i].length,131 (const char *)spn_el->values[i].data, upper_realm);132 if (!principals[i]->string_form) {133 talloc_free(tmp_ctx);134 *error_string = "Cannot allocate full samAccountName";135 return ENOMEM;136 }137 138 ret = krb5_parse_name(smb_krb5_context->krb5_context,139 principals[i]->string_form, &principals[i]->principal);140 141 if (ret) {142 talloc_free(tmp_ctx);143 (*error_string) = smb_get_krb5_error_message(smb_krb5_context->krb5_context, ret, parent_ctx);144 return ret;145 }146 147 /* This song-and-dance effectivly puts the principal148 * 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 principal177 * into talloc, so we can't loose it. */178 talloc_set_destructor(principals[i], free_principal);179 i++;180 }181 182 principals[i] = NULL;183 *principals_out = talloc_steal(parent_ctx, principals);184 185 talloc_free(tmp_ctx);186 return ret;187 }188 189 static krb5_error_code salt_principal_from_msg(TALLOC_CTX *parent_ctx,190 struct ldb_message *msg,191 struct smb_krb5_context *smb_krb5_context,192 krb5_principal *salt_princ,193 const char **error_string)194 {195 const char *salt_principal = ldb_msg_find_attr_as_string(msg, "saltPrincipal", NULL);196 const char *samAccountName = ldb_msg_find_attr_as_string(msg, "samAccountName", NULL);197 const char *realm = ldb_msg_find_attr_as_string(msg, "realm", NULL);198 if (salt_principal) {199 return parse_principal(parent_ctx, salt_principal, smb_krb5_context, salt_princ, error_string);200 } else if (samAccountName) {201 krb5_error_code ret;202 char *machine_username;203 char *salt_body;204 char *lower_realm;205 char *upper_realm;206 207 TALLOC_CTX *tmp_ctx;208 struct principal_container *mem_ctx = talloc(parent_ctx, struct principal_container);209 if (!mem_ctx) {210 *error_string = "Cannot allocate mem_ctx";211 return ENOMEM;212 }213 214 tmp_ctx = talloc_new(mem_ctx);215 if (!tmp_ctx) {216 talloc_free(mem_ctx);217 *error_string = "Cannot allocate tmp_ctx";218 return ENOMEM;219 }220 221 if (!realm) {222 *error_string = "Cannot have a kerberos secret in secrets.ldb without a realm";223 return EINVAL;224 }225 226 machine_username = talloc_strdup(tmp_ctx, samAccountName);227 if (!machine_username) {228 talloc_free(mem_ctx);229 *error_string = "Cannot duplicate samAccountName";230 return ENOMEM;231 }232 233 if (machine_username[strlen(machine_username)-1] == '$') {234 machine_username[strlen(machine_username)-1] = '\0';235 }236 237 lower_realm = strlower_talloc(tmp_ctx, realm);238 if (!lower_realm) {239 talloc_free(mem_ctx);240 *error_string = "Cannot allocate to lower case realm";241 return ENOMEM;242 }243 244 upper_realm = strupper_talloc(tmp_ctx, realm);245 if (!upper_realm) {246 talloc_free(mem_ctx);247 *error_string = "Cannot allocate to upper case realm";248 return ENOMEM;249 }250 251 salt_body = talloc_asprintf(tmp_ctx, "%s.%s", machine_username,252 lower_realm);253 talloc_free(lower_realm);254 talloc_free(machine_username);255 if (!salt_body) {256 talloc_free(mem_ctx);257 *error_string = "Cannot form salt principal body";258 return ENOMEM;259 }260 261 ret = krb5_make_principal(smb_krb5_context->krb5_context, salt_princ,262 upper_realm,263 "host", salt_body, NULL);264 if (ret == 0) {265 /* This song-and-dance effectivly puts the principal266 * 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 }279 83 } 280 84 … … 284 88 * system by means of a destructor (do *not* free). */ 285 89 286 krb5_error_code principal_from_credentials(TALLOC_CTX *parent_ctx, 287 struct cli_credentials *credentials,288 289 290 291 90 krb5_error_code principal_from_credentials(TALLOC_CTX *parent_ctx, 91 struct cli_credentials *credentials, 92 struct smb_krb5_context *smb_krb5_context, 93 krb5_principal *princ, 94 enum credentials_obtained *obtained, 95 const char **error_string) 292 96 { 293 97 krb5_error_code ret; 294 98 const char *princ_string; 295 99 TALLOC_CTX *mem_ctx = talloc_new(parent_ctx); 100 *obtained = CRED_UNINITIALISED; 101 296 102 if (!mem_ctx) { 297 103 (*error_string) = error_message(ENOMEM); 298 104 return ENOMEM; 299 105 } 300 princ_string = cli_credentials_get_principal_and_obtained(credentials, mem_ctx, obtained); 106 princ_string = cli_credentials_get_principal_and_obtained(credentials, 107 mem_ctx, 108 obtained); 301 109 if (!princ_string) { 302 (*error_string) = error_message(ENOMEM);303 return ENOMEM;110 *princ = NULL; 111 return 0; 304 112 } 305 113 … … 315 123 * system by means of a destructor (do *not* free). */ 316 124 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); 125 static krb5_error_code impersonate_principal_from_credentials( 126 TALLOC_CTX *parent_ctx, 127 struct cli_credentials *credentials, 128 struct smb_krb5_context *smb_krb5_context, 129 krb5_principal *princ, 130 const char **error_string) 131 { 132 return parse_principal(parent_ctx, 133 cli_credentials_get_impersonate_principal(credentials), 134 smb_krb5_context, princ, error_string); 135 } 136 137 krb5_error_code smb_krb5_create_principals_array(TALLOC_CTX *mem_ctx, 138 krb5_context context, 139 const char *account_name, 140 const char *realm, 141 uint32_t num_spns, 142 const char *spns[], 143 uint32_t *pnum_principals, 144 krb5_principal **pprincipals, 145 const char **error_string) 146 { 147 krb5_error_code code; 148 TALLOC_CTX *tmp_ctx; 149 uint32_t num_principals = 0; 150 krb5_principal *principals; 151 uint32_t i; 152 153 tmp_ctx = talloc_new(mem_ctx); 154 if (tmp_ctx == NULL) { 155 *error_string = "Cannot allocate tmp_ctx"; 156 return ENOMEM; 157 } 158 159 if (realm == NULL) { 160 *error_string = "Cannot create principal without a realm"; 161 code = EINVAL; 162 goto done; 163 } 164 165 if (account_name == NULL && (num_spns == 0 || spns == NULL)) { 166 *error_string = "Cannot create principal without an account or SPN"; 167 code = EINVAL; 168 goto done; 169 } 170 171 if (account_name != NULL && account_name[0] != '\0') { 172 num_principals++; 173 } 174 num_principals += num_spns; 175 176 principals = talloc_zero_array(tmp_ctx, 177 krb5_principal, 178 num_principals); 179 if (principals == NULL) { 180 *error_string = "Cannot allocate principals"; 181 code = ENOMEM; 182 goto done; 183 } 184 185 for (i = 0; i < num_spns; i++) { 186 code = krb5_parse_name(context, spns[i], &(principals[i])); 187 if (code != 0) { 188 *error_string = smb_get_krb5_error_message(context, 189 code, 190 mem_ctx); 191 goto done; 192 } 193 } 194 195 if (account_name != NULL && account_name[0] != '\0') { 196 code = smb_krb5_make_principal(context, 197 &(principals[i]), 198 realm, 199 account_name, 200 NULL); 201 if (code != 0) { 202 *error_string = smb_get_krb5_error_message(context, 203 code, 204 mem_ctx); 205 goto done; 206 } 207 } 208 209 if (pnum_principals != NULL) { 210 *pnum_principals = num_principals; 211 212 if (pprincipals != NULL) { 213 *pprincipals = talloc_steal(mem_ctx, principals); 214 } 215 } 216 217 code = 0; 218 done: 219 talloc_free(tmp_ctx); 220 return code; 325 221 } 326 222 … … 339 235 { 340 236 krb5_error_code ret; 341 const char *password, *target_service; 237 const char *password; 238 #ifdef SAMBA4_USES_HEIMDAL 239 const char *self_service; 240 #endif 241 const char *target_service; 342 242 time_t kdc_time = 0; 343 243 krb5_principal princ; … … 358 258 } 359 259 260 if (princ == NULL) { 261 (*error_string) = talloc_asprintf(credentials, "principal, username or realm was not specified in the credentials"); 262 talloc_free(mem_ctx); 263 return KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN; 264 } 265 360 266 ret = impersonate_principal_from_credentials(mem_ctx, credentials, smb_krb5_context, &impersonate_principal, error_string); 361 267 if (ret) { … … 364 270 } 365 271 272 #ifdef SAMBA4_USES_HEIMDAL 273 self_service = cli_credentials_get_self_service(credentials); 274 #endif 366 275 target_service = cli_credentials_get_target_service(credentials); 367 276 … … 377 286 } 378 287 288 #ifdef SAMBA4_USES_HEIMDAL /* Disable for now MIT reads defaults when needed */ 379 289 /* get the defaults */ 380 290 krb5_get_init_creds_opt_set_default_flags(smb_krb5_context->krb5_context, NULL, NULL, krb_options); 381 291 #endif 382 292 /* set if we want a forwardable ticket */ 383 293 switch (cli_credentials_get_krb_forwardable(credentials)) { … … 392 302 } 393 303 304 #ifdef SAMBA4_USES_HEIMDAL /* FIXME: MIT does not have this yet */ 305 /* 306 * In order to work against windows KDCs even if we use 307 * the netbios domain name as realm, we need to add the following 308 * flags: 309 * KRB5_INIT_CREDS_NO_C_CANON_CHECK; 310 * KRB5_INIT_CREDS_NO_C_NO_EKU_CHECK; 311 * 312 * On MIT: Set pkinit_eku_checking to none 313 */ 314 krb5_get_init_creds_opt_set_win2k(smb_krb5_context->krb5_context, 315 krb_options, true); 316 #else /* MIT */ 317 krb5_get_init_creds_opt_set_canonicalize(krb_options, true); 318 #endif 319 394 320 tries = 2; 395 321 while (tries--) { 322 #ifdef SAMBA4_USES_HEIMDAL 396 323 struct tevent_context *previous_ev; 397 324 /* Do this every time, in case we have weird recursive issues here */ … … 401 328 return ret; 402 329 } 330 #endif 403 331 if (password) { 404 ret = kerberos_kinit_password_cc(smb_krb5_context->krb5_context, ccache, 405 princ, password, 406 impersonate_principal, target_service, 407 krb_options, 408 NULL, &kdc_time); 332 if (impersonate_principal) { 333 #ifdef SAMBA4_USES_HEIMDAL 334 ret = kerberos_kinit_s4u2_cc( 335 smb_krb5_context->krb5_context, 336 ccache, princ, password, 337 impersonate_principal, 338 self_service, target_service, 339 krb_options, NULL, &kdc_time); 340 #else 341 talloc_free(mem_ctx); 342 (*error_string) = "INTERNAL error: s4u2 ops " 343 "are not supported with MIT build yet"; 344 return EINVAL; 345 #endif 346 } else { 347 ret = kerberos_kinit_password_cc( 348 smb_krb5_context->krb5_context, 349 ccache, princ, password, 350 target_service, 351 krb_options, NULL, &kdc_time); 352 } 409 353 } else if (impersonate_principal) { 410 354 talloc_free(mem_ctx); … … 421 365 (*error_string) = "kinit_to_ccache: No password available for kinit\n"; 422 366 krb5_get_init_creds_opt_free(smb_krb5_context->krb5_context, krb_options); 367 #ifdef SAMBA4_USES_HEIMDAL 423 368 smb_krb5_context_remove_event_ctx(smb_krb5_context, previous_ev, event_ctx); 369 #endif 424 370 return EINVAL; 425 371 } 426 ret = krb5_keyblock_init(smb_krb5_context->krb5_context,372 ret = smb_krb5_keyblock_init_contents(smb_krb5_context->krb5_context, 427 373 ENCTYPE_ARCFOUR_HMAC, 428 374 mach_pwd->hash, sizeof(mach_pwd->hash), … … 438 384 } 439 385 386 #ifdef SAMBA4_USES_HEIMDAL 440 387 smb_krb5_context_remove_event_ctx(smb_krb5_context, previous_ev, event_ctx); 388 #endif 441 389 442 390 if (ret == KRB5KRB_AP_ERR_SKEW || ret == KRB5_KDCREP_SKEW) { … … 485 433 talloc_free(mem_ctx); 486 434 return ret; 487 } 435 } 436 437 DEBUG(10,("kinit for %s succeeded\n", 438 cli_credentials_get_principal(credentials, mem_ctx))); 439 440 488 441 talloc_free(mem_ctx); 489 442 return 0; 490 443 } 491 444 492 static krb5_error_code free_keytab (struct keytab_container *ktc)445 static krb5_error_code free_keytab_container(struct keytab_container *ktc) 493 446 { 494 447 return krb5_kt_close(ktc->smb_krb5_context->krb5_context, ktc->keytab); 495 448 } 496 449 497 krb5_error_code smb_krb5_open_keytab(TALLOC_CTX *mem_ctx, 498 struct smb_krb5_context *smb_krb5_context, 499 const char *keytab_name, struct keytab_container **ktc) 450 krb5_error_code smb_krb5_get_keytab_container(TALLOC_CTX *mem_ctx, 451 struct smb_krb5_context *smb_krb5_context, 452 krb5_keytab opt_keytab, 453 const char *keytab_name, 454 struct keytab_container **ktc) 500 455 { 501 456 krb5_keytab keytab; 502 457 krb5_error_code ret; 503 ret = krb5_kt_resolve(smb_krb5_context->krb5_context, keytab_name, &keytab); 504 if (ret) { 505 DEBUG(1,("failed to open krb5 keytab: %s\n", 506 smb_get_krb5_error_message(smb_krb5_context->krb5_context, 507 ret, mem_ctx))); 508 return ret; 458 459 if (opt_keytab) { 460 keytab = opt_keytab; 461 } else { 462 ret = krb5_kt_resolve(smb_krb5_context->krb5_context, 463 keytab_name, &keytab); 464 if (ret) { 465 DEBUG(1,("failed to open krb5 keytab: %s\n", 466 smb_get_krb5_error_message( 467 smb_krb5_context->krb5_context, 468 ret, mem_ctx))); 469 return ret; 470 } 509 471 } 510 472 … … 516 478 (*ktc)->smb_krb5_context = talloc_reference(*ktc, smb_krb5_context); 517 479 (*ktc)->keytab = keytab; 518 talloc_set_destructor(*ktc, free_keytab); 480 (*ktc)->password_based = false; 481 talloc_set_destructor(*ktc, free_keytab_container); 519 482 520 483 return 0; 521 484 } 522 485 523 static krb5_error_code keytab_add_keys(TALLOC_CTX *parent_ctx,524 struct principal_container **principals,525 krb5_principal salt_princ,526 int kvno,527 const char *password_s,528 struct smb_krb5_context *smb_krb5_context,529 krb5_enctype *enctypes,530 krb5_keytab keytab,531 const char **error_string)532 {533 unsigned int i, p;534 krb5_error_code ret;535 krb5_data password;536 537 password.data = discard_const_p(char *, password_s);538 password.length = strlen(password_s);539 540 for (i=0; enctypes[i]; i++) {541 krb5_keytab_entry entry;542 543 ZERO_STRUCT(entry);544 545 ret = create_kerberos_key_from_string(smb_krb5_context->krb5_context,546 salt_princ, &password, &entry.keyblock, enctypes[i]);547 if (ret != 0) {548 return ret;549 }550 551 entry.vno = kvno;552 553 for (p=0; principals[p]; p++) {554 entry.principal = principals[p]->principal;555 ret = krb5_kt_add_entry(smb_krb5_context->krb5_context, keytab, &entry);556 if (ret != 0) {557 char *k5_error_string = smb_get_krb5_error_message(smb_krb5_context->krb5_context,558 ret, NULL);559 *error_string = talloc_asprintf(parent_ctx, "Failed to add enctype %d entry for %s(kvno %d) to keytab: %s\n",560 (int)enctypes[i],561 principals[p]->string_form,562 kvno,563 k5_error_string);564 talloc_free(k5_error_string);565 krb5_free_keyblock_contents(smb_krb5_context->krb5_context, &entry.keyblock);566 return ret;567 }568 569 DEBUG(5, ("Added %s(kvno %d) to keytab (enctype %d)\n",570 principals[p]->string_form, kvno,571 (int)enctypes[i]));572 }573 krb5_free_keyblock_contents(smb_krb5_context->krb5_context, &entry.keyblock);574 }575 return 0;576 }577 578 static krb5_error_code create_keytab(TALLOC_CTX *parent_ctx,579 struct ldb_message *msg,580 struct principal_container **principals,581 struct smb_krb5_context *smb_krb5_context,582 krb5_keytab keytab,583 bool add_old,584 const char **error_string)585 {586 krb5_error_code ret;587 const char *password_s;588 const char *old_secret;589 int kvno;590 uint32_t enctype_bitmap;591 krb5_principal salt_princ;592 krb5_enctype *enctypes;593 TALLOC_CTX *mem_ctx = talloc_new(parent_ctx);594 if (!mem_ctx) {595 *error_string = "unable to allocate tmp_ctx for create_keytab";596 return ENOMEM;597 }598 599 /* The salt used to generate these entries may be different however, fetch that */600 ret = salt_principal_from_msg(mem_ctx, msg,601 smb_krb5_context,602 &salt_princ, error_string);603 if (ret) {604 talloc_free(mem_ctx);605 return ret;606 }607 608 kvno = ldb_msg_find_attr_as_int(msg, "msDS-KeyVersionNumber", 0);609 610 /* Finally, do the dance to get the password to put in the entry */611 password_s = ldb_msg_find_attr_as_string(msg, "secret", NULL);612 613 if (!password_s) {614 /* There is no password here, so nothing to do */615 talloc_free(mem_ctx);616 return 0;617 }618 619 if (add_old && kvno != 0) {620 old_secret = ldb_msg_find_attr_as_string(msg, "priorSecret", NULL);621 } else {622 old_secret = NULL;623 }624 625 enctype_bitmap = (uint32_t)ldb_msg_find_attr_as_int(msg, "msDS-SupportedEncryptionTypes", ENC_ALL_TYPES);626 627 ret = kerberos_enctype_bitmap_to_enctypes(mem_ctx, enctype_bitmap, &enctypes);628 if (ret) {629 *error_string = talloc_asprintf(parent_ctx, "create_keytab: generating list of encryption types failed (%s)\n",630 smb_get_krb5_error_message(smb_krb5_context->krb5_context,631 ret, mem_ctx));632 talloc_free(mem_ctx);633 return ret;634 }635 636 ret = keytab_add_keys(mem_ctx, principals,637 salt_princ,638 kvno, password_s, smb_krb5_context,639 enctypes, keytab, error_string);640 if (ret) {641 talloc_free(mem_ctx);642 return ret;643 }644 645 if (old_secret) {646 ret = keytab_add_keys(mem_ctx, principals,647 salt_princ,648 kvno - 1, old_secret, smb_krb5_context,649 enctypes, keytab, error_string);650 if (ret) {651 talloc_free(mem_ctx);652 return ret;653 }654 }655 656 talloc_free(mem_ctx);657 return ret;658 }659 660 486 /* 661 * Walk the keytab, looking for entries of this principal name, with KVNO other than current kvno -1. 487 * Walk the keytab, looking for entries of this principal name, 488 * with KVNO other than current kvno -1. 662 489 * 663 * These entries are now stale, we only keep the current, and previous entries around. 490 * These entries are now stale, 491 * we only keep the current and previous entries around. 664 492 * 665 493 * Inspired by the code in Samba3 for 'use kerberos keytab'. 666 *667 494 */ 668 669 static krb5_error_code remove_old_entries(TALLOC_CTX *parent_ctx, 670 struct ldb_message *msg, 671 struct principal_container **principals, 672 bool delete_all_kvno, 673 struct smb_krb5_context *smb_krb5_context, 674 krb5_keytab keytab, bool *found_previous, 675 const char **error_string) 676 { 677 krb5_error_code ret, ret2; 495 krb5_error_code smb_krb5_remove_obsolete_keytab_entries(TALLOC_CTX *mem_ctx, 496 krb5_context context, 497 krb5_keytab keytab, 498 uint32_t num_principals, 499 krb5_principal *principals, 500 krb5_kvno kvno, 501 bool *found_previous, 502 const char **error_string) 503 { 504 TALLOC_CTX *tmp_ctx; 505 krb5_error_code code; 678 506 krb5_kt_cursor cursor; 679 int kvno; 680 TALLOC_CTX *mem_ctx = talloc_new(parent_ctx);681 682 if (!mem_ctx) {507 508 tmp_ctx = talloc_new(mem_ctx); 509 if (tmp_ctx == NULL) { 510 *error_string = "Cannot allocate tmp_ctx"; 683 511 return ENOMEM; 684 512 } 685 513 686 *found_previous = false; 687 688 kvno = ldb_msg_find_attr_as_int(msg, "msDS-KeyVersionNumber", 0); 689 690 /* for each entry in the keytab */ 691 ret = krb5_kt_start_seq_get(smb_krb5_context->krb5_context, keytab, &cursor); 692 switch (ret) { 514 *found_previous = true; 515 516 code = krb5_kt_start_seq_get(context, keytab, &cursor); 517 switch (code) { 693 518 case 0: 694 519 break; 520 #ifdef HEIM_ERR_OPNOTSUPP 695 521 case HEIM_ERR_OPNOTSUPP: 522 #endif 696 523 case ENOENT: 697 524 case KRB5_KT_END: 698 525 /* no point enumerating if there isn't anything here */ 699 talloc_free(mem_ctx);700 return 0;526 code = 0; 527 goto done; 701 528 default: 702 *error_string = talloc_asprintf( parent_ctx, "failed to open keytab for read of old entries: %s\n",703 smb_get_krb5_error_message(smb_krb5_context->krb5_context,704 ret, mem_ctx));705 talloc_free(mem_ctx);706 return ret;707 } 708 709 while (!ret) {710 unsigned int i;529 *error_string = talloc_asprintf(mem_ctx, 530 "failed to open keytab for read of old entries: %s\n", 531 smb_get_krb5_error_message(context, code, mem_ctx)); 532 goto done; 533 } 534 535 do { 536 krb5_kvno old_kvno = kvno - 1; 537 krb5_keytab_entry entry; 711 538 bool matched = false; 712 krb5_keytab_entry entry; 713 ret = krb5_kt_next_entry(smb_krb5_context->krb5_context, keytab, &entry, &cursor); 714 if (ret) { 539 uint32_t i; 540 541 code = krb5_kt_next_entry(context, keytab, &entry, &cursor); 542 if (code) { 715 543 break; 716 544 } 717 for (i = 0; principals[i]; i++) { 718 /* if it matches our principal */ 719 if (krb5_kt_compare(smb_krb5_context->krb5_context, &entry, principals[i]->principal, 0, 0)) { 545 546 for (i = 0; i < num_principals; i++) { 547 krb5_boolean ok; 548 549 ok = smb_krb5_kt_compare(context, 550 &entry, 551 principals[i], 552 0, 553 0); 554 if (ok) { 720 555 matched = true; 721 556 break; … … 724 559 725 560 if (!matched) { 726 /* Free the entry, it wasn't the one we were looking for anyway */ 727 krb5_kt_free_entry(smb_krb5_context->krb5_context, &entry); 561 /* 562 * Free the entry, it wasn't the one we were looking 563 * for anyway 564 */ 565 krb5_kt_free_entry(context, &entry); 566 /* Make sure we do not double free */ 567 ZERO_STRUCT(entry); 728 568 continue; 729 569 } 730 570 731 /* delete it, if it is not kvno -1 */ 732 if (entry.vno != (kvno - 1 )) { 571 /* 572 * Delete it, if it is not kvno - 1. 573 * 574 * Some keytab files store the kvno only in 8bits. Limit the 575 * compare to 8bits, so that we don't miss old keys and delete 576 * them. 577 */ 578 if ((entry.vno & 0xff) != (old_kvno & 0xff)) { 579 krb5_error_code rc; 580 733 581 /* Release the enumeration. We are going to 734 582 * have to start this from the top again, 735 583 * because deletes during enumeration may not 736 * always be consist ant.584 * always be consistent. 737 585 * 738 586 * Also, the enumeration locks a FILE: keytab 739 587 */ 740 741 krb5_kt_end_seq_get(smb_krb5_context->krb5_context, keytab, &cursor); 742 743 ret = krb5_kt_remove_entry(smb_krb5_context->krb5_context, keytab, &entry); 744 krb5_kt_free_entry(smb_krb5_context->krb5_context, &entry); 588 krb5_kt_end_seq_get(context, keytab, &cursor); 589 590 code = krb5_kt_remove_entry(context, keytab, &entry); 591 krb5_kt_free_entry(context, &entry); 592 593 /* Make sure we do not double free */ 594 ZERO_STRUCT(entry); 745 595 746 596 /* Deleted: Restart from the top */ 747 ret2 = krb5_kt_start_seq_get(smb_krb5_context->krb5_context, keytab, &cursor); 748 if (ret2) { 749 krb5_kt_free_entry(smb_krb5_context->krb5_context, &entry); 750 DEBUG(1,("failed to restart enumeration of keytab: %s\n", 751 smb_get_krb5_error_message(smb_krb5_context->krb5_context, 752 ret, mem_ctx))); 753 754 talloc_free(mem_ctx); 755 return ret2; 597 rc = krb5_kt_start_seq_get(context, keytab, &cursor); 598 if (rc != 0) { 599 krb5_kt_free_entry(context, &entry); 600 601 /* Make sure we do not double free */ 602 ZERO_STRUCT(entry); 603 604 DEBUG(1, ("failed to restart enumeration of keytab: %s\n", 605 smb_get_krb5_error_message(context, 606 code, 607 tmp_ctx))); 608 609 talloc_free(tmp_ctx); 610 return rc; 756 611 } 757 612 758 if ( ret) {613 if (code != 0) { 759 614 break; 760 615 } 761 616 762 617 } else { 763 618 *found_previous = true; 764 619 } 765 620 766 621 /* Free the entry, we don't need it any more */ 767 krb5_kt_free_entry(smb_krb5_context->krb5_context, &entry); 768 769 770 } 771 krb5_kt_end_seq_get(smb_krb5_context->krb5_context, keytab, &cursor); 772 773 switch (ret) { 622 krb5_kt_free_entry(context, &entry); 623 /* Make sure we do not double free */ 624 ZERO_STRUCT(entry); 625 } while (code != 0); 626 627 krb5_kt_end_seq_get(context, keytab, &cursor); 628 629 switch (code) { 774 630 case 0: 775 631 break; 776 632 case ENOENT: 777 633 case KRB5_KT_END: 778 ret= 0;634 code = 0; 779 635 break; 780 636 default: 781 *error_string = talloc_asprintf(parent_ctx, "failed in deleting old entries for principal: %s\n", 782 smb_get_krb5_error_message(smb_krb5_context->krb5_context, 783 ret, mem_ctx)); 784 } 785 talloc_free(mem_ctx); 786 return ret; 787 } 788 789 krb5_error_code smb_krb5_update_keytab(TALLOC_CTX *parent_ctx, 790 struct smb_krb5_context *smb_krb5_context, 791 struct ldb_context *ldb, 792 struct ldb_message *msg, 793 bool delete_all_kvno, 794 const char **error_string) 795 { 796 krb5_error_code ret; 797 bool found_previous; 798 TALLOC_CTX *mem_ctx = talloc_new(NULL); 799 struct keytab_container *keytab_container; 800 struct principal_container **principals; 801 const char *keytab_name; 802 803 if (!mem_ctx) { 804 return ENOMEM; 805 } 806 807 keytab_name = keytab_name_from_msg(mem_ctx, ldb, msg); 808 if (!keytab_name) { 809 return ENOENT; 810 } 811 812 ret = smb_krb5_open_keytab(mem_ctx, smb_krb5_context, keytab_name, &keytab_container); 813 814 if (ret != 0) { 815 talloc_free(mem_ctx); 816 return ret; 817 } 818 819 DEBUG(5, ("Opened keytab %s\n", keytab_name)); 820 821 /* Get the principal we will store the new keytab entries under */ 822 ret = principals_from_msg(mem_ctx, msg, smb_krb5_context, &principals, error_string); 823 824 if (ret != 0) { 825 *error_string = talloc_asprintf(parent_ctx, "Failed to load principals from ldb message: %s\n", *error_string); 826 talloc_free(mem_ctx); 827 return ret; 828 } 829 830 ret = remove_old_entries(mem_ctx, msg, principals, delete_all_kvno, 831 smb_krb5_context, keytab_container->keytab, &found_previous, error_string); 832 if (ret != 0) { 833 *error_string = talloc_asprintf(parent_ctx, "Failed to remove old principals from keytab: %s\n", *error_string); 834 talloc_free(mem_ctx); 835 return ret; 836 } 837 838 if (!delete_all_kvno) { 839 /* Create a new keytab. If during the cleanout we found 840 * entires for kvno -1, then don't try and duplicate them. 841 * Otherwise, add kvno, and kvno -1 */ 842 843 ret = create_keytab(mem_ctx, msg, principals, 844 smb_krb5_context, 845 keytab_container->keytab, 846 found_previous ? false : true, error_string); 847 } 848 talloc_free(mem_ctx); 849 return ret; 850 } 851 852 krb5_error_code smb_krb5_create_memory_keytab(TALLOC_CTX *parent_ctx, 853 struct cli_credentials *machine_account, 854 struct smb_krb5_context *smb_krb5_context, 855 struct keytab_container **keytab_container) 856 { 857 krb5_error_code ret; 858 TALLOC_CTX *mem_ctx = talloc_new(parent_ctx); 859 const char *rand_string; 860 const char *keytab_name; 861 struct ldb_message *msg; 862 const char *error_string; 863 if (!mem_ctx) { 864 return ENOMEM; 865 } 866 867 *keytab_container = talloc(mem_ctx, struct keytab_container); 868 869 rand_string = generate_random_str(mem_ctx, 16); 870 if (!rand_string) { 871 talloc_free(mem_ctx); 872 return ENOMEM; 873 } 874 875 keytab_name = talloc_asprintf(mem_ctx, "MEMORY:%s", 876 rand_string); 877 if (!keytab_name) { 878 talloc_free(mem_ctx); 879 return ENOMEM; 880 } 881 882 ret = smb_krb5_open_keytab(mem_ctx, smb_krb5_context, keytab_name, keytab_container); 883 if (ret) { 884 return ret; 885 } 886 887 msg = ldb_msg_new(mem_ctx); 888 if (!msg) { 889 talloc_free(mem_ctx); 890 return ENOMEM; 891 } 892 ldb_msg_add_string(msg, "krb5Keytab", keytab_name); 893 ldb_msg_add_string(msg, "secret", cli_credentials_get_password(machine_account)); 894 ldb_msg_add_string(msg, "samAccountName", cli_credentials_get_username(machine_account)); 895 ldb_msg_add_string(msg, "realm", cli_credentials_get_realm(machine_account)); 896 ldb_msg_add_fmt(msg, "msDS-KeyVersionNumber", "%d", (int)cli_credentials_get_kvno(machine_account)); 897 898 ret = smb_krb5_update_keytab(mem_ctx, smb_krb5_context, NULL, msg, false, &error_string); 899 if (ret == 0) { 900 talloc_steal(parent_ctx, *keytab_container); 901 } else { 902 DEBUG(0, ("Failed to create in-memory keytab: %s\n", error_string)); 903 *keytab_container = NULL; 904 } 905 talloc_free(mem_ctx); 906 return ret; 907 } 908 /* Translate between the IETF encryption type values and the Microsoft msDS-SupportedEncryptionTypes values */ 909 uint32_t kerberos_enctype_to_bitmap(krb5_enctype enc_type_enum) 910 { 911 switch (enc_type_enum) { 912 case ENCTYPE_DES_CBC_CRC: 913 return ENC_CRC32; 914 case ENCTYPE_DES_CBC_MD5: 915 return ENC_RSA_MD5; 916 case ENCTYPE_ARCFOUR_HMAC_MD5: 917 return ENC_RC4_HMAC_MD5; 918 case ENCTYPE_AES128_CTS_HMAC_SHA1_96: 919 return ENC_HMAC_SHA1_96_AES128; 920 case ENCTYPE_AES256_CTS_HMAC_SHA1_96: 921 return ENC_HMAC_SHA1_96_AES256; 922 default: 923 return 0; 924 } 925 } 926 927 /* Translate between the Microsoft msDS-SupportedEncryptionTypes values and the IETF encryption type values */ 928 krb5_enctype kerberos_enctype_bitmap_to_enctype(uint32_t enctype_bitmap) 929 { 930 switch (enctype_bitmap) { 931 case ENC_CRC32: 932 return ENCTYPE_DES_CBC_CRC; 933 case ENC_RSA_MD5: 934 return ENCTYPE_DES_CBC_MD5; 935 case ENC_RC4_HMAC_MD5: 936 return ENCTYPE_ARCFOUR_HMAC_MD5; 937 case ENC_HMAC_SHA1_96_AES128: 938 return ENCTYPE_AES128_CTS_HMAC_SHA1_96; 939 case ENC_HMAC_SHA1_96_AES256: 940 return ENCTYPE_AES256_CTS_HMAC_SHA1_96; 941 default: 942 return 0; 943 } 944 } 945 946 /* Return an array of krb5_enctype values */ 947 krb5_error_code kerberos_enctype_bitmap_to_enctypes(TALLOC_CTX *mem_ctx, uint32_t enctype_bitmap, krb5_enctype **enctypes) 948 { 949 unsigned int i, j = 0; 950 *enctypes = talloc_zero_array(mem_ctx, krb5_enctype, (8*sizeof(enctype_bitmap))+1); 951 if (!*enctypes) { 952 return ENOMEM; 953 } 954 for (i=0; i<(8*sizeof(enctype_bitmap)); i++) { 955 uint32_t bit_value = (1 << i) & enctype_bitmap; 956 if (bit_value & enctype_bitmap) { 957 (*enctypes)[j] = kerberos_enctype_bitmap_to_enctype(bit_value); 958 if (!(*enctypes)[j]) { 959 continue; 960 } 961 j++; 962 } 963 } 964 (*enctypes)[j] = 0; 965 return 0; 966 } 637 *error_string = talloc_asprintf(mem_ctx, 638 "failed in deleting old entries for principal: %s\n", 639 smb_get_krb5_error_message(context, 640 code, 641 mem_ctx)); 642 } 643 644 code = 0; 645 done: 646 talloc_free(tmp_ctx); 647 return code; 648 } -
vendor/current/source4/auth/kerberos/krb5_init_context.c
r740 r988 23 23 #include "includes.h" 24 24 #include "system/kerberos.h" 25 #include "system/gssapi.h" 25 26 #include <tevent.h> 26 27 #include "auth/kerberos/kerberos.h" … … 31 32 #include "libcli/resolve/resolve.h" 32 33 #include "../lib/tsocket/tsocket.h" 33 34 #include "krb5_init_context.h" 34 35 /* 35 36 context structure for operations on cldap packets … … 47 48 48 49 size_t partial_read; 49 50 #ifdef SAMBA4_USES_HEIMDAL 50 51 krb5_krbhst_info *hi; 52 #endif 51 53 }; 52 54 53 55 static krb5_error_code smb_krb5_context_destroy(struct smb_krb5_context *ctx) 54 56 { 55 /* Otherwise krb5_free_context will try and close what we have already free()ed */ 56 krb5_set_warn_dest(ctx->krb5_context, NULL); 57 krb5_closelog(ctx->krb5_context, ctx->logf); 57 #ifdef SAMBA4_USES_HEIMDAL 58 if (ctx->pvt_log_data) { 59 /* Otherwise krb5_free_context will try and close what we 60 * have already free()ed */ 61 krb5_set_warn_dest(ctx->krb5_context, NULL); 62 krb5_closelog(ctx->krb5_context, 63 (krb5_log_facility *)ctx->pvt_log_data); 64 } 65 #endif 58 66 krb5_free_context(ctx->krb5_context); 59 67 return 0; 60 68 } 61 69 70 #ifdef SAMBA4_USES_HEIMDAL 62 71 /* We never close down the DEBUG system, and no need to unreference the use */ 63 72 static void smb_krb5_debug_close(void *private_data) { 64 73 return; 65 74 } 66 75 #endif 76 77 #ifdef SAMBA4_USES_HEIMDAL 67 78 static void smb_krb5_debug_wrapper(const char *timestr, const char *msg, void *private_data) 68 79 { 69 80 DEBUG(3, ("Kerberos: %s\n", msg)); 70 81 } 71 82 #endif 83 84 #ifdef SAMBA4_USES_HEIMDAL 72 85 /* 73 86 handle recv events on a smb_krb5 socket … … 105 118 } 106 119 107 DEBUG( 2,("Received smb_krb5 packet of length %d\n",120 DEBUG(4,("Received smb_krb5 packet of length %d\n", 108 121 (int)blob.length)); 109 122 … … 198 211 } 199 212 200 201 krb5_error_code smb_krb5_send_and_recv_func(krb5_context context, 202 void *data, 203 krb5_krbhst_info *hi, 204 time_t timeout, 205 const krb5_data *send_buf, 206 krb5_data *recv_buf) 213 static krb5_error_code smb_krb5_send_and_recv_func_int(krb5_context context, 214 struct tevent_context *ev, 215 krb5_krbhst_info *hi, 216 struct addrinfo *ai, 217 krb5_send_to_kdc_func func, 218 void *data, 219 time_t timeout, 220 const krb5_data *send_buf, 221 krb5_data *recv_buf) 207 222 { 208 223 krb5_error_code ret; 209 224 NTSTATUS status; 210 225 const char *name; 211 struct addrinfo *a i, *a;226 struct addrinfo *a; 212 227 struct smb_krb5_socket *smb_krb5; 213 228 214 229 DATA_BLOB send_blob; 215 230 216 struct tevent_context *ev; 217 TALLOC_CTX *tmp_ctx = talloc_new(NULL); 218 if (!tmp_ctx) { 231 TALLOC_CTX *frame = talloc_stackframe(); 232 if (frame == NULL) { 219 233 return ENOMEM; 220 234 } 221 235 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 236 send_blob = data_blob_const(send_buf->data, send_buf->length); 234 235 ret = krb5_krbhst_get_addrinfo(context, hi, &ai);236 if (ret) {237 talloc_free(tmp_ctx);238 return ret;239 }240 237 241 238 for (a = ai; a; a = a->ai_next) { 242 239 struct socket_address *remote_addr; 243 smb_krb5 = talloc( tmp_ctx, struct smb_krb5_socket);240 smb_krb5 = talloc(frame, struct smb_krb5_socket); 244 241 if (!smb_krb5) { 245 talloc_free(tmp_ctx);242 TALLOC_FREE(frame); 246 243 return ENOMEM; 247 244 } … … 258 255 #endif 259 256 default: 260 talloc_free(tmp_ctx);257 TALLOC_FREE(frame); 261 258 return EINVAL; 262 259 } … … 271 268 break; 272 269 case KRB5_KRBHST_HTTP: 273 talloc_free(tmp_ctx);270 TALLOC_FREE(frame); 274 271 return EINVAL; 275 272 } … … 339 336 break; 340 337 case KRB5_KRBHST_HTTP: 341 talloc_free(tmp_ctx);338 TALLOC_FREE(frame); 342 339 return EINVAL; 343 340 } 344 341 while ((NT_STATUS_IS_OK(smb_krb5->status)) && !smb_krb5->reply.length) { 345 342 if (tevent_loop_once(ev) != 0) { 346 talloc_free(tmp_ctx);343 TALLOC_FREE(frame); 347 344 return EINVAL; 348 345 } 349 346 350 /* After each and every event loop, reset the 351 * send_to_kdc pointers to what they were when 352 * we entered this loop. That way, if a 353 * nested event has invalidated them, we put 354 * it back before we return to the heimdal 355 * code */ 356 ret = krb5_set_send_to_kdc_func(context, 357 smb_krb5_send_and_recv_func, 358 data); 359 if (ret != 0) { 360 talloc_free(tmp_ctx); 361 return ret; 347 if (func) { 348 /* After each and every event loop, reset the 349 * send_to_kdc pointers to what they were when 350 * we entered this loop. That way, if a 351 * nested event has invalidated them, we put 352 * it back before we return to the heimdal 353 * code */ 354 ret = krb5_set_send_to_kdc_func(context, 355 func, 356 data); 357 if (ret != 0) { 358 TALLOC_FREE(frame); 359 return ret; 360 } 362 361 } 363 362 } … … 383 382 ret = krb5_data_copy(recv_buf, smb_krb5->reply.data, smb_krb5->reply.length); 384 383 if (ret) { 385 talloc_free(tmp_ctx);384 TALLOC_FREE(frame); 386 385 return ret; 387 386 } … … 390 389 break; 391 390 } 392 talloc_free(tmp_ctx);391 TALLOC_FREE(frame); 393 392 if (a) { 394 393 return 0; … … 396 395 return KRB5_KDC_UNREACH; 397 396 } 397 398 krb5_error_code smb_krb5_send_and_recv_func(krb5_context context, 399 void *data, 400 krb5_krbhst_info *hi, 401 time_t timeout, 402 const krb5_data *send_buf, 403 krb5_data *recv_buf) 404 { 405 krb5_error_code ret; 406 struct addrinfo *ai; 407 408 struct tevent_context *ev; 409 TALLOC_CTX *frame = talloc_stackframe(); 410 if (frame == NULL) { 411 return ENOMEM; 412 } 413 414 if (data == NULL) { 415 /* If no event context was available, then create one for this loop */ 416 ev = samba_tevent_context_init(frame); 417 if (ev == NULL) { 418 TALLOC_FREE(frame); 419 return ENOMEM; 420 } 421 } else { 422 ev = talloc_get_type_abort(data, struct tevent_context); 423 } 424 425 ret = krb5_krbhst_get_addrinfo(context, hi, &ai); 426 if (ret) { 427 TALLOC_FREE(frame); 428 return ret; 429 } 430 431 ret = smb_krb5_send_and_recv_func_int(context, ev, hi, ai, smb_krb5_send_and_recv_func, data, timeout, send_buf, recv_buf); 432 TALLOC_FREE(frame); 433 return ret; 434 } 435 436 krb5_error_code smb_krb5_send_and_recv_func_forced(krb5_context context, 437 void *data, /* struct addrinfo */ 438 krb5_krbhst_info *hi, 439 time_t timeout, 440 const krb5_data *send_buf, 441 krb5_data *recv_buf) 442 { 443 krb5_error_code k5ret; 444 struct addrinfo *ai = data; 445 446 struct tevent_context *ev; 447 TALLOC_CTX *frame = talloc_stackframe(); 448 if (frame == NULL) { 449 return ENOMEM; 450 } 451 452 /* no event context is passed in, create one for this loop */ 453 ev = samba_tevent_context_init(frame); 454 if (ev == NULL) { 455 TALLOC_FREE(frame); 456 return ENOMEM; 457 } 458 459 /* No need to pass in send_and_recv functions, we won't nest on this private event loop */ 460 k5ret = smb_krb5_send_and_recv_func_int(context, ev, hi, ai, NULL, NULL, 461 timeout, send_buf, recv_buf); 462 TALLOC_FREE(frame); 463 return k5ret; 464 } 465 #endif 398 466 399 467 krb5_error_code … … 403 471 { 404 472 krb5_error_code ret; 473 #ifdef SAMBA4_USES_HEIMDAL 405 474 char **config_files; 406 475 const char *config_file, *realm; 476 #endif 407 477 krb5_context krb5_ctx; 408 478 … … 416 486 } 417 487 418 config_file = config_path(tmp_ctx, lp_ctx, "krb5.conf"); 488 /* The MIT Kerberos build relies on using the system krb5.conf file. 489 * If you really want to use another file please set KRB5_CONFIG 490 * accordingly. */ 491 #ifdef SAMBA4_USES_HEIMDAL 492 config_file = lpcfg_config_path(tmp_ctx, lp_ctx, "krb5.conf"); 419 493 if (!config_file) { 420 494 krb5_free_context(krb5_ctx); … … 423 497 424 498 /* Use our local krb5.conf file by default */ 425 ret = krb5_prepend_config_files_default(config_file == NULL?"":config_file, &config_files);499 ret = krb5_prepend_config_files_default(config_file, &config_files); 426 500 if (ret) { 427 501 DEBUG(1,("krb5_prepend_config_files_default failed (%s)\n", … … 450 524 } 451 525 } 452 526 #endif 453 527 *_krb5_context = krb5_ctx; 454 528 return 0; … … 456 530 457 531 krb5_error_code smb_krb5_init_context(void *parent_ctx, 458 struct tevent_context *ev,459 532 struct loadparm_context *lp_ctx, 460 533 struct smb_krb5_context **smb_krb5_context) … … 462 535 krb5_error_code ret; 463 536 TALLOC_CTX *tmp_ctx; 537 krb5_context kctx; 538 #ifdef SAMBA4_USES_HEIMDAL 539 krb5_log_facility *logf; 540 #endif 464 541 465 542 initialize_krb5_error_table(); … … 473 550 } 474 551 475 ret = smb_krb5_init_context_basic(tmp_ctx, lp_ctx, 476 &(*smb_krb5_context)->krb5_context); 552 ret = smb_krb5_init_context_basic(tmp_ctx, lp_ctx, &kctx); 477 553 if (ret) { 478 554 DEBUG(1,("smb_krb5_context_init_basic failed (%s)\n", … … 481 557 return ret; 482 558 } 483 559 (*smb_krb5_context)->krb5_context = kctx; 560 561 talloc_set_destructor(*smb_krb5_context, smb_krb5_context_destroy); 562 563 #ifdef SAMBA4_USES_HEIMDAL 484 564 /* TODO: Should we have a different name here? */ 485 ret = krb5_initlog( (*smb_krb5_context)->krb5_context, "Samba", &(*smb_krb5_context)->logf);565 ret = krb5_initlog(kctx, "Samba", &logf); 486 566 487 567 if (ret) { 488 568 DEBUG(1,("krb5_initlog failed (%s)\n", 489 smb_get_krb5_error_message((*smb_krb5_context)->krb5_context, ret, tmp_ctx))); 490 krb5_free_context((*smb_krb5_context)->krb5_context); 491 talloc_free(tmp_ctx); 492 return ret; 493 } 494 495 talloc_set_destructor(*smb_krb5_context, smb_krb5_context_destroy); 496 497 ret = krb5_addlog_func((*smb_krb5_context)->krb5_context, (*smb_krb5_context)->logf, 0 /* min */, -1 /* max */, 498 smb_krb5_debug_wrapper, smb_krb5_debug_close, NULL); 569 smb_get_krb5_error_message(kctx, ret, tmp_ctx))); 570 talloc_free(tmp_ctx); 571 return ret; 572 } 573 (*smb_krb5_context)->pvt_log_data = logf; 574 575 ret = krb5_addlog_func(kctx, logf, 0 /* min */, -1 /* max */, 576 smb_krb5_debug_wrapper, 577 smb_krb5_debug_close, NULL); 499 578 if (ret) { 500 579 DEBUG(1,("krb5_addlog_func failed (%s)\n", 501 smb_get_krb5_error_message((*smb_krb5_context)->krb5_context, ret, tmp_ctx))); 502 talloc_free(tmp_ctx); 503 return ret; 504 } 505 krb5_set_warn_dest((*smb_krb5_context)->krb5_context, (*smb_krb5_context)->logf); 506 507 /* Set use of our socket lib */ 508 if (ev) { 509 struct tevent_context *previous_ev; 510 ret = smb_krb5_context_set_event_ctx(*smb_krb5_context, 511 ev, &previous_ev); 512 if (ret) { 513 talloc_free(tmp_ctx); 514 return ret; 515 } 516 } 517 580 smb_get_krb5_error_message(kctx, ret, tmp_ctx))); 581 talloc_free(tmp_ctx); 582 return ret; 583 } 584 krb5_set_warn_dest(kctx, logf); 585 586 /* Set options in kerberos */ 587 588 krb5_set_dns_canonicalize_hostname(kctx, 589 lpcfg_parm_bool(lp_ctx, NULL, "krb5", 590 "set_dns_canonicalize", false)); 591 #endif 518 592 talloc_steal(parent_ctx, *smb_krb5_context); 519 593 talloc_free(tmp_ctx); 520 594 521 /* Set options in kerberos */522 523 krb5_set_dns_canonicalize_hostname((*smb_krb5_context)->krb5_context,524 lpcfg_parm_bool(lp_ctx, NULL, "krb5", "set_dns_canonicalize", false));525 526 595 return 0; 527 596 } 528 597 598 #ifdef SAMBA4_USES_HEIMDAL 529 599 krb5_error_code smb_krb5_context_set_event_ctx(struct smb_krb5_context *smb_krb5_context, 530 600 struct tevent_context *ev, … … 580 650 return 0; 581 651 } 652 #endif -
vendor/current/source4/auth/kerberos/krb5_init_context.h
r740 r988 18 18 */ 19 19 20 #ifndef _KRB5_INIT_CONTEXT_H_ 21 #define _KRB5_INIT_CONTEXT_H_ 22 20 23 struct smb_krb5_context { 21 24 krb5_context krb5_context; 22 krb5_log_facility *logf;25 void *pvt_log_data; 23 26 struct tevent_context *current_ev; 24 27 }; 25 28 26 29 struct tevent_context; 27 30 struct loadparm_context; … … 32 35 krb5_context *_krb5_context); 33 36 34 krb5_error_code smb_krb5_init_context(void *parent_ctx, struct tevent_context *ev,37 krb5_error_code smb_krb5_init_context(void *parent_ctx, 35 38 struct loadparm_context *lp_ctx, 36 39 struct smb_krb5_context **smb_krb5_context); 37 40 41 #ifdef SAMBA4_USES_HEIMDAL 38 42 krb5_error_code smb_krb5_send_and_recv_func(krb5_context context, 39 43 void *data, … … 42 46 const krb5_data *send_buf, 43 47 krb5_data *recv_buf); 48 krb5_error_code smb_krb5_send_and_recv_func_forced(krb5_context context, 49 void *data, /* struct addrinfo */ 50 krb5_krbhst_info *hi, 51 time_t timeout, 52 const krb5_data *send_buf, 53 krb5_data *recv_buf); 54 krb5_error_code smb_krb5_context_set_event_ctx(struct smb_krb5_context *smb_krb5_context, 55 struct tevent_context *ev, 56 struct tevent_context **previous_ev); 57 krb5_error_code smb_krb5_context_remove_event_ctx(struct smb_krb5_context *smb_krb5_context, 58 struct tevent_context *previous_ev, 59 struct tevent_context *ev); 60 #endif 61 62 #endif /* _KRB5_INIT_CONTEXT_H_ */ -
vendor/current/source4/auth/kerberos/wscript_build
r740 r988 1 1 #!/usr/bin/env python 2 2 3 bld.SAMBA_SUBSYSTEM('KRB_INIT_CTX', 4 source='krb5_init_context.c', 5 deps='gssapi krb5samba' 6 ) 7 3 8 bld.SAMBA_LIBRARY('authkrb5', 4 source='kerberos .c clikrb5.c kerberos_heimdal.c kerberos_pac.c gssapi_parse.c krb5_init_context.c keytab_copy.c',9 source='kerberos_pac.c', 5 10 autoproto='proto.h', 6 public_deps=' krb5 ndr-krb5pac samba_socket LIBCLI_RESOLVE com_errasn1',7 deps=' ASN1_UTIL auth_sam_reply tevent LIBPACKET ndr ldb',11 public_deps='ndr-krb5pac krb5samba samba_socket LIBCLI_RESOLVE asn1', 12 deps='auth_sam_reply tevent LIBPACKET ndr ldb krb5samba KRB_INIT_CTX KRB5_PAC samba-errors', 8 13 private_library=True 9 14 ) … … 12 17 autoproto='kerberos_util.h', 13 18 source='kerberos_util.c', 14 deps='authkrb5 com_err ldb CREDENTIALS_KRB5 SECRETS',19 deps='authkrb5 krb5samba com_err CREDENTIALS_KRB5', 15 20 ) 16 21 22 bld.SAMBA_SUBSYSTEM('KERBEROS_SRV_KEYTAB', 23 autoproto='kerberos_srv_keytab.h', 24 source='srv_keytab.c', 25 deps='authkrb5', 26 )
Note:
See TracChangeset
for help on using the changeset viewer.