From: Alexandra Ellwood Date: Mon, 10 Jul 2006 18:51:23 +0000 (+0000) Subject: Fixed up warnings and converted to Unix line endings X-Git-Tag: krb5-1.6-alpha1~215 X-Git-Url: http://git.tremily.us/?a=commitdiff_plain;h=0eb148db5bbbaa4c741caa65d78f3e965105ce40;p=krb5.git Fixed up warnings and converted to Unix line endings git-svn-id: svn://anonsvn.mit.edu/krb5/trunk@18325 dc483132-0cff-0310-8789-dd5450dbe970 --- diff --git a/src/lib/ccapi/common/marshall.c b/src/lib/ccapi/common/marshall.c index 48abb3370..b2433cb1d 100644 --- a/src/lib/ccapi/common/marshall.c +++ b/src/lib/ccapi/common/marshall.c @@ -1,441 +1,441 @@ -/* $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 -#include -#include -#include -#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; -} - - -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; -} - -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; iaddresses[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; iauthdata[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: + * + * 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 +#include +#include +#include +#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; iaddresses[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; iauthdata[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; +} + diff --git a/src/lib/ccapi/common/msg.c b/src/lib/ccapi/common/msg.c index 789fc8746..fa051e95a 100644 --- a/src/lib/ccapi/common/msg.c +++ b/src/lib/ccapi/common/msg.c @@ -1,622 +1,622 @@ -/* $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: - * - * - * - * - * - * - * - * - * - * ... - * - * - * 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 -#include -#include -#include - -/** - * 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; - 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 - (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, int flat_len, cc_uint32 * magicp) -{ - cc_uint32 magic = 0; - int 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, int 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, int 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; -} - +/* $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: + * + * + * + * + * + * + * + * + * + * ... + * + * + * 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 +#include +#include +#include + +/** + * 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; +} +