-/* $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;
+}
+
-/* $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;
+}
+