File 0129-Fix-vulnerabilities-in-GSS-message-token-handling.patch of Package krb5.34946

From 55db6d6c6fc1d8ee135ce47be0ee8e4babf52339 Mon Sep 17 00:00:00 2001
From: Greg Hudson <ghudson@mit.edu>
Date: Mon, 5 May 2014 00:05:54 -0400
Subject: [PATCH 1/5] Add k5-input.h

Add a header containing a declaration for struct k5input and static
inline functions to use it.  A k5input structure can be used to safely
extract bytes and integers from a fixed-sized input buffer without
overrunning the buffer.  It supports deferred error checking (similar
to k5buf) by returning dummy values and storing a status value in the
input structure.

(cherry picked from commit 1263ed281d1f50b97399137b90344a75e991129c)
---
 src/include/k5-input.h | 143 +++++++++++++++++++++++++++++++++++++++++
 1 file changed, 143 insertions(+)
 create mode 100644 src/include/k5-input.h

diff --git a/src/include/k5-input.h b/src/include/k5-input.h
new file mode 100644
index 0000000000..d42ebce8f2
--- /dev/null
+++ b/src/include/k5-input.h
@@ -0,0 +1,143 @@
+/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+/* include/k5-input.h - k5input helper functions */
+/*
+ * Copyright (C) 2014 by the Massachusetts Institute of Technology.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in
+ *   the documentation and/or other materials provided with the
+ *   distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef K5_INPUT_H
+#define K5_INPUT_H
+
+#include "k5-int.h"
+
+/*
+ * The k5input module defines helpers for safely consuming a fixed-sized block
+ * of memory.  If an overrun or allocation failure occurs at any step,
+ * subsequent functions will return default values until the error is detected
+ * by looking at the status field.
+ */
+
+struct k5input {
+    const unsigned char *ptr;
+    size_t len;
+    krb5_error_code status;
+};
+
+static inline void
+k5_input_init(struct k5input *in, const void *ptr, size_t len)
+{
+    in->ptr = ptr;
+    in->len = len;
+    in->status = 0;
+}
+
+/* Only set the status value of in if it hasn't already been set, so status
+ * reflects the first thing to go wrong. */
+static inline void
+k5_input_set_status(struct k5input *in, krb5_error_code status)
+{
+    if (!in->status)
+        in->status = status;
+}
+
+static inline const unsigned char *
+k5_input_get_bytes(struct k5input *in, size_t len)
+{
+    if (in->len < len)
+        k5_input_set_status(in, EINVAL);
+    if (in->status)
+        return NULL;
+    in->len -= len;
+    in->ptr += len;
+    return in->ptr - len;
+}
+
+static inline unsigned char
+k5_input_get_byte(struct k5input *in)
+{
+    const unsigned char *ptr = k5_input_get_bytes(in, 1);
+    return (ptr == NULL) ? '\0' : *ptr;
+}
+
+static inline uint16_t
+k5_input_get_uint16_be(struct k5input *in)
+{
+    const unsigned char *ptr = k5_input_get_bytes(in, 2);
+    return (ptr == NULL) ? 0 : load_16_be(ptr);
+}
+
+static inline uint16_t
+k5_input_get_uint16_le(struct k5input *in)
+{
+    const unsigned char *ptr = k5_input_get_bytes(in, 2);
+    return (ptr == NULL) ? 0 : load_16_le(ptr);
+}
+
+static inline uint16_t
+k5_input_get_uint16_n(struct k5input *in)
+{
+    const unsigned char *ptr = k5_input_get_bytes(in, 2);
+    return (ptr == NULL) ? 0 : load_16_n(ptr);
+}
+
+static inline uint32_t
+k5_input_get_uint32_be(struct k5input *in)
+{
+    const unsigned char *ptr = k5_input_get_bytes(in, 4);
+    return (ptr == NULL) ? 0 : load_32_be(ptr);
+}
+
+static inline uint32_t
+k5_input_get_uint32_le(struct k5input *in)
+{
+    const unsigned char *ptr = k5_input_get_bytes(in, 4);
+    return (ptr == NULL) ? 0 : load_32_le(ptr);
+}
+
+static inline uint32_t
+k5_input_get_uint32_n(struct k5input *in)
+{
+    const unsigned char *ptr = k5_input_get_bytes(in, 4);
+    return (ptr == NULL) ? 0 : load_32_n(ptr);
+}
+
+static inline uint64_t
+k5_input_get_uint64_be(struct k5input *in)
+{
+    const unsigned char *ptr = k5_input_get_bytes(in, 8);
+    return (ptr == NULL) ? 0 : load_64_be(ptr);
+}
+
+static inline uint64_t
+k5_input_get_uint64_le(struct k5input *in)
+{
+    const unsigned char *ptr = k5_input_get_bytes(in, 8);
+    return (ptr == NULL) ? 0 : load_64_le(ptr);
+}
+
+#endif /* K5_BUF_H */
-- 
2.45.2


