Changeset 745 for trunk/server/source4/auth/kerberos
- Timestamp:
- Nov 27, 2012, 4:43:17 PM (13 years ago)
- Location:
- trunk/server
- Files:
-
- 2 deleted
- 7 edited
- 2 copied
Legend:
- Unmodified
- Added
- Removed
-
trunk/server
- Property svn:mergeinfo changed
/vendor/current merged: 581,587,591,594,597,600,615,618,740
- Property svn:mergeinfo changed
-
trunk/server/source4/auth/kerberos/kerberos.c
r414 r745 34 34 This version is built to use a keyblock, rather than needing the 35 35 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) 36 40 */ 37 41 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) 40 46 { 41 47 krb5_error_code code = 0; 42 48 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);50 49 51 50 if ((code = krb5_get_init_creds_keyblock(ctx, &my_creds, principal, keyblock, 52 0, NULL,options))) {51 0, target_service, krb_options))) { 53 52 return code; 54 53 } 55 54 56 55 if ((code = krb5_cc_initialize(ctx, cc, principal))) { 57 krb5_get_init_creds_opt_free(ctx, options);58 56 krb5_free_cred_contents(ctx, &my_creds); 59 57 return code; … … 61 59 62 60 if ((code = krb5_cc_store_cred(ctx, cc, &my_creds))) { 63 krb5_get_init_creds_opt_free(ctx, options);64 61 krb5_free_cred_contents(ctx, &my_creds); 65 62 return code; … … 74 71 } 75 72 76 krb5_get_init_creds_opt_free(ctx, options);77 73 krb5_free_cred_contents(ctx, &my_creds); 78 74 … … 83 79 simulate a kinit, putting the tgt in the given credentials cache. 84 80 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 85 86 */ 86 87 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) 89 92 { 90 93 krb5_error_code code = 0; 91 94 krb5_creds my_creds; 92 krb5_get_init_creds_opt *options; 95 krb5_creds *impersonate_creds; 96 krb5_get_creds_opt options; 93 97 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))) { 95 106 return code; 96 107 } 97 108 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 106 109 if ((code = krb5_cc_initialize(ctx, cc, principal))) { 107 krb5_get_init_creds_opt_free(ctx, options);108 110 krb5_free_cred_contents(ctx, &my_creds); 109 111 return code; … … 111 113 112 114 if ((code = krb5_cc_store_cred(ctx, cc, &my_creds))) { 113 krb5_get_init_creds_opt_free(ctx, options);114 115 krb5_free_cred_contents(ctx, &my_creds); 115 116 return code; … … 124 125 } 125 126 126 krb5_get_init_creds_opt_free(ctx, options);127 127 krb5_free_cred_contents(ctx, &my_creds); 128 128 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 129 164 return 0; 130 165 } -
trunk/server/source4/auth/kerberos/kerberos.h
r414 r745 24 24 #include "librpc/gen_ndr/krb5pac.h" 25 25 26 struct auth_ serversupplied_info;26 struct auth_user_info_dc; 27 27 struct cli_credentials; 28 28 … … 53 53 #define KRB5_KEY_DATA(k) ((k)->contents) 54 54 #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) 55 58 56 59 #ifndef HAVE_KRB5_SET_REAL_TIME … … 89 92 krb5_data *outbuf); 90 93 bool 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); 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); 97 104 krb5_principal kerberos_fetch_salt_princ_for_host_princ(krb5_context context, 98 105 krb5_principal host_princ, … … 103 110 krb5_error_code smb_krb5_kt_free_entry(krb5_context context, krb5_keytab_entry *kt_entry); 104 111 char *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);113 112 NTSTATUS kerberos_decode_pac(TALLOC_CTX *mem_ctx, 114 struct smb_iconv_convenience *iconv_convenience,115 113 struct PAC_DATA **pac_data_out, 116 114 DATA_BLOB blob, … … 122 120 krb5_error_code *k5ret); 123 121 NTSTATUS kerberos_pac_logon_info(TALLOC_CTX *mem_ctx, 124 struct smb_iconv_convenience *iconv_convenience,125 122 struct PAC_LOGON_INFO **logon_info, 126 123 DATA_BLOB blob, … … 132 129 krb5_error_code *k5ret); 133 130 krb5_error_code kerberos_encode_pac(TALLOC_CTX *mem_ctx, 134 struct smb_iconv_convenience *iconv_convenience,135 131 struct PAC_DATA *pac_data, 136 132 krb5_context context, … … 139 135 DATA_BLOB *pac); 140 136 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, 143 138 krb5_context context, 144 139 const krb5_keyblock *krbtgt_keyblock, … … 148 143 DATA_BLOB *pac); 149 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); 150 156 151 157 #include "auth/kerberos/proto.h" -
trunk/server/source4/auth/kerberos/kerberos_pac.c
r414 r745 1 /* 1 /* 2 2 Unix SMB/CIFS implementation. 3 3 4 4 Create and parse the krb5 PAC 5 5 6 6 Copyright (C) Andrew Bartlett <abartlet@samba.org> 2004-2005,2008 7 7 Copyright (C) Andrew Tridgell 2001 … … 13 13 the Free Software Foundation; either version 3 of the License, or 14 14 (at your option) any later version. 15 15 16 16 This program is distributed in the hope that it will be useful, 17 17 but WITHOUT ANY WARRANTY; without even the implied warranty of … … 19 19 GNU General Public License for more details. 20 20 21 21 22 22 You should have received a copy of the GNU General Public License 23 23 along with this program. If not, see <http://www.gnu.org/licenses/>. … … 29 29 #include "auth/kerberos/kerberos.h" 30 30 #include "librpc/gen_ndr/ndr_krb5pac.h" 31 #include "lib/ldb/include/ldb.h"31 #include <ldb.h> 32 32 #include "auth/auth_sam_reply.h" 33 33 34 krb5_error_code check_pac_checksum(TALLOC_CTX *mem_ctx, 34 krb5_error_code check_pac_checksum(TALLOC_CTX *mem_ctx, 35 35 DATA_BLOB pac_data, 36 36 struct PAC_SIGNATURE_DATA *sig, … … 51 51 &crypto); 52 52 if (ret) { 53 DEBUG(0,("krb5_crypto_init() failed: %s\n", 53 DEBUG(0,("krb5_crypto_init() failed: %s\n", 54 54 smb_get_krb5_error_message(context, ret, mem_ctx))); 55 55 return ret; … … 67 67 68 68 NTSTATUS kerberos_decode_pac(TALLOC_CTX *mem_ctx, 69 struct smb_iconv_convenience *iconv_convenience,70 69 struct PAC_DATA **pac_data_out, 71 70 DATA_BLOB blob, … … 95 94 NTTIME tgs_authtime_nttime; 96 95 krb5_principal client_principal_pac; 97 int i;96 uint32_t i; 98 97 99 98 krb5_clear_error_message(context); … … 114 113 } 115 114 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); 119 117 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { 120 118 status = ndr_map_error2ntstatus(ndr_err); … … 130 128 } 131 129 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, 134 132 (ndr_pull_flags_fn_t)ndr_pull_PAC_DATA_RAW); 135 133 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { … … 211 209 212 210 /* 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, 215 213 (ndr_pull_flags_fn_t)ndr_pull_PAC_SIGNATURE_DATA); 216 214 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { … … 220 218 return status; 221 219 } 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, 225 223 (ndr_pull_flags_fn_t)ndr_pull_PAC_SIGNATURE_DATA); 226 224 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { … … 234 232 memset(kdc_sig_wipe->signature.data, '\0', kdc_sig_wipe->signature.length); 235 233 memset(srv_sig_wipe->signature.data, '\0', srv_sig_wipe->signature.length); 236 234 237 235 /* 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, 240 237 kdc_sig_wipe, 241 238 (ndr_push_flags_fn_t)ndr_push_PAC_SIGNATURE_DATA); … … 246 243 return status; 247 244 } 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, 250 246 srv_sig_wipe, 251 247 (ndr_push_flags_fn_t)ndr_push_PAC_SIGNATURE_DATA); … … 258 254 259 255 /* 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, 262 257 pac_data_raw, 263 258 (ndr_push_flags_fn_t)ndr_push_PAC_DATA_RAW); … … 270 265 271 266 /* 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, 275 270 service_keyblock); 276 271 if (ret) { … … 284 279 285 280 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, 288 283 context, krbtgt_keyblock); 289 284 if (ret) { … … 307 302 } 308 303 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, 310 305 &client_principal_pac); 311 306 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, 314 309 smb_get_krb5_error_message(context, ret, mem_ctx))); 315 310 if (k5ret) { … … 320 315 321 316 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", 323 318 logon_name->account_name)); 319 krb5_free_principal(context, client_principal_pac); 324 320 return NT_STATUS_ACCESS_DENIED; 325 321 } 326 322 323 krb5_free_principal(context, client_principal_pac); 324 327 325 #if 0 328 if (strcasecmp(logon_info->info3.base.account_name.string, 326 if (strcasecmp(logon_info->info3.base.account_name.string, 329 327 "Administrator")== 0) { 330 328 file_save("tmp_pac_data-admin.dat",blob.data,blob.length); … … 333 331 334 332 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, 336 334 logon_info->info3.base.full_name.string)); 337 335 *pac_data_out = pac_data; … … 341 339 342 340 _PUBLIC_ NTSTATUS kerberos_pac_logon_info(TALLOC_CTX *mem_ctx, 343 struct smb_iconv_convenience *iconv_convenience,344 341 struct PAC_LOGON_INFO **logon_info, 345 342 DATA_BLOB blob, … … 348 345 const krb5_keyblock *service_keyblock, 349 346 krb5_const_principal client_principal, 350 time_t tgs_authtime, 347 time_t tgs_authtime, 351 348 krb5_error_code *k5ret) 352 349 { … … 354 351 struct PAC_DATA *pac_data; 355 352 int i; 356 nt_status = kerberos_decode_pac(mem_ctx, 357 iconv_convenience, 353 nt_status = kerberos_decode_pac(mem_ctx, 358 354 &pac_data, 359 355 blob, … … 361 357 krbtgt_keyblock, 362 358 service_keyblock, 363 client_principal, 359 client_principal, 364 360 tgs_authtime, 365 361 k5ret); … … 373 369 continue; 374 370 } 375 *logon_info = pac_data->buffers[i].info->logon_info.info; 371 *logon_info = pac_data->buffers[i].info->logon_info.info; 376 372 } 377 373 if (!*logon_info) { … … 381 377 } 382 378 383 static krb5_error_code make_pac_checksum(TALLOC_CTX *mem_ctx, 379 static krb5_error_code make_pac_checksum(TALLOC_CTX *mem_ctx, 384 380 DATA_BLOB *pac_data, 385 381 struct PAC_SIGNATURE_DATA *sig, … … 409 405 &cksum); 410 406 if (ret) { 411 DEBUG(2, ("PAC Verification failed: %s\n", 407 DEBUG(2, ("PAC Verification failed: %s\n", 412 408 smb_get_krb5_error_message(context, ret, mem_ctx))); 413 409 } … … 427 423 428 424 krb5_error_code kerberos_encode_pac(TALLOC_CTX *mem_ctx, 429 struct smb_iconv_convenience *iconv_convenience,430 425 struct PAC_DATA *pac_data, 431 426 krb5_context context, 432 427 const krb5_keyblock *krbtgt_keyblock, 433 428 const krb5_keyblock *service_keyblock, 434 DATA_BLOB *pac) 429 DATA_BLOB *pac) 435 430 { 436 431 NTSTATUS nt_status; … … 448 443 continue; 449 444 } 450 kdc_checksum = &pac_data->buffers[i].info->kdc_cksum, 445 kdc_checksum = &pac_data->buffers[i].info->kdc_cksum, 451 446 ret = make_pac_checksum(mem_ctx, &zero_blob, 452 kdc_checksum, 447 kdc_checksum, 453 448 context, krbtgt_keyblock); 454 449 if (ret) { 455 DEBUG(2, ("making krbtgt PAC checksum failed: %s\n", 450 DEBUG(2, ("making krbtgt PAC checksum failed: %s\n", 456 451 smb_get_krb5_error_message(context, ret, mem_ctx))); 457 452 talloc_free(pac_data); … … 459 454 } 460 455 } 461 456 462 457 for (i=0; i < pac_data->num_buffers; i++) { 463 458 if (pac_data->buffers[i].type != PAC_TYPE_SRV_CHECKSUM) { 464 459 continue; 465 460 } 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, 469 464 context, service_keyblock); 470 465 if (ret) { 471 DEBUG(2, ("making service PAC checksum failed: %s\n", 466 DEBUG(2, ("making service PAC checksum failed: %s\n", 472 467 smb_get_krb5_error_message(context, ret, mem_ctx))); 473 468 talloc_free(pac_data); … … 489 484 memset(srv_checksum->signature.data, '\0', srv_checksum->signature.length); 490 485 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, 493 487 pac_data, 494 488 (ndr_push_flags_fn_t)ndr_push_PAC_DATA); … … 507 501 ret = make_pac_checksum(mem_ctx, &srv_checksum->signature, kdc_checksum, context, krbtgt_keyblock); 508 502 if (ret) { 509 DEBUG(2, ("making krbtgt PAC checksum failed: %s\n", 503 DEBUG(2, ("making krbtgt PAC checksum failed: %s\n", 510 504 smb_get_krb5_error_message(context, ret, mem_ctx))); 511 505 talloc_free(pac_data); … … 514 508 515 509 /* 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, 518 511 pac_data, 519 512 (ndr_push_flags_fn_t)ndr_push_PAC_DATA); … … 532 525 533 526 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, 536 528 krb5_context context, 537 529 const krb5_keyblock *krbtgt_keyblock, … … 553 545 554 546 char *name; 555 547 556 548 enum { 557 549 PAC_BUF_LOGON_INFO = 0, … … 569 561 pac_data->version = 0; 570 562 571 pac_data->buffers = talloc_array(pac_data, 563 pac_data->buffers = talloc_array(pac_data, 572 564 struct PAC_BUFFER, 573 565 pac_data->num_buffers); … … 621 613 return ENOMEM; 622 614 } 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); 624 616 if (!NT_STATUS_IS_OK(nt_status)) { 625 617 DEBUG(1, ("Getting Samba info failed: %s\n", nt_errstr(nt_status))); … … 631 623 LOGON_INFO->info3 = *sam3; 632 624 633 ret = krb5_unparse_name_flags(context, client_principal, 625 ret = krb5_unparse_name_flags(context, client_principal, 634 626 KRB5_PRINCIPAL_UNPARSE_NO_REALM, &name); 635 627 if (ret) { … … 644 636 unix_to_nt_time(&LOGON_NAME->logon_time, tgs_authtime); 645 637 646 ret = kerberos_encode_pac(mem_ctx, 647 iconv_convenience, 648 pac_data, 638 ret = kerberos_encode_pac(mem_ctx, 639 pac_data, 649 640 context, 650 641 krbtgt_keyblock, … … 655 646 } 656 647 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) 648 krb5_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) 662 654 { 663 655 NTSTATUS nt_status; … … 669 661 670 662 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; 673 664 674 665 TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx); … … 686 677 pac_logon_info_in = data_blob_const(k5pac_logon_info_in.data, k5pac_logon_info_in.length); 687 678 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, 689 680 PAC_TYPE_LOGON_INFO, 690 681 (ndr_pull_flags_fn_t)ndr_pull_PAC_INFO); … … 698 689 699 690 /* 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); 705 694 if (!NT_STATUS_IS_OK(nt_status)) { 706 695 talloc_free(tmp_ctx); 707 696 return EINVAL; 708 697 } 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 750 742 return 0; 751 743 } 752 744 753 745 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) 746 NTSTATUS 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) 759 752 { 760 753 krb5_error_code ret; 761 754 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, 764 757 &pac); 765 758 if (ret) { … … 768 761 769 762 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); 771 764 krb5_pac_free(context, pac); 772 765 if (ret) { -
trunk/server/source4/auth/kerberos/kerberos_util.c
r414 r745 27 27 #include "auth/credentials/credentials_proto.h" 28 28 #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" 29 33 30 34 struct principal_container { 31 35 struct smb_krb5_context *smb_krb5_context; 32 36 krb5_principal principal; 37 const char *string_form; /* Optional */ 33 38 }; 34 39 … … 41 46 } 42 47 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 49 static 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 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; 48 91 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 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); 59 198 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); 64 227 if (!machine_username) { 65 228 talloc_free(mem_ctx); 229 *error_string = "Cannot duplicate samAccountName"; 66 230 return ENOMEM; 67 231 } … … 70 234 machine_username[strlen(machine_username)-1] = '\0'; 71 235 } 72 lower_realm = strlower_talloc(mem_ctx, cli_credentials_get_realm(machine_account)); 236 237 lower_realm = strlower_talloc(tmp_ctx, realm); 73 238 if (!lower_realm) { 74 239 talloc_free(mem_ctx); 240 *error_string = "Cannot allocate to lower case realm"; 75 241 return ENOMEM; 76 242 } 77 243 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, 79 252 lower_realm); 253 talloc_free(lower_realm); 254 talloc_free(machine_username); 80 255 if (!salt_body) { 81 256 talloc_free(mem_ctx); 82 return ENOMEM; 257 *error_string = "Cannot form salt principal body"; 258 return ENOMEM; 83 259 } 84 260 85 261 ret = krb5_make_principal(smb_krb5_context->krb5_context, salt_princ, 86 cli_credentials_get_realm(machine_account),262 upper_realm, 87 263 "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 } 98 279 } 99 280 … … 103 284 * system by means of a destructor (do *not* free). */ 104 285 105 286 krb5_error_code principal_from_credentials(TALLOC_CTX *parent_ctx, 106 287 struct cli_credentials *credentials, 107 288 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) 109 292 { 110 293 krb5_error_code ret; 111 294 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); 113 296 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); 121 301 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); 137 309 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); 138 325 } 139 326 … … 146 333 struct cli_credentials *credentials, 147 334 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) 149 339 { 150 340 krb5_error_code ret; 151 const char *password ;341 const char *password, *target_service; 152 342 time_t kdc_time = 0; 153 343 krb5_principal princ; 344 krb5_principal impersonate_principal; 154 345 int tries; 155 346 TALLOC_CTX *mem_ctx = talloc_new(parent_ctx); 347 krb5_get_init_creds_opt *krb_options; 156 348 157 349 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); 162 355 if (ret) { 163 356 talloc_free(mem_ctx); … … 165 358 } 166 359 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 167 368 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 } 168 393 169 394 tries = 2; 170 395 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 } 171 403 if (password) { 172 404 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; 175 413 } else { 176 414 /* No password available, try to use a keyblock instead */ … … 181 419 if (!mach_pwd) { 182 420 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); 184 424 return EINVAL; 185 425 } … … 191 431 if (ret == 0) { 192 432 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); 195 436 krb5_free_keyblock_contents(smb_krb5_context->krb5_context, &keyblock); 196 437 } 197 438 } 439 440 smb_krb5_context_remove_event_ctx(smb_krb5_context, previous_ev, event_ctx); 198 441 199 442 if (ret == KRB5KRB_AP_ERR_SKEW || ret == KRB5_KDCREP_SKEW) { … … 207 450 } 208 451 452 krb5_get_init_creds_opt_free(smb_krb5_context->krb5_context, krb_options); 453 209 454 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)); 214 459 talloc_free(mem_ctx); 215 460 return ret; … … 228 473 credentials, 229 474 smb_krb5_context, 230 ccache); 231 } 475 event_ctx, 476 ccache, obtained, 477 error_string); 478 } 479 232 480 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)); 237 485 talloc_free(mem_ctx); 238 486 return ret; … … 274 522 275 523 static krb5_error_code keytab_add_keys(TALLOC_CTX *parent_ctx, 276 const char *princ_string, 277 krb5_principal princ, 524 struct principal_container **principals, 278 525 krb5_principal salt_princ, 279 526 int kvno, 280 527 const char *password_s, 281 528 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; 286 534 krb5_error_code ret; 287 535 krb5_data password; 288 TALLOC_CTX *mem_ctx = talloc_new(parent_ctx);289 if (!mem_ctx) {290 return ENOMEM;291 }292 536 293 537 password.data = discard_const_p(char *, password_s); 294 538 password.length = strlen(password_s); 295 539 296 for (i=0; enctype _strings[i]; i++) {540 for (i=0; enctypes[i]; i++) { 297 541 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]); 300 547 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);306 548 return ret; 307 549 } 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 } 334 573 krb5_free_keyblock_contents(smb_krb5_context->krb5_context, &entry.keyblock); 335 574 } 336 talloc_free(mem_ctx);337 575 return 0; 338 576 } 339 577 340 578 static 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) 346 585 { 347 586 krb5_error_code ret; … … 349 588 const char *old_secret; 350 589 int kvno; 590 uint32_t enctype_bitmap; 351 591 krb5_principal salt_princ; 352 krb5_principal princ; 353 const char *princ_string; 354 592 krb5_enctype *enctypes; 355 593 TALLOC_CTX *mem_ctx = talloc_new(parent_ctx); 356 594 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); 363 603 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); 375 628 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); 408 650 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)));412 651 talloc_free(mem_ctx); 413 652 return ret; 414 653 } 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;467 654 } 468 655 469 656 talloc_free(mem_ctx); 470 return 0; 471 } 472 657 return ret; 658 } 473 659 474 660 /* … … 482 668 483 669 static 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, 485 673 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) 487 676 { 488 677 krb5_error_code ret, ret2; 489 678 krb5_kt_cursor cursor; 490 krb5_principal princ;491 679 int kvno; 492 680 TALLOC_CTX *mem_ctx = talloc_new(parent_ctx); 493 const char *princ_string; 681 494 682 if (!mem_ctx) { 495 683 return ENOMEM; … … 497 685 498 686 *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); 512 689 513 690 /* for each entry in the keytab */ … … 523 700 return 0; 524 701 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)); 528 705 talloc_free(mem_ctx); 529 706 return ret; … … 531 708 532 709 while (!ret) { 710 unsigned int i; 711 bool matched = false; 533 712 krb5_keytab_entry entry; 534 713 ret = krb5_kt_next_entry(smb_krb5_context->krb5_context, keytab, &entry, &cursor); … … 536 715 break; 537 716 } 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) { 540 726 /* Free the entry, it wasn't the one we were looking for anyway */ 541 727 krb5_kt_free_entry(smb_krb5_context->krb5_context, &entry); … … 593 779 break; 594 780 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)); 599 784 } 600 785 talloc_free(mem_ctx); … … 603 788 604 789 krb5_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) 609 795 { 610 796 krb5_error_code ret; 611 797 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 613 803 if (!mem_ctx) { 614 804 return ENOMEM; 615 805 } 616 806 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 619 814 if (ret != 0) { 620 815 talloc_free(mem_ctx); 621 816 return ret; 622 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 } 623 837 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 } 632 848 talloc_free(mem_ctx); 633 849 return ret; … … 637 853 struct cli_credentials *machine_account, 638 854 struct smb_krb5_context *smb_krb5_context, 639 const char **enctype_strings,640 855 struct keytab_container **keytab_container) 641 856 { … … 644 859 const char *rand_string; 645 860 const char *keytab_name; 861 struct ldb_message *msg; 862 const char *error_string; 646 863 if (!mem_ctx) { 647 864 return ENOMEM; … … 668 885 } 669 886 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); 671 899 if (ret == 0) { 672 900 talloc_steal(parent_ctx, *keytab_container); 673 901 } else { 902 DEBUG(0, ("Failed to create in-memory keytab: %s\n", error_string)); 674 903 *keytab_container = NULL; 675 904 } … … 677 906 return ret; 678 907 } 679 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 } -
trunk/server/source4/auth/kerberos/krb5_init_context.c
r414 r745 1 /* 1 /* 2 2 Unix SMB/CIFS implementation. 3 3 Wrapper for krb5_init_context … … 11 11 the Free Software Foundation; either version 3 of the License, or 12 12 (at your option) any later version. 13 13 14 14 This program is distributed in the hope that it will be useful, 15 15 but WITHOUT ANY WARRANTY; without even the implied warranty of 16 16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 17 GNU General Public License for more details. 18 18 19 19 You should have received a copy of the GNU General Public License 20 20 along with this program. If not, see <http://www.gnu.org/licenses/>. … … 30 30 #include "param/param.h" 31 31 #include "libcli/resolve/resolve.h" 32 #include "../lib/tsocket/tsocket.h" 32 33 33 34 /* … … 42 43 NTSTATUS status; 43 44 DATA_BLOB request, reply; 44 45 45 46 struct packet_context *packet; 46 47 … … 50 51 }; 51 52 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) 53 static krb5_error_code smb_krb5_context_destroy(struct smb_krb5_context *ctx) 59 54 { 60 55 /* Otherwise krb5_free_context will try and close what we have already free()ed */ 61 56 krb5_set_warn_dest(ctx->krb5_context, NULL); 62 57 krb5_closelog(ctx->krb5_context, ctx->logf); 63 smb_krb5_context_destroy_1(ctx);58 krb5_free_context(ctx->krb5_context); 64 59 return 0; 65 60 } … … 72 67 static void smb_krb5_debug_wrapper(const char *timestr, const char *msg, void *private_data) 73 68 { 74 DEBUG( 2, ("Kerberos: %s\n", msg));69 DEBUG(3, ("Kerberos: %s\n", msg)); 75 70 } 76 71 … … 89 84 return; 90 85 } 91 86 92 87 blob = data_blob_talloc(tmp_ctx, NULL, dsize); 93 88 if (blob.data == NULL && dsize != 0) { … … 96 91 return; 97 92 } 98 93 99 94 smb_krb5->status = socket_recv(smb_krb5->sock, blob.data, blob.length, &nread); 100 95 if (!NT_STATUS_IS_OK(smb_krb5->status)) { … … 103 98 } 104 99 blob.length = nread; 105 100 106 101 if (nread == 0) { 107 102 smb_krb5->status = NT_STATUS_UNEXPECTED_NETWORK_ERROR; … … 109 104 return; 110 105 } 111 112 DEBUG(2,("Received smb_krb5 packet of length %d\n", 106 107 DEBUG(2,("Received smb_krb5 packet of length %d\n", 113 108 (int)blob.length)); 114 109 115 110 talloc_steal(smb_krb5, blob.data); 116 111 smb_krb5->reply = blob; … … 131 126 handle request timeouts 132 127 */ 133 static void smb_krb5_request_timeout(struct tevent_context *event_ctx, 128 static void smb_krb5_request_timeout(struct tevent_context *event_ctx, 134 129 struct tevent_timer *te, struct timeval t, 135 130 void *private_data) … … 154 149 155 150 size_t len; 156 151 157 152 len = smb_krb5->request.length; 158 153 status = socket_send(smb_krb5->sock, &smb_krb5->request, &len); 159 154 160 155 if (!NT_STATUS_IS_OK(status)) return; 161 156 162 157 TEVENT_FD_READABLE(smb_krb5->fde); 163 158 … … 213 208 krb5_error_code ret; 214 209 NTSTATUS status; 215 struct socket_address *remote_addr;216 210 const char *name; 217 211 struct addrinfo *ai, *a; 218 212 struct smb_krb5_socket *smb_krb5; 219 213 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); 223 234 224 235 ret = krb5_krbhst_get_addrinfo(context, hi, &ai); 225 236 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); 231 244 if (!smb_krb5) { 245 talloc_free(tmp_ctx); 232 246 return ENOMEM; 233 247 } 234 248 smb_krb5->hi = hi; 235 249 236 250 switch (a->ai_family) { 237 251 case PF_INET: … … 244 258 #endif 245 259 default: 246 talloc_free( smb_krb5);260 talloc_free(tmp_ctx); 247 261 return EINVAL; 248 262 } 249 263 250 264 status = NT_STATUS_INVALID_PARAMETER; 251 265 switch (hi->proto) { … … 257 271 break; 258 272 case KRB5_KRBHST_HTTP: 259 talloc_free( smb_krb5);273 talloc_free(tmp_ctx); 260 274 return EINVAL; 261 275 } … … 266 280 267 281 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); 270 284 if (!remote_addr) { 271 285 talloc_free(smb_krb5); … … 278 292 continue; 279 293 } 280 talloc_free(remote_addr);281 294 282 295 /* Setup the FDE, start listening for read events … … 326 339 break; 327 340 case KRB5_KRBHST_HTTP: 328 talloc_free( smb_krb5);341 talloc_free(tmp_ctx); 329 342 return EINVAL; 330 343 } 331 344 while ((NT_STATUS_IS_OK(smb_krb5->status)) && !smb_krb5->reply.length) { 332 345 if (tevent_loop_once(ev) != 0) { 333 talloc_free( smb_krb5);346 talloc_free(tmp_ctx); 334 347 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; 335 362 } 336 363 } … … 341 368 342 369 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)); 344 379 talloc_free(smb_krb5); 345 380 continue; … … 348 383 ret = krb5_data_copy(recv_buf, smb_krb5->reply.data, smb_krb5->reply.length); 349 384 if (ret) { 350 talloc_free( smb_krb5);385 talloc_free(tmp_ctx); 351 386 return ret; 352 387 } 353 388 talloc_free(smb_krb5); 354 389 355 390 break; 356 391 } 392 talloc_free(tmp_ctx); 357 393 if (a) { 358 394 return 0; … … 361 397 } 362 398 363 krb5_error_code smb_krb5_init_context(void *parent_ctx, 399 krb5_error_code 400 smb_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 457 krb5_error_code smb_krb5_init_context(void *parent_ctx, 364 458 struct tevent_context *ev, 365 459 struct loadparm_context *lp_ctx, 366 struct smb_krb5_context **smb_krb5_context)460 struct smb_krb5_context **smb_krb5_context) 367 461 { 368 462 krb5_error_code ret; 369 463 TALLOC_CTX *tmp_ctx; 370 char **config_files; 371 const char *config_file; 372 464 373 465 initialize_krb5_error_table(); 374 466 375 467 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); 377 469 378 470 if (!*smb_krb5_context || !tmp_ctx) { … … 381 473 } 382 474 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", 386 479 error_message(ret))); 387 480 talloc_free(tmp_ctx); 388 481 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 }432 482 } 433 483 434 484 /* TODO: Should we have a different name here? */ 435 485 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", 439 489 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 */, 447 498 smb_krb5_debug_wrapper, smb_krb5_debug_close, NULL); 448 499 if (ret) { 449 DEBUG(1,("krb5_addlog_func failed (%s)\n", 500 DEBUG(1,("krb5_addlog_func failed (%s)\n", 450 501 smb_get_krb5_error_message((*smb_krb5_context)->krb5_context, ret, tmp_ctx))); 451 502 talloc_free(tmp_ctx); … … 455 506 456 507 /* 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 } 465 516 } 466 517 … … 471 522 472 523 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)); 474 525 475 526 return 0; 476 527 } 477 528 529 krb5_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 561 krb5_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 21 21 krb5_context krb5_context; 22 22 krb5_log_facility *logf; 23 struct tevent_context *current_ev; 23 24 }; 24 25 25 26 struct tevent_context; 26 27 struct loadparm_context; 28 29 krb5_error_code 30 smb_krb5_init_context_basic(TALLOC_CTX *tmp_ctx, 31 struct loadparm_context *lp_ctx, 32 krb5_context *_krb5_context); 33 27 34 krb5_error_code smb_krb5_init_context(void *parent_ctx, struct tevent_context *ev, 28 35 struct loadparm_context *lp_ctx, 29 36 struct smb_krb5_context **smb_krb5_context); 30 void smb_krb5_free_context(struct smb_krb5_context *smb_krb5_context);31 37 32 38 krb5_error_code smb_krb5_send_and_recv_func(krb5_context context,
Note:
See TracChangeset
for help on using the changeset viewer.