/*
* 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.
+ * valid, advance in past the tag and length, set *len_out to the decoded
+ * length, and return true. Otherwise return false. Only set an error on in
+ * if the next byte matches idbyte but the ensuing length is invalid.
*/
static inline bool
-k5_der_get_value(struct k5input *in, uint8_t idbyte,
- struct k5input *contents_out)
+k5_der_get_taglen(struct k5input *in, uint8_t idbyte, size_t *len_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)
}
}
+ if (in->status)
+ return false;
+
+ *len_out = len;
+ return true;
+}
+
+/*
+ * 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 byte 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)
+{
+ size_t len;
+ const void *bytes;
+
+ if (!k5_der_get_taglen(in, idbyte, &len))
+ return false;
bytes = k5_input_get_bytes(in, len);
if (bytes == NULL)
return false;
#include "k5-platform.h"
#include "k5-buf.h"
+#include "k5-input.h"
/** helper macros **/
#define g_make_string_buffer gssint_g_make_string_buffer
#define g_token_size gssint_g_token_size
#define g_make_token_header gssint_g_make_token_header
+#define g_get_token_header gssint_g_get_token_header
#define g_verify_token_header gssint_g_verify_token_header
#define g_display_major_status gssint_g_display_major_status
#define g_display_com_err_status gssint_g_display_com_err_status
void g_make_token_header (struct k5buf *buf, const gss_OID_desc *mech,
size_t body_size, int tok_type);
-/* flags for g_verify_token_header() */
-#define G_VFY_TOKEN_HDR_WRAPPER_REQUIRED 0x01
+int g_get_token_header (struct k5input *in, gss_OID oid_out,
+ size_t *token_len_out);
-gss_int32 g_verify_token_header (const gss_OID_desc * mech,
- unsigned int *body_size,
- unsigned char **buf, int tok_type,
- unsigned int toksize_in,
- int flags);
+int g_verify_token_header(struct k5input *in, gss_const_OID expected_mech);
OM_uint32 g_display_major_status (OM_uint32 *minor_status,
OM_uint32 status_value,
}
/*
- * Given a buffer containing a token, reads and verifies the token,
- * leaving buf advanced past the token header, and setting body_size
- * to the number of remaining bytes. Returns 0 on success,
- * G_BAD_TOK_HEADER for a variety of errors, and G_WRONG_MECH if the
- * mechanism in the token does not match the mech argument. buf and
- * *body_size are left unmodified on error.
+ * If a valid GSSAPI generic token header is present at the beginning of *in,
+ * advance past it, set *oid_out to the mechanism OID in the header, set
+ * *token_len_out to the total token length (including the header) as indicated
+ * by length of the outermost DER value, and return true. Otherwise return
+ * false, leaving *in unchanged if it did not begin with a 0x60 byte.
+ *
+ * Do not verify that the outermost length matches or fits within in->len, as
+ * we need to be able to handle a detached header for krb5 IOV unwrap. It is
+ * the caller's responsibility to validate *token_len_out if necessary.
*/
-
-gss_int32
-g_verify_token_header(
- const gss_OID_desc * mech,
- unsigned int *body_size,
- unsigned char **buf_in,
- int tok_type,
- unsigned int toksize_in,
- int flags)
+int
+g_get_token_header(struct k5input *in, gss_OID oid_out, size_t *token_len_out)
{
- struct k5input in, mech_der;
- gss_OID_desc toid;
+ size_t len, tlen;
+ const uint8_t *orig_ptr = in->ptr;
+ struct k5input oidbytes;
- k5_input_init(&in, *buf_in, toksize_in);
+ /* Read the outermost tag and length, and compute the full token length. */
+ if (!k5_der_get_taglen(in, 0x60, &len))
+ return 0;
+ tlen = len + (in->ptr - orig_ptr);
- if (k5_der_get_value(&in, 0x60, &in)) {
- if (in.ptr + in.len != *buf_in + toksize_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;
- } else if (flags & G_VFY_TOKEN_HDR_WRAPPER_REQUIRED) {
- return G_BAD_TOK_HEADER;
- }
+ /* Read the mechanism OID. */
+ if (!k5_der_get_value(in, 0x06, &oidbytes))
+ return 0;
+ oid_out->length = oidbytes.len;
+ oid_out->elements = (uint8_t *)oidbytes.ptr;
- if (tok_type != -1) {
- if (k5_input_get_uint16_be(&in) != tok_type)
- return in.status ? G_BAD_TOK_HEADER : G_WRONG_TOKID;
- }
+ *token_len_out = tlen;
+ return 1;
+}
- *buf_in = (uint8_t *)in.ptr;
- *body_size = in.len;
- return 0;
+/*
+ * If a token header for expected_mech is present in *in and the token length
+ * indicated by the header is equal to in->len, advance past the header and
+ * return true. Otherwise return false. Leave *in unmodified if no token
+ * header is present or it is for a different mechanism.
+ */
+int
+g_verify_token_header(struct k5input *in, gss_const_OID expected_mech)
+{
+ struct k5input orig = *in;
+ gss_OID_desc mech;
+ size_t tlen, orig_len = in->len;
+
+ if (!g_get_token_header(in, &mech, &tlen) || tlen != orig_len)
+ return 0;
+ if (!g_OID_equal(&mech, expected_mech)) {
+ *in = orig;
+ return 0;
+ }
+ return 1;
}
return status;
}
+/*
+ * Verify the ASN.1 framing and token type in an RFC 4121 initiator token. Set
+ * *mech_used_out to the mechanism in the framing, as a pointer to a global OID
+ * for one of the expected mechanisms. Set *ap_req_out to the portion of the
+ * token containing the AP-REQ encoding. Return G_BAD_TOK_HEADER if the
+ * framing is invalid. Return G_WRONG_TOKID if the token type is incorrect.
+ * Return G_WRONG_MECH if the mechanism OID in the framing is not one of the
+ * expected Kerberos mechanisms.
+ */
+static OM_uint32
+parse_init_token(gss_buffer_t input_token, gss_const_OID *mech_used_out,
+ krb5_data *ap_req_out)
+{
+ struct k5input in;
+ gss_OID_desc mech;
+ size_t tlen;
+
+ k5_input_init(&in, input_token->value, input_token->length);
+ if (!g_get_token_header(&in, &mech, &tlen) || tlen != input_token->length)
+ return G_BAD_TOK_HEADER;
+ if (k5_input_get_uint16_be(&in) != KG_TOK_CTX_AP_REQ)
+ return G_WRONG_TOKID;
+
+ if (g_OID_equal(&mech, gss_mech_krb5))
+ *mech_used_out = gss_mech_krb5;
+ else if (g_OID_equal(&mech, gss_mech_iakerb))
+ *mech_used_out = gss_mech_iakerb;
+ else if (g_OID_equal(&mech, gss_mech_krb5_wrong))
+ *mech_used_out = gss_mech_krb5_wrong;
+ else if (g_OID_equal(&mech, gss_mech_krb5_old))
+ *mech_used_out = gss_mech_krb5_old;
+ else
+ return G_WRONG_MECH;
+
+ *ap_req_out = make_data((uint8_t *)in.ptr, in.len);
+ return 0;
+}
+
static OM_uint32
kg_accept_krb5(OM_uint32 *minor_status, gss_ctx_id_t *context_handle,
gss_cred_id_t verifier_cred_handle, gss_buffer_t input_token,
krb5_gss_ctx_ext_t exts)
{
krb5_context context;
- unsigned char *ptr;
krb5_gss_cred_id_t cred = 0;
krb5_data ap_rep, ap_req;
krb5_error_code code;
goto fail;
}
- /* verify the token's integrity, and leave the token in ap_req.
- figure out which mech oid was used, and save it */
-
- ptr = (unsigned char *) input_token->value;
-
- if (!(code = g_verify_token_header(gss_mech_krb5,
- &(ap_req.length),
- &ptr, KG_TOK_CTX_AP_REQ,
- input_token->length, 1))) {
- mech_used = gss_mech_krb5;
- } else if ((code == G_WRONG_MECH)
- &&!(code = g_verify_token_header((gss_OID) gss_mech_iakerb,
- &(ap_req.length),
- &ptr, KG_TOK_CTX_AP_REQ,
- input_token->length, 1))) {
- mech_used = gss_mech_iakerb;
- } else if ((code == G_WRONG_MECH)
- &&!(code = g_verify_token_header((gss_OID) gss_mech_krb5_wrong,
- &(ap_req.length),
- &ptr, KG_TOK_CTX_AP_REQ,
- input_token->length, 1))) {
- mech_used = gss_mech_krb5_wrong;
- } else if ((code == G_WRONG_MECH) &&
- !(code = g_verify_token_header(gss_mech_krb5_old,
- &(ap_req.length),
- &ptr, KG_TOK_CTX_AP_REQ,
- input_token->length, 1))) {
- /*
- * Previous versions of this library used the old mech_id
- * and some broken behavior (wrong IV on checksum
- * encryption). We support the old mech_id for
- * compatibility, and use it to decide when to use the
- * old behavior.
- */
- mech_used = gss_mech_krb5_old;
- } else if (code == G_WRONG_TOKID) {
+ code = parse_init_token(input_token, &mech_used, &ap_req);
+ if (code == G_WRONG_TOKID) {
major_status = GSS_S_CONTINUE_NEEDED;
code = KRB5KRB_AP_ERR_MSG_TYPE;
mech_used = gss_mech_krb5;
goto fail;
} else if (code == G_BAD_TOK_HEADER) {
/* DCE style not encapsulated */
- ap_req.length = input_token->length;
+ ap_req = make_data(input_token->value, input_token->length);
mech_used = gss_mech_krb5;
no_encap = 1;
- } else {
+ } else if (code) {
major_status = GSS_S_DEFECTIVE_TOKEN;
goto fail;
}
- ap_req.data = (char *)ptr;
/* construct the sender_addr */
{
krb5_error_code code;
krb5_iakerb_header *iah = NULL;
- unsigned int bodysize;
- uint8_t *body;
+ const uint8_t *token_body;
krb5_data data;
struct k5input in, seq;
goto cleanup;
}
- body = token->value;
- code = g_verify_token_header(gss_mech_iakerb, &bodysize, &body,
- IAKERB_TOK_PROXY, token->length,
- G_VFY_TOKEN_HDR_WRAPPER_REQUIRED);
- if (code != 0)
+ k5_input_init(&in, token->value, token->length);
+ if (!g_verify_token_header(&in, gss_mech_iakerb) ||
+ k5_input_get_uint16_be(&in) != IAKERB_TOK_PROXY) {
+ code = G_BAD_TOK_HEADER;
goto cleanup;
+ }
/* Find the end of the DER sequence tag and decode it (with the tag) as the
- * IAKERB jeader. */
- k5_input_init(&in, body, bodysize);
+ * IAKERB header. */
+ token_body = in.ptr;
if (!k5_der_get_value(&in, 0x30, &seq)) {
code = ASN1_BAD_ID;
goto cleanup;
}
- data = make_data(body, seq.ptr + seq.len - body);
+ data = make_data((uint8_t *)token_body, seq.ptr + seq.len - token_body);
code = decode_krb5_iakerb_header(&data, &iah);
if (code != 0)
goto cleanup;
static krb5_boolean
iakerb_is_iakerb_token(const gss_buffer_t token)
{
- krb5_error_code code;
- unsigned int bodysize = token->length;
- unsigned char *ptr = token->value;
-
- code = g_verify_token_header(gss_mech_iakerb,
- &bodysize, &ptr,
- IAKERB_TOK_PROXY,
- token->length, 0);
+ struct k5input in;
- return (code == 0);
+ k5_input_init(&in, token->value, token->length);
+ return g_verify_token_header(&in, gss_mech_iakerb) &&
+ k5_input_get_uint16_be(&in) == IAKERB_TOK_PROXY;
}
static void
krb5_context context)
{
OM_uint32 major_status;
- unsigned char *ptr;
- krb5_data ap_rep;
+ struct k5input in;
+ uint16_t toktype;
+ krb5_data body;
krb5_ap_rep_enc_part *ap_rep_data;
krb5_timestamp now;
krb5_gss_ctx_id_rec *ctx;
goto fail;
}
- ptr = (unsigned char *) input_token->value;
-
if (ctx->gss_flags & GSS_C_DCE_STYLE) {
/* Raw AP-REP */
- ap_rep.length = input_token->length;
- } else if (g_verify_token_header(ctx->mech_used,
- &(ap_rep.length),
- &ptr, KG_TOK_CTX_AP_REP,
- input_token->length, 1)) {
- if (g_verify_token_header((gss_OID) ctx->mech_used,
- &(ap_rep.length),
- &ptr, KG_TOK_CTX_ERROR,
- input_token->length, 1) == 0) {
-
- /* Handle a KRB_ERROR message from the server */
-
- ap_rep.data = (char *)ptr;
- code = krb5_rd_error(context, &ap_rep, &krb_error);
+ body = make_data(input_token->value, input_token->length);
+ } else {
+ k5_input_init(&in, input_token->value, input_token->length);
+ if (!g_verify_token_header(&in, ctx->mech_used)) {
+ *minor_status = 0;
+ return(GSS_S_DEFECTIVE_TOKEN);
+ }
+ toktype = k5_input_get_uint16_be(&in);
+ body = make_data((uint8_t *)in.ptr, in.len);
+ if (toktype == KG_TOK_CTX_ERROR) {
+ code = krb5_rd_error(context, &body, &krb_error);
if (code)
goto fail;
if (krb_error->error)
code = 0;
krb5_free_error(context, krb_error);
goto fail;
- } else {
+ } else if (toktype != KG_TOK_CTX_AP_REP) {
*minor_status = 0;
return(GSS_S_DEFECTIVE_TOKEN);
}
}
- ap_rep.data = (char *)ptr;
/* decode the ap_rep */
- if ((code = krb5_rd_rep(context, ctx->auth_context, &ap_rep,
- &ap_rep_data))) {
+ code = krb5_rd_rep(context, ctx->auth_context, &body, &ap_rep_data);
+ if (code) {
/*
* XXX A hack for backwards compatibility.
* To be removed in 1999 -- proven
*/
krb5_auth_con_setuseruserkey(context, ctx->auth_context,
&ctx->subkey->keyblock);
- if ((krb5_rd_rep(context, ctx->auth_context, &ap_rep,
- &ap_rep_data)))
+ if (krb5_rd_rep(context, ctx->auth_context, &body, &ap_rep_data) != 0)
goto fail;
}
int *conf_state, gss_qop_t *qop_state, int toktype)
{
krb5_gss_ctx_id_rec *ctx;
- unsigned char *ptr;
- unsigned int bodysize;
- int err;
int toktype2;
- int vfyflags = 0;
OM_uint32 ret;
+ struct k5input in;
ctx = (krb5_gss_ctx_id_rec *) context_handle;
/* verify the header */
- ptr = (unsigned char *) input_token_buffer->value;
-
-
- err = g_verify_token_header(ctx->mech_used,
- &bodysize, &ptr, -1,
- input_token_buffer->length,
- vfyflags);
- if (err) {
- *minor_status = err;
- return GSS_S_DEFECTIVE_TOKEN;
- }
-
- if (bodysize < 2) {
- *minor_status = (OM_uint32)G_BAD_TOK_HEADER;
- return GSS_S_DEFECTIVE_TOKEN;
- }
-
- toktype2 = load_16_be(ptr);
-
- ptr += 2;
- bodysize -= 2;
+ k5_input_init(&in, input_token_buffer->value, input_token_buffer->length);
+ (void)g_verify_token_header(&in, ctx->mech_used);
+ toktype2 = k5_input_get_uint16_be(&in);
switch (toktype2) {
case KG2_TOK_MIC_MSG:
case KG2_TOK_WRAP_MSG:
case KG2_TOK_DEL_CTX:
ret = gss_krb5int_unseal_token_v3(&ctx->k5_context, minor_status, ctx,
- ptr, bodysize, message_buffer,
- conf_state, qop_state, toktype);
+ (uint8_t *)in.ptr, in.len,
+ message_buffer, conf_state,
+ qop_state, toktype);
break;
case KG_TOK_MIC_MSG:
case KG_TOK_WRAP_MSG:
case KG_TOK_DEL_CTX:
- ret = kg_unseal_v1(ctx->k5_context, minor_status, ctx, ptr, bodysize,
- message_buffer, conf_state, qop_state,
- toktype);
+ ret = kg_unseal_v1(ctx->k5_context, minor_status, ctx,
+ (uint8_t *)in.ptr, in.len, message_buffer,
+ conf_state, qop_state, toktype);
break;
default:
*minor_status = (OM_uint32)G_BAD_TOK_HEADER;
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
{
krb5_error_code code;
krb5_context context = ctx->k5_context;
- unsigned char *ptr;
+ struct k5input in;
+ gss_OID_desc mech;
+ size_t tlen, header_tlen;
gss_iov_buffer_t header;
gss_iov_buffer_t padding;
gss_iov_buffer_t trailer;
- size_t input_length, hlen;
int toktype2;
header = kg_locate_header_iov(iov, iov_count, toktype);
padding = kg_locate_iov(iov, iov_count, GSS_IOV_BUFFER_TYPE_PADDING);
trailer = kg_locate_iov(iov, iov_count, GSS_IOV_BUFFER_TYPE_TRAILER);
- ptr = (unsigned char *)header->buffer.value;
- input_length = header->buffer.length;
-
+ tlen = header->buffer.length;
if ((ctx->gss_flags & GSS_C_DCE_STYLE) == 0 &&
toktype == KG_TOK_WRAP_MSG) {
size_t data_length, assoc_data_length;
kg_iov_msglen(iov, iov_count, &data_length, &assoc_data_length);
- input_length += data_length - assoc_data_length;
+ tlen += data_length - assoc_data_length;
if (padding != NULL)
- input_length += padding->buffer.length;
+ tlen += padding->buffer.length;
if (trailer != NULL)
- input_length += trailer->buffer.length;
+ tlen += trailer->buffer.length;
}
- 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 (hlen < 2) {
- *minor_status = (OM_uint32)G_BAD_TOK_HEADER;
- return GSS_S_DEFECTIVE_TOKEN;
+ /* If there is a token header, advance past it and verify its mech and
+ * token length. */
+ k5_input_init(&in, header->buffer.value, header->buffer.length);
+ if (g_get_token_header(&in, &mech, &header_tlen)) {
+ if (!g_OID_equal(&mech, ctx->mech_used) || header_tlen != tlen) {
+ *minor_status = G_BAD_TOK_HEADER;
+ return GSS_S_DEFECTIVE_TOKEN;
+ }
}
-
- toktype2 = load_16_be(ptr);
-
- ptr += 2;
- hlen -= 2;
+ toktype2 = k5_input_get_uint16_be(&in);
switch (toktype2) {
case KG2_TOK_MIC_MSG:
case KG_TOK_WRAP_MSG:
case KG_TOK_DEL_CTX:
code = kg_unseal_v1_iov(context, minor_status, ctx, iov, iov_count,
- (size_t)(ptr - (unsigned char *)header->buffer.value),
+ (size_t)(in.ptr - (unsigned char *)header->buffer.value),
conf_state, qop_state, toktype);
break;
default:
int iov_count,
int toktype)
{
+ struct k5input in;
unsigned char *ptr;
unsigned int bodysize;
OM_uint32 code = 0, major_status = GSS_S_FAILURE;
ptr = (unsigned char *)stream->buffer.value;
- code = g_verify_token_header(ctx->mech_used,
- &bodysize, &ptr, -1,
- stream->buffer.length, 0);
- if (code != 0) {
- major_status = GSS_S_DEFECTIVE_TOKEN;
- goto cleanup;
- }
-
- if (bodysize < 2) {
+ k5_input_init(&in, stream->buffer.value, stream->buffer.length);
+ (void)g_verify_token_header(&in, ctx->mech_used);
+ toktype2 = k5_input_get_uint16_be(&in);
+ if (in.status) {
*minor_status = (OM_uint32)G_BAD_TOK_HEADER;
return GSS_S_DEFECTIVE_TOKEN;
}
- toktype2 = load_16_be(ptr);
-
- ptr += 2;
- bodysize -= 2;
+ ptr = (uint8_t *)in.ptr;
+ bodysize = in.len;
tiov = (gss_iov_buffer_desc *)calloc((size_t)iov_count + 2, sizeof(gss_iov_buffer_desc));
if (tiov == NULL) {
gss_const_OID token_oid,
gss_buffer_t output_token)
{
- OM_uint32 minor;
- unsigned int body_size = 0;
- unsigned char *buf_in;
+ struct k5input in;
if (input_token == GSS_C_NO_BUFFER || token_oid == GSS_C_NO_OID)
return GSS_S_CALL_INACCESSIBLE_READ;
if (output_token == GSS_C_NO_BUFFER)
return GSS_S_CALL_INACCESSIBLE_WRITE;
- buf_in = input_token->value;
-
- minor = g_verify_token_header(token_oid, &body_size, &buf_in,
- -1, input_token->length,
- G_VFY_TOKEN_HDR_WRAPPER_REQUIRED);
- if (minor != 0)
+ k5_input_init(&in, input_token->value, input_token->length);
+ if (!g_verify_token_header(&in, token_oid))
return GSS_S_DEFECTIVE_TOKEN;
- output_token->value = gssalloc_malloc(body_size);
+ output_token->value = gssalloc_malloc(in.len);
if (output_token->value == NULL)
return GSS_S_FAILURE;
- memcpy(output_token->value, buf_in, body_size);
- output_token->length = body_size;
+ memcpy(output_token->value, in.ptr, in.len);
+ output_token->length = in.len;
return GSS_S_COMPLETE;
}
* This file contains the support routines for the glue layer.
*/
-/* Retrieve the mechanism OID from an RFC 2743 InitialContextToken. Place
- * the result into *oid_out, aliasing memory from token. */
-OM_uint32 gssint_get_mech_type_oid(gss_OID oid_out, gss_buffer_t token)
-{
- struct k5input in;
-
- if (oid_out == NULL)
- return (GSS_S_CALL_INACCESSIBLE_WRITE);
- if (token == NULL || token->value == NULL)
- return (GSS_S_DEFECTIVE_TOKEN);
-
- k5_input_init(&in, token->value, token->length);
- if (!k5_der_get_value(&in, 0x60, &in))
- return (GSS_S_DEFECTIVE_TOKEN);
- if (!k5_der_get_value(&in, 0x06, &in))
- return (GSS_S_DEFECTIVE_TOKEN);
- oid_out->length = in.len;
- oid_out->elements = (uint8_t *)in.ptr;
- return (GSS_S_COMPLETE);
-}
-
/*
* The following mechanisms do not always identify themselves
* per the GSS-API specification, when interoperating with MS
OM_uint32
gssint_get_mech_type(gss_OID OID, gss_buffer_t token)
{
+ struct k5input in;
+ size_t tlen;
+
/* Check for interoperability exceptions */
if (token->length >= sizeof(NTLMSSP_SIGNATURE) &&
memcmp(token->value, NTLMSSP_SIGNATURE,
} else if (token->length == 0) {
*OID = gss_spnego_mechanism_oid_desc;
} else {
- return gssint_get_mech_type_oid(OID, token);
+ k5_input_init(&in, token->value, token->length);
+ return (g_get_token_header(&in, OID, &tlen) ? GSS_S_COMPLETE :
+ GSS_S_DEFECTIVE_TOKEN);
}
return (GSS_S_COMPLETE);
/* it to initialize the GSSAPI library */
int gssint_mechglue_initialize_library(void);
-OM_uint32 gssint_get_mech_type_oid(gss_OID OID, gss_buffer_t token);
-
/*
* This table is used to access mechanism-specific versions of the GSSAPI
* functions. It contains all of the functions defined in gssapi.h except for