--- /dev/null
+!INCLUDE <WIN32.MAK>\r
+\r
+CFLAGS = -I../include $(cdebug) $(cflags) $(cvarsdll)\r
+\r
+CC_COMMON_OBJS = marshall.obj msg.obj generic_lists.obj\r
+\r
+CC_COMMON_LIB = cc_common.lib\r
+\r
+$(CC_COMMON_LIB): $(CC_COMMON_OBJS)\r
+ $(implib) /NOLOGO /OUT:$@ $**\r
+\r
+all: $(CC_COMMON_LIB)\r
+\r
+clean:\r
+ del *.obj *.lib\r
--- /dev/null
+/* $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
+/*\r
+ * Lists implementation.\r
+ * \r
+ */\r
+\r
+#include <stdio.h>\r
+#include <stdlib.h>\r
+#include <memory.h>\r
+\r
+#include "CredentialsCache.h"\r
+#include "generic_lists.h"\r
+\r
+/* this is an incomplete enumeration just including the generic type */\r
+enum cc_list_type {\r
+ generic = 0\r
+};\r
+\r
+/**\r
+ * cci_generic_iterate_has_next()\r
+ *\r
+ * Purpose: Determine if an iterator has a next element\r
+ *\r
+ * Return: 1 if another element exists\r
+ * 0 if no additional elements exist\r
+ *\r
+ * Errors: None\r
+ *\r
+ */\r
+cc_int32 \r
+cci_generic_iterate_has_next(cc_generic_iterate_t *iterate) \r
+{\r
+ return ((iterate == NULL || iterate->next == NULL) ? 0 : 1);\r
+}\r
+\r
+/**\r
+ * cci_generic_iterate_next()\r
+ *\r
+ * Purpose: Retrieve the next element from an iterator and advance\r
+ * the iterator\r
+ *\r
+ * Return: non-NULL, the next element in the iterator\r
+ * NULL, the iterator list is empty or iterator is invalid\r
+ *\r
+ * Errors: ccErrBadParam\r
+ *\r
+ */\r
+cc_int32\r
+cci_generic_iterate_next(cc_generic_iterate_t *iterator, cc_generic_list_node_t** nodepp) \r
+{\r
+ cc_generic_list_node_t* ret;\r
+ \r
+ if (iterator == NULL || nodepp == NULL)\r
+ return ccErrBadParam;\r
+\r
+ ret = iterator->next;\r
+ if (iterator->next != NULL)\r
+ iterator->next = iterator->next->next;\r
+\r
+ *nodepp = ret;\r
+ return ccNoError;\r
+}\r
+\r
+/**\r
+ * cci_generic_list_new()\r
+ *\r
+ * Purpose: Allocate new generic list\r
+ *\r
+ * Return: non-NULL, an empty list\r
+ * NULL, failure\r
+ *\r
+ * Errors: ccErrNoMem\r
+ *\r
+ */\r
+cc_int32\r
+cci_generic_list_new(cc_generic_list_head_t ** listpp) \r
+{\r
+ cc_generic_list_head_t* ret = (cc_generic_list_head_t *)malloc(sizeof(cc_generic_list_head_t));\r
+ if (ret == NULL)\r
+ return ccErrNoMem;\r
+ \r
+ ret->type = generic;\r
+ ret->head = ret->tail = NULL;\r
+ *listpp = ret;\r
+\r
+ return ccNoError;\r
+}\r
+\r
+/**\r
+ * cci_generic_list_append()\r
+ *\r
+ * Purpose: Appends a new node containing a copy of 'len' bytes of 'data' \r
+ *\r
+ * Return: non-NULL, a pointer to the newly allocated node\r
+ * NULL, failure\r
+ *\r
+ * Errors: ccErrNoMem,ccErrBadParam\r
+ *\r
+ */\r
+cc_int32\r
+cci_generic_list_append(cc_generic_list_head_t *head, void *data, cc_uint32 len, cc_generic_list_node_t** nodepp) \r
+{\r
+ cc_generic_list_node_t* new_node;\r
+\r
+ if ( data == NULL || len == 0 )\r
+ return ccErrBadParam;\r
+\r
+ new_node = (cc_generic_list_node_t *)malloc(sizeof(cc_generic_list_node_t));\r
+ if (new_node == NULL)\r
+ return ccErrNoMem;\r
+\r
+ new_node->data = malloc(len);\r
+ if ( new_node->data == NULL ) {\r
+ free(new_node);\r
+ return ccErrNoMem; \r
+ }\r
+ \r
+ memcpy(new_node->data,data,len);\r
+ new_node->len = len;\r
+\r
+ if (head->head == NULL) { /*empty list*/\r
+ head->head = new_node;\r
+ head->tail = new_node;\r
+ new_node->next = new_node->prev = NULL;\r
+ } else {\r
+ new_node->prev = head->tail;\r
+ head->tail->next = new_node;\r
+ head->tail = new_node;\r
+ new_node->next = NULL;\r
+ }\r
+ if (nodepp != NULL)\r
+ *nodepp = new_node;\r
+ return ccNoError;\r
+}\r
+\r
+/**\r
+ * cci_generic_list_prepend()\r
+ *\r
+ * Purpose: Prepends a new node containing a copy of 'len' bytes of 'data'\r
+ *\r
+ * Return: non-NULL, a pointer to the newly allocated node\r
+ * NULL, failure\r
+ *\r
+ * Errors: ccErrNoMem, ccErrBadParam\r
+ *\r
+ */\r
+cc_int32 \r
+cci_generic_list_prepend(cc_generic_list_head_t *head, void *data, cc_uint32 len, cc_generic_list_node_t** nodepp) \r
+{\r
+ cc_generic_list_node_t* new_node;\r
+\r
+ if ( data == NULL || len == 0 )\r
+ return ccErrBadParam;\r
+\r
+ new_node = (cc_generic_list_node_t *)malloc(sizeof(cc_generic_list_node_t));\r
+ if (new_node == NULL)\r
+ return ccErrNoMem;\r
+\r
+ new_node->data = malloc(len);\r
+ if ( new_node->data == NULL ) {\r
+ free(new_node);\r
+ return ccErrNoMem;\r
+ }\r
+ \r
+ memcpy(new_node->data,data,len);\r
+ new_node->len = len;\r
+ \r
+ if (head->head == NULL) { /*empty list*/\r
+ head->head = new_node;\r
+ head->tail = new_node;\r
+ new_node->prev = new_node->next = NULL;\r
+ } else {\r
+ new_node->next = head->head;\r
+ head->head->prev = new_node;\r
+ new_node->prev = NULL;\r
+ head->head = new_node;\r
+ }\r
+\r
+ if (nodepp != NULL)\r
+ *nodepp = new_node;\r
+\r
+ return ccNoError;\r
+}\r
+\r
+/**\r
+ * cci_generic_list_remove_element()\r
+ *\r
+ * Purpose: Remove a node from the list\r
+ *\r
+ * Return: 0, success\r
+ * -1, failure\r
+ *\r
+ * Errors: ccErrBadParam\r
+ *\r
+ */\r
+cc_int32 \r
+cci_generic_list_remove_element(cc_generic_list_head_t* head, cc_generic_list_node_t* rem) \r
+{\r
+ if (head->head == NULL || rem == NULL)\r
+ return ccErrBadParam;\r
+\r
+ if (head->head == rem && head->tail == rem) { /*removing only element of list*/\r
+ head->head = head->tail = NULL;\r
+ } else if (head->head == rem) { /*removing head*/\r
+ head->head = head->head->next;\r
+ } else if (head->tail == rem) { /*removing tail*/\r
+ head->tail = head->tail->prev;\r
+ head->tail->next = NULL;\r
+ } else {\r
+ rem->prev->next = rem->next;\r
+ rem->next->prev = rem->prev;\r
+ }\r
+ free(rem);\r
+ return ccNoError;\r
+}\r
+\r
+/**\r
+ * cci_generic_free_element()\r
+ *\r
+ * Purpose: Free the memory associated with a node\r
+ *\r
+ * Return: 0, success\r
+ * -1, failure\r
+ *\r
+ * Errors: ccErrBadParam\r
+ *\r
+ */\r
+cc_int32\r
+cci_generic_free_element(cc_generic_list_node_t* node)\r
+{\r
+ if ( node == NULL )\r
+ return ccErrBadParam;\r
+\r
+ if ( node->data ) {\r
+ free(node->data);\r
+ node->data = NULL;\r
+ }\r
+ node->len = 0;\r
+ node->next = node->prev = NULL;\r
+ free(node);\r
+ return ccNoError;\r
+}\r
+\r
+\r
+/**\r
+ * cci_generic_list_destroy()\r
+ *\r
+ * Purpose: Deallocate a list and all of its contents\r
+ *\r
+ * Return: 0, success\r
+ * -1, failure\r
+ *\r
+ * Errors: ccErrBadParam\r
+ */\r
+cc_int32\r
+cci_generic_list_destroy(cc_generic_list_head_t* head) \r
+{\r
+ cc_generic_list_node_t *cur, *next;\r
+ cc_int32 ret = ccNoError;\r
+\r
+ if ( head == NULL )\r
+ return ccErrBadParam;\r
+ \r
+ for (cur = head->head; ret == ccNoError && cur != NULL; cur = next) {\r
+ next = cur->next;\r
+ ret = cci_generic_free_element(cur);\r
+ } \r
+ free(head);\r
+ return(ret);\r
+}\r
+\r
+/**\r
+ * cci_generic_list_copy()\r
+ *\r
+ * Purpose: Copy a list\r
+ *\r
+ * Return: non-NULL, a new list\r
+ * NULL, failure\r
+ *\r
+ * Errors: ccErrBadParam, ccErrNoMem\r
+ *\r
+ */\r
+cc_int32\r
+cci_generic_list_copy(cc_generic_list_head_t* head, cc_generic_list_head_t** headpp) \r
+{\r
+ cc_generic_list_head_t* copy;\r
+ cc_generic_list_node_t *src_node, *dst_node;\r
+ cc_int32 code;\r
+\r
+ if (head == NULL || headpp == NULL)\r
+ return ccErrBadParam;\r
+\r
+ code = cci_generic_list_new(©);\r
+ if (code != ccNoError)\r
+ return code;\r
+\r
+ for (src_node = head->head; src_node != NULL; src_node = src_node->next) {\r
+ code = cci_generic_list_append(copy, src_node->data, src_node->len, &dst_node);\r
+ if (code != ccNoError) {\r
+ cci_generic_list_destroy(copy);\r
+ return code;\r
+ }\r
+ }\r
+ *headpp = copy;\r
+ return ccNoError;\r
+}\r
+\r
+/**\r
+ * cci_generic_list_iterator()\r
+ *\r
+ * Purpose: Allocate an iterator for the specified list\r
+ *\r
+ * Return: non-NULL, an iterator\r
+ * NULL, failure\r
+ *\r
+ * Errors: ccErrNoMem\r
+ *\r
+ */\r
+cc_int32\r
+cci_generic_list_iterator(cc_generic_list_head_t *head, cc_generic_iterate_t** headpp) \r
+{\r
+ cc_generic_iterate_t* iterator;\r
+\r
+ if ( head == NULL || headpp == NULL )\r
+ return ccErrBadParam;\r
+\r
+ iterator = (cc_generic_iterate_t*)malloc(sizeof(cc_generic_iterate_t));\r
+ if (iterator == NULL)\r
+ return ccErrNoMem;\r
+ \r
+ iterator->next = head->head;\r
+ *headpp = iterator;\r
+ return ccNoError;\r
+}\r
+\r
+/**\r
+ * cci_generic_free_iterator()\r
+ *\r
+ * Purpose: Deallocate memory associated with an iterator\r
+ *\r
+ * Return: 0, success\r
+ * -1, failure\r
+ *\r
+ * Errors: ccErrBadParam\r
+ *\r
+ */\r
+cc_int32\r
+cci_generic_free_iterator(cc_generic_iterate_t* iterator)\r
+{\r
+ if ( iterator == NULL )\r
+ return ccErrBadParam;\r
+\r
+ iterator->next = NULL;\r
+ free(iterator);\r
+ return ccNoError;\r
+}\r
+\r
+\r
+\r
--- /dev/null
+/* $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 <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
--- /dev/null
+/* $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 = htonl(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 || flatpp == 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 = msg->header_len;\r
+ htonl(u32);\r
+ memcpy(cur_pos,&u32,sizeof(cc_uint32));\r
+ cur_pos+=sizeof(cc_uint32);\r
+\r
+ u32 = msg->flat_len;\r
+ htonl(u32);\r
+ memcpy(cur_pos,&u32,sizeof(cc_uint32));\r
+ cur_pos+=sizeof(cc_uint32);\r
+\r
+ u32 = msg->type;\r
+ htonl(u32);\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 = zero;\r
+ 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 = gen_node->len;\r
+ htonl(u32);\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 = zero;\r
+ 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, void **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->flat);\r
+ cci_generic_list_destroy(msg->data_blobs);\r
+ free(msg);\r
+ return ccNoError;\r
+}\r
+\r