From 99777452f0d191461bf7b92397bb44378cdb4cfb Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Tue, 28 Jun 2005 08:27:50 +0000 Subject: r7978: A start again on PAC verification. I have noticed that the kerberos keys appear at the end of the PAC, which I feel is deliberate (it makes this much easier). I still can't make it work, but I'm sure we are closer. Andrew Bartlett (This used to be commit 6f0e1c80ae7b1e31e7a3fbff84f07442ee5a31cf) --- source4/auth/gensec/gensec_gssapi.c | 10 ++++- source4/auth/kerberos/kerberos.h | 8 ++++ source4/auth/kerberos/kerberos_pac.c | 77 +++++++++++++----------------------- 3 files changed, 43 insertions(+), 52 deletions(-) diff --git a/source4/auth/gensec/gensec_gssapi.c b/source4/auth/gensec/gensec_gssapi.c index a95805f9fa..2b7c4ca2cc 100644 --- a/source4/auth/gensec/gensec_gssapi.c +++ b/source4/auth/gensec/gensec_gssapi.c @@ -737,6 +737,7 @@ static NTSTATUS gensec_gssapi_session_info(struct gensec_security *gensec_securi OM_uint32 maj_stat, min_stat; gss_buffer_desc name_token; gss_buffer_desc pac; + krb5_keyblock *keyblock; mem_ctx = talloc_named(gensec_gssapi_state, 0, "gensec_gssapi_session_info context"); NT_STATUS_HAVE_NO_MEMORY(mem_ctx); @@ -768,9 +769,13 @@ static NTSTATUS gensec_gssapi_session_info(struct gensec_security *gensec_securi } account_name = principal; + maj_stat = gss_krb5_copy_service_keyblock(&min_stat, + gensec_gssapi_state->gssapi_context, + &keyblock); + maj_stat = gsskrb5_extract_authz_data_from_sec_context(&min_stat, gensec_gssapi_state->gssapi_context, - 1, + KRB5_AUTHDATA_IF_RELEVANT, &pac); if (maj_stat == 0) { @@ -780,7 +785,8 @@ static NTSTATUS gensec_gssapi_session_info(struct gensec_security *gensec_securi /* decode and verify the pac */ nt_status = kerberos_decode_pac(mem_ctx, &logon_info, pac_blob, - gensec_gssapi_state->smb_krb5_context); + gensec_gssapi_state->smb_krb5_context, + keyblock); if (NT_STATUS_IS_OK(nt_status)) { union netr_Validation validation; diff --git a/source4/auth/kerberos/kerberos.h b/source4/auth/kerberos/kerberos.h index 0f8fd28155..ca0bbbed0e 100644 --- a/source4/auth/kerberos/kerberos.h +++ b/source4/auth/kerberos/kerberos.h @@ -101,6 +101,9 @@ NTSTATUS ads_verify_ticket(TALLOC_CTX *mem_ctx, int kerberos_kinit_password_cc(krb5_context ctx, krb5_ccache cc, const char *principal, const char *password, time_t *expire_time, time_t *kdc_time); +int kerberos_kinit_keyblock_cc(krb5_context ctx, krb5_ccache cc, + const char *principal, krb5_keyblock *keyblock, + time_t *expire_time, time_t *kdc_time); krb5_principal kerberos_fetch_salt_princ_for_host_princ(krb5_context context, krb5_principal host_princ, int enctype); @@ -124,5 +127,10 @@ NTSTATUS create_memory_keytab(TALLOC_CTX *parent_ctx, struct cli_credentials *machine_account, struct smb_krb5_context *smb_krb5_context, krb5_keytab *keytab); +NTSTATUS kerberos_decode_pac(TALLOC_CTX *mem_ctx, + struct PAC_LOGON_INFO **logon_info_out, + DATA_BLOB blob, + struct smb_krb5_context *smb_krb5_context, + krb5_keyblock *keyblock); #endif /* HAVE_KRB5 */ diff --git a/source4/auth/kerberos/kerberos_pac.c b/source4/auth/kerberos/kerberos_pac.c index 8f3d2cd72c..84a7c56cc9 100644 --- a/source4/auth/kerberos/kerberos_pac.c +++ b/source4/auth/kerberos/kerberos_pac.c @@ -32,11 +32,12 @@ #include "librpc/gen_ndr/ndr_krb5pac.h" #include "auth/auth.h" -#ifdef KRB5_DO_VERIFY_PAC -static NTSTATUS kerberos_pac_checksum(DATA_BLOB pac_data, - struct PAC_SIGNATURE_DATA *sig, - struct smb_krb5_context *smb_krb5_context, - uint32 keyusage) +static NTSTATUS kerberos_pac_checksum(TALLOC_CTX *mem_ctx, + DATA_BLOB pac_data, + struct PAC_SIGNATURE_DATA *sig, + struct smb_krb5_context *smb_krb5_context, + krb5_keyblock *keyblock, + uint32_t keyusage) { krb5_error_code ret; krb5_crypto crypto; @@ -49,9 +50,9 @@ static NTSTATUS kerberos_pac_checksum(DATA_BLOB pac_data, ret = krb5_crypto_init(smb_krb5_context->krb5_context, - &gensec_krb5_state->keyblock, - 0, - &crypto); + keyblock, + 0, + &crypto); if (ret) { DEBUG(0,("krb5_crypto_init() failed\n")); return NT_STATUS_FOOBAR; @@ -65,10 +66,14 @@ static NTSTATUS kerberos_pac_checksum(DATA_BLOB pac_data, pac_data.length, &cksum); if (!ret) { - DEBUG(0,("PAC Verified: keyusage: %d\n", keyusage)); + DEBUG(0, ("PAC Verified: keyusage: %d\n", keyusage)); break; + } else { + DEBUG(2, ("PAC Verification failed: %s\n", + smb_get_krb5_error_message(smb_krb5_context->krb5_context, ret, mem_ctx))); } } + krb5_crypto_destroy(smb_krb5_context->krb5_context, crypto); if (ret) { @@ -80,23 +85,22 @@ static NTSTATUS kerberos_pac_checksum(DATA_BLOB pac_data, return NT_STATUS_OK; } -#endif -NTSTATUS kerberos_decode_pac(TALLOC_CTX *mem_ctx, + NTSTATUS kerberos_decode_pac(TALLOC_CTX *mem_ctx, struct PAC_LOGON_INFO **logon_info_out, DATA_BLOB blob, - struct smb_krb5_context *smb_krb5_context) + struct smb_krb5_context *smb_krb5_context, + krb5_keyblock *keyblock) { NTSTATUS status; struct PAC_SIGNATURE_DATA srv_sig; - struct PAC_SIGNATURE_DATA *srv_sig_ptr; + struct PAC_SIGNATURE_DATA *srv_sig_ptr = NULL; struct PAC_SIGNATURE_DATA kdc_sig; - struct PAC_SIGNATURE_DATA *kdc_sig_ptr; + struct PAC_SIGNATURE_DATA *kdc_sig_ptr = NULL; struct PAC_LOGON_INFO *logon_info = NULL; struct PAC_DATA pac_data; -#ifdef KRB5_DO_VERIFY_PAC - DATA_BLOB tmp_blob = data_blob(NULL, 0); -#endif + DATA_BLOB modified_pac_blob = data_blob_talloc(mem_ctx, blob.data, blob.length); + DATA_BLOB tmp_blob; int i; status = ndr_pull_struct_blob(&blob, mem_ctx, &pac_data, @@ -156,39 +160,11 @@ NTSTATUS kerberos_decode_pac(TALLOC_CTX *mem_ctx, DEBUG(0,("PAC no kdc_key\n")); return NT_STATUS_FOOBAR; } -#ifdef KRB5_DO_VERIFY_PAC - /* clear the kdc_key */ -/* memset((void *)kdc_sig_ptr , '\0', sizeof(*kdc_sig_ptr));*/ - - status = ndr_push_struct_blob(&tmp_blob, mem_ctx, &pac_data, - (ndr_push_flags_fn_t)ndr_push_PAC_DATA); - if (!NT_STATUS_IS_OK(status)) { - return status; - } - status = ndr_pull_struct_blob(&tmp_blob, mem_ctx, &pac_data, - (ndr_pull_flags_fn_t)ndr_pull_PAC_DATA); - if (!NT_STATUS_IS_OK(status)) { - DEBUG(0,("can't parse the PAC\n")); - return status; - } - /*NDR_PRINT_DEBUG(PAC_DATA, &pac_data);*/ - - /* verify by kdc_key */ - status = kerberos_pac_checksum(tmp_blob, &kdc_sig, smb_krb5_context, 0); - if (!NT_STATUS_IS_OK(status)) { - return status; - } + memset(&modified_pac_blob.data[modified_pac_blob.length - 48], + '\0', 48); - /* clear the service_key */ -/* memset((void *)srv_sig_ptr , '\0', sizeof(*srv_sig_ptr));*/ - - status = ndr_push_struct_blob(&tmp_blob, mem_ctx, &pac_data, - (ndr_push_flags_fn_t)ndr_push_PAC_DATA); - if (!NT_STATUS_IS_OK(status)) { - return status; - } - status = ndr_pull_struct_blob(&tmp_blob, mem_ctx, &pac_data, + status = ndr_pull_struct_blob(&modified_pac_blob, mem_ctx, &pac_data, (ndr_pull_flags_fn_t)ndr_pull_PAC_DATA); if (!NT_STATUS_IS_OK(status)) { DEBUG(0,("can't parse the PAC\n")); @@ -197,12 +173,13 @@ NTSTATUS kerberos_decode_pac(TALLOC_CTX *mem_ctx, NDR_PRINT_DEBUG(PAC_DATA, &pac_data); /* verify by servie_key */ - status = kerberos_pac_checksum(tmp_blob, &srv_sig, smb_krb5_context, 0); + status = kerberos_pac_checksum(mem_ctx, + modified_pac_blob, &srv_sig, + smb_krb5_context, keyblock, 0); if (!NT_STATUS_IS_OK(status)) { return status; } -#endif DEBUG(0,("account_name: %s [%s]\n", logon_info->info3.base.account_name.string, logon_info->info3.base.full_name.string)); -- cgit