!INCLUDE <WIN32.MAK>
-CFLAGS = -I../include
+CFLAGS = -I../include $(cdebug) $(cflags) $(cvarsdll)
-CCAPI_OBJS = cacheapi.obj context.obj ccache.obj credentials.obj ccache_iterator.obj \
- credentials_iterator.obj ccstring.obj marshall.obj msg.obj
+CC_CLIENT_OBJS = cacheapi.obj context.obj ccache.obj credentials.obj ccache_iterator.obj \
+ credentials_iterator.obj ccstring.obj ccapiv2.obj
-CCAPI_LIB = ccapi.lib
+CC_CLIENT_LIB = cc_client.lib
-$(CCAPI_LIB): $(CCAPI_OBJS)
+CC_COMMON_LIB = ..\common\cc_common.lib
+
+$(CC_CLIENT_LIB): $(CC_CLIENT_OBJS)
$(implib) /NOLOGO /OUT:$@ $**
CCAPI_DLLFILE = krbcc32.dll
-$(CCAPI_DLLFILE): $(CCAPI_LIB)
- $(DLLGUILINK) -def:windows\krbcc32.def
- $(DLLPREP)
+WINLIBS = ws2_32.lib $(guilibsdll) msvcrt.lib
+
+$(CCAPI_DLLFILE): dllmain.obj $(CC_CLIENT_LIB) $(CC_COMMON_LIB)
+ $(link) /OUT:$@ $(ldebug) $(dlllflags) /NODEFAULTLIB:libcmt.lib -def:cacheapi.def $** $(WINLIBS)
all: $(CCAPI_DLLFILE)
clean:
- del *.obj *.lib
+ del *.obj *.lib *.dll *.exp
} else if (type == ccmsg_ACK) {
response_header = (ccmsg_init_resp_t *)response->header;
*outSupportedVersion = ntohl(response_header->out_version);
- code = cc_int_context_new(outContext, ntohl(response_header->out_ctx), ntohl(response_header->out_version));
+ code = cc_int_context_new(outContext, ntohll(response_header->out_ctx), ntohl(response_header->out_version));
if (!vendor[0]) {
char * string;
#include <stdio.h>
#include <CredentialsCache.h>
#include "credentials.h"
+#include "credentials_iterator.h"
#include "ccache.h"
#include "cc_rpc.h"
#include "msg.h"
#include "msg_headers.h"
+#include "ccstring.h"
/*
* cc_int_ccache_new
code = cci_msg_retrieve_blob(response, response_header->name_offset,
response_header->name_len, &string);
if (code == ccNoError) {
- code = cc_string_new(&name, string);
+ code = cci_string_new(name, string);
free(string);
}
} else {
code = cci_msg_retrieve_blob(response, response_header->principal_offset,
response_header->principal_len, &string);
if (code == ccNoError) {
- code = cc_string_new(&principal, string);
+ code = cci_string_new(principal, string);
free(string);
}
} else {
code = ntohl(nack_header->err_code);
} else if (response->type == ccmsg_ACK) {
ccmsg_ccache_get_kdc_time_offset_resp_t * response_header = (ccmsg_ccache_get_kdc_time_offset_resp_t*)response->header;
- *time_offset = ntohll(response_header->offset);
+ *time_offset = (cc_time64)ntohll(response_header->offset);
code = ccNoError;
} else {
code = ccErrBadInternalMessage;
#include <stdlib.h>
#include <stdio.h>
#include <CredentialsCache.h>
+#include "ccache.h"
#include "ccache_iterator.h"
#include "cc_rpc.h"
#include "msg.h"
\r
CCACHE_API cc_int32 cc_get_change_time (\r
apiCB* inContext,\r
- cc_time_t* outTime)\r
+ cc_time* outTime)\r
{\r
\r
/* replace this return value when the function is implemented */\r
return CC_NOT_SUPP;\r
}\r
\r
+CCACHE_API cc_int32 cc_lock_request(\r
+ apiCB* inContext,\r
+ const ccache_p* inCCache,\r
+ const cc_int32 lock_type)\r
+{\r
+ /* replace this return value when the function is implemented */\r
+ return CC_NOT_SUPP;\r
+}\r
+\r
\r
#ifdef __cplusplus\r
}\r
#include "ccstring.h"
cc_int32
-cc_int_string_new( cc_string_t * pstring, char * data )
+cci_string_new( cc_string_t * pstring, char * data )
{
- cc_int_string_t string = (cc_int_string_t)malloc(sizeof(cc_int_string_d));
+ cci_string_t string = (cci_string_t)malloc(sizeof(cci_string_d));
if ( string == NULL )
return ccErrNoMem;
}
string->magic = CC_STRING_MAGIC;
- string->functions->release = cc_int_string_release;
+ string->functions->release = cci_string_release;
string->data = strdup(data);
if ( string->data == NULL ) {
}
cc_int32
-cc_int_string_release( cc_string_t str )
+cci_string_release( cc_string_t str )
{
- cc_int_string_t int_string;
+ cci_string_t int_string;
if ( str == NULL )
return ccErrBadParam;
- int_string = (cc_int_string_t)str;
+ int_string = (cci_string_t)str;
if ( int_string->magic != CC_STRING_MAGIC )
return ccErrInvalidString;
#define CC_STRING_MAGIC ('S'<<24 | 'T'<<16 | 'R'<<8 | 'I')
-struct cc_int_string_d {
+struct cci_string_d {
char* data;
cc_string_f* functions;
#if TARGET_OS_MAC
#endif
cc_uint32 magic;
};
-typedef struct cc_int_string_d cc_int_string_d;
-typedef cc_int_string_d* cc_int_string_t;
+typedef struct cci_string_d cci_string_d;
+typedef cci_string_d* cci_string_t;
cc_int32
-cc_int_string_new( cc_string_t * pstring, char * data );
+cci_string_new( cc_string_t * pstring, char * data );
cc_int32
-cc_int_string_release( cc_string_t string );
+cci_string_release( cc_string_t string );
#include <stdio.h>
#include <CredentialsCache.h>
#include "context.h"
+#include "ccache.h"
+#include "ccache_iterator.h"
#include "cc_rpc.h"
#include "msg.h"
#include "msg_headers.h"
+#include "ccstring.h"
/* cc_int_context_new
*
ccmsg_ctx_release_t *request_header;
cc_msg_t *response;
cc_uint32 type;
- cc_time64 t64;
cc_int32 code;
if ( context == NULL )
request_header = (ccmsg_ctx_release_t*)malloc(sizeof(ccmsg_ctx_release_t));
if (request_header == NULL)
return ccErrNoMem;
- request_header->ctx = htonl(int_context->handle);
+ request_header->ctx = htonll(int_context->handle);
code = cci_msg_new(ccmsg_CTX_RELEASE, &request);
if (code != ccNoError) {
code = cci_msg_retrieve_blob(response, response_header->name_offset,
response_header->name_len, &string);
if (code == ccNoError) {
- code = cc_string_new(&name, string);
+ code = cci_string_new(name, string);
free(string);
}
} else {
request_header = (ccmsg_ctx_compare_t*)malloc(sizeof(ccmsg_ctx_compare_t));
if (request_header == NULL)
return ccErrNoMem;
- request_header->ctx1 = htonl(int_context->handle);
- request_header->ctx2 = htonl(int_compare_to->handle);
+ request_header->ctx1 = htonll(int_context->handle);
+ request_header->ctx2 = htonll(int_compare_to->handle);
code = cci_msg_new(ccmsg_CTX_COMPARE, &request);
if (code != ccNoError) {
code = ntohl(nack_header->err_code);
} else if (type == ccmsg_ACK) {
response_header = (ccmsg_ccache_open_resp_t*)response->header;
- code = cc_int_cache_new(ccache, int_context->handle, ntohll(response_header->ccache));
+ code = cc_int_ccache_new(ccache, int_context->handle, ntohll(response_header->ccache));
} else {
code = ccErrBadInternalMessage;
}
code = ntohl(nack_header->err_code);
} else if (type == ccmsg_ACK) {
response_header = (ccmsg_ccache_open_resp_t*)response->header;
- code = cc_int_cache_new(ccache, int_context->handle, ntohll(response_header->ccache));
+ code = cc_int_ccache_new(ccache, int_context->handle, ntohll(response_header->ccache));
} else {
code = ccErrBadInternalMessage;
}
code = ntohl(nack_header->err_code);
} else if (type == ccmsg_ACK) {
response_header = (ccmsg_ccache_create_resp_t*)response->header;
- code = cc_int_cache_new(ccache, int_context->handle, ntohll(response_header->ccache));
+ code = cc_int_ccache_new(ccache, int_context->handle, ntohll(response_header->ccache));
} else {
code = ccErrBadInternalMessage;
}
code = ntohl(nack_header->err_code);
} else if (type == ccmsg_ACK) {
response_header = (ccmsg_ccache_create_resp_t*)response->header;
- code = cc_int_cache_new(ccache, int_context->handle, ntohll(response_header->ccache));
+ code = cc_int_ccache_new(ccache, int_context->handle, ntohll(response_header->ccache));
} else {
code = ccErrBadInternalMessage;
}
code = ntohl(nack_header->err_code);
} else if (type == ccmsg_ACK) {
response_header = (ccmsg_ccache_create_resp_t*)response-> header;
- code = cc_int_cache_new(ccache, int_context->handle, ntohll(response_header->ccache));
+ code = cc_int_ccache_new(ccache, int_context->handle, ntohll(response_header->ccache));
} else {
code = ccErrBadInternalMessage;
}
cc_int32* supportedVersion,
char const** vendor )
{
- cc_int_context_t int_context, new_context;
+ cc_int_context_t int_context;
static char vendor_st[128] = "";
cc_msg_t *request;
ccmsg_ctx_clone_t *request_header;
} else if (type == ccmsg_ACK) {
response_header = (ccmsg_ctx_clone_resp_t *)response->header;
*supportedVersion = ntohl(response_header->out_version);
- code = cc_int_context_new(outContext, ntohll(response_header->out_ctx), nthol(response_header->out_version));
+ code = cc_int_context_new(outContext, ntohll(response_header->out_ctx), ntohl(response_header->out_version));
if (!vendor_st[0]) {
char * string;
cc_int32* version )
{
cc_int_context_t int_context;
- cc_int32 code;
if ( context == NULL ||
version == NULL )
switch ( version ) {
case cc_credentials_v4:
- code = cci_cred_v4_unmarshall(data, len, credentials->data);
+ code = cci_creds_v4_unmarshall(data, len, credentials->data);
break;
case cc_credentials_v5:
- code = cci_cred_v5_unmarshall(data, len, credentials->data);
+ code = cci_creds_v5_unmarshall(data, len, credentials->data);
break;
default:
free(credentials);
#include <stdlib.h>
#include <stdio.h>
#include <CredentialsCache.h>
+#include "credentials.h"
#include "credentials_iterator.h"
#include "cc_rpc.h"
#include "msg.h"
--- /dev/null
+#include <windows.h>\r
+\r
+BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, \r
+ LPVOID lpvReserved)\r
+{\r
+ switch (fdwReason) {\r
+ case DLL_PROCESS_ATTACH:\r
+ case DLL_THREAD_ATTACH:\r
+ case DLL_THREAD_DETACH:\r
+ case DLL_PROCESS_DETACH:\r
+ default:\r
+ return TRUE;\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_uint32 length;\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_flat_data * flat_data;\r
- cc_time64 t64;\r
- cc_uint32 length;\r
- cc_int32 code;\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 = ntohll(t64);\r
- creds->lifetime = 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
- cc_int32 code;\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 = nothl(*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 = nothl(*(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