From d733ea4b387270a6e85744964fc4d972b32f1c1d Mon Sep 17 00:00:00 2001
From: Greg Hudson <ghudson@mit.edu>
Date: Tue, 7 Mar 2023 00:19:33 -0500
Subject: [PATCH 2/5] Add a simple DER support header

(cherry picked from commit 548da160b52b25a106e9f6077d6a42c2c049586c)
---
 src/include/k5-der.h | 149 +++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 149 insertions(+)
 create mode 100644 src/include/k5-der.h

diff --git a/src/include/k5-der.h b/src/include/k5-der.h
new file mode 100644
index 0000000000..b8371d9b4d
--- /dev/null
+++ b/src/include/k5-der.h
@@ -0,0 +1,149 @@
+/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+/* include/k5-der.h - Distinguished Encoding Rules (DER) declarations */
+/*
+ * Copyright (C) 2023 by the Massachusetts Institute of Technology.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in
+ *   the documentation and/or other materials provided with the
+ *   distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * Most ASN.1 encoding and decoding is done using the table-driven framework in
+ * libkrb5.  When that is not an option, these helpers can be used to encode
+ * and decode simple types.
+ */
+
+#ifndef K5_DER_H
+#define K5_DER_H
+
+#include <stdint.h>
+#include <stdbool.h>
+#include "k5-buf.h"
+#include "k5-input.h"
+
+/* Return the number of bytes needed to encode len as a DER encoding length. */
+static inline size_t
+k5_der_len_len(size_t len)
+{
+    size_t llen;
+
+    if (len < 128)
+        return 1;
+    llen = 1;
+    while (len > 0) {
+        len >>= 8;
+        llen++;
+    }
+    return llen;
+}
+
+/* Return the number of bytes needed to encode a DER value (with identifier
+ * byte and length) for a given contents length. */
+static inline size_t
+k5_der_value_len(size_t contents_len)
+{
+    return 1 + k5_der_len_len(contents_len) + contents_len;
+}
+
+/* Add a DER identifier byte (composed by the caller, including the ASN.1
+ * class, tag, and constructed bit) and length. */
+static inline void
+k5_der_add_taglen(struct k5buf *buf, uint8_t idbyte, size_t len)
+{
+    uint8_t *p;
+    size_t llen = k5_der_len_len(len);
+
+    p = k5_buf_get_space(buf, 1 + llen);
+    if (p == NULL)
+        return;
+    *p++ = idbyte;
+    if (len < 128) {
+        *p = len;
+    } else {
+        *p = 0x80 | (llen - 1);
+        /* Encode the length bytes backwards so the most significant byte is
+         * first. */
+        p += llen;
+        while (len > 0) {
+            *--p = len & 0xFF;
+            len >>= 8;
+        }
+    }
+}
+
+/* Add a DER value (identifier byte, length, and contents). */
+static inline void
+k5_der_add_value(struct k5buf *buf, uint8_t idbyte, const void *contents,
+                 size_t len)
+{
+    k5_der_add_taglen(buf, idbyte, len);
+    k5_buf_add_len(buf, contents, len);
+}
+
+/*
+ * If the next byte in in matches idbyte and the subsequent DER length is
+ * valid, advance in past the value, set *contents_out to the value contents,
+ * and return true.  Otherwise return false.  Only set an error on in if the
+ * next bytes matches idbyte but the ensuing length is invalid.  contents_out
+ * may be aliased to in; it will only be written to on successful decoding of a
+ * value.
+ */
+static inline bool
+k5_der_get_value(struct k5input *in, uint8_t idbyte,
+                 struct k5input *contents_out)
+{
+    uint8_t lenbyte, i;
+    size_t len;
+    const void *bytes;
+
+    /* Do nothing if in is empty or the next byte doesn't match idbyte. */
+    if (in->status || in->len == 0 || *in->ptr != idbyte)
+        return false;
+
+    /* Advance past the identifier byte and decode the length. */
+    (void)k5_input_get_byte(in);
+    lenbyte = k5_input_get_byte(in);
+    if (lenbyte < 128) {
+        len = lenbyte;
+    } else {
+        len = 0;
+        for (i = 0; i < (lenbyte & 0x7F); i++) {
+            if (len > (SIZE_MAX >> 8)) {
+                k5_input_set_status(in, EOVERFLOW);
+                return false;
+            }
+            len = (len << 8) | k5_input_get_byte(in);
+        }
+    }
+
+    bytes = k5_input_get_bytes(in, len);
+    if (bytes == NULL)
+        return false;
+    k5_input_init(contents_out, bytes, len);
+    return true;
+}
+
+#endif /* K5_DER_H */
-- 
2.45.2


