Skip to content

Commit

Permalink
Correct IAKERB protocol implementation
Browse files Browse the repository at this point in the history
The initial implementation of IAKERB in MIT krb5 mistakenly used
draft-zhu-ws-kerb instead of draft-kitten-ietf-iakerb, and
additionally used the wrong ASN.1 tag value for the target-realm field
of the IAKERB-HEADER sequence.  Correct the following aspects of the
protocol implementation:

* Require and use framing on all messages, not just the initial
  context token.
* Use extension value 2 for the finish message instead of 1.
* Use key usage value 41 instead of 42 for the finish message
  checksum.
* Use UTF8String (12) for target-realm instead of OCTET STRING (4).

With these changes, the IAKERB implementation is interoperable with
other krb5 implementations, but not with the implementation before
these changes.

ticket: 9123 (new)
  • Loading branch information
greghudson committed May 23, 2024
1 parent 4b21b2e commit de71318
Show file tree
Hide file tree
Showing 11 changed files with 26 additions and 44 deletions.
1 change: 1 addition & 0 deletions doc/appdev/refs/macros/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,7 @@ Public
KRB5_KEYUSAGE_GSS_TOK_MIC.rst
KRB5_KEYUSAGE_GSS_TOK_WRAP_INTEG.rst
KRB5_KEYUSAGE_GSS_TOK_WRAP_PRIV.rst
KRB5_KEYUSAGE_FINISHED.rst
KRB5_KEYUSAGE_IAKERB_FINISHED.rst
KRB5_KEYUSAGE_KDC_REP_TICKET.rst
KRB5_KEYUSAGE_KRB_CRED_ENCPART.rst
Expand Down
1 change: 1 addition & 0 deletions src/include/krb5/krb5.hin
Original file line number Diff line number Diff line change
Expand Up @@ -977,6 +977,7 @@ krb5_c_keyed_checksum_types(krb5_context context, krb5_enctype enctype,
#define KRB5_KEYUSAGE_PA_REFERRAL 26

#define KRB5_KEYUSAGE_AD_SIGNEDPATH -21
#define KRB5_KEYUSAGE_FINISHED 41
#define KRB5_KEYUSAGE_IAKERB_FINISHED 42
#define KRB5_KEYUSAGE_PA_PKINIT_KX 44
#define KRB5_KEYUSAGE_PA_OTP_REQUEST 45 /**< See RFC 6560 section 4.2 */
Expand Down
2 changes: 1 addition & 1 deletion src/lib/gssapi/krb5/accept_sec_context.c
Original file line number Diff line number Diff line change
Expand Up @@ -378,7 +378,7 @@ kg_process_extension(krb5_context context,
assert(exts != NULL);

switch (ext_type) {
case KRB5_GSS_EXTS_IAKERB_FINISHED:
case GSS_EXTS_FINISHED:
if (exts->iakerb.conv == NULL) {
code = KRB5KRB_AP_ERR_MSG_TYPE; /* XXX */
} else {
Expand Down
2 changes: 1 addition & 1 deletion src/lib/gssapi/krb5/gssapiP_krb5.h
Original file line number Diff line number Diff line change
Expand Up @@ -1291,7 +1291,7 @@ data_to_gss(krb5_data *input_k5data, gss_buffer_t output_buffer)
return code;
}

#define KRB5_GSS_EXTS_IAKERB_FINISHED 1
#define GSS_EXTS_FINISHED 2


/* Credential store extensions */
Expand Down
45 changes: 13 additions & 32 deletions src/lib/gssapi/krb5/iakerb.c
Original file line number Diff line number Diff line change
Expand Up @@ -97,8 +97,8 @@ iakerb_make_finished(krb5_context context,
if (key == NULL)
return KRB5KDC_ERR_NULL_KEY;

code = krb5_k_make_checksum(context, 0, key, KRB5_KEYUSAGE_IAKERB_FINISHED,
conv, &iaf.checksum);
code = krb5_k_make_checksum(context, 0, key, KRB5_KEYUSAGE_FINISHED, conv,
&iaf.checksum);
if (code != 0)
return code;

Expand Down Expand Up @@ -129,8 +129,8 @@ iakerb_verify_finished(krb5_context context,
if (code != 0)
return code;

code = krb5_k_verify_checksum(context, key, KRB5_KEYUSAGE_IAKERB_FINISHED,
conv, &iaf->checksum, &valid);
code = krb5_k_verify_checksum(context, key, KRB5_KEYUSAGE_FINISHED, conv,
&iaf->checksum, &valid);
if (code == 0 && valid == FALSE)
code = KRB5KRB_AP_ERR_BAD_INTEGRITY;

Expand Down Expand Up @@ -163,7 +163,6 @@ iakerb_save_token(iakerb_ctx_id_t ctx, const gss_buffer_t token)
*/
static krb5_error_code
iakerb_parse_token(iakerb_ctx_id_t ctx,
int initialContextToken,
const gss_buffer_t token,
krb5_data *realm,
krb5_data **cookie,
Expand All @@ -173,7 +172,6 @@ iakerb_parse_token(iakerb_ctx_id_t ctx,
krb5_iakerb_header *iah = NULL;
unsigned int bodysize;
uint8_t *body;
int flags = 0;
krb5_data data;
struct k5input in, seq;

Expand All @@ -182,12 +180,10 @@ iakerb_parse_token(iakerb_ctx_id_t ctx,
goto cleanup;
}

if (initialContextToken)
flags |= G_VFY_TOKEN_HDR_WRAPPER_REQUIRED;

body = token->value;
code = g_verify_token_header(gss_mech_iakerb, &bodysize, &body,
IAKERB_TOK_PROXY, token->length, flags);
IAKERB_TOK_PROXY, token->length,
G_VFY_TOKEN_HDR_WRAPPER_REQUIRED);
if (code != 0)
goto cleanup;

Expand Down Expand Up @@ -232,7 +228,6 @@ iakerb_make_token(iakerb_ctx_id_t ctx,
krb5_data *realm,
krb5_data *cookie,
krb5_data *request,
int initialContextToken,
gss_buffer_t token)
{
krb5_error_code code;
Expand Down Expand Up @@ -269,11 +264,7 @@ iakerb_make_token(iakerb_ctx_id_t ctx,
memcpy(data->data + data->length, request->data, request->length);
data->length += request->length;

if (initialContextToken)
tokenSize = g_token_size(gss_mech_iakerb, data->length);
else
tokenSize = 2 + data->length;

tokenSize = g_token_size(gss_mech_iakerb, data->length);
token->value = gssalloc_malloc(tokenSize);
if (token->value == NULL) {
code = ENOMEM;
Expand All @@ -282,12 +273,7 @@ iakerb_make_token(iakerb_ctx_id_t ctx,
token->length = tokenSize;
k5_buf_init_fixed(&buf, token->value, token->length);

if (initialContextToken) {
g_make_token_header(&buf, gss_mech_iakerb, data->length,
IAKERB_TOK_PROXY);
} else {
k5_buf_add_uint16_be(&buf, IAKERB_TOK_PROXY);
}
g_make_token_header(&buf, gss_mech_iakerb, data->length, IAKERB_TOK_PROXY);
k5_buf_add_len(&buf, data->data, data->length);
assert(buf.len == token->length);

Expand All @@ -305,7 +291,6 @@ iakerb_make_token(iakerb_ctx_id_t ctx,
*/
static krb5_error_code
iakerb_acceptor_step(iakerb_ctx_id_t ctx,
int initialContextToken,
const gss_buffer_t input_token,
gss_buffer_t output_token)
{
Expand All @@ -324,8 +309,7 @@ iakerb_acceptor_step(iakerb_ctx_id_t ctx,
goto cleanup;
}

code = iakerb_parse_token(ctx, initialContextToken, input_token, &realm,
NULL, &request);
code = iakerb_parse_token(ctx, input_token, &realm, NULL, &request);
if (code != 0)
goto cleanup;

Expand Down Expand Up @@ -374,7 +358,7 @@ iakerb_acceptor_step(iakerb_ctx_id_t ctx,
} else if (code != 0)
goto cleanup;

code = iakerb_make_token(ctx, &realm, NULL, &reply, 0, output_token);
code = iakerb_make_token(ctx, &realm, NULL, &reply, output_token);
if (code != 0)
goto cleanup;

Expand Down Expand Up @@ -524,7 +508,7 @@ iakerb_initiator_step(iakerb_ctx_id_t ctx,
output_token->value = NULL;

if (input_token != GSS_C_NO_BUFFER) {
code = iakerb_parse_token(ctx, 0, input_token, NULL, &cookie, &in);
code = iakerb_parse_token(ctx, input_token, NULL, &cookie, &in);
if (code != 0)
goto cleanup;

Expand Down Expand Up @@ -593,9 +577,7 @@ iakerb_initiator_step(iakerb_ctx_id_t ctx,
if (out.length != 0) {
assert(ctx->state != IAKERB_AP_REQ);

code = iakerb_make_token(ctx, &realm, cookie, &out,
(input_token == GSS_C_NO_BUFFER),
output_token);
code = iakerb_make_token(ctx, &realm, cookie, &out, output_token);
if (code != 0)
goto cleanup;

Expand Down Expand Up @@ -788,8 +770,7 @@ iakerb_gss_accept_sec_context(OM_uint32 *minor_status,
major_status = GSS_S_DEFECTIVE_TOKEN;
goto cleanup;
}
code = iakerb_acceptor_step(ctx, initialContextToken,
input_token, output_token);
code = iakerb_acceptor_step(ctx, input_token, output_token);
if (code == (OM_uint32)KRB5_BAD_MSIZE)
major_status = GSS_S_DEFECTIVE_TOKEN;
if (code != 0)
Expand Down
2 changes: 1 addition & 1 deletion src/lib/gssapi/krb5/init_sec_context.c
Original file line number Diff line number Diff line change
Expand Up @@ -339,7 +339,7 @@ make_gss_checksum (krb5_context context, krb5_auth_context auth_context,
k5_buf_add_len(&buf, credmsg.data, credmsg.length);
}
if (data->exts->iakerb.conv != NULL) {
k5_buf_add_uint32_be(&buf, KRB5_GSS_EXTS_IAKERB_FINISHED);
k5_buf_add_uint32_be(&buf, GSS_EXTS_FINISHED);
k5_buf_add_uint32_be(&buf, finished->length);
k5_buf_add_len(&buf, finished->data, finished->length);
}
Expand Down
2 changes: 1 addition & 1 deletion src/lib/krb5/asn.1/asn1_k_encode.c
Original file line number Diff line number Diff line change
Expand Up @@ -1092,7 +1092,7 @@ DEFOPTIONALEMPTYTYPE(opt_ptr_seqof_princ_plus_realm,
ptr_seqof_princ_plus_realm);

/* First context tag is 1, not 0. */
DEFFIELD(iakerb_header_1, krb5_iakerb_header, target_realm, 1, ostring_data);
DEFFIELD(iakerb_header_1, krb5_iakerb_header, target_realm, 1, utf8_data);
DEFFIELD(iakerb_header_2, krb5_iakerb_header, cookie, 2, opt_ostring_data_ptr);
static const struct atype_info *iakerb_header_fields[] = {
&k5_atype_iakerb_header_1, &k5_atype_iakerb_header_2
Expand Down
2 changes: 1 addition & 1 deletion src/tests/asn.1/krb5_decode_test.c
Original file line number Diff line number Diff line change
Expand Up @@ -1001,7 +1001,7 @@ main(int argc, char **argv)
/* decode_iakerb_header */
{
setup(krb5_iakerb_header,ktest_make_sample_iakerb_header);
decode_run("iakerb_header","","30 18 A1 0A 04 08 6B 72 62 35 64 61 74 61 A2 0A 04 08 6B 72 62 35 64 61 74 61",decode_krb5_iakerb_header,ktest_equal_iakerb_header,krb5_free_iakerb_header);
decode_run("iakerb_header","","30 18 A1 0A 0C 08 6B 72 62 35 64 61 74 61 A2 0A 04 08 6B 72 62 35 64 61 74 61",decode_krb5_iakerb_header,ktest_equal_iakerb_header,krb5_free_iakerb_header);
ktest_empty_iakerb_header(&ref);
}

Expand Down
2 changes: 1 addition & 1 deletion src/tests/asn.1/reference_encode.out
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ encode_krb5_enc_sam_response_enc_2: 30 1F A0 03 02 01 58 A1 18 04 16 65 6E 63 5F
encode_krb5_pa_for_user: 30 4B A0 1A 30 18 A0 03 02 01 01 A1 11 30 0F 1B 06 68 66 74 73 61 69 1B 05 65 78 74 72 61 A1 10 1B 0E 41 54 48 45 4E 41 2E 4D 49 54 2E 45 44 55 A2 0F 30 0D A0 03 02 01 01 A1 06 04 04 31 32 33 34 A3 0A 1B 08 6B 72 62 35 64 61 74 61
encode_krb5_pa_s4u_x509_user: 30 68 A0 55 30 53 A0 06 02 04 00 CA 14 9A A1 1A 30 18 A0 03 02 01 01 A1 11 30 0F 1B 06 68 66 74 73 61 69 1B 05 65 78 74 72 61 A2 10 1B 0E 41 54 48 45 4E 41 2E 4D 49 54 2E 45 44 55 A3 12 04 10 70 61 5F 73 34 75 5F 78 35 30 39 5F 75 73 65 72 A4 07 03 05 00 80 00 00 00 A1 0F 30 0D A0 03 02 01 01 A1 06 04 04 31 32 33 34
encode_krb5_ad_kdcissued: 30 65 A0 0F 30 0D A0 03 02 01 01 A1 06 04 04 31 32 33 34 A1 10 1B 0E 41 54 48 45 4E 41 2E 4D 49 54 2E 45 44 55 A2 1A 30 18 A0 03 02 01 01 A1 11 30 0F 1B 06 68 66 74 73 61 69 1B 05 65 78 74 72 61 A3 24 30 22 30 0F A0 03 02 01 01 A1 08 04 06 66 6F 6F 62 61 72 30 0F A0 03 02 01 01 A1 08 04 06 66 6F 6F 62 61 72
encode_krb5_iakerb_header: 30 18 A1 0A 04 08 6B 72 62 35 64 61 74 61 A2 0A 04 08 6B 72 62 35 64 61 74 61
encode_krb5_iakerb_header: 30 18 A1 0A 0C 08 6B 72 62 35 64 61 74 61 A2 0A 04 08 6B 72 62 35 64 61 74 61
encode_krb5_iakerb_finished: 30 11 A1 0F 30 0D A0 03 02 01 01 A1 06 04 04 31 32 33 34
encode_krb5_fast_response: 30 81 9F A0 26 30 24 30 10 A1 03 02 01 0D A2 09 04 07 70 61 2D 64 61 74 61 30 10 A1 03 02 01 0D A2 09 04 07 70 61 2D 64 61 74 61 A1 13 30 11 A0 03 02 01 01 A1 0A 04 08 31 32 33 34 35 36 37 38 A2 5B 30 59 A0 11 18 0F 31 39 39 34 30 36 31 30 30 36 30 33 31 37 5A A1 05 02 03 01 E2 40 A2 10 1B 0E 41 54 48 45 4E 41 2E 4D 49 54 2E 45 44 55 A3 1A 30 18 A0 03 02 01 01 A1 11 30 0F 1B 06 68 66 74 73 61 69 1B 05 65 78 74 72 61 A4 0F 30 0D A0 03 02 01 01 A1 06 04 04 31 32 33 34 A3 03 02 01 2A
encode_krb5_pa_fx_fast_reply: A0 29 30 27 A0 25 30 23 A0 03 02 01 00 A1 03 02 01 05 A2 17 04 15 6B 72 62 41 53 4E 2E 31 20 74 65 73 74 20 6D 65 73 73 61 67 65
Expand Down
4 changes: 3 additions & 1 deletion src/tests/asn.1/trval.c
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@
#define PRIM_REAL 0x09 /* Real */
#define PRIM_ENUM 0x0a /* Enumerated type */
#define PRIM_ENCR 0x0b /* Encrypted */
#define PRIM_UTF8 0x0c /* UTF8String */
#define CONS_SEQ 0x10 /* SEQUENCE/SEQUENCE OF */
#define CONS_SET 0x11 /* SET/SET OF */
#define DEFN_NUMS 0x12 /* Numeric String */
Expand Down Expand Up @@ -321,7 +322,7 @@ do_prim_string(FILE *fp, int tag, unsigned char *enc, int len, int lev)
/*
* Only try this printing function with "reasonable" types
*/
if ((tag < DEFN_NUMS) && (tag != PRIM_OCTS))
if ((tag < DEFN_NUMS) && (tag != PRIM_OCTS) && (tag != PRIM_UTF8))
return 0;

for (i=0; i < len; i++)
Expand Down Expand Up @@ -433,6 +434,7 @@ struct typestring_table univ_types[] = {
{ PRIM_REAL, -1, "Real"},
{ PRIM_ENUM, -1, "Enumerated type"},
{ PRIM_ENCR, -1, "Encrypted"},
{ PRIM_UTF8, -1, "UTF8String"},
{ CONS_SEQ, -1, "Sequence/Sequence Of"},
{ CONS_SET, -1, "Set/Set Of"},
{ DEFN_NUMS, -1, "Numeric String"},
Expand Down
7 changes: 2 additions & 5 deletions src/tests/asn.1/trval_reference.out
Original file line number Diff line number Diff line change
Expand Up @@ -1254,7 +1254,7 @@ encode_krb5_ad_kdcissued:
encode_krb5_iakerb_header:

[Sequence/Sequence Of]
. [1] [Octet String] "krb5data"
. [1] [UTF8String] "krb5data"
. [2] [Octet String] "krb5data"

encode_krb5_iakerb_finished:
Expand Down Expand Up @@ -1417,10 +1417,7 @@ encode_krb5_pa_otp_req:
02 .
. [11] <9>
79 6f 75 72 74 6f 6b 65 6e yourtoken
. [12] <40>
75 72 6e 3a 69 65 74 66 3a 70 61 72 61 6d 73 3a urn:ietf:params:
78 6d 6c 3a 6e 73 3a 6b 65 79 70 72 6f 76 3a 70 xml:ns:keyprov:p
73 6b 63 3a 68 6f 74 70 skc:hotp
. [12] "urn:ietf:params:xml:ns:keyprov:pskc:hotp"
. [13] <11>
45 78 61 6d 70 6c 65 63 6f 72 70 Examplecorp

Expand Down

0 comments on commit de71318

Please sign in to comment.