X-Git-Url: http://www.project-moonshot.org/gitweb/?a=blobdiff_plain;f=util_token.c;h=a929198ff3efff242fcfd97ccb5c8142b5d55aea;hb=refs%2Fheads%2Fjson-name;hp=7ddc5828e5d864333a54c5e85a2e6aa7cf49f7ca;hpb=40bf3d686a893e69a9c24dac8ead23d499a9fbd2;p=mech_eap.orig diff --git a/util_token.c b/util_token.c index 7ddc582..a929198 100644 --- a/util_token.c +++ b/util_token.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, JANET(UK) + * Copyright (c) 2011, JANET(UK) * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -30,7 +30,7 @@ * SUCH DAMAGE. */ /* - * Copyright 1993 by OpenVision Technologies, Inc. + * Portions Copyright 1993 by OpenVision Technologies, Inc. * * Permission to use, copy, modify, distribute, and sell this software * and its documentation for any purpose is hereby granted without fee, @@ -51,8 +51,155 @@ * PERFORMANCE OF THIS SOFTWARE. */ +/* + * Utility routines for GSS tokens. + */ + #include "gssapiP_eap.h" +OM_uint32 +gssEapEncodeInnerTokens(OM_uint32 *minor, + gss_buffer_set_t extensions, + OM_uint32 *types, + gss_buffer_t buffer) +{ + OM_uint32 major, tmpMinor; + size_t required = 0, i; + unsigned char *p; + + buffer->value = NULL; + buffer->length = 0; + + if (extensions != GSS_C_NO_BUFFER_SET) { + for (i = 0; i < extensions->count; i++) { + required += 8 + extensions->elements[i].length; + } + } + + /* + * We must always return a non-NULL token otherwise the calling state + * machine assumes we are finished. Hence care in case malloc(0) does + * return NULL. + */ + buffer->value = GSSEAP_MALLOC(required ? required : 1); + if (buffer->value == NULL) { + major = GSS_S_FAILURE; + *minor = ENOMEM; + goto cleanup; + } + + buffer->length = required; + p = (unsigned char *)buffer->value; + + if (extensions != GSS_C_NO_BUFFER_SET) { + for (i = 0; i < extensions->count; i++) { + gss_buffer_t extension = &extensions->elements[i]; + + assert((types[i] & ITOK_FLAG_VERIFIED) == 0); /* private flag */ + + /* + * Extensions are encoded as type-length-value, where the upper + * bit of the type indicates criticality. + */ + store_uint32_be(types[i], &p[0]); + store_uint32_be(extension->length, &p[4]); + memcpy(&p[8], extension->value, extension->length); + + p += 8 + extension->length; + } + } + + assert(p == (unsigned char *)buffer->value + required); + assert(buffer->value != NULL); + + major = GSS_S_COMPLETE; + *minor = 0; + +cleanup: + if (GSS_ERROR(major)) { + gss_release_buffer(&tmpMinor, buffer); + } + + return major; +} + +OM_uint32 +gssEapDecodeInnerTokens(OM_uint32 *minor, + const gss_buffer_t buffer, + gss_buffer_set_t *pExtensions, + OM_uint32 **pTypes) +{ + OM_uint32 major, tmpMinor; + gss_buffer_set_t extensions = GSS_C_NO_BUFFER_SET; + OM_uint32 *types = NULL; + unsigned char *p; + size_t remain; + + *pExtensions = GSS_C_NO_BUFFER_SET; + *pTypes = NULL; + + major = gss_create_empty_buffer_set(minor, &extensions); + if (GSS_ERROR(major)) + goto cleanup; + + if (buffer->length == 0) { + major = GSS_S_COMPLETE; + goto cleanup; + } + + p = (unsigned char *)buffer->value; + remain = buffer->length; + + do { + OM_uint32 *ntypes; + gss_buffer_desc extension; + + if (remain < 8) { + major = GSS_S_DEFECTIVE_TOKEN; + *minor = GSSEAP_TOK_TRUNC; + goto cleanup; + } + + ntypes = GSSEAP_REALLOC(types, + (extensions->count + 1) * sizeof(OM_uint32)); + if (ntypes == NULL) { + major = GSS_S_FAILURE; + *minor = ENOMEM; + goto cleanup; + } + types = ntypes; + + types[extensions->count] = load_uint32_be(&p[0]); + extension.length = load_uint32_be(&p[4]); + + if (remain < 8 + extension.length) { + major = GSS_S_DEFECTIVE_TOKEN; + *minor = GSSEAP_TOK_TRUNC; + goto cleanup; + } + extension.value = &p[8]; + + major = gss_add_buffer_set_member(minor, &extension, &extensions); + if (GSS_ERROR(major)) + goto cleanup; + + p += 8 + extension.length; + remain -= 8 + extension.length; + } while (remain != 0); + +cleanup: + if (GSS_ERROR(major)) { + gss_release_buffer_set(&tmpMinor, &extensions); + if (types != NULL) + GSSEAP_FREE(types); + } else { + *pExtensions = extensions; + *pTypes = types; + } + + return major; +} + /* * $Id: util_token.c 23457 2009-12-08 00:04:48Z tlyu $ */ @@ -160,6 +307,8 @@ der_read_length(unsigned char **buf, ssize_t *bufsize) size_t tokenSize(const gss_OID_desc *mech, size_t body_size) { + assert(mech != GSS_C_NO_OID); + /* set body_size to sequence contents size */ body_size += 4 + (size_t) mech->length; /* NEED overflow check */ return 1 + der_length_size(body_size) + body_size; @@ -181,10 +330,9 @@ makeTokenHeader( *(*buf)++ = (unsigned char)mech->length; memcpy(*buf, mech->elements, mech->length); *buf += mech->length; - if (tok_type != TOK_TYPE_NONE) { - *(*buf)++ = (unsigned char)((tok_type>>8) & 0xff); - *(*buf)++ = (unsigned char)(tok_type & 0xff); - } + assert(tok_type != TOK_TYPE_NONE); + *(*buf)++ = (unsigned char)((tok_type>>8) & 0xff); + *(*buf)++ = (unsigned char)(tok_type & 0xff); } /* @@ -202,7 +350,6 @@ verifyTokenHeader(OM_uint32 *minor, size_t *body_size, unsigned char **buf_in, size_t toksize_in, - enum gss_eap_token_type tok_type, enum gss_eap_token_type *ret_tok_type) { unsigned char *buf = *buf_in; @@ -210,7 +357,10 @@ verifyTokenHeader(OM_uint32 *minor, gss_OID_desc toid; ssize_t toksize = (ssize_t)toksize_in; - *minor = 0; + *minor = GSSEAP_BAD_TOK_HEADER; + + if (ret_tok_type != NULL) + *ret_tok_type = TOK_TYPE_NONE; if ((toksize -= 1) < 0) return GSS_S_DEFECTIVE_TOKEN; @@ -247,20 +397,21 @@ verifyTokenHeader(OM_uint32 *minor, if (toid.length == 0) return GSS_S_BAD_MECH; } else if (!oidEqual(&toid, mech)) { + *minor = GSSEAP_WRONG_MECH; return GSS_S_BAD_MECH; } - if (tok_type != TOK_TYPE_NONE) { + if (ret_tok_type != NULL) { if ((toksize -= 2) < 0) return GSS_S_DEFECTIVE_TOKEN; - *ret_tok_type = load_uint16_be(*buf); - if (tok_type != *ret_tok_type) - return GSS_S_DEFECTIVE_TOKEN; - *buf += 2; + *ret_tok_type = load_uint16_be(buf); + buf += 2; } + *buf_in = buf; *body_size = toksize; + *minor = 0; return GSS_S_COMPLETE; }