Fixed up warnings and converted to Unix line endings
authorAlexandra Ellwood <lxs@mit.edu>
Mon, 10 Jul 2006 18:51:23 +0000 (18:51 +0000)
committerAlexandra Ellwood <lxs@mit.edu>
Mon, 10 Jul 2006 18:51:23 +0000 (18:51 +0000)
git-svn-id: svn://anonsvn.mit.edu/krb5/trunk@18325 dc483132-0cff-0310-8789-dd5450dbe970

src/lib/ccapi/common/marshall.c
src/lib/ccapi/common/msg.c

index 48abb3370268ea1dc0192188e6bb3a4bb17b1b6a..b2433cb1da5ab7a7cb7c79186c0a2d8a4e5ae00b 100644 (file)
-/* $Copyright:\r
- *\r
- * Copyright 2004-2006 by the Massachusetts Institute of Technology.\r
- * \r
- * All rights reserved.\r
- * \r
- * Export of this software from the United States of America may require a\r
- * specific license from the United States Government.  It is the\r
- * responsibility of any person or organization contemplating export to\r
- * obtain such a license before exporting.\r
- * \r
- * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and distribute\r
- * this software and its documentation for any purpose and without fee is\r
- * hereby granted, provided that the above copyright notice appear in all\r
- * copies and that both that copyright notice and this permission notice\r
- * appear in supporting documentation, and that the name of M.I.T. not be\r
- * used in advertising or publicity pertaining to distribution of the\r
- * software without specific, written prior permission.  Furthermore if you\r
- * modify this software you must label your software as modified software\r
- * and not distribute it in such a fashion that it might be confused with\r
- * the original MIT software. M.I.T. makes no representations about the\r
- * suitability of this software for any purpose.  It is provided "as is"\r
- * without express or implied warranty.\r
- * \r
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED\r
- * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF\r
- * MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.\r
- * \r
- * Individual source code files are copyright MIT, Cygnus Support,\r
- * OpenVision, Oracle, Sun Soft, FundsXpress, and others.\r
- * \r
- * Project Athena, Athena, Athena MUSE, Discuss, Hesiod, Kerberos, Moira,\r
- * and Zephyr are trademarks of the Massachusetts Institute of Technology\r
- * (MIT).  No commercial use of these trademarks may be made without prior\r
- * written permission of MIT.\r
- * \r
- * "Commercial use" means use of a name in a product or other for-profit\r
- * manner.  It does NOT prevent a commercial firm from referring to the MIT\r
- * trademarks in order to convey information (although in doing so,\r
- * recognition of their trademark status should be given).\r
- * $\r
- */\r
-\r
-/* marshall.c */\r
-\r
-#include <stdlib.h>\r
-#include <stdio.h>\r
-#include <string.h>\r
-#include <CredentialsCache.h>\r
-#include "msg.h"\r
-#include "msg_headers.h"\r
-#include "marshall.h"\r
-\r
-cc_int32\r
-cci_creds_v4_marshall( cc_credentials_v4_t * creds, \r
-                       char ** pflat, \r
-                       cc_uint32 * plen)\r
-{\r
-    cc_uint32 len;\r
-    char * flat;\r
-    cci_flat_creds_v4_t * header;\r
-    cc_time64 t64;\r
-\r
-    if ( creds == NULL || pflat == NULL || plen == NULL )\r
-        return ccErrBadParam;\r
-\r
-    len = sizeof(cci_flat_creds_v4_t);\r
-    flat = (char *)malloc(len);\r
-    if ( flat == NULL )\r
-        return ccErrNoMem;\r
-    memset(flat, 0, len);\r
-\r
-    header = (cci_flat_creds_v4_t *)flat;\r
-    header->version = htonl(creds->version);\r
-    memcpy(header->principal, creds->principal, cc_v4_name_size);\r
-    memcpy(header->principal_instance, creds->principal_instance, cc_v4_instance_size);\r
-    memcpy(header->service, creds->service, cc_v4_name_size);\r
-    memcpy(header->service_instance, creds->service_instance, cc_v4_instance_size);\r
-    memcpy(header->realm, creds->realm, cc_v4_realm_size);\r
-    memcpy(header->session_key, creds->session_key, cc_v4_key_size);\r
-    header->kvno = htonl(creds->kvno);\r
-    header->string_to_key_type = htonl(creds->string_to_key_type);\r
-    t64 = creds->issue_date;\r
-    header->issue_date = htonll(t64);\r
-    header->lifetime = htonl(creds->lifetime);\r
-    /* TODO: verify that address is stored in host order */\r
-    header->address = htonl(creds->address);\r
-    header->ticket_size = htonl(creds->ticket_size);\r
-    memcpy(header->ticket, creds->ticket, cc_v4_ticket_size);\r
-\r
-    *pflat = flat;\r
-    *plen = len;\r
-\r
-    return ccNoError;  \r
-}\r
-\r
-cc_int32\r
-cci_creds_v4_unmarshall( char * flat, \r
-                         cc_uint32 len,\r
-                         cc_credentials_union * creds_union)\r
-{\r
-    struct cci_flat_creds_v4 * header;\r
-    cc_credentials_v4_t * creds;\r
-    cc_time64 t64;\r
-\r
-    if ( flat == NULL || len == 0 || creds_union == NULL )\r
-        return ccErrBadParam;\r
-\r
-    creds_union->version = cc_credentials_v4;\r
-\r
-    header = (cci_flat_creds_v4_t *)flat;\r
-\r
-    creds = (cc_credentials_v4_t *)malloc(sizeof(cc_credentials_v4_t));\r
-    if ( creds == NULL )\r
-       return ccErrNoMem;\r
-\r
-    creds->version = ntohl(header->version);\r
-    memcpy(creds->principal, header->principal, cc_v4_name_size);\r
-    memcpy(creds->principal_instance, header->principal_instance, cc_v4_instance_size);\r
-    memcpy(creds->service, header->service, cc_v4_name_size);\r
-    memcpy(creds->service_instance, header->service_instance, cc_v4_instance_size);\r
-    memcpy(creds->realm, header->realm, cc_v4_realm_size);\r
-    memcpy(creds->session_key, header->session_key, cc_v4_key_size);\r
-    creds->kvno = htonl(header->kvno);\r
-    creds->string_to_key_type = htonl(header->string_to_key_type);\r
-    t64 = header->issue_date;\r
-    creds->issue_date = (cc_time64)ntohll(t64);\r
-    creds->lifetime = (cc_int32)ntohl(header->lifetime);\r
-    /* TODO: verify that address is stored in host order */\r
-    creds->address = ntohl(header->address);\r
-    creds->ticket_size = ntohl(header->ticket_size);\r
-    memcpy(creds->ticket, header->ticket, cc_v4_ticket_size);\r
-\r
-    creds_union->credentials.credentials_v4 = creds;\r
-\r
-    return ccNoError;\r
-}\r
-\r
-\r
-cc_int32\r
-cci_creds_cc_data_array_count_entries( cc_data ** array, cc_uint32 * pcount)\r
-{\r
-    cc_uint32 count;\r
-\r
-    if (array == NULL) {\r
-        *pcount = 0;\r
-        return ccNoError;\r
-    }\r
-\r
-    for ( count=0; array[count] != NULL ; count++) ;\r
-\r
-    *pcount = count;\r
-    return ccNoError;\r
-}\r
-\r
-cc_int32\r
-cci_creds_v5_compute_flat_size( cc_credentials_v5_t * creds, cc_uint32 * plen)\r
-{\r
-    cc_uint32 len;\r
-    cc_uint32 i, count;\r
-\r
-    len = sizeof(struct cci_flat_creds_v5);\r
-\r
-    if (creds->client)\r
-        len += strlen(creds->client) + 1;\r
-\r
-    if (creds->server)\r
-        len += strlen(creds->server) + 1;\r
-\r
-    len += creds->keyblock.length;\r
-\r
-    cci_creds_cc_data_array_count_entries( creds->addresses, &count );\r
-    len += count * sizeof(cc_flat_data);\r
-    for ( i=0; i<count; i++ ) {\r
-        len += creds->addresses[i]->length;\r
-    }\r
-\r
-    len += creds->ticket.length;\r
-    len += creds->second_ticket.length;\r
-\r
-    cci_creds_cc_data_array_count_entries( creds->authdata, &count );\r
-    len += count * sizeof(cc_flat_data);\r
-    for ( i=0; i<count; i++ ) {\r
-        len += creds->authdata[i]->length;\r
-    }\r
-\r
-    *plen = len;\r
-    return ccNoError;\r
-}\r
-\r
-cc_int32\r
-cci_creds_v5_marshall( cc_credentials_v5_t * creds, \r
-                       char ** pflat, \r
-                       cc_uint32 * plen)\r
-{\r
-    cc_uint32 len;\r
-    char * flat;\r
-    struct cci_flat_creds_v5 * header;\r
-    cc_uint32 length;\r
-    cc_uint32 offset;\r
-    cc_time64 t64;\r
-    cc_uint32 count;\r
-    cc_uint32 i;\r
-\r
-    if ( creds == NULL || pflat == NULL || plen == NULL )\r
-        return ccErrBadParam;\r
-\r
-    cci_creds_v5_compute_flat_size(creds, &len);\r
-\r
-    flat = (char *)malloc(len);\r
-    if ( flat == NULL )\r
-        return ccErrNoMem;\r
-    memset(flat, 0, len);\r
-\r
-    offset = sizeof(struct cci_flat_creds_v5);\r
-    header = (struct cci_flat_creds_v5 *)flat;\r
-    header->version = htonl(FLAT_CREDS_V5_VERSION);\r
-    if (creds->client) {\r
-       length = strlen(creds->client) + 1;\r
-        header->client.length = htonl(length);\r
-        header->client.data = htonl(offset);\r
-        memcpy(flat + offset, creds->client, length);\r
-        offset += length;\r
-    }\r
-\r
-    if (creds->server) {\r
-       length = strlen(creds->server) + 1;\r
-        header->server.length = htonl(length);\r
-        header->server.data = htonl(offset);\r
-        memcpy(flat + offset, creds->server, length);\r
-        offset += length;\r
-    }\r
-\r
-    header->keyblock.type = htonl(creds->keyblock.type);\r
-    if (creds->keyblock.length) {\r
-       length = creds->keyblock.length;\r
-        header->keyblock.length = htonl(length);\r
-        header->keyblock.data = htonl(offset);\r
-        memcpy(flat + offset, creds->keyblock.data, length);\r
-        offset += length;\r
-    }           \r
-\r
-    t64 = creds->authtime;\r
-    header->authtime = htonll(t64);\r
-    t64 = creds->starttime;\r
-    header->starttime = htonll(t64);\r
-    t64 = creds->endtime;\r
-    header->endtime = htonll(t64);\r
-    t64 = creds->renew_till;\r
-    header->renew_till = htonll(t64);\r
-\r
-    header->is_skey = htonl(creds->is_skey);\r
-    header->ticket_flags = htonl(creds->ticket_flags);\r
-\r
-    cci_creds_cc_data_array_count_entries( creds->addresses, &count );\r
-    if ( count ) {\r
-        cc_flat_data * addresses = (cc_flat_data *)flat + offset;\r
-       header->address_count = htonl(count);\r
-        header->addresses = htonl(offset);\r
-        offset += count * sizeof(cc_flat_data);\r
-\r
-        for ( i=0; i < count; i++ ) {\r
-            addresses[i].type = htonl(creds->addresses[i]->type);\r
-            if (creds->addresses[i]->length) {\r
-               length = creds->addresses[i]->length;\r
-                addresses[i].length = htonl(length);\r
-                addresses[i].data = htonl(offset);\r
-               /* TODO: verify that addresses are stored in network order */\r
-                memcpy(flat + offset, creds->addresses[i]->data, length);\r
-                offset += length;\r
-            }\r
-        }\r
-    }\r
-\r
-    header->ticket.type = htonl(creds->ticket.type);\r
-    if (creds->ticket.length) {\r
-       length = creds->ticket.length;\r
-        header->ticket.length = htonl(length);\r
-        header->ticket.data = htonl(offset);\r
-        memcpy(flat + offset, creds->ticket.data, length);\r
-        offset += length;\r
-    }           \r
-\r
-    header->second_ticket.type = htonl(creds->second_ticket.type);\r
-    if (creds->second_ticket.length) {\r
-       length = creds->second_ticket.length;\r
-        header->second_ticket.length = htonl(length);\r
-        header->second_ticket.data = htonl(offset);\r
-        memcpy(flat + offset, creds->second_ticket.data, length);\r
-        offset += length;\r
-    }           \r
-\r
-    cci_creds_cc_data_array_count_entries( creds->authdata, &count );\r
-    if ( count ) {\r
-        cc_flat_data * authdata = (cc_flat_data *)flat + offset;\r
-\r
-       header->authdata_count = htonl(count);\r
-        header->authdata = (offset);\r
-        offset += count * sizeof(cc_flat_data);\r
-\r
-        for ( i=0; i < count; i++ ) {\r
-            authdata[i].type = htonl(creds->authdata[i]->type);\r
-            if (creds->authdata[i]->length) {\r
-               length = creds->authdata[i]->length;\r
-                authdata[i].length = htonl(length);\r
-                authdata[i].data = htonl(offset);\r
-                memcpy(flat + offset, creds->authdata[i]->data, length);\r
-                offset += length;\r
-            }\r
-        }\r
-    }\r
-\r
-    *pflat = flat;\r
-    *plen = len;\r
-    return ccNoError;\r
-}\r
-\r
-\r
-// TODO: a much better job of checking for out of memory errors\r
-//       and validating that we do not read beyond the flat input\r
-//       data buffer\r
-\r
-cc_int32\r
-cci_creds_v5_unmarshall( char * flat, \r
-                         cc_uint32 len,\r
-                         cc_credentials_union * creds_union)\r
-{\r
-    struct cci_flat_creds_v5 * header;\r
-    cc_credentials_v5_t * creds;\r
-    cc_flat_data * flat_data;\r
-    cc_time64 t64;\r
-    cc_uint32  length;\r
-    cc_uint32  count;\r
-    cc_uint32  i;\r
-\r
-    if ( flat == NULL || len == 0 || creds_union == NULL )\r
-        return ccErrBadParam;\r
-\r
-    creds_union->version = cc_credentials_v5;\r
-\r
-    header = (struct cci_flat_creds_v5 *)flat;\r
-\r
-    if ( ntohl(header->version) != FLAT_CREDS_V5_VERSION )\r
-        return ccErrBadParam;\r
-\r
-    creds = (cc_credentials_v5_t *)malloc(sizeof(cc_credentials_v5_t));\r
-    if ( creds == NULL )\r
-        return ccErrNoMem;\r
-    memset(creds, 0, sizeof(cc_credentials_v5_t));\r
-\r
-    if ( header->client.length ) {\r
-       length = ntohl(header->client.length);\r
-        creds->client = (char *)malloc(length);\r
-        memcpy(creds->client, flat + header->client.data, length);\r
-    }\r
-\r
-    if ( header->server.length ) {\r
-       length = ntohl(header->server.length);\r
-        creds->server = (char *)malloc(length);\r
-        memcpy(creds->server, flat + header->server.data, length);\r
-    }\r
-\r
-    creds->keyblock.type = ntohl(header->keyblock.type);\r
-    if ( header->keyblock.length ) {\r
-       length = ntohl(header->keyblock.length);\r
-        creds->keyblock.length = length;\r
-        creds->keyblock.data = malloc(length);\r
-        memcpy(creds->keyblock.data, flat + header->keyblock.data, length);\r
-    }\r
-\r
-    /* TODO: need to perform overflow validation checks to ensure\r
-     * that we do not attempt to store too large a value into cc_time_t\r
-     * when it is a 32-bit field.\r
-     */\r
-    t64 = ntohll(header->authtime);\r
-    creds->authtime = (cc_time)t64;\r
-    t64 = ntohll(header->starttime);\r
-    creds->starttime = (cc_time)t64;\r
-    t64 = ntohll(header->endtime);\r
-    creds->endtime = (cc_time)t64;\r
-    t64 = ntohll(header->renew_till);\r
-    creds->renew_till = (cc_time)t64;\r
-\r
-    creds->is_skey = ntohl(header->is_skey);\r
-    creds->ticket_flags = ntohl(header->ticket_flags);\r
-\r
-    count = ntohl(header->address_count);\r
-    creds->addresses = (cc_data **) malloc((count + 1) * sizeof(cc_data *));\r
-    flat_data = (cc_flat_data *)flat + header->addresses;\r
-    for ( i=0 ; i < count ; i++ ) {\r
-        creds->addresses[i] = (cc_data *)malloc(sizeof(cc_data));\r
-        creds->addresses[i]->type = ntohl(flat_data[i].type);\r
-       length = ntohl(flat_data[i].length);\r
-        creds->addresses[i]->length = length;\r
-        if ( length ) {\r
-            creds->addresses[i]->data = malloc(length);\r
-           /* TODO: verify that addresses are stored in network order */\r
-            memcpy(creds->addresses[i]->data, flat + flat_data[i].data, length);\r
-        } else {\r
-            creds->addresses[i]->data = NULL;\r
-        }\r
-    }\r
-    creds->addresses[i] = NULL;\r
-\r
-    creds->ticket.type = ntohl(header->ticket.type);\r
-    length = ntohl(header->ticket.length);\r
-    if ( length ) {\r
-        creds->ticket.length = length;\r
-        creds->ticket.data = malloc(length);\r
-        memcpy(creds->ticket.data, flat + header->ticket.data, length);\r
-    }\r
-\r
-    creds->second_ticket.type = header->second_ticket.type;\r
-    if ( header->second_ticket.length ) {\r
-        creds->second_ticket.length = header->second_ticket.length;\r
-        creds->second_ticket.data = malloc(creds->second_ticket.length);\r
-        memcpy(creds->second_ticket.data, flat + header->second_ticket.data, creds->second_ticket.length);\r
-    }\r
-\r
-    count = ntohl(header->authdata_count);\r
-    creds->authdata = (cc_data **) malloc((count + 1) * sizeof(cc_data *));\r
-    flat_data = (cc_flat_data *)flat + header->authdata;\r
-    for ( i=0 ; i < count ; i++ ) {\r
-        creds->authdata[i] = (cc_data *)malloc(sizeof(cc_data));\r
-        creds->authdata[i]->type = ntohl(flat_data[i].type);\r
-       length = ntohl(flat_data[i].length);\r
-        creds->authdata[i]->length = length;\r
-        if ( length ) {\r
-            creds->authdata[i]->data = malloc(length);\r
-            memcpy(creds->authdata[i]->data, flat + flat_data[i].data, length);\r
-        } else {\r
-            creds->authdata[i]->data = NULL;\r
-        }\r
-    }\r
-    creds->authdata[i] = NULL;\r
-\r
-    creds_union->credentials.credentials_v5 = creds;\r
-\r
-    return ccNoError;\r
-}\r
-\r
+/* $Copyright:
+ *
+ * Copyright 2004-2006 by the Massachusetts Institute of Technology.
+ * 
+ * All rights reserved.
+ * 
+ * Export of this software from the United States of America may require a
+ * specific license from the United States Government.  It is the
+ * responsibility of any person or organization contemplating export to
+ * obtain such a license before exporting.
+ * 
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and distribute
+ * this software and its documentation for any purpose and without fee is
+ * hereby granted, provided that the above copyright notice appear in all
+ * copies and that both that copyright notice and this permission notice
+ * appear in supporting documentation, and that the name of M.I.T. not be
+ * used in advertising or publicity pertaining to distribution of the
+ * software without specific, written prior permission.  Furthermore if you
+ * modify this software you must label your software as modified software
+ * and not distribute it in such a fashion that it might be confused with
+ * the original MIT software. M.I.T. makes no representations about the
+ * suitability of this software for any purpose.  It is provided "as is"
+ * without express or implied warranty.
+ * 
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ * 
+ * Individual source code files are copyright MIT, Cygnus Support,
+ * OpenVision, Oracle, Sun Soft, FundsXpress, and others.
+ * 
+ * Project Athena, Athena, Athena MUSE, Discuss, Hesiod, Kerberos, Moira,
+ * and Zephyr are trademarks of the Massachusetts Institute of Technology
+ * (MIT).  No commercial use of these trademarks may be made without prior
+ * written permission of MIT.
+ * 
+ * "Commercial use" means use of a name in a product or other for-profit
+ * manner.  It does NOT prevent a commercial firm from referring to the MIT
+ * trademarks in order to convey information (although in doing so,
+ * recognition of their trademark status should be given).
+ * $
+ */
+
+/* marshall.c */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <CredentialsCache.h>
+#include "msg.h"
+#include "msg_headers.h"
+#include "marshall.h"
+
+cc_int32
+cci_creds_v4_marshall( cc_credentials_v4_t * creds, 
+                       char ** pflat, 
+                       cc_uint32 * plen)
+{
+    cc_uint32 len;
+    char * flat;
+    cci_flat_creds_v4_t * header;
+    cc_time64 t64;
+
+    if ( creds == NULL || pflat == NULL || plen == NULL )
+        return ccErrBadParam;
+
+    len = sizeof(cci_flat_creds_v4_t);
+    flat = (char *)malloc(len);
+    if ( flat == NULL )
+        return ccErrNoMem;
+    memset(flat, 0, len);
+
+    header = (cci_flat_creds_v4_t *)flat;
+    header->version = htonl(creds->version);
+    memcpy(header->principal, creds->principal, cc_v4_name_size);
+    memcpy(header->principal_instance, creds->principal_instance, cc_v4_instance_size);
+    memcpy(header->service, creds->service, cc_v4_name_size);
+    memcpy(header->service_instance, creds->service_instance, cc_v4_instance_size);
+    memcpy(header->realm, creds->realm, cc_v4_realm_size);
+    memcpy(header->session_key, creds->session_key, cc_v4_key_size);
+    header->kvno = htonl(creds->kvno);
+    header->string_to_key_type = htonl(creds->string_to_key_type);
+    t64 = creds->issue_date;
+    header->issue_date = htonll(t64);
+    header->lifetime = htonl(creds->lifetime);
+    /* TODO: verify that address is stored in host order */
+    header->address = htonl(creds->address);
+    header->ticket_size = htonl(creds->ticket_size);
+    memcpy(header->ticket, creds->ticket, cc_v4_ticket_size);
+
+    *pflat = flat;
+    *plen = len;
+
+    return ccNoError;  
+}
+
+cc_int32
+cci_creds_v4_unmarshall( char * flat, 
+                         cc_uint32 len,
+                         cc_credentials_union * creds_union)
+{
+    struct cci_flat_creds_v4 * header;
+    cc_credentials_v4_t * creds;
+    cc_time64 t64;
+
+    if ( flat == NULL || len == 0 || creds_union == NULL )
+        return ccErrBadParam;
+
+    creds_union->version = cc_credentials_v4;
+
+    header = (cci_flat_creds_v4_t *)flat;
+
+    creds = (cc_credentials_v4_t *)malloc(sizeof(cc_credentials_v4_t));
+    if ( creds == NULL )
+       return ccErrNoMem;
+
+    creds->version = ntohl(header->version);
+    memcpy(creds->principal, header->principal, cc_v4_name_size);
+    memcpy(creds->principal_instance, header->principal_instance, cc_v4_instance_size);
+    memcpy(creds->service, header->service, cc_v4_name_size);
+    memcpy(creds->service_instance, header->service_instance, cc_v4_instance_size);
+    memcpy(creds->realm, header->realm, cc_v4_realm_size);
+    memcpy(creds->session_key, header->session_key, cc_v4_key_size);
+    creds->kvno = htonl(header->kvno);
+    creds->string_to_key_type = htonl(header->string_to_key_type);
+    t64 = header->issue_date;
+    creds->issue_date = (cc_time64)ntohll(t64);
+    creds->lifetime = (cc_int32)ntohl(header->lifetime);
+    /* TODO: verify that address is stored in host order */
+    creds->address = ntohl(header->address);
+    creds->ticket_size = ntohl(header->ticket_size);
+    memcpy(creds->ticket, header->ticket, cc_v4_ticket_size);
+
+    creds_union->credentials.credentials_v4 = creds;
+
+    return ccNoError;
+}
+
+
+static cc_int32
+cci_creds_cc_data_array_count_entries( cc_data ** array, cc_uint32 * pcount)
+{
+    cc_uint32 count;
+
+    if (array == NULL) {
+        *pcount = 0;
+        return ccNoError;
+    }
+
+    for ( count=0; array[count] != NULL ; count++) ;
+
+    *pcount = count;
+    return ccNoError;
+}
+
+static cc_int32
+cci_creds_v5_compute_flat_size( cc_credentials_v5_t * creds, cc_uint32 * plen)
+{
+    cc_uint32 len;
+    cc_uint32 i, count;
+
+    len = sizeof(struct cci_flat_creds_v5);
+
+    if (creds->client)
+        len += strlen(creds->client) + 1;
+
+    if (creds->server)
+        len += strlen(creds->server) + 1;
+
+    len += creds->keyblock.length;
+
+    cci_creds_cc_data_array_count_entries( creds->addresses, &count );
+    len += count * sizeof(cc_flat_data);
+    for ( i=0; i<count; i++ ) {
+        len += creds->addresses[i]->length;
+    }
+
+    len += creds->ticket.length;
+    len += creds->second_ticket.length;
+
+    cci_creds_cc_data_array_count_entries( creds->authdata, &count );
+    len += count * sizeof(cc_flat_data);
+    for ( i=0; i<count; i++ ) {
+        len += creds->authdata[i]->length;
+    }
+
+    *plen = len;
+    return ccNoError;
+}
+
+cc_int32
+cci_creds_v5_marshall( cc_credentials_v5_t * creds, 
+                       char ** pflat, 
+                       cc_uint32 * plen)
+{
+    cc_uint32 len;
+    char * flat;
+    struct cci_flat_creds_v5 * header;
+    cc_uint32 length;
+    cc_uint32 offset;
+    cc_time64 t64;
+    cc_uint32 count;
+    cc_uint32 i;
+
+    if ( creds == NULL || pflat == NULL || plen == NULL )
+        return ccErrBadParam;
+
+    cci_creds_v5_compute_flat_size(creds, &len);
+
+    flat = (char *)malloc(len);
+    if ( flat == NULL )
+        return ccErrNoMem;
+    memset(flat, 0, len);
+
+    offset = sizeof(struct cci_flat_creds_v5);
+    header = (struct cci_flat_creds_v5 *)flat;
+    header->version = htonl(FLAT_CREDS_V5_VERSION);
+    if (creds->client) {
+       length = strlen(creds->client) + 1;
+        header->client.length = htonl(length);
+        header->client.data = htonl(offset);
+        memcpy(flat + offset, creds->client, length);
+        offset += length;
+    }
+
+    if (creds->server) {
+       length = strlen(creds->server) + 1;
+        header->server.length = htonl(length);
+        header->server.data = htonl(offset);
+        memcpy(flat + offset, creds->server, length);
+        offset += length;
+    }
+
+    header->keyblock.type = htonl(creds->keyblock.type);
+    if (creds->keyblock.length) {
+       length = creds->keyblock.length;
+        header->keyblock.length = htonl(length);
+        header->keyblock.data = htonl(offset);
+        memcpy(flat + offset, creds->keyblock.data, length);
+        offset += length;
+    }           
+
+    t64 = creds->authtime;
+    header->authtime = htonll(t64);
+    t64 = creds->starttime;
+    header->starttime = htonll(t64);
+    t64 = creds->endtime;
+    header->endtime = htonll(t64);
+    t64 = creds->renew_till;
+    header->renew_till = htonll(t64);
+
+    header->is_skey = htonl(creds->is_skey);
+    header->ticket_flags = htonl(creds->ticket_flags);
+
+    cci_creds_cc_data_array_count_entries( creds->addresses, &count );
+    if ( count ) {
+        cc_flat_data * addresses = (cc_flat_data *)flat + offset;
+       header->address_count = htonl(count);
+        header->addresses = htonl(offset);
+        offset += count * sizeof(cc_flat_data);
+
+        for ( i=0; i < count; i++ ) {
+            addresses[i].type = htonl(creds->addresses[i]->type);
+            if (creds->addresses[i]->length) {
+               length = creds->addresses[i]->length;
+                addresses[i].length = htonl(length);
+                addresses[i].data = htonl(offset);
+               /* TODO: verify that addresses are stored in network order */
+                memcpy(flat + offset, creds->addresses[i]->data, length);
+                offset += length;
+            }
+        }
+    }
+
+    header->ticket.type = htonl(creds->ticket.type);
+    if (creds->ticket.length) {
+       length = creds->ticket.length;
+        header->ticket.length = htonl(length);
+        header->ticket.data = htonl(offset);
+        memcpy(flat + offset, creds->ticket.data, length);
+        offset += length;
+    }           
+
+    header->second_ticket.type = htonl(creds->second_ticket.type);
+    if (creds->second_ticket.length) {
+       length = creds->second_ticket.length;
+        header->second_ticket.length = htonl(length);
+        header->second_ticket.data = htonl(offset);
+        memcpy(flat + offset, creds->second_ticket.data, length);
+        offset += length;
+    }           
+
+    cci_creds_cc_data_array_count_entries( creds->authdata, &count );
+    if ( count ) {
+        cc_flat_data * authdata = (cc_flat_data *)flat + offset;
+
+       header->authdata_count = htonl(count);
+        header->authdata = (offset);
+        offset += count * sizeof(cc_flat_data);
+
+        for ( i=0; i < count; i++ ) {
+            authdata[i].type = htonl(creds->authdata[i]->type);
+            if (creds->authdata[i]->length) {
+               length = creds->authdata[i]->length;
+                authdata[i].length = htonl(length);
+                authdata[i].data = htonl(offset);
+                memcpy(flat + offset, creds->authdata[i]->data, length);
+                offset += length;
+            }
+        }
+    }
+
+    *pflat = flat;
+    *plen = len;
+    return ccNoError;
+}
+
+
+// TODO: a much better job of checking for out of memory errors
+//       and validating that we do not read beyond the flat input
+//       data buffer
+
+cc_int32
+cci_creds_v5_unmarshall( char * flat, 
+                         cc_uint32 len,
+                         cc_credentials_union * creds_union)
+{
+    struct cci_flat_creds_v5 * header;
+    cc_credentials_v5_t * creds;
+    cc_flat_data * flat_data;
+    cc_time64 t64;
+    cc_uint32  length;
+    cc_uint32  count;
+    cc_uint32  i;
+
+    if ( flat == NULL || len == 0 || creds_union == NULL )
+        return ccErrBadParam;
+
+    creds_union->version = cc_credentials_v5;
+
+    header = (struct cci_flat_creds_v5 *)flat;
+
+    if ( ntohl(header->version) != FLAT_CREDS_V5_VERSION )
+        return ccErrBadParam;
+
+    creds = (cc_credentials_v5_t *)malloc(sizeof(cc_credentials_v5_t));
+    if ( creds == NULL )
+        return ccErrNoMem;
+    memset(creds, 0, sizeof(cc_credentials_v5_t));
+
+    if ( header->client.length ) {
+       length = ntohl(header->client.length);
+        creds->client = (char *)malloc(length);
+        memcpy(creds->client, flat + header->client.data, length);
+    }
+
+    if ( header->server.length ) {
+       length = ntohl(header->server.length);
+        creds->server = (char *)malloc(length);
+        memcpy(creds->server, flat + header->server.data, length);
+    }
+
+    creds->keyblock.type = ntohl(header->keyblock.type);
+    if ( header->keyblock.length ) {
+       length = ntohl(header->keyblock.length);
+        creds->keyblock.length = length;
+        creds->keyblock.data = malloc(length);
+        memcpy(creds->keyblock.data, flat + header->keyblock.data, length);
+    }
+
+    /* TODO: need to perform overflow validation checks to ensure
+     * that we do not attempt to store too large a value into cc_time_t
+     * when it is a 32-bit field.
+     */
+    t64 = ntohll(header->authtime);
+    creds->authtime = (cc_time)t64;
+    t64 = ntohll(header->starttime);
+    creds->starttime = (cc_time)t64;
+    t64 = ntohll(header->endtime);
+    creds->endtime = (cc_time)t64;
+    t64 = ntohll(header->renew_till);
+    creds->renew_till = (cc_time)t64;
+
+    creds->is_skey = ntohl(header->is_skey);
+    creds->ticket_flags = ntohl(header->ticket_flags);
+
+    count = ntohl(header->address_count);
+    creds->addresses = (cc_data **) malloc((count + 1) * sizeof(cc_data *));
+    flat_data = (cc_flat_data *)flat + header->addresses;
+    for ( i=0 ; i < count ; i++ ) {
+        creds->addresses[i] = (cc_data *)malloc(sizeof(cc_data));
+        creds->addresses[i]->type = ntohl(flat_data[i].type);
+       length = ntohl(flat_data[i].length);
+        creds->addresses[i]->length = length;
+        if ( length ) {
+            creds->addresses[i]->data = malloc(length);
+           /* TODO: verify that addresses are stored in network order */
+            memcpy(creds->addresses[i]->data, flat + flat_data[i].data, length);
+        } else {
+            creds->addresses[i]->data = NULL;
+        }
+    }
+    creds->addresses[i] = NULL;
+
+    creds->ticket.type = ntohl(header->ticket.type);
+    length = ntohl(header->ticket.length);
+    if ( length ) {
+        creds->ticket.length = length;
+        creds->ticket.data = malloc(length);
+        memcpy(creds->ticket.data, flat + header->ticket.data, length);
+    }
+
+    creds->second_ticket.type = header->second_ticket.type;
+    if ( header->second_ticket.length ) {
+        creds->second_ticket.length = header->second_ticket.length;
+        creds->second_ticket.data = malloc(creds->second_ticket.length);
+        memcpy(creds->second_ticket.data, flat + header->second_ticket.data, creds->second_ticket.length);
+    }
+
+    count = ntohl(header->authdata_count);
+    creds->authdata = (cc_data **) malloc((count + 1) * sizeof(cc_data *));
+    flat_data = (cc_flat_data *)flat + header->authdata;
+    for ( i=0 ; i < count ; i++ ) {
+        creds->authdata[i] = (cc_data *)malloc(sizeof(cc_data));
+        creds->authdata[i]->type = ntohl(flat_data[i].type);
+       length = ntohl(flat_data[i].length);
+        creds->authdata[i]->length = length;
+        if ( length ) {
+            creds->authdata[i]->data = malloc(length);
+            memcpy(creds->authdata[i]->data, flat + flat_data[i].data, length);
+        } else {
+            creds->authdata[i]->data = NULL;
+        }
+    }
+    creds->authdata[i] = NULL;
+
+    creds_union->credentials.credentials_v5 = creds;
+
+    return ccNoError;
+}
+
index 789fc874649c374f457923e1f5e5ecbad643d6d4..fa051e95a5eb8db0b6ff86d5e089b70045fc4a21 100644 (file)
-/* $Copyright:\r
- *\r
- * Copyright 2004-2006 by the Massachusetts Institute of Technology.\r
- * \r
- * All rights reserved.\r
- * \r
- * Export of this software from the United States of America may require a\r
- * specific license from the United States Government.  It is the\r
- * responsibility of any person or organization contemplating export to\r
- * obtain such a license before exporting.\r
- * \r
- * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and distribute\r
- * this software and its documentation for any purpose and without fee is\r
- * hereby granted, provided that the above copyright notice appear in all\r
- * copies and that both that copyright notice and this permission notice\r
- * appear in supporting documentation, and that the name of M.I.T. not be\r
- * used in advertising or publicity pertaining to distribution of the\r
- * software without specific, written prior permission.  Furthermore if you\r
- * modify this software you must label your software as modified software\r
- * and not distribute it in such a fashion that it might be confused with\r
- * the original MIT software. M.I.T. makes no representations about the\r
- * suitability of this software for any purpose.  It is provided "as is"\r
- * without express or implied warranty.\r
- * \r
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED\r
- * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF\r
- * MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.\r
- * \r
- * Individual source code files are copyright MIT, Cygnus Support,\r
- * OpenVision, Oracle, Sun Soft, FundsXpress, and others.\r
- * \r
- * Project Athena, Athena, Athena MUSE, Discuss, Hesiod, Kerberos, Moira,\r
- * and Zephyr are trademarks of the Massachusetts Institute of Technology\r
- * (MIT).  No commercial use of these trademarks may be made without prior\r
- * written permission of MIT.\r
- * \r
- * "Commercial use" means use of a name in a product or other for-profit\r
- * manner.  It does NOT prevent a commercial firm from referring to the MIT\r
- * trademarks in order to convey information (although in doing so,\r
- * recognition of their trademark status should be given).\r
- * $\r
- */\r
-\r
-/*\r
- * Verifiable, extensible message format.\r
- *\r
- * Format:\r
- * <size of header block (header_len)>\r
- * <size of *entire* message, including previous field (flat_len)>\r
- * <message type (type)>\r
- * <type specific header (header)>\r
- * <magic number (magic)>\r
- * <data blob 1 length>\r
- * <data blob 1>\r
- * <data blob 2 length>\r
- * <data blob 2>\r
- * ...\r
- * <magic number (magic)>\r
- *\r
- * If the header has variable length data it is included in the data blobs. \r
- * The header field has the offset from the beginning of the message of the 1st \r
- * byte of the data and the length of the data.\r
- */\r
-\r
-#include "CredentialsCache.h"\r
-#include "msg.h"\r
-#include "generic_lists.h"\r
-\r
-#include <stdlib.h>\r
-#include <memory.h>\r
-#include <stdio.h>\r
-#include <string.h>\r
-\r
-/**\r
- * cci_msg_new()\r
- *\r
- * Purpose: Allocate and initialize a new cc_msg_t structure\r
- *\r
- * Input parameter (type) in host order\r
- *\r
- * Return:  non-NULL, the msg\r
- *          NULL, failure\r
- *\r
- * Errors:  ccErrNoMem\r
- *\r
- */\r
-cc_int32\r
-cci_msg_new(cc_uint32 type, cc_msg_t** msgpp) \r
-{\r
-    // type should be validated.  If invalid set error to ccErrBadParam\r
-    cc_msg_t* msg;\r
-    \r
-    if ( type > CC_MSG_MAX_TYPE || msgpp == NULL )\r
-        return ccErrBadParam;\r
-\r
-    msg = (cc_msg_t*)malloc(sizeof(cc_msg_t));\r
-    if (msg == NULL)\r
-        return ccErrNoMem;\r
-\r
-    msg->type = type;\r
-    msg->flat = NULL;\r
-    msg->header = NULL;\r
-    msg->flat_len = 0;\r
-    msg->header_len = 0;\r
-    msg->magic = 0;\r
-    cci_generic_list_new(&msg->data_blobs);\r
-    if (msg->data_blobs == NULL) {\r
-        // pass on error from previous call\r
-        free(msg);\r
-        return ccErrNoMem;\r
-    }\r
-\r
-    *msgpp = msg;     \r
-    return ccNoError;\r
-}\r
-\r
-/**\r
- * cci_msg_calc_header_size()\r
- *\r
- * Purpose: Calculates the size of the header\r
- *\r
- * Return:  the size in bytes\r
- *\r
- * Errors:  ccErrBadParam\r
- *\r
- */\r
-cc_int32\r
-cci_msg_calc_header_size(cc_msg_t* msg, cc_uint32 * lenp) \r
-{\r
-    int header_len = 12; /* header size, entire size, type */\r
-\r
-    if ( msg == NULL || lenp == NULL )\r
-        return ccErrBadParam;\r
-\r
-    header_len += msg->header_len;\r
-    *lenp = header_len;\r
-    return ccNoError;\r
-}\r
-\r
-/**\r
- * cci_msg_calc_size()\r
- *\r
- * Purpose: Calculates the size of the message\r
- *          (does not include the magic bytes)\r
- *\r
- * Return:  the size in bytes\r
- *\r
- * Errors:  ccErrBadParam\r
- *\r
- */\r
-cc_int32 \r
-cci_msg_calc_size(cc_msg_t* msg, cc_uint32 * lenp) \r
-{\r
-    cc_uint32 flat_len;\r
-    cc_generic_list_node_t* gen_node;\r
-    cc_generic_iterate_t* gen_iterator;\r
-       cc_int32 code;\r
-\r
-    if ( msg == NULL || lenp == NULL ) \r
-        return ccErrBadParam;\r
-\r
-    code = cci_msg_calc_header_size(msg, &flat_len);\r
-    if (code != ccNoError)\r
-        goto bad;\r
-\r
-    code = cci_generic_list_iterator(msg->data_blobs, &gen_iterator);\r
-    if ( code != ccNoError )\r
-        goto bad;\r
-\r
-    while (cci_generic_iterate_has_next(gen_iterator)) {\r
-        code = cci_generic_iterate_next(gen_iterator, &gen_node);\r
-        if (code != ccNoError)\r
-            break;\r
-        flat_len += gen_node->len + BLOB_LEN;\r
-    }\r
-    cci_generic_free_iterator(gen_iterator);\r
-    if (code != ccNoError)\r
-        goto bad;\r
-\r
-    flat_len += MAGIC_HEAD_LEN + MAGIC_DATA_LEN;\r
-    *lenp = flat_len;\r
-\r
-  bad:\r
-    return code;\r
-}\r
-\r
-/**\r
- * cci_msg_add_data_blob()\r
- *\r
- * Purpose: Adds 'len' bytes of data to the msg\r
- *\r
- * Return: \r
- *\r
- * Errors: \r
- *\r
- */\r
-cc_int32 \r
-cci_msg_add_data_blob(cc_msg_t* msg, void *data, cc_uint32 len, cc_uint32 *lenp) \r
-{\r
-    cc_int32 code;\r
-\r
-    if (msg == NULL || data == NULL || len <= 0 || lenp == NULL)\r
-        return ccErrBadParam;\r
-\r
-    code = cci_generic_list_append(msg->data_blobs, data, len, NULL);\r
-    if ( code != ccNoError )\r
-        return code;\r
-    return cci_msg_calc_blob_pos(msg, data, len, lenp);\r
-}\r
-\r
-/**\r
- * cc_msg_\r
- *\r
- * Purpose:\r
- *\r
- * Return: \r
- *\r
- * Errors: \r
- *\r
- */\r
-cc_int32 \r
-cci_msg_calc_blob_pos(cc_msg_t* msg, void *data, cc_uint32 len, cc_uint32 * posp) \r
-{\r
-    cc_uint32 pos;\r
-    cc_generic_list_node_t* gen_node;\r
-    cc_generic_iterate_t* gen_iterator;\r
-    cc_int32 code;\r
-\r
-    code = cci_msg_calc_header_size(msg, &pos);\r
-    pos += sizeof(cc_uint32); /*+ sizeof(cc_uint32) for magic*/\r
-\r
-    code = cci_generic_list_iterator(msg->data_blobs, &gen_iterator);\r
-    while (cci_generic_iterate_has_next(gen_iterator)) {\r
-        code = cci_generic_iterate_next(gen_iterator, &gen_node);\r
-        if (gen_node->len != len && gen_node->data != data) {\r
-            pos += gen_node->len + sizeof(cc_uint32);\r
-        } else {\r
-            cci_generic_free_iterator(gen_iterator);\r
-            *posp = pos + sizeof(cc_uint32);\r
-            return ccNoError;\r
-        }\r
-    }\r
-    \r
-    cci_generic_free_iterator(gen_iterator);\r
-    return ccIteratorEnd;\r
-}\r
-\r
-/**\r
- * cc_msg_\r
- *\r
- * Purpose:\r
- *\r
- * Return: \r
- *\r
- * Errors: \r
- *\r
- */\r
-cc_int32 \r
-cci_msg_add_header(cc_msg_t* msg, void *header, cc_uint32 header_len) \r
-{\r
-    if ( msg == NULL || header == NULL )\r
-        return ccErrBadParam;\r
-\r
-    msg->header = header;\r
-    msg->header_len = header_len;\r
-    return ccNoError;\r
-}\r
-\r
-\r
-/**\r
- * cc_msg_\r
- *\r
- * Purpose:\r
- *\r
- * Return: \r
- *\r
- * Errors: \r
- *\r
- */\r
-cc_int32\r
-cci_msg_flatten(cc_msg_t* msg, void **flatpp) \r
-{\r
-    cc_generic_list_node_t* gen_node;\r
-    cc_generic_iterate_t* gen_iterator;\r
-    char *cur_pos;\r
-    cc_uint32 zero = 0;\r
-    cc_uint32 magic = 0;\r
-    cc_uint32 msg_len;\r
-    cc_uint32 u32;\r
-    cc_int32 code;\r
-\r
-    if (msg == NULL)\r
-        return ccErrBadParam;\r
-\r
-    code = cci_msg_calc_size(msg,&msg->flat_len);\r
-    if ( code != ccNoError )\r
-        return code;\r
-\r
-    if (msg->flat_len > CC_MSG_MAX_SIZE)\r
-        return ccErrBadParam;\r
-\r
-    msg->flat = (void *)malloc(msg->flat_len);\r
-    if (msg->flat == NULL)\r
-        return ccErrNoMem;\r
-    \r
-    cur_pos = msg->flat;\r
-\r
-    u32 = htonl(msg->header_len);\r
-    memcpy(cur_pos,&u32,sizeof(cc_uint32));\r
-    cur_pos+=sizeof(cc_uint32);\r
-\r
-    u32 = htonl(msg->flat_len);\r
-    memcpy(cur_pos,&u32,sizeof(cc_uint32));\r
-    cur_pos+=sizeof(cc_uint32);\r
-\r
-    u32 = htonl(msg->type);\r
-    memcpy(cur_pos,&u32,sizeof(cc_uint32));\r
-    cur_pos+=sizeof(cc_uint32);\r
-\r
-    /* header data is already in network order */\r
-    memcpy(cur_pos, msg->header, msg->header_len);\r
-    cur_pos += msg->header_len;\r
-\r
-    u32 = htonl(zero);\r
-    memcpy(cur_pos, &u32, sizeof(cc_uint32)); /*will be magic number later*/\r
-    cur_pos += sizeof(cc_uint32);\r
-\r
-    code = cci_generic_list_iterator(msg->data_blobs, &gen_iterator);\r
-    if ( code != ccNoError ) {\r
-        free(msg->flat);\r
-        return code;\r
-    }\r
-\r
-    while (cci_generic_iterate_has_next(gen_iterator)) {\r
-        code = cci_generic_iterate_next(gen_iterator, &gen_node);\r
-        if (code != ccNoError) {\r
-            free(gen_iterator);\r
-            free(msg->flat);\r
-            return code;\r
-        }\r
-       u32 = htonl(gen_node->len);\r
-           memcpy(cur_pos, &u32, sizeof(cc_uint32));\r
-        cur_pos+=sizeof(cc_uint32);\r
-               \r
-       /* data already in network order */\r
-        memcpy(cur_pos, gen_node->data, gen_node->len);\r
-        cur_pos += gen_node->len;\r
-    }\r
-    free(gen_iterator);\r
-\r
-    u32 = htonl(zero);\r
-    memcpy(cur_pos, &u32, sizeof(cc_uint32)); /*magic number will go here later*/\r
-    cur_pos += sizeof(cc_uint32);\r
-\r
-    if (cur_pos - (char *)msg->flat != msg->flat_len) {\r
-        fprintf(stderr, "ERROR cur_pos - msg->flat = %d\n",msg->flat_len);\r
-    }\r
-\r
-    cci_msg_calc_magic(msg->flat, msg->flat_len, &magic);\r
-    printf("magic = %d\n",magic);\r
-       \r
-    cci_msg_calc_header_size(msg, &msg_len);\r
-    memcpy((char *)msg->flat + msg_len, &magic, sizeof(cc_uint32));\r
-    memcpy((char *)msg->flat + msg->flat_len - sizeof(cc_uint32), &magic, sizeof(cc_uint32));\r
-\r
-    if ( flatpp != NULL )\r
-        *flatpp = msg->flat;\r
-\r
-    return ccNoError;\r
-}\r
-\r
-/**\r
- * cc_msg_\r
- *\r
- * Purpose:\r
- *\r
- * Return: \r
- *\r
- * Errors: \r
- *\r
- */\r
-cc_int32\r
-cci_msg_calc_magic(void *flat, int flat_len, cc_uint32 * magicp)\r
-{\r
-    cc_uint32 magic = 0;\r
-    int i;\r
-       \r
-    for (i = 0; i < flat_len; i += sizeof(cc_uint32)) {\r
-        magic = magic ^ *(int *)((char *)flat + i);\r
-    }\r
-    *magicp = htonl(magic);\r
-    return ccNoError;\r
-}\r
-\r
-/**\r
- * cc_msg_\r
- *\r
- * Purpose:\r
- *\r
- * Return: \r
- *\r
- * Errors: \r
- *\r
- */\r
-cc_int32 \r
-cci_msg_verify(void *flat, int flat_len, cc_uint32 * validp)  \r
-{\r
-    cc_uint32 *magic1, *magic2;\r
-    cc_uint32 *pheader_len;\r
-    cc_uint32 header_len;\r
-    cc_uint32 *ptotal_len;\r
-    cc_uint32 total_len;\r
-    cc_uint32 *pblob_len;\r
-    cc_uint32 blob_len;\r
-    cc_uint32 *ptype;\r
-    cc_uint32 type;\r
-    cc_uint32 num_blobs = 0;\r
-    cc_uint32 zero = 0;\r
-    cc_uint32 msg_magic, msg_magic2;\r
-\r
-    if (flat == NULL || flat_len <= 0 || validp == NULL)\r
-        return ccErrBadParam;\r
-\r
-    pheader_len = flat;\r
-    ptotal_len = (cc_uint32 *)((char *)pheader_len + sizeof(cc_uint32));\r
-    ptype = (cc_uint32 *)((char *)ptotal_len + sizeof(cc_uint32));\r
-\r
-    header_len = ntohl(*pheader_len);\r
-    total_len = ntohl(*ptotal_len);\r
-    type = ntohl(*ptype);\r
-\r
-    if (total_len != flat_len) {\r
-        *validp = 0;\r
-        return ccNoError;\r
-    }\r
-    \r
-    if (header_len > flat_len) {\r
-        /*too weak. We could verify header_len against type spec header.*/\r
-        *validp = 0;\r
-        return ccNoError;\r
-    }\r
-    if (type > CC_MSG_MAX_TYPE) {\r
-        *validp = 0;\r
-        return ccNoError;\r
-    }\r
-\r
-    magic1 = (cc_uint32 *)((char *)ptype + sizeof(cc_uint32) + header_len); \r
-    if ((char *)magic1 - (char *)flat == (flat_len - 8)) {\r
-        /*There are no data blobs*/\r
-        magic2 = (cc_uint32 *)((char *)magic1 + sizeof(cc_uint32));\r
-        num_blobs = 0;\r
-    } else {\r
-        pblob_len = (cc_uint32 *)((char *)magic1 + sizeof(cc_uint32));\r
-        num_blobs = 1;\r
-       blob_len = ntohl(*pblob_len);\r
-\r
-        while (blob_len + sizeof(cc_uint32) + ((char *)pblob_len - (char *)flat) < (flat_len - sizeof(cc_uint32))) {\r
-            pblob_len = (cc_uint32 *)((char *)pblob_len + blob_len + sizeof(cc_uint32));\r
-            num_blobs++;\r
-           blob_len = ntohl(*pblob_len);\r
-        }\r
-\r
-        if (blob_len + sizeof(cc_uint32) + ((char *)pblob_len - (char *)flat) != (flat_len - sizeof(cc_uint32))) {\r
-            /*blobs didn't line up*/\r
-            *validp = 0;\r
-            return ccNoError;\r
-        }\r
-        magic2 = (cc_uint32 *)((char *)pblob_len + blob_len + sizeof(cc_uint32)); /*2nd magic should be directly after the last blob*/\r
-    }\r
-       \r
-    if (*magic1 != *magic2) {\r
-        *validp = 0;\r
-        return ccNoError;\r
-    }\r
-    msg_magic = *magic1;\r
-\r
-    printf("%d %d\n", (char *)magic1 - (char *)flat, (char *)magic2 - (char *)flat);\r
-\r
-    memcpy(magic1, &zero, sizeof(cc_uint32));\r
-    memcpy(magic2, &zero, sizeof(cc_uint32));\r
-    cci_msg_calc_magic(flat, flat_len, &msg_magic2);\r
-    /* both msg_magic and msg_magic2 are in network order */\r
-    if (msg_magic != msg_magic2) {\r
-        *validp = 0;\r
-        return ccNoError;\r
-    }\r
-    memcpy(magic1, &msg_magic, sizeof(cc_uint32));\r
-    memcpy(magic2, &msg_magic, sizeof(cc_uint32));\r
-\r
-    *validp = 1;\r
-    return ccNoError;\r
-}\r
-\r
-/**\r
- * cc_msg_\r
- *\r
- * Purpose:\r
- *\r
- * Return: \r
- *\r
- * Errors: \r
- *\r
- */\r
-cc_int32\r
-cci_msg_unflatten(void *flat, int flat_len, cc_msg_t** msgpp) \r
-{\r
-    cc_msg_t* msg;\r
-    char *cur_pos;\r
-    cc_uint32 blob_len;\r
-    char *blob;\r
-    cc_uint32 valid;\r
-    cc_int32 code;\r
-\r
-    if ( flat == NULL || flat_len <= 0 || msgpp == NULL )\r
-        return ccErrBadParam;\r
-\r
-    code = cci_msg_new(0, &msg);\r
-    if (code)\r
-        return code;\r
-\r
-    cci_msg_verify(flat, flat_len, &valid);\r
-    if (valid != 1) {\r
-        cci_msg_destroy(msg);\r
-        return ccErrBadParam;\r
-    }\r
-\r
-    cur_pos = flat;\r
-    msg->flat = flat;\r
-\r
-    msg->header_len = ntohl(*(cc_uint32 *)cur_pos);\r
-    cur_pos += sizeof(cc_uint32);\r
-\r
-    msg->flat_len = ntohl(*(cc_uint32 *)cur_pos);\r
-    cur_pos += sizeof(cc_uint32);\r
-\r
-    msg->type = ntohl(*(cc_uint32 *)cur_pos);\r
-    cur_pos += sizeof(cc_uint32);\r
-\r
-    msg->header = (void *)malloc(msg->header_len);\r
-    if (msg->header == NULL) {\r
-        cci_msg_destroy(msg);\r
-        return ccErrNoMem;\r
-    }\r
-    memcpy(msg->header, cur_pos, msg->header_len);\r
-    cur_pos += msg->header_len;\r
-       \r
-    msg->magic = ntohl(*(cc_uint32 *)cur_pos);\r
-    cur_pos += sizeof(cc_uint32);\r
-\r
-    if (cur_pos - (char *)flat != flat_len - 8) { /*at least 1 blob*/\r
-        blob_len = ntohl(*(cc_uint32 *)cur_pos);\r
-        while (blob_len + (cur_pos - (char *)flat) + sizeof(cc_uint32) <= flat_len - sizeof(cc_uint32)) {\r
-            blob = (void *)malloc(blob_len);\r
-            if (blob == NULL) {\r
-                cci_msg_destroy(msg);\r
-                return ccErrNoMem;\r
-            }\r
-            memcpy(blob, cur_pos + sizeof(cc_uint32), blob_len);\r
-            cci_generic_list_append(msg->data_blobs, blob, blob_len, NULL);\r
-\r
-            cur_pos += sizeof(cc_uint32) + blob_len;\r
-            blob_len = ntohl(*(int *)cur_pos);\r
-        }\r
-    }\r
-    *msgpp = msg;\r
-    return ccNoError;\r
-}\r
-\r
-cc_int32\r
-cci_msg_retrieve_blob(cc_msg_t* msg, cc_uint32 blob_offset, cc_uint32 blob_len, char **blobp) \r
-{\r
-    cc_generic_iterate_t*      gen_iterator;\r
-    cc_generic_list_node_t*    gen_node;\r
-    void *ret;\r
-    cc_uint32                   blob_pos;\r
-    cc_int32                    code;\r
-\r
-    /*Ensure that the message has been unflattened*/\r
-    if ( msg == NULL || msg->flat == NULL || blob_offset > msg->flat_len || \r
-         blob_len > msg->flat_len - blob_offset || blobp == NULL)\r
-        return ccErrBadParam;\r
-\r
-    code = cci_generic_list_iterator(msg->data_blobs, &gen_iterator);\r
-    while (cci_generic_iterate_has_next(gen_iterator)) {\r
-        code = cci_generic_iterate_next(gen_iterator, &gen_node);\r
-        code = cci_msg_calc_blob_pos(msg, gen_node->data, gen_node->len, &blob_pos);\r
-        if (blob_pos == blob_offset && gen_node->len == blob_len)  {\r
-            free(gen_iterator);\r
-            ret = (void *)malloc(blob_len);\r
-            if (ret == NULL)\r
-                return ccErrNoMem;\r
-            memcpy(ret,(char *)msg->flat + blob_offset, blob_len);     \r
-            *blobp = ret;\r
-            return ccNoError;\r
-        }\r
-    }\r
-    free(gen_iterator);\r
-    return ccIteratorEnd;\r
-}\r
-\r
-/**\r
- * cc_msg_\r
- *\r
- * Purpose:\r
- *\r
- * Return: \r
- *\r
- * Errors: \r
- *\r
- */\r
-cc_int32 \r
-cci_msg_destroy(cc_msg_t* msg) \r
-{\r
-    if (msg->flat != NULL) \r
-        free(msg->flat);\r
-    if (msg->header != NULL)\r
-        free(msg->header);\r
-    cci_generic_list_destroy(msg->data_blobs);\r
-    free(msg);\r
-    return ccNoError;\r
-}\r
-\r
+/* $Copyright:
+ *
+ * Copyright 2004-2006 by the Massachusetts Institute of Technology.
+ * 
+ * All rights reserved.
+ * 
+ * Export of this software from the United States of America may require a
+ * specific license from the United States Government.  It is the
+ * responsibility of any person or organization contemplating export to
+ * obtain such a license before exporting.
+ * 
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and distribute
+ * this software and its documentation for any purpose and without fee is
+ * hereby granted, provided that the above copyright notice appear in all
+ * copies and that both that copyright notice and this permission notice
+ * appear in supporting documentation, and that the name of M.I.T. not be
+ * used in advertising or publicity pertaining to distribution of the
+ * software without specific, written prior permission.  Furthermore if you
+ * modify this software you must label your software as modified software
+ * and not distribute it in such a fashion that it might be confused with
+ * the original MIT software. M.I.T. makes no representations about the
+ * suitability of this software for any purpose.  It is provided "as is"
+ * without express or implied warranty.
+ * 
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ * 
+ * Individual source code files are copyright MIT, Cygnus Support,
+ * OpenVision, Oracle, Sun Soft, FundsXpress, and others.
+ * 
+ * Project Athena, Athena, Athena MUSE, Discuss, Hesiod, Kerberos, Moira,
+ * and Zephyr are trademarks of the Massachusetts Institute of Technology
+ * (MIT).  No commercial use of these trademarks may be made without prior
+ * written permission of MIT.
+ * 
+ * "Commercial use" means use of a name in a product or other for-profit
+ * manner.  It does NOT prevent a commercial firm from referring to the MIT
+ * trademarks in order to convey information (although in doing so,
+ * recognition of their trademark status should be given).
+ * $
+ */
+
+/*
+ * Verifiable, extensible message format.
+ *
+ * Format:
+ * <size of header block (header_len)>
+ * <size of *entire* message, including previous field (flat_len)>
+ * <message type (type)>
+ * <type specific header (header)>
+ * <magic number (magic)>
+ * <data blob 1 length>
+ * <data blob 1>
+ * <data blob 2 length>
+ * <data blob 2>
+ * ...
+ * <magic number (magic)>
+ *
+ * If the header has variable length data it is included in the data blobs. 
+ * The header field has the offset from the beginning of the message of the 1st 
+ * byte of the data and the length of the data.
+ */
+
+#include "CredentialsCache.h"
+#include "msg.h"
+#include "generic_lists.h"
+
+#include <stdlib.h>
+#include <memory.h>
+#include <stdio.h>
+#include <string.h>
+
+/**
+ * cci_msg_new()
+ *
+ * Purpose: Allocate and initialize a new cc_msg_t structure
+ *
+ * Input parameter (type) in host order
+ *
+ * Return:  non-NULL, the msg
+ *          NULL, failure
+ *
+ * Errors:  ccErrNoMem
+ *
+ */
+cc_int32
+cci_msg_new(cc_uint32 type, cc_msg_t** msgpp) 
+{
+    // type should be validated.  If invalid set error to ccErrBadParam
+    cc_msg_t* msg;
+    
+    if ( type > CC_MSG_MAX_TYPE || msgpp == NULL )
+        return ccErrBadParam;
+
+    msg = (cc_msg_t*)malloc(sizeof(cc_msg_t));
+    if (msg == NULL)
+        return ccErrNoMem;
+
+    msg->type = type;
+    msg->flat = NULL;
+    msg->header = NULL;
+    msg->flat_len = 0;
+    msg->header_len = 0;
+    msg->magic = 0;
+    cci_generic_list_new(&msg->data_blobs);
+    if (msg->data_blobs == NULL) {
+        // pass on error from previous call
+        free(msg);
+        return ccErrNoMem;
+    }
+
+    *msgpp = msg;     
+    return ccNoError;
+}
+
+/**
+ * cci_msg_calc_header_size()
+ *
+ * Purpose: Calculates the size of the header
+ *
+ * Return:  the size in bytes
+ *
+ * Errors:  ccErrBadParam
+ *
+ */
+cc_int32
+cci_msg_calc_header_size(cc_msg_t* msg, cc_uint32 * lenp) 
+{
+    int header_len = 12; /* header size, entire size, type */
+
+    if ( msg == NULL || lenp == NULL )
+        return ccErrBadParam;
+
+    header_len += msg->header_len;
+    *lenp = header_len;
+    return ccNoError;
+}
+
+/**
+ * cci_msg_calc_size()
+ *
+ * Purpose: Calculates the size of the message
+ *          (does not include the magic bytes)
+ *
+ * Return:  the size in bytes
+ *
+ * Errors:  ccErrBadParam
+ *
+ */
+cc_int32 
+cci_msg_calc_size(cc_msg_t* msg, cc_uint32 * lenp) 
+{
+    cc_uint32 flat_len;
+    cc_generic_list_node_t* gen_node;
+    cc_generic_iterate_t* gen_iterator;
+       cc_int32 code;
+
+    if ( msg == NULL || lenp == NULL ) 
+        return ccErrBadParam;
+
+    code = cci_msg_calc_header_size(msg, &flat_len);
+    if (code != ccNoError)
+        goto bad;
+
+    code = cci_generic_list_iterator(msg->data_blobs, &gen_iterator);
+    if ( code != ccNoError )
+        goto bad;
+
+    while (cci_generic_iterate_has_next(gen_iterator)) {
+        code = cci_generic_iterate_next(gen_iterator, &gen_node);
+        if (code != ccNoError)
+            break;
+        flat_len += gen_node->len + BLOB_LEN;
+    }
+    cci_generic_free_iterator(gen_iterator);
+    if (code != ccNoError)
+        goto bad;
+
+    flat_len += MAGIC_HEAD_LEN + MAGIC_DATA_LEN;
+    *lenp = flat_len;
+
+  bad:
+    return code;
+}
+
+/**
+ * cci_msg_add_data_blob()
+ *
+ * Purpose: Adds 'len' bytes of data to the msg
+ *
+ * Return: 
+ *
+ * Errors: 
+ *
+ */
+cc_int32 
+cci_msg_add_data_blob(cc_msg_t* msg, void *data, cc_uint32 len, cc_uint32 *lenp) 
+{
+    cc_int32 code;
+
+    if (msg == NULL || data == NULL || len <= 0 || lenp == NULL)
+        return ccErrBadParam;
+
+    code = cci_generic_list_append(msg->data_blobs, data, len, NULL);
+    if ( code != ccNoError )
+        return code;
+    return cci_msg_calc_blob_pos(msg, data, len, lenp);
+}
+
+/**
+ * cc_msg_
+ *
+ * Purpose:
+ *
+ * Return: 
+ *
+ * Errors: 
+ *
+ */
+cc_int32 
+cci_msg_calc_blob_pos(cc_msg_t* msg, void *data, cc_uint32 len, cc_uint32 * posp) 
+{
+    cc_uint32 pos;
+    cc_generic_list_node_t* gen_node;
+    cc_generic_iterate_t* gen_iterator;
+    cc_int32 code;
+
+    code = cci_msg_calc_header_size(msg, &pos);
+    pos += sizeof(cc_uint32); /*+ sizeof(cc_uint32) for magic*/
+
+    code = cci_generic_list_iterator(msg->data_blobs, &gen_iterator);
+    while (cci_generic_iterate_has_next(gen_iterator)) {
+        code = cci_generic_iterate_next(gen_iterator, &gen_node);
+        if (gen_node->len != len && gen_node->data != data) {
+            pos += gen_node->len + sizeof(cc_uint32);
+        } else {
+            cci_generic_free_iterator(gen_iterator);
+            *posp = pos + sizeof(cc_uint32);
+            return ccNoError;
+        }
+    }
+    
+    cci_generic_free_iterator(gen_iterator);
+    return ccIteratorEnd;
+}
+
+/**
+ * cc_msg_
+ *
+ * Purpose:
+ *
+ * Return: 
+ *
+ * Errors: 
+ *
+ */
+cc_int32 
+cci_msg_add_header(cc_msg_t* msg, void *header, cc_uint32 header_len) 
+{
+    if ( msg == NULL || header == NULL )
+        return ccErrBadParam;
+
+    msg->header = header;
+    msg->header_len = header_len;
+    return ccNoError;
+}
+
+
+/**
+ * cc_msg_
+ *
+ * Purpose:
+ *
+ * Return: 
+ *
+ * Errors: 
+ *
+ */
+cc_int32
+cci_msg_flatten(cc_msg_t* msg, void **flatpp) 
+{
+    cc_generic_list_node_t* gen_node;
+    cc_generic_iterate_t* gen_iterator;
+    unsigned char *cur_pos;
+    cc_uint32 zero = 0;
+    cc_uint32 magic = 0;
+    cc_uint32 msg_len;
+    cc_uint32 u32;
+    cc_int32 code;
+
+    if (msg == NULL)
+        return ccErrBadParam;
+
+    code = cci_msg_calc_size(msg,&msg->flat_len);
+    if ( code != ccNoError )
+        return code;
+
+    if (msg->flat_len > CC_MSG_MAX_SIZE)
+        return ccErrBadParam;
+
+    msg->flat = (void *)malloc(msg->flat_len);
+    if (msg->flat == NULL)
+        return ccErrNoMem;
+    
+    cur_pos = msg->flat;
+
+    u32 = htonl(msg->header_len);
+    memcpy(cur_pos,&u32,sizeof(cc_uint32));
+    cur_pos+=sizeof(cc_uint32);
+
+    u32 = htonl(msg->flat_len);
+    memcpy(cur_pos,&u32,sizeof(cc_uint32));
+    cur_pos+=sizeof(cc_uint32);
+
+    u32 = htonl(msg->type);
+    memcpy(cur_pos,&u32,sizeof(cc_uint32));
+    cur_pos+=sizeof(cc_uint32);
+
+    /* header data is already in network order */
+    memcpy(cur_pos, msg->header, msg->header_len);
+    cur_pos += msg->header_len;
+
+    u32 = htonl(zero);
+    memcpy(cur_pos, &u32, sizeof(cc_uint32)); /*will be magic number later*/
+    cur_pos += sizeof(cc_uint32);
+
+    code = cci_generic_list_iterator(msg->data_blobs, &gen_iterator);
+    if ( code != ccNoError ) {
+        free(msg->flat);
+        return code;
+    }
+
+    while (cci_generic_iterate_has_next(gen_iterator)) {
+        code = cci_generic_iterate_next(gen_iterator, &gen_node);
+        if (code != ccNoError) {
+            free(gen_iterator);
+            free(msg->flat);
+            return code;
+        }
+       u32 = htonl(gen_node->len);
+           memcpy(cur_pos, &u32, sizeof(cc_uint32));
+        cur_pos+=sizeof(cc_uint32);
+               
+       /* data already in network order */
+        memcpy(cur_pos, gen_node->data, gen_node->len);
+        cur_pos += gen_node->len;
+    }
+    free(gen_iterator);
+
+    u32 = htonl(zero);
+    memcpy(cur_pos, &u32, sizeof(cc_uint32)); /*magic number will go here later*/
+    cur_pos += sizeof(cc_uint32);
+
+    if (cur_pos - (unsigned char *)msg->flat != msg->flat_len) {
+        fprintf(stderr, "ERROR cur_pos - msg->flat = %d\n",msg->flat_len);
+    }
+
+    cci_msg_calc_magic(msg->flat, msg->flat_len, &magic);
+    printf("magic = %d\n",magic);
+       
+    cci_msg_calc_header_size(msg, &msg_len);
+    memcpy((char *)msg->flat + msg_len, &magic, sizeof(cc_uint32));
+    memcpy((char *)msg->flat + msg->flat_len - sizeof(cc_uint32), &magic, sizeof(cc_uint32));
+
+    if ( flatpp != NULL )
+        *flatpp = msg->flat;
+
+    return ccNoError;
+}
+
+/**
+ * cc_msg_
+ *
+ * Purpose:
+ *
+ * Return: 
+ *
+ * Errors: 
+ *
+ */
+cc_int32
+cci_msg_calc_magic(void *flat, cc_uint32 flat_len, cc_uint32 * magicp)
+{
+    cc_uint32 magic = 0;
+    cc_uint32 i;
+       
+    for (i = 0; i < flat_len; i += sizeof(cc_uint32)) {
+        magic = magic ^ *(int *)((char *)flat + i);
+    }
+    *magicp = htonl(magic);
+    return ccNoError;
+}
+
+/**
+ * cc_msg_
+ *
+ * Purpose:
+ *
+ * Return: 
+ *
+ * Errors: 
+ *
+ */
+cc_int32 
+cci_msg_verify(void *flat, cc_uint32 flat_len, cc_uint32 * validp)  
+{
+    cc_uint32 *magic1, *magic2;
+    cc_uint32 *pheader_len;
+    cc_uint32 header_len;
+    cc_uint32 *ptotal_len;
+    cc_uint32 total_len;
+    cc_uint32 *pblob_len;
+    cc_uint32 blob_len;
+    cc_uint32 *ptype;
+    cc_uint32 type;
+    cc_uint32 num_blobs = 0;
+    cc_uint32 zero = 0;
+    cc_uint32 msg_magic, msg_magic2;
+
+    if (flat == NULL || flat_len <= 0 || validp == NULL)
+        return ccErrBadParam;
+
+    pheader_len = flat;
+    ptotal_len = (cc_uint32 *)((char *)pheader_len + sizeof(cc_uint32));
+    ptype = (cc_uint32 *)((char *)ptotal_len + sizeof(cc_uint32));
+
+    header_len = ntohl(*pheader_len);
+    total_len = ntohl(*ptotal_len);
+    type = ntohl(*ptype);
+
+    if (total_len != flat_len) {
+        *validp = 0;
+        return ccNoError;
+    }
+    
+    if (header_len > flat_len) {
+        /*too weak. We could verify header_len against type spec header.*/
+        *validp = 0;
+        return ccNoError;
+    }
+    if (type > CC_MSG_MAX_TYPE) {
+        *validp = 0;
+        return ccNoError;
+    }
+
+    magic1 = (cc_uint32 *)((char *)ptype + sizeof(cc_uint32) + header_len); 
+    if ((char *)magic1 - (char *)flat == (flat_len - 8)) {
+        /*There are no data blobs*/
+        magic2 = (cc_uint32 *)((char *)magic1 + sizeof(cc_uint32));
+        num_blobs = 0;
+    } else {
+        pblob_len = (cc_uint32 *)((char *)magic1 + sizeof(cc_uint32));
+        num_blobs = 1;
+       blob_len = ntohl(*pblob_len);
+
+        while (blob_len + sizeof(cc_uint32) + ((char *)pblob_len - (char *)flat) < (flat_len - sizeof(cc_uint32))) {
+            pblob_len = (cc_uint32 *)((char *)pblob_len + blob_len + sizeof(cc_uint32));
+            num_blobs++;
+           blob_len = ntohl(*pblob_len);
+        }
+
+        if (blob_len + sizeof(cc_uint32) + ((char *)pblob_len - (char *)flat) != (flat_len - sizeof(cc_uint32))) {
+            /*blobs didn't line up*/
+            *validp = 0;
+            return ccNoError;
+        }
+        magic2 = (cc_uint32 *)((char *)pblob_len + blob_len + sizeof(cc_uint32)); /*2nd magic should be directly after the last blob*/
+    }
+       
+    if (*magic1 != *magic2) {
+        *validp = 0;
+        return ccNoError;
+    }
+    msg_magic = *magic1;
+
+    printf("%d %d\n", (char *)magic1 - (char *)flat, (char *)magic2 - (char *)flat);
+
+    memcpy(magic1, &zero, sizeof(cc_uint32));
+    memcpy(magic2, &zero, sizeof(cc_uint32));
+    cci_msg_calc_magic(flat, flat_len, &msg_magic2);
+    /* both msg_magic and msg_magic2 are in network order */
+    if (msg_magic != msg_magic2) {
+        *validp = 0;
+        return ccNoError;
+    }
+    memcpy(magic1, &msg_magic, sizeof(cc_uint32));
+    memcpy(magic2, &msg_magic, sizeof(cc_uint32));
+
+    *validp = 1;
+    return ccNoError;
+}
+
+/**
+ * cc_msg_
+ *
+ * Purpose:
+ *
+ * Return: 
+ *
+ * Errors: 
+ *
+ */
+cc_int32
+cci_msg_unflatten(void *flat, cc_uint32 flat_len, cc_msg_t** msgpp) 
+{
+    cc_msg_t* msg;
+    char *cur_pos;
+    cc_uint32 blob_len;
+    char *blob;
+    cc_uint32 valid;
+    cc_int32 code;
+
+    if ( flat == NULL || flat_len <= 0 || msgpp == NULL )
+        return ccErrBadParam;
+
+    code = cci_msg_new(0, &msg);
+    if (code)
+        return code;
+
+    cci_msg_verify(flat, flat_len, &valid);
+    if (valid != 1) {
+        cci_msg_destroy(msg);
+        return ccErrBadParam;
+    }
+
+    cur_pos = flat;
+    msg->flat = flat;
+
+    msg->header_len = ntohl(*(cc_uint32 *)cur_pos);
+    cur_pos += sizeof(cc_uint32);
+
+    msg->flat_len = ntohl(*(cc_uint32 *)cur_pos);
+    cur_pos += sizeof(cc_uint32);
+
+    msg->type = ntohl(*(cc_uint32 *)cur_pos);
+    cur_pos += sizeof(cc_uint32);
+
+    msg->header = (void *)malloc(msg->header_len);
+    if (msg->header == NULL) {
+        cci_msg_destroy(msg);
+        return ccErrNoMem;
+    }
+    memcpy(msg->header, cur_pos, msg->header_len);
+    cur_pos += msg->header_len;
+       
+    msg->magic = ntohl(*(cc_uint32 *)cur_pos);
+    cur_pos += sizeof(cc_uint32);
+
+    if (cur_pos - (char *)flat != flat_len - 8) { /*at least 1 blob*/
+        blob_len = ntohl(*(cc_uint32 *)cur_pos);
+        while (blob_len + (cur_pos - (char *)flat) + sizeof(cc_uint32) <= flat_len - sizeof(cc_uint32)) {
+            blob = (void *)malloc(blob_len);
+            if (blob == NULL) {
+                cci_msg_destroy(msg);
+                return ccErrNoMem;
+            }
+            memcpy(blob, cur_pos + sizeof(cc_uint32), blob_len);
+            cci_generic_list_append(msg->data_blobs, blob, blob_len, NULL);
+
+            cur_pos += sizeof(cc_uint32) + blob_len;
+            blob_len = ntohl(*(int *)cur_pos);
+        }
+    }
+    *msgpp = msg;
+    return ccNoError;
+}
+
+cc_int32
+cci_msg_retrieve_blob(cc_msg_t* msg, cc_uint32 blob_offset, cc_uint32 blob_len, char **blobp) 
+{
+    cc_generic_iterate_t*      gen_iterator;
+    cc_generic_list_node_t*    gen_node;
+    void *ret;
+    cc_uint32                   blob_pos;
+    cc_int32                    code;
+
+    /*Ensure that the message has been unflattened*/
+    if ( msg == NULL || msg->flat == NULL || blob_offset > msg->flat_len || 
+         blob_len > msg->flat_len - blob_offset || blobp == NULL)
+        return ccErrBadParam;
+
+    code = cci_generic_list_iterator(msg->data_blobs, &gen_iterator);
+    while (cci_generic_iterate_has_next(gen_iterator)) {
+        code = cci_generic_iterate_next(gen_iterator, &gen_node);
+        code = cci_msg_calc_blob_pos(msg, gen_node->data, gen_node->len, &blob_pos);
+        if (blob_pos == blob_offset && gen_node->len == blob_len)  {
+            free(gen_iterator);
+            ret = (void *)malloc(blob_len);
+            if (ret == NULL)
+                return ccErrNoMem;
+            memcpy(ret,(char *)msg->flat + blob_offset, blob_len);     
+            *blobp = ret;
+            return ccNoError;
+        }
+    }
+    free(gen_iterator);
+    return ccIteratorEnd;
+}
+
+/**
+ * cc_msg_
+ *
+ * Purpose:
+ *
+ * Return: 
+ *
+ * Errors: 
+ *
+ */
+cc_int32 
+cci_msg_destroy(cc_msg_t* msg) 
+{
+    if (msg->flat != NULL) 
+        free(msg->flat);
+    if (msg->header != NULL)
+        free(msg->header);
+    cci_generic_list_destroy(msg->data_blobs);
+    free(msg);
+    return ccNoError;
+}
+