From 6c3322b313f887730b5871109d1b867fe34deb40 Mon Sep 17 00:00:00 2001
From: Greg Hudson <ghudson@mit.edu>
Date: Sun, 4 May 2014 15:43:35 -0400
Subject: [PATCH 3/5] Add k5_buf_get_space

Add a new k5_buf method to make room in the buffer for the caller to
fill in.

(cherry picked from commit ccd989bdc2656b153bc226462e0c13800810ae04)
---
 src/include/k5-buf.h                          |  4 ++++
 src/util/support/k5buf.c                      | 10 ++++++++++
 src/util/support/libkrb5support-fixed.exports |  1 +
 3 files changed, 15 insertions(+)

diff --git a/src/include/k5-buf.h b/src/include/k5-buf.h
index c5576a3e32..da10fd9f4d 100644
--- a/src/include/k5-buf.h
+++ b/src/include/k5-buf.h
@@ -91,6 +91,10 @@ void k5_buf_add_fmt(struct k5buf *buf, const char *fmt, ...)
 #endif
     ;
 
+/* Extend the length of buf by len and return a pointer to the reserved space,
+ * to be filled in by the caller.  Return NULL on error. */
+void *k5_buf_get_space(struct k5buf *buf, size_t len);
+
 /* Truncate BUF.  LEN must be between 0 and the existing buffer
  * length, or an assertion failure will result. */
 void k5_buf_truncate(struct k5buf *buf, size_t len);
diff --git a/src/util/support/k5buf.c b/src/util/support/k5buf.c
index 778e68b39b..c3c81b0b2c 100644
--- a/src/util/support/k5buf.c
+++ b/src/util/support/k5buf.c
@@ -191,6 +191,16 @@ k5_buf_add_fmt(struct k5buf *buf, const char *fmt, ...)
     free(tmp);
 }
 
