krb5 commit: Correct IAKERB protocol implementation

ghudson at mit.edu ghudson at mit.edu
Thu Jun 20 17:15:53 EDT 2024


https://github.com/krb5/krb5/commit/04f9c19c98aed91d96afa377557da86e04db6b44
commit 04f9c19c98aed91d96afa377557da86e04db6b44
Author: Greg Hudson <ghudson at mit.edu>
Date:   Tue Apr 16 13:32:04 2013 -0400

    Correct IAKERB protocol implementation
    
    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)

 doc/appdev/refs/macros/index.rst         |  1 +
 src/include/krb5/krb5.hin                |  1 +
 src/lib/gssapi/krb5/accept_sec_context.c |  2 +-
 src/lib/gssapi/krb5/gssapiP_krb5.h       |  2 +-
 src/lib/gssapi/krb5/iakerb.c             | 45 +++++++++-----------------------
 src/lib/gssapi/krb5/init_sec_context.c   |  2 +-
 src/lib/krb5/asn.1/asn1_k_encode.c       |  2 +-
 src/tests/asn.1/krb5_decode_test.c       |  2 +-
 src/tests/asn.1/reference_encode.out     |  2 +-
 src/tests/asn.1/trval.c                  |  4 ++-
 src/tests/asn.1/trval_reference.out      |  7 ++---
 11 files changed, 26 insertions(+), 44 deletions(-)

diff --git a/doc/appdev/refs/macros/index.rst b/doc/appdev/refs/macros/index.rst
index ee9fe2c61..645b59f02 100644
--- a/doc/appdev/refs/macros/index.rst
+++ b/doc/appdev/refs/macros/index.rst
@@ -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
diff --git a/src/include/krb5/krb5.hin b/src/include/krb5/krb5.hin
index 74963832d..7c4fc10dd 100644
--- a/src/include/krb5/krb5.hin
+++ b/src/include/krb5/krb5.hin
@@ -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 */
diff --git a/src/lib/gssapi/krb5/accept_sec_context.c b/src/lib/gssapi/krb5/accept_sec_context.c
index 227aa5448..c224ee9ac 100644
--- a/src/lib/gssapi/krb5/accept_sec_context.c
+++ b/src/lib/gssapi/krb5/accept_sec_context.c
@@ -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 {
diff --git a/src/lib/gssapi/krb5/gssapiP_krb5.h b/src/lib/gssapi/krb5/gssapiP_krb5.h
index 736460719..0ebe3a63c 100644
--- a/src/lib/gssapi/krb5/gssapiP_krb5.h
+++ b/src/lib/gssapi/krb5/gssapiP_krb5.h
@@ -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 */
diff --git a/src/lib/gssapi/krb5/iakerb.c b/src/lib/gssapi/krb5/iakerb.c
index 3ee926e69..9e8bc05da 100644
--- a/src/lib/gssapi/krb5/iakerb.c
+++ b/src/lib/gssapi/krb5/iakerb.c
@@ -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;
 
@@ -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;
 
@@ -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,
@@ -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;
 
@@ -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;
 
@@ -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;
@@ -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;
@@ -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);
 
@@ -305,7 +291,6 @@ cleanup:
  */
 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)
 {
@@ -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;
 
@@ -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;
 
@@ -524,7 +508,7 @@ iakerb_initiator_step(iakerb_ctx_id_t ctx,
     output_token->value = NULL;
 
     if (input_token != GSS_C_NO_BUFFER && input_token->length > 0) {
-        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;
 
@@ -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;
 
@@ -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)
diff --git a/src/lib/gssapi/krb5/init_sec_context.c b/src/lib/gssapi/krb5/init_sec_context.c
index 3cc9d4ceb..0a088c574 100644
--- a/src/lib/gssapi/krb5/init_sec_context.c
+++ b/src/lib/gssapi/krb5/init_sec_context.c
@@ -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);
     }
diff --git a/src/lib/krb5/asn.1/asn1_k_encode.c b/src/lib/krb5/asn.1/asn1_k_encode.c
index 5378b5c23..ad5a18a24 100644
--- a/src/lib/krb5/asn.1/asn1_k_encode.c
+++ b/src/lib/krb5/asn.1/asn1_k_encode.c
@@ -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
diff --git a/src/tests/asn.1/krb5_decode_test.c b/src/tests/asn.1/krb5_decode_test.c
index 2fa6dce8e..391bf0f20 100644
--- a/src/tests/asn.1/krb5_decode_test.c
+++ b/src/tests/asn.1/krb5_decode_test.c
@@ -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);
     }
 
diff --git a/src/tests/asn.1/reference_encode.out b/src/tests/asn.1/reference_encode.out
index faa3dbab7..20c6ce1f3 100644
--- a/src/tests/asn.1/reference_encode.out
+++ b/src/tests/asn.1/reference_encode.out
@@ -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
diff --git a/src/tests/asn.1/trval.c b/src/tests/asn.1/trval.c
index e0e58cc19..f84c515d5 100644
--- a/src/tests/asn.1/trval.c
+++ b/src/tests/asn.1/trval.c
@@ -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 */
@@ -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++)
@@ -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"},
diff --git a/src/tests/asn.1/trval_reference.out b/src/tests/asn.1/trval_reference.out
index 9bedad49c..29f88c5b6 100644
--- a/src/tests/asn.1/trval_reference.out
+++ b/src/tests/asn.1/trval_reference.out
@@ -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:
@@ -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
 


More information about the cvs-krb5 mailing list