forked from osmocom/wireshark
packet-kerberos: implement PAC Ticket checksum verification
We use some private functions from MIT kerberos: - krb5_free_enc_tkt_part() - decode_krb5_enc_tkt_part() - encode_krb5_enc_tkt_part() but we already do that for krb5int_c_mandatory_cksumtype(), which is newer than the above functions. We use all of them only under HAVE_KRB5_PAC_VERIFY, so we don't seem to need additional configure tests. Signed-off-by: Stefan Metzmacher <metze@samba.org>pespin/rlcmac
parent
8cd877fc4d
commit
94ac641efa
|
@ -92,6 +92,8 @@ if(KERBEROS_FOUND)
|
|||
check_symbol_exists("krb5_pac_verify" "krb5.h" HAVE_KRB5_PAC_VERIFY)
|
||||
# see also HAVE_KRB5_C_FX_CF2_SIMPLE in cmakeconfig.h.in
|
||||
check_symbol_exists("krb5_c_fx_cf2_simple" "krb5.h" HAVE_KRB5_C_FX_CF2_SIMPLE)
|
||||
check_function_exists(decode_krb5_enc_tkt_part HAVE_DECODE_KRB5_ENC_TKT_PART)
|
||||
check_function_exists(encode_krb5_enc_tkt_part HAVE_ENCODE_KRB5_ENC_TKT_PART)
|
||||
set(CMAKE_REQUIRED_INCLUDES)
|
||||
set(CMAKE_REQUIRED_LIBRARIES)
|
||||
if(NOT HAVE_HEIMDAL_KERBEROS)
|
||||
|
|
|
@ -91,6 +91,12 @@
|
|||
/* Define to 1 if you have the `krb5_c_fx_cf2_simple' function. */
|
||||
#cmakedefine HAVE_KRB5_C_FX_CF2_SIMPLE 1
|
||||
|
||||
/* Define to 1 if you have the `decode_krb5_enc_tkt_part' function. */
|
||||
#cmakedefine HAVE_DECODE_KRB5_ENC_TKT_PART 1
|
||||
|
||||
/* Define to 1 if you have the `encode_krb5_enc_tkt_part' function. */
|
||||
#cmakedefine HAVE_ENCODE_KRB5_ENC_TKT_PART 1
|
||||
|
||||
/* Define to 1 if you have the `inflatePrime' function. */
|
||||
#cmakedefine HAVE_INFLATEPRIME 1
|
||||
|
||||
|
|
|
@ -126,6 +126,7 @@ typedef struct {
|
|||
#ifdef HAVE_KERBEROS
|
||||
enc_key_t *last_decryption_key;
|
||||
enc_key_t *last_added_key;
|
||||
tvbuff_t *last_ticket_enc_part_tvb;
|
||||
#endif
|
||||
gint save_encryption_key_parent_hf_index;
|
||||
kerberos_key_save_fn save_encryption_key_fn;
|
||||
|
@ -1792,6 +1793,12 @@ decrypt_krb5_krb_cfx_dce(proto_tree *tree,
|
|||
extern krb5_error_code
|
||||
krb5int_c_mandatory_cksumtype(krb5_context, krb5_enctype, krb5_cksumtype *);
|
||||
|
||||
extern void krb5_free_enc_tkt_part(krb5_context, krb5_enc_tkt_part *);
|
||||
extern krb5_error_code
|
||||
decode_krb5_enc_tkt_part(const krb5_data *output, krb5_enc_tkt_part **rep);
|
||||
extern krb5_error_code
|
||||
encode_krb5_enc_tkt_part(const krb5_enc_tkt_part *rep, krb5_data **code);
|
||||
|
||||
static int
|
||||
keytype_for_cksumtype(krb5_cksumtype checksum)
|
||||
{
|
||||
|
@ -1829,6 +1836,8 @@ struct verify_krb5_pac_state {
|
|||
krb5_cksumtype kdc_checksum;
|
||||
guint kdc_count;
|
||||
enc_key_t *kdc_ek;
|
||||
krb5_cksumtype ticket_checksum_type;
|
||||
const krb5_data *ticket_checksum_data;
|
||||
};
|
||||
|
||||
static void
|
||||
|
@ -1929,12 +1938,236 @@ verify_krb5_pac_try_kdc_key(gpointer __key _U_, gpointer value, gpointer userdat
|
|||
}
|
||||
}
|
||||
|
||||
#define __KRB5_PAC_TICKET_CHECKSUM 16
|
||||
|
||||
static void
|
||||
verify_krb5_pac_ticket_checksum(proto_tree *tree _U_,
|
||||
asn1_ctx_t *actx _U_,
|
||||
tvbuff_t *pactvb _U_,
|
||||
struct verify_krb5_pac_state *state _U_)
|
||||
{
|
||||
#ifdef HAVE_DECODE_KRB5_ENC_TKT_PART
|
||||
kerberos_private_data_t *private_data = kerberos_get_private_data(actx);
|
||||
tvbuff_t *teptvb = private_data->last_ticket_enc_part_tvb;
|
||||
guint teplength = 0;
|
||||
const guint8 *tepbuffer = NULL;
|
||||
krb5_data tepdata = { .length = 0, };
|
||||
krb5_enc_tkt_part *tep = NULL;
|
||||
krb5_data *tmpdata = NULL;
|
||||
krb5_error_code ret;
|
||||
krb5_authdata **recoded_container = NULL;
|
||||
gint ad_orig_idx = -1;
|
||||
krb5_authdata *ad_orig_ptr = NULL;
|
||||
gint l0idx = 0;
|
||||
krb5_keyblock kdc_key = { .magic = KV5M_KEYBLOCK, };
|
||||
size_t checksum_length = 0;
|
||||
krb5_checksum checksum = { .checksum_type = 0, };
|
||||
krb5_boolean valid = FALSE;
|
||||
|
||||
if (state->kdc_ek == NULL) {
|
||||
int keytype = keytype_for_cksumtype(state->ticket_checksum_type);
|
||||
missing_signing_key(tree, actx->pinfo, private_data,
|
||||
pactvb, state->ticket_checksum_type,
|
||||
keytype,
|
||||
"Missing KDC (for ticket)",
|
||||
"kdc_checksum_key",
|
||||
0,
|
||||
0);
|
||||
return;
|
||||
}
|
||||
|
||||
if (teptvb == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
teplength = tvb_captured_length(teptvb);
|
||||
/* make sure we have all the data we need */
|
||||
if (teplength < tvb_reported_length(teptvb)) {
|
||||
return;
|
||||
}
|
||||
|
||||
tepbuffer = tvb_get_ptr(teptvb, 0, teplength);
|
||||
if (tepbuffer == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
kdc_key.magic = KV5M_KEYBLOCK;
|
||||
kdc_key.enctype = state->kdc_ek->keytype;
|
||||
kdc_key.length = state->kdc_ek->keylength;
|
||||
kdc_key.contents = (guint8 *)state->kdc_ek->keyvalue;
|
||||
|
||||
checksum.checksum_type = state->ticket_checksum_type;
|
||||
checksum.length = state->ticket_checksum_data->length;
|
||||
checksum.contents = (guint8 *)state->ticket_checksum_data->data;
|
||||
if (checksum.length >= 4) {
|
||||
checksum.length -= 4;
|
||||
checksum.contents += 4;
|
||||
}
|
||||
|
||||
ret = krb5_c_checksum_length(krb5_ctx,
|
||||
checksum.checksum_type,
|
||||
&checksum_length);
|
||||
if (ret != 0) {
|
||||
missing_signing_key(tree, actx->pinfo, private_data,
|
||||
pactvb, state->ticket_checksum_type,
|
||||
state->kdc_ek->keytype,
|
||||
"krb5_c_checksum_length failed for Ticket Signature",
|
||||
"kdc_checksum_key",
|
||||
1,
|
||||
0);
|
||||
return;
|
||||
}
|
||||
checksum.length = MIN(checksum.length, (unsigned int)checksum_length);
|
||||
|
||||
tepdata.data = (void *)(uintptr_t)tepbuffer;
|
||||
tepdata.length = teplength;
|
||||
|
||||
ret = decode_krb5_enc_tkt_part(&tepdata, &tep);
|
||||
if (ret != 0) {
|
||||
missing_signing_key(tree, actx->pinfo, private_data,
|
||||
pactvb, state->ticket_checksum_type,
|
||||
state->kdc_ek->keytype,
|
||||
"decode_krb5_enc_tkt_part failed",
|
||||
"kdc_checksum_key",
|
||||
1,
|
||||
0);
|
||||
return;
|
||||
}
|
||||
|
||||
for (l0idx = 0; tep->authorization_data[l0idx]; l0idx++) {
|
||||
krb5_authdata *adl0 = tep->authorization_data[l0idx];
|
||||
krb5_authdata **decoded_container = NULL;
|
||||
krb5_authdata *ad_pac = NULL;
|
||||
gint l1idx = 0;
|
||||
|
||||
if (adl0->ad_type != KRB5_AUTHDATA_IF_RELEVANT) {
|
||||
continue;
|
||||
}
|
||||
|
||||
ret = krb5_decode_authdata_container(krb5_ctx,
|
||||
KRB5_AUTHDATA_IF_RELEVANT,
|
||||
adl0,
|
||||
&decoded_container);
|
||||
if (ret != 0) {
|
||||
missing_signing_key(tree, actx->pinfo, private_data,
|
||||
pactvb, state->ticket_checksum_type,
|
||||
state->kdc_ek->keytype,
|
||||
"krb5_decode_authdata_container failed",
|
||||
"kdc_checksum_key",
|
||||
1,
|
||||
0);
|
||||
krb5_free_enc_tkt_part(krb5_ctx, tep);
|
||||
return;
|
||||
}
|
||||
|
||||
for (l1idx = 0; decoded_container[l1idx]; l1idx++) {
|
||||
krb5_authdata *adl1 = decoded_container[l1idx];
|
||||
|
||||
if (adl1->ad_type != KRB5_AUTHDATA_WIN2K_PAC) {
|
||||
continue;
|
||||
}
|
||||
|
||||
ad_pac = adl1;
|
||||
break;
|
||||
}
|
||||
|
||||
if (ad_pac == NULL) {
|
||||
krb5_free_authdata(krb5_ctx, decoded_container);
|
||||
continue;
|
||||
}
|
||||
|
||||
ad_pac->length = 1;
|
||||
ad_pac->contents[0] = '\0';
|
||||
|
||||
ret = krb5_encode_authdata_container(krb5_ctx,
|
||||
KRB5_AUTHDATA_IF_RELEVANT,
|
||||
decoded_container,
|
||||
&recoded_container);
|
||||
krb5_free_authdata(krb5_ctx, decoded_container);
|
||||
decoded_container = NULL;
|
||||
if (ret != 0) {
|
||||
missing_signing_key(tree, actx->pinfo, private_data,
|
||||
pactvb, state->ticket_checksum_type,
|
||||
state->kdc_ek->keytype,
|
||||
"krb5_encode_authdata_container failed",
|
||||
"kdc_checksum_key",
|
||||
1,
|
||||
0);
|
||||
krb5_free_enc_tkt_part(krb5_ctx, tep);
|
||||
return;
|
||||
}
|
||||
|
||||
ad_orig_idx = l0idx;
|
||||
ad_orig_ptr = adl0;
|
||||
tep->authorization_data[l0idx] = recoded_container[0];
|
||||
break;
|
||||
}
|
||||
|
||||
ret = encode_krb5_enc_tkt_part(tep, &tmpdata);
|
||||
if (ad_orig_ptr != NULL) {
|
||||
tep->authorization_data[ad_orig_idx] = ad_orig_ptr;
|
||||
}
|
||||
krb5_free_enc_tkt_part(krb5_ctx, tep);
|
||||
tep = NULL;
|
||||
if (recoded_container != NULL) {
|
||||
krb5_free_authdata(krb5_ctx, recoded_container);
|
||||
recoded_container = NULL;
|
||||
}
|
||||
if (ret != 0) {
|
||||
missing_signing_key(tree, actx->pinfo, private_data,
|
||||
pactvb, state->ticket_checksum_type,
|
||||
state->kdc_ek->keytype,
|
||||
"encode_krb5_enc_tkt_part failed",
|
||||
"kdc_checksum_key",
|
||||
1,
|
||||
0);
|
||||
return;
|
||||
}
|
||||
|
||||
ret = krb5_c_verify_checksum(krb5_ctx, &kdc_key,
|
||||
KRB5_KEYUSAGE_APP_DATA_CKSUM,
|
||||
tmpdata, &checksum, &valid);
|
||||
krb5_free_data(krb5_ctx, tmpdata);
|
||||
tmpdata = NULL;
|
||||
if (ret != 0) {
|
||||
missing_signing_key(tree, actx->pinfo, private_data,
|
||||
pactvb, state->ticket_checksum_type,
|
||||
state->kdc_ek->keytype,
|
||||
"krb5_c_verify_checksum failed for Ticket Signature",
|
||||
"kdc_checksum_key",
|
||||
1,
|
||||
1);
|
||||
return;
|
||||
}
|
||||
|
||||
if (valid == FALSE) {
|
||||
missing_signing_key(tree, actx->pinfo, private_data,
|
||||
pactvb, state->ticket_checksum_type,
|
||||
state->kdc_ek->keytype,
|
||||
"Invalid Ticket",
|
||||
"kdc_checksum_key",
|
||||
1,
|
||||
1);
|
||||
return;
|
||||
}
|
||||
|
||||
used_signing_key(tree, actx->pinfo, private_data,
|
||||
state->kdc_ek, pactvb,
|
||||
state->ticket_checksum_type,
|
||||
"Verified Ticket",
|
||||
"kdc_checksum_key",
|
||||
1,
|
||||
1);
|
||||
#endif /* HAVE_DECODE_KRB5_ENC_TKT_PART */
|
||||
}
|
||||
|
||||
static void
|
||||
verify_krb5_pac(proto_tree *tree _U_, asn1_ctx_t *actx, tvbuff_t *pactvb)
|
||||
{
|
||||
kerberos_private_data_t *private_data = kerberos_get_private_data(actx);
|
||||
krb5_error_code ret;
|
||||
krb5_data checksum_data = {0,0,NULL};
|
||||
krb5_data ticket_checksum_data = {0,0,NULL};
|
||||
int length = tvb_captured_length(pactvb);
|
||||
const guint8 *pacbuffer = NULL;
|
||||
struct verify_krb5_pac_state state = {
|
||||
|
@ -1974,6 +2207,13 @@ verify_krb5_pac(proto_tree *tree _U_, asn1_ctx_t *actx, tvbuff_t *pactvb)
|
|||
state.kdc_checksum = pletoh32(checksum_data.data);
|
||||
krb5_free_data_contents(krb5_ctx, &checksum_data);
|
||||
};
|
||||
ret = krb5_pac_get_buffer(krb5_ctx, state.pac,
|
||||
__KRB5_PAC_TICKET_CHECKSUM,
|
||||
&ticket_checksum_data);
|
||||
if (ret == 0) {
|
||||
state.ticket_checksum_data = &ticket_checksum_data;
|
||||
state.ticket_checksum_type = pletoh32(ticket_checksum_data.data);
|
||||
};
|
||||
|
||||
read_keytab_file_from_preferences();
|
||||
|
||||
|
@ -2016,6 +2256,14 @@ verify_krb5_pac(proto_tree *tree _U_, asn1_ctx_t *actx, tvbuff_t *pactvb)
|
|||
state.kdc_count);
|
||||
}
|
||||
|
||||
if (state.ticket_checksum_type != 0) {
|
||||
verify_krb5_pac_ticket_checksum(tree, actx, pactvb, &state);
|
||||
}
|
||||
|
||||
if (state.ticket_checksum_data != NULL) {
|
||||
krb5_free_data_contents(krb5_ctx, &ticket_checksum_data);
|
||||
}
|
||||
|
||||
krb5_pac_free(krb5_ctx, state.pac);
|
||||
}
|
||||
#endif /* HAVE_KRB5_PAC_VERIFY */
|
||||
|
@ -2829,13 +3077,17 @@ dissect_krb5_decrypt_ticket_data (gboolean imp_tag _U_, tvbuff_t *tvb, int offse
|
|||
plaintext=decrypt_krb5_data_asn1(tree, actx, 2, next_tvb, &length);
|
||||
|
||||
if(plaintext){
|
||||
kerberos_private_data_t *private_data = kerberos_get_private_data(actx);
|
||||
tvbuff_t *last_ticket_enc_part_tvb = private_data->last_ticket_enc_part_tvb;
|
||||
tvbuff_t *child_tvb;
|
||||
child_tvb = tvb_new_child_real_data(tvb, plaintext, length, length);
|
||||
|
||||
/* Add the decrypted data to the data source list. */
|
||||
add_new_data_source(actx->pinfo, child_tvb, "Krb5 Ticket");
|
||||
|
||||
private_data->last_ticket_enc_part_tvb = child_tvb;
|
||||
offset=dissect_kerberos_Applications(FALSE, child_tvb, 0, actx , tree, /* hf_index*/ -1);
|
||||
private_data->last_ticket_enc_part_tvb = last_ticket_enc_part_tvb;
|
||||
}
|
||||
return offset;
|
||||
}
|
||||
|
|
|
@ -134,6 +134,7 @@ typedef struct {
|
|||
#ifdef HAVE_KERBEROS
|
||||
enc_key_t *last_decryption_key;
|
||||
enc_key_t *last_added_key;
|
||||
tvbuff_t *last_ticket_enc_part_tvb;
|
||||
#endif
|
||||
gint save_encryption_key_parent_hf_index;
|
||||
kerberos_key_save_fn save_encryption_key_fn;
|
||||
|
@ -533,7 +534,7 @@ static int hf_kerberos_PAC_OPTIONS_FLAGS_forward_to_full_dc = -1;
|
|||
static int hf_kerberos_PAC_OPTIONS_FLAGS_resource_based_constrained_delegation = -1;
|
||||
|
||||
/*--- End of included file: packet-kerberos-hf.c ---*/
|
||||
#line 295 "./asn1/kerberos/packet-kerberos-template.c"
|
||||
#line 296 "./asn1/kerberos/packet-kerberos-template.c"
|
||||
|
||||
/* Initialize the subtree pointers */
|
||||
static gint ett_kerberos = -1;
|
||||
|
@ -650,7 +651,7 @@ static gint ett_kerberos_SPAKEResponse = -1;
|
|||
static gint ett_kerberos_PA_SPAKE = -1;
|
||||
|
||||
/*--- End of included file: packet-kerberos-ett.c ---*/
|
||||
#line 322 "./asn1/kerberos/packet-kerberos-template.c"
|
||||
#line 323 "./asn1/kerberos/packet-kerberos-template.c"
|
||||
|
||||
static expert_field ei_kerberos_missing_keytype = EI_INIT;
|
||||
static expert_field ei_kerberos_decrypted_keytype = EI_INIT;
|
||||
|
@ -781,7 +782,7 @@ typedef enum _KERBEROS_KRBFASTARMORTYPES_enum {
|
|||
} KERBEROS_KRBFASTARMORTYPES_enum;
|
||||
|
||||
/*--- End of included file: packet-kerberos-val.h ---*/
|
||||
#line 336 "./asn1/kerberos/packet-kerberos-template.c"
|
||||
#line 337 "./asn1/kerberos/packet-kerberos-template.c"
|
||||
|
||||
static void
|
||||
call_kerberos_callbacks(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int tag, kerberos_callbacks *cb)
|
||||
|
@ -2241,6 +2242,12 @@ decrypt_krb5_krb_cfx_dce(proto_tree *tree,
|
|||
extern krb5_error_code
|
||||
krb5int_c_mandatory_cksumtype(krb5_context, krb5_enctype, krb5_cksumtype *);
|
||||
|
||||
extern void krb5_free_enc_tkt_part(krb5_context, krb5_enc_tkt_part *);
|
||||
extern krb5_error_code
|
||||
decode_krb5_enc_tkt_part(const krb5_data *output, krb5_enc_tkt_part **rep);
|
||||
extern krb5_error_code
|
||||
encode_krb5_enc_tkt_part(const krb5_enc_tkt_part *rep, krb5_data **code);
|
||||
|
||||
static int
|
||||
keytype_for_cksumtype(krb5_cksumtype checksum)
|
||||
{
|
||||
|
@ -2278,6 +2285,8 @@ struct verify_krb5_pac_state {
|
|||
krb5_cksumtype kdc_checksum;
|
||||
guint kdc_count;
|
||||
enc_key_t *kdc_ek;
|
||||
krb5_cksumtype ticket_checksum_type;
|
||||
const krb5_data *ticket_checksum_data;
|
||||
};
|
||||
|
||||
static void
|
||||
|
@ -2378,12 +2387,236 @@ verify_krb5_pac_try_kdc_key(gpointer __key _U_, gpointer value, gpointer userdat
|
|||
}
|
||||
}
|
||||
|
||||
#define __KRB5_PAC_TICKET_CHECKSUM 16
|
||||
|
||||
static void
|
||||
verify_krb5_pac_ticket_checksum(proto_tree *tree _U_,
|
||||
asn1_ctx_t *actx _U_,
|
||||
tvbuff_t *pactvb _U_,
|
||||
struct verify_krb5_pac_state *state _U_)
|
||||
{
|
||||
#ifdef HAVE_DECODE_KRB5_ENC_TKT_PART
|
||||
kerberos_private_data_t *private_data = kerberos_get_private_data(actx);
|
||||
tvbuff_t *teptvb = private_data->last_ticket_enc_part_tvb;
|
||||
guint teplength = 0;
|
||||
const guint8 *tepbuffer = NULL;
|
||||
krb5_data tepdata = { .length = 0, };
|
||||
krb5_enc_tkt_part *tep = NULL;
|
||||
krb5_data *tmpdata = NULL;
|
||||
krb5_error_code ret;
|
||||
krb5_authdata **recoded_container = NULL;
|
||||
gint ad_orig_idx = -1;
|
||||
krb5_authdata *ad_orig_ptr = NULL;
|
||||
gint l0idx = 0;
|
||||
krb5_keyblock kdc_key = { .magic = KV5M_KEYBLOCK, };
|
||||
size_t checksum_length = 0;
|
||||
krb5_checksum checksum = { .checksum_type = 0, };
|
||||
krb5_boolean valid = FALSE;
|
||||
|
||||
if (state->kdc_ek == NULL) {
|
||||
int keytype = keytype_for_cksumtype(state->ticket_checksum_type);
|
||||
missing_signing_key(tree, actx->pinfo, private_data,
|
||||
pactvb, state->ticket_checksum_type,
|
||||
keytype,
|
||||
"Missing KDC (for ticket)",
|
||||
"kdc_checksum_key",
|
||||
0,
|
||||
0);
|
||||
return;
|
||||
}
|
||||
|
||||
if (teptvb == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
teplength = tvb_captured_length(teptvb);
|
||||
/* make sure we have all the data we need */
|
||||
if (teplength < tvb_reported_length(teptvb)) {
|
||||
return;
|
||||
}
|
||||
|
||||
tepbuffer = tvb_get_ptr(teptvb, 0, teplength);
|
||||
if (tepbuffer == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
kdc_key.magic = KV5M_KEYBLOCK;
|
||||
kdc_key.enctype = state->kdc_ek->keytype;
|
||||
kdc_key.length = state->kdc_ek->keylength;
|
||||
kdc_key.contents = (guint8 *)state->kdc_ek->keyvalue;
|
||||
|
||||
checksum.checksum_type = state->ticket_checksum_type;
|
||||
checksum.length = state->ticket_checksum_data->length;
|
||||
checksum.contents = (guint8 *)state->ticket_checksum_data->data;
|
||||
if (checksum.length >= 4) {
|
||||
checksum.length -= 4;
|
||||
checksum.contents += 4;
|
||||
}
|
||||
|
||||
ret = krb5_c_checksum_length(krb5_ctx,
|
||||
checksum.checksum_type,
|
||||
&checksum_length);
|
||||
if (ret != 0) {
|
||||
missing_signing_key(tree, actx->pinfo, private_data,
|
||||
pactvb, state->ticket_checksum_type,
|
||||
state->kdc_ek->keytype,
|
||||
"krb5_c_checksum_length failed for Ticket Signature",
|
||||
"kdc_checksum_key",
|
||||
1,
|
||||
0);
|
||||
return;
|
||||
}
|
||||
checksum.length = MIN(checksum.length, (unsigned int)checksum_length);
|
||||
|
||||
tepdata.data = (void *)(uintptr_t)tepbuffer;
|
||||
tepdata.length = teplength;
|
||||
|
||||
ret = decode_krb5_enc_tkt_part(&tepdata, &tep);
|
||||
if (ret != 0) {
|
||||
missing_signing_key(tree, actx->pinfo, private_data,
|
||||
pactvb, state->ticket_checksum_type,
|
||||
state->kdc_ek->keytype,
|
||||
"decode_krb5_enc_tkt_part failed",
|
||||
"kdc_checksum_key",
|
||||
1,
|
||||
0);
|
||||
return;
|
||||
}
|
||||
|
||||
for (l0idx = 0; tep->authorization_data[l0idx]; l0idx++) {
|
||||
krb5_authdata *adl0 = tep->authorization_data[l0idx];
|
||||
krb5_authdata **decoded_container = NULL;
|
||||
krb5_authdata *ad_pac = NULL;
|
||||
gint l1idx = 0;
|
||||
|
||||
if (adl0->ad_type != KRB5_AUTHDATA_IF_RELEVANT) {
|
||||
continue;
|
||||
}
|
||||
|
||||
ret = krb5_decode_authdata_container(krb5_ctx,
|
||||
KRB5_AUTHDATA_IF_RELEVANT,
|
||||
adl0,
|
||||
&decoded_container);
|
||||
if (ret != 0) {
|
||||
missing_signing_key(tree, actx->pinfo, private_data,
|
||||
pactvb, state->ticket_checksum_type,
|
||||
state->kdc_ek->keytype,
|
||||
"krb5_decode_authdata_container failed",
|
||||
"kdc_checksum_key",
|
||||
1,
|
||||
0);
|
||||
krb5_free_enc_tkt_part(krb5_ctx, tep);
|
||||
return;
|
||||
}
|
||||
|
||||
for (l1idx = 0; decoded_container[l1idx]; l1idx++) {
|
||||
krb5_authdata *adl1 = decoded_container[l1idx];
|
||||
|
||||
if (adl1->ad_type != KRB5_AUTHDATA_WIN2K_PAC) {
|
||||
continue;
|
||||
}
|
||||
|
||||
ad_pac = adl1;
|
||||
break;
|
||||
}
|
||||
|
||||
if (ad_pac == NULL) {
|
||||
krb5_free_authdata(krb5_ctx, decoded_container);
|
||||
continue;
|
||||
}
|
||||
|
||||
ad_pac->length = 1;
|
||||
ad_pac->contents[0] = '\0';
|
||||
|
||||
ret = krb5_encode_authdata_container(krb5_ctx,
|
||||
KRB5_AUTHDATA_IF_RELEVANT,
|
||||
decoded_container,
|
||||
&recoded_container);
|
||||
krb5_free_authdata(krb5_ctx, decoded_container);
|
||||
decoded_container = NULL;
|
||||
if (ret != 0) {
|
||||
missing_signing_key(tree, actx->pinfo, private_data,
|
||||
pactvb, state->ticket_checksum_type,
|
||||
state->kdc_ek->keytype,
|
||||
"krb5_encode_authdata_container failed",
|
||||
"kdc_checksum_key",
|
||||
1,
|
||||
0);
|
||||
krb5_free_enc_tkt_part(krb5_ctx, tep);
|
||||
return;
|
||||
}
|
||||
|
||||
ad_orig_idx = l0idx;
|
||||
ad_orig_ptr = adl0;
|
||||
tep->authorization_data[l0idx] = recoded_container[0];
|
||||
break;
|
||||
}
|
||||
|
||||
ret = encode_krb5_enc_tkt_part(tep, &tmpdata);
|
||||
if (ad_orig_ptr != NULL) {
|
||||
tep->authorization_data[ad_orig_idx] = ad_orig_ptr;
|
||||
}
|
||||
krb5_free_enc_tkt_part(krb5_ctx, tep);
|
||||
tep = NULL;
|
||||
if (recoded_container != NULL) {
|
||||
krb5_free_authdata(krb5_ctx, recoded_container);
|
||||
recoded_container = NULL;
|
||||
}
|
||||
if (ret != 0) {
|
||||
missing_signing_key(tree, actx->pinfo, private_data,
|
||||
pactvb, state->ticket_checksum_type,
|
||||
state->kdc_ek->keytype,
|
||||
"encode_krb5_enc_tkt_part failed",
|
||||
"kdc_checksum_key",
|
||||
1,
|
||||
0);
|
||||
return;
|
||||
}
|
||||
|
||||
ret = krb5_c_verify_checksum(krb5_ctx, &kdc_key,
|
||||
KRB5_KEYUSAGE_APP_DATA_CKSUM,
|
||||
tmpdata, &checksum, &valid);
|
||||
krb5_free_data(krb5_ctx, tmpdata);
|
||||
tmpdata = NULL;
|
||||
if (ret != 0) {
|
||||
missing_signing_key(tree, actx->pinfo, private_data,
|
||||
pactvb, state->ticket_checksum_type,
|
||||
state->kdc_ek->keytype,
|
||||
"krb5_c_verify_checksum failed for Ticket Signature",
|
||||
"kdc_checksum_key",
|
||||
1,
|
||||
1);
|
||||
return;
|
||||
}
|
||||
|
||||
if (valid == FALSE) {
|
||||
missing_signing_key(tree, actx->pinfo, private_data,
|
||||
pactvb, state->ticket_checksum_type,
|
||||
state->kdc_ek->keytype,
|
||||
"Invalid Ticket",
|
||||
"kdc_checksum_key",
|
||||
1,
|
||||
1);
|
||||
return;
|
||||
}
|
||||
|
||||
used_signing_key(tree, actx->pinfo, private_data,
|
||||
state->kdc_ek, pactvb,
|
||||
state->ticket_checksum_type,
|
||||
"Verified Ticket",
|
||||
"kdc_checksum_key",
|
||||
1,
|
||||
1);
|
||||
#endif /* HAVE_DECODE_KRB5_ENC_TKT_PART */
|
||||
}
|
||||
|
||||
static void
|
||||
verify_krb5_pac(proto_tree *tree _U_, asn1_ctx_t *actx, tvbuff_t *pactvb)
|
||||
{
|
||||
kerberos_private_data_t *private_data = kerberos_get_private_data(actx);
|
||||
krb5_error_code ret;
|
||||
krb5_data checksum_data = {0,0,NULL};
|
||||
krb5_data ticket_checksum_data = {0,0,NULL};
|
||||
int length = tvb_captured_length(pactvb);
|
||||
const guint8 *pacbuffer = NULL;
|
||||
struct verify_krb5_pac_state state = {
|
||||
|
@ -2423,6 +2656,13 @@ verify_krb5_pac(proto_tree *tree _U_, asn1_ctx_t *actx, tvbuff_t *pactvb)
|
|||
state.kdc_checksum = pletoh32(checksum_data.data);
|
||||
krb5_free_data_contents(krb5_ctx, &checksum_data);
|
||||
};
|
||||
ret = krb5_pac_get_buffer(krb5_ctx, state.pac,
|
||||
__KRB5_PAC_TICKET_CHECKSUM,
|
||||
&ticket_checksum_data);
|
||||
if (ret == 0) {
|
||||
state.ticket_checksum_data = &ticket_checksum_data;
|
||||
state.ticket_checksum_type = pletoh32(ticket_checksum_data.data);
|
||||
};
|
||||
|
||||
read_keytab_file_from_preferences();
|
||||
|
||||
|
@ -2465,6 +2705,14 @@ verify_krb5_pac(proto_tree *tree _U_, asn1_ctx_t *actx, tvbuff_t *pactvb)
|
|||
state.kdc_count);
|
||||
}
|
||||
|
||||
if (state.ticket_checksum_type != 0) {
|
||||
verify_krb5_pac_ticket_checksum(tree, actx, pactvb, &state);
|
||||
}
|
||||
|
||||
if (state.ticket_checksum_data != NULL) {
|
||||
krb5_free_data_contents(krb5_ctx, &ticket_checksum_data);
|
||||
}
|
||||
|
||||
krb5_pac_free(krb5_ctx, state.pac);
|
||||
}
|
||||
#endif /* HAVE_KRB5_PAC_VERIFY */
|
||||
|
@ -3278,13 +3526,17 @@ dissect_krb5_decrypt_ticket_data (gboolean imp_tag _U_, tvbuff_t *tvb, int offse
|
|||
plaintext=decrypt_krb5_data_asn1(tree, actx, 2, next_tvb, &length);
|
||||
|
||||
if(plaintext){
|
||||
kerberos_private_data_t *private_data = kerberos_get_private_data(actx);
|
||||
tvbuff_t *last_ticket_enc_part_tvb = private_data->last_ticket_enc_part_tvb;
|
||||
tvbuff_t *child_tvb;
|
||||
child_tvb = tvb_new_child_real_data(tvb, plaintext, length, length);
|
||||
|
||||
/* Add the decrypted data to the data source list. */
|
||||
add_new_data_source(actx->pinfo, child_tvb, "Krb5 Ticket");
|
||||
|
||||
private_data->last_ticket_enc_part_tvb = child_tvb;
|
||||
offset=dissect_kerberos_Applications(FALSE, child_tvb, 0, actx , tree, /* hf_index*/ -1);
|
||||
private_data->last_ticket_enc_part_tvb = last_ticket_enc_part_tvb;
|
||||
}
|
||||
return offset;
|
||||
}
|
||||
|
@ -7429,7 +7681,7 @@ dissect_kerberos_PA_SPAKE(gboolean implicit_tag _U_, tvbuff_t *tvb _U_, int offs
|
|||
|
||||
|
||||
/*--- End of included file: packet-kerberos-fn.c ---*/
|
||||
#line 3902 "./asn1/kerberos/packet-kerberos-template.c"
|
||||
#line 4154 "./asn1/kerberos/packet-kerberos-template.c"
|
||||
|
||||
#ifdef HAVE_KERBEROS
|
||||
static const ber_sequence_t PA_ENC_TS_ENC_sequence[] = {
|
||||
|
@ -9239,7 +9491,7 @@ void proto_register_kerberos(void) {
|
|||
NULL, HFILL }},
|
||||
|
||||
/*--- End of included file: packet-kerberos-hfarr.c ---*/
|
||||
#line 4795 "./asn1/kerberos/packet-kerberos-template.c"
|
||||
#line 5047 "./asn1/kerberos/packet-kerberos-template.c"
|
||||
};
|
||||
|
||||
/* List of subtrees */
|
||||
|
@ -9358,7 +9610,7 @@ void proto_register_kerberos(void) {
|
|||
&ett_kerberos_PA_SPAKE,
|
||||
|
||||
/*--- End of included file: packet-kerberos-ettarr.c ---*/
|
||||
#line 4824 "./asn1/kerberos/packet-kerberos-template.c"
|
||||
#line 5076 "./asn1/kerberos/packet-kerberos-template.c"
|
||||
};
|
||||
|
||||
static ei_register_info ei[] = {
|
||||
|
|
Loading…
Reference in New Issue