comment out dumping code
[mech_eap.orig] / util_token.c
index e089690..a929198 100644 (file)
@@ -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,
  * 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);
 }
 
 /*
@@ -196,44 +344,50 @@ makeTokenHeader(
  * *body_size are left unmodified on error.
  */
 
-int
-verifyTokenHeader(gss_OID mech,
+OM_uint32
+verifyTokenHeader(OM_uint32 *minor,
+                  gss_OID mech,
                   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;
     ssize_t seqsize;
     gss_OID_desc toid;
     ssize_t toksize = (ssize_t)toksize_in;
 
-    if (toksize -= 1 < 0)
-        return ERANGE;
+    *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;
 
     if (*buf++ != 0x60)
-        return EINVAL;
+        return GSS_S_DEFECTIVE_TOKEN;
 
     seqsize = der_read_length(&buf, &toksize);
     if (seqsize < 0)
-        return ERANGE;
+        return GSS_S_DEFECTIVE_TOKEN;
 
     if (seqsize != toksize)
-        return ERANGE;
+        return GSS_S_DEFECTIVE_TOKEN;
 
-    if (toksize -= 1 < 0)
-        return ERANGE;
+    if ((toksize -= 1) < 0)
+        return GSS_S_DEFECTIVE_TOKEN;
 
     if (*buf++ != 0x06)
-        return EINVAL;
+        return GSS_S_DEFECTIVE_TOKEN;
 
-    if (toksize -= 1 < 0)
-        return ERANGE;
+    if ((toksize -= 1) < 0)
+        return GSS_S_DEFECTIVE_TOKEN;
 
     toid.length = *buf++;
 
-    if (toksize -= toid.length < 0)
-        return ERANGE;
+    if ((toksize -= toid.length) < 0)
+        return GSS_S_DEFECTIVE_TOKEN;
 
     toid.elements = buf;
     buf += toid.length;
@@ -241,21 +395,23 @@ verifyTokenHeader(gss_OID mech,
     if (mech->elements == NULL) {
         *mech = toid;
         if (toid.length == 0)
-            return EINVAL;
+            return GSS_S_BAD_MECH;
     } else if (!oidEqual(&toid, mech)) {
-        return EINVAL;
+        *minor = GSSEAP_WRONG_MECH;
+        return GSS_S_BAD_MECH;
     }
 
-    if (tok_type != TOK_TYPE_NONE) {
-        if (toksize -= 2 < 0)
-            return EINVAL;
+    if (ret_tok_type != NULL) {
+        if ((toksize -= 2) < 0)
+            return GSS_S_DEFECTIVE_TOKEN;
 
-        if ((*buf++ != ((tok_type >> 8) & 0xff)) ||
-            (*buf++ != (tok_type & 0xff)))
-            return EINVAL;
+        *ret_tok_type = load_uint16_be(buf);
+        buf += 2;
     }
+
     *buf_in = buf;
     *body_size = toksize;
 
-    return 0;
+    *minor = 0;
+    return GSS_S_COMPLETE;
 }