+void *
+k5_buf_get_space(struct k5buf *buf, size_t len)
+{
+    if (!ensure_space(buf, len))
+        return NULL;
+    buf->len += len;
+    buf->data[buf->len] = '\0';
+    return &buf->data[buf->len - len];
+}
+
 void
 k5_buf_truncate(struct k5buf *buf, size_t len)
 {
diff --git a/src/util/support/libkrb5support-fixed.exports b/src/util/support/libkrb5support-fixed.exports
index 2f38242d91..f5fbe9e0cb 100644
--- a/src/util/support/libkrb5support-fixed.exports
+++ b/src/util/support/libkrb5support-fixed.exports
@@ -6,6 +6,7 @@ k5_buf_init_dynamic
 k5_buf_add
 k5_buf_add_len
 k5_buf_add_fmt
+k5_buf_get_space
 k5_buf_truncate
 k5_buf_data
 k5_buf_len
-- 
2.45.2


From e152c50288378ac80f0180e3a6ca9c1521ff7b53 Mon Sep 17 00:00:00 2001
From: Greg Hudson <ghudson@mit.edu>
Date: Sat, 11 Nov 2017 13:42:28 -0500
Subject: [PATCH 4/5] Length check when parsing GSS token encapsulation

gssint_get_mech_type_oid() is used by gss_accept_sec_context() to
determine the mechanism of the token.  Without length checking, it
might read a few bytes past the end of the input token buffer.  Add
length checking as well as test cases for truncated encapsulations.
Reported by Bar Katz.

ticket: 8620 (new)
target_version: 1.16
target_version: 1.15-next
target_version: 1.14-next
tags: pullup

(cherry picked from commit f949e990f930f48df1f108fe311c58ae3da18b24)
---
 src/lib/gssapi/mechglue/g_glue.c | 20 ++++++++++++++------
 1 file changed, 14 insertions(+), 6 deletions(-)

diff --git a/src/lib/gssapi/mechglue/g_glue.c b/src/lib/gssapi/mechglue/g_glue.c
index e438a032ca..bfddf64ba7 100644
--- a/src/lib/gssapi/mechglue/g_glue.c
+++ b/src/lib/gssapi/mechglue/g_glue.c
@@ -189,7 +189,7 @@ OM_uint32 gssint_get_mech_type_oid(OID, token)
     gss_buffer_t	token;
 {
     unsigned char * buffer_ptr;
-    int length;
+    size_t buflen, lenbytes, length, oidlen;
 
     /*
      * This routine reads the prefix of "token" in order to determine
@@ -223,25 +223,33 @@ OM_uint32 gssint_get_mech_type_oid(OID, token)
     /* Skip past the APP/Sequnce byte and the token length */
 
     buffer_ptr = (unsigned char *) token->value;
+    buflen = token->length;
 
-    if (*(buffer_ptr++) != 0x60)
+    if (buflen < 2 || *buffer_ptr++ != 0x60)
 	return (GSS_S_DEFECTIVE_TOKEN);
     length = *buffer_ptr++;
+    buflen -= 2;
 
 	/* check if token length is null */
 	if (length == 0)
 	    return (GSS_S_DEFECTIVE_TOKEN);
 
     if (length & 0x80) {
-	if ((length & 0x7f) > 4)
+	lenbytes = length & 0x7f;
+	if (lenbytes > 4 || lenbytes > buflen)
 	    return (GSS_S_DEFECTIVE_TOKEN);
-	buffer_ptr += length & 0x7f;
+	buffer_ptr += lenbytes;
+	buflen -= lenbytes;
     }
 
-    if (*(buffer_ptr++) != 0x06)
+    if (buflen < 2 || *buffer_ptr++ != 0x06)
+	return (GSS_S_DEFECTIVE_TOKEN);
+    oidlen = *buffer_ptr++;
+    buflen -= 2;
+    if (oidlen > 0x7f || oidlen > buflen)
 	return (GSS_S_DEFECTIVE_TOKEN);
 
-    OID->length = (OM_uint32) *(buffer_ptr++);
+    OID->length = oidlen;
     OID->elements = (void *) buffer_ptr;
     return (GSS_S_COMPLETE);
 }
-- 
2.45.2


From b22c0093eab772e92a1df4e0c0fecdb2cdea594f Mon Sep 17 00:00:00 2001
From: Greg Hudson <ghudson@mit.edu>
Date: Fri, 14 Jun 2024 10:56:12 -0400
Subject: [PATCH 5/5] Fix vulnerabilities in GSS message token handling

In gss_krb5int_unseal_token_v3() and gss_krb5int_unseal_v3_iov(),
verify the Extra Count field of CFX wrap tokens against the encrypted
header.  Reported by Jacob Champion.

In gss_krb5int_unseal_token_v3(), check for a decrypted plaintext
length too short to contain the encrypted header and extra count
bytes.  Reported by Jacob Champion.

In kg_unseal_iov_token(), separately track the header IOV length and
complete token length when parsing the token's ASN.1 wrapper.  This
fix contains modified versions of functions from k5-der.h and
util_token.c; this duplication will be cleaned up in a future commit.

CVE-2024-37370:

In MIT krb5 release 1.3 and later, an attacker can modify the
plaintext Extra Count field of a confidential GSS krb5 wrap token,
causing the unwrapped token to appear truncated to the application.

CVE-2024-37371:

In MIT krb5 release 1.3 and later, an attacker can cause invalid
memory reads by sending message tokens with invalid length fields.

(cherry picked from commit b0a2f8a5365f2eec3e27d78907de9f9d2c80505a)

ticket: 9128
version_fixed: 1.21.3

(cherry picked from commit 55fbf435edbe2e92dd8101669b1ce7144bc96fef)
---
 src/lib/gssapi/krb5/k5sealv3.c    |  5 ++
 src/lib/gssapi/krb5/k5sealv3iov.c |  3 +-
 src/lib/gssapi/krb5/k5unsealiov.c | 80 ++++++++++++++++++++++++++++---
 3 files changed, 80 insertions(+), 8 deletions(-)

diff --git a/src/lib/gssapi/krb5/k5sealv3.c b/src/lib/gssapi/krb5/k5sealv3.c
index 7e4de86c8c..57c0476e22 100644
--- a/src/lib/gssapi/krb5/k5sealv3.c
+++ b/src/lib/gssapi/krb5/k5sealv3.c
@@ -409,10 +409,15 @@ gss_krb5int_unseal_token_v3(krb5_context *contextptr,
             /* Don't use bodysize here!  Use the fact that
                cipher.ciphertext.length has been adjusted to the
                correct length.  */
+            if (plain.length < 16 + ec) {
+                free(plain.data);
+                goto defective;
+            }
             althdr = (unsigned char *)plain.data + plain.length - 16;
             if (load_16_be(althdr) != KG2_TOK_WRAP_MSG
                 || althdr[2] != ptr[2]
                 || althdr[3] != ptr[3]
+                || load_16_be(althdr+4) != ec
                 || memcmp(althdr+8, ptr+8, 8)) {
                 free(plain.data);
                 goto defective;
diff --git a/src/lib/gssapi/krb5/k5sealv3iov.c b/src/lib/gssapi/krb5/k5sealv3iov.c
index 8f6c4d4413..8a3d140b3e 100644
--- a/src/lib/gssapi/krb5/k5sealv3iov.c
+++ b/src/lib/gssapi/krb5/k5sealv3iov.c
@@ -406,9 +406,10 @@ gss_krb5int_unseal_v3_iov(krb5_context context,
             if (load_16_be(althdr) != KG2_TOK_WRAP_MSG
                 || althdr[2] != ptr[2]
                 || althdr[3] != ptr[3]
+                || load_16_be(althdr + 4) != ec
                 || memcmp(althdr + 8, ptr + 8, 8) != 0) {
                 *minor_status = 0;
-                return GSS_S_BAD_SIG;
+                return GSS_S_DEFECTIVE_TOKEN;
             }
         } else {
             /* Verify checksum: note EC is checksum size here, not padding */
diff --git a/src/lib/gssapi/krb5/k5unsealiov.c b/src/lib/gssapi/krb5/k5unsealiov.c
index 191de2cff1..35e571b637 100644
--- a/src/lib/gssapi/krb5/k5unsealiov.c
+++ b/src/lib/gssapi/krb5/k5unsealiov.c
@@ -27,6 +27,7 @@
 #include <assert.h>
 #include "k5-platform.h"        /* for 64-bit support */
 #include "k5-int.h"          /* for zap() */
+#include "k5-der.h"
 #include "gssapiP_krb5.h"
 #include <stdarg.h>
 
@@ -297,6 +298,73 @@ cleanup:
     return retval;
 }
 
+/* Similar to k5_der_get_value(), but output an unchecked content length
+ * instead of a k5input containing the contents. */
+static inline bool
+get_der_tag(struct k5input *in, uint8_t idbyte, size_t *len_out)
+{
+    uint8_t lenbyte, i;
+    size_t len;
+
+    /* Do nothing if in is empty or the next byte doesn't match idbyte. */
+    if (in->status || in->len == 0 || *in->ptr != idbyte)
+        return false;
+
+    /* Advance past the identifier byte and decode the length. */
+    (void)k5_input_get_byte(in);
+    lenbyte = k5_input_get_byte(in);
+    if (lenbyte < 128) {
+        len = lenbyte;
+    } else {
+        len = 0;
+        for (i = 0; i < (lenbyte & 0x7F); i++) {
+            if (len > (SIZE_MAX >> 8)) {
+                k5_input_set_status(in, EOVERFLOW);
+                return false;
+            }
+            len = (len << 8) | k5_input_get_byte(in);
+        }
+    }
+
+    if (in->status)
+        return false;
+
+    *len_out = len;
+    return true;
+}
+
+/*
+ * Similar to g_verify_token_header() without toktype or flags, but do not read
+ * more than *header_len bytes of ASN.1 wrapper, and on output set *header_len
+ * to the remaining number of header bytes.  Verify the outer DER tag's length
+ * against token_len, which may be larger (but not smaller) than *header_len.
+ */
+static gss_int32
+verify_detached_wrapper(const gss_OID_desc *mech, size_t *header_len,
+                        uint8_t **header_in, size_t token_len)
+{
+    struct k5input in, mech_der;
+    gss_OID_desc toid;
+    size_t len;
+
+    k5_input_init(&in, *header_in, *header_len);
+
+    if (get_der_tag(&in, 0x60, &len)) {
+        if (len != token_len - (in.ptr - *header_in))
+            return G_BAD_TOK_HEADER;
+        if (!k5_der_get_value(&in, 0x06, &mech_der))
+            return G_BAD_TOK_HEADER;
+        toid.elements = (uint8_t *)mech_der.ptr;
+        toid.length = mech_der.len;
+        if (!g_OID_equal(&toid, mech))
+            return G_WRONG_MECH;
+    }
+
+    *header_in = (uint8_t *)in.ptr;
+    *header_len = in.len;
+    return 0;
+}
+
 /*
  * Caller must provide TOKEN | DATA | PADDING | TRAILER, except
  * for DCE in which case it can just provide TOKEN | DATA (must
@@ -317,8 +385,7 @@ kg_unseal_iov_token(OM_uint32 *minor_status,
     gss_iov_buffer_t header;
     gss_iov_buffer_t padding;
     gss_iov_buffer_t trailer;
-    size_t input_length;
-    unsigned int bodysize;
+    size_t input_length, hlen;
     int toktype2;
 
     header = kg_locate_header_iov(iov, iov_count, toktype);
@@ -348,15 +415,14 @@ kg_unseal_iov_token(OM_uint32 *minor_status,
             input_length += trailer->buffer.length;
     }
 
-    code = g_verify_token_header(ctx->mech_used,
-                                 &bodysize, &ptr, -1,
-                                 input_length, 0);
+    hlen = header->buffer.length;
+    code = verify_detached_wrapper(ctx->mech_used, &hlen, &ptr, input_length);
     if (code != 0) {
         *minor_status = code;
         return GSS_S_DEFECTIVE_TOKEN;
     }
 
-    if (bodysize < 2) {
+    if (hlen < 2) {
         *minor_status = (OM_uint32)G_BAD_TOK_HEADER;
         return GSS_S_DEFECTIVE_TOKEN;
     }
@@ -364,7 +430,7 @@ kg_unseal_iov_token(OM_uint32 *minor_status,
     toktype2 = load_16_be(ptr);
 
     ptr += 2;
-    bodysize -= 2;
+    hlen -= 2;
 
     switch (toktype2) {
     case KG2_TOK_MIC_MSG:
-- 
2.45.2

openSUSE Build Service is sponsored by