diff options
Diffstat (limited to 'src/lib/ccapi/server/serv_ops.c')
-rw-r--r-- | src/lib/ccapi/server/serv_ops.c | 1500 |
1 files changed, 1500 insertions, 0 deletions
diff --git a/src/lib/ccapi/server/serv_ops.c b/src/lib/ccapi/server/serv_ops.c new file mode 100644 index 000000000..30a108a34 --- /dev/null +++ b/src/lib/ccapi/server/serv_ops.c @@ -0,0 +1,1500 @@ +/* $Copyright: + * + * Copyright 2004 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). + * $ + */ + +/* + * Server side implementation of each API function. + */ + +#include "CredentialsCache.h" +#include "serv_ops.h" +#include "datastore.h" +#include "rpc_auth.h" +#include "msg_headers.h" + +#include <stdlib.h> +#include <string.h> + +cc_context_list_head_t* AllContexts = NULL; +type_to_op_mapping_t* TypeToOpMapping = NULL; + +extern int cc_err_code; +extern int cc_myversion; +extern char cc_vendor[]; + +cc_int32 +cci_serv_initialize(void) +{ + cc_int32 code; + + code = cci_context_list_new(&AllContexts); + if ( code != ccNoError ) + return code; + TypeToOpMapping = (type_to_op_mapping_t*)malloc(sizeof(type_to_op_mapping_t)); + if (TypeToOpMapping == NULL) { + cci_context_list_destroy(AllContexts); + return ccErrNoMem; + } + + TypeToOpMapping->operations[ccmsg_INIT] = ccop_INIT; + TypeToOpMapping->operations[ccmsg_CTX_RELEASE] = ccop_CTX_RELEASE; + TypeToOpMapping->operations[ccmsg_CTX_GET_CHANGE_TIME] = ccop_CTX_GET_CHANGE_TIME; + TypeToOpMapping->operations[ccmsg_CTX_GET_DEFAULT_CCACHE_NAME] = ccop_CTX_GET_DEFAULT_CCACHE_NAME; + TypeToOpMapping->operations[ccmsg_CTX_COMPARE] = ccop_CTX_COMPARE; + TypeToOpMapping->operations[ccmsg_CTX_NEW_CCACHE_ITERATOR] = ccop_CTX_NEW_CCACHE_ITERATOR; + TypeToOpMapping->operations[ccmsg_CTX_LOCK] = ccop_CTX_LOCK; + TypeToOpMapping->operations[ccmsg_CTX_UNLOCK] = ccop_CTX_UNLOCK; + TypeToOpMapping->operations[ccmsg_CTX_CLONE] = ccop_CTX_CLONE; + TypeToOpMapping->operations[ccmsg_CCACHE_OPEN] = ccop_CCACHE_OPEN; + TypeToOpMapping->operations[ccmsg_CCACHE_OPEN_DEFAULT] = ccop_CCACHE_OPEN_DEFAULT; + TypeToOpMapping->operations[ccmsg_CCACHE_CREATE] = ccop_CCACHE_CREATE; + TypeToOpMapping->operations[ccmsg_CCACHE_CREATE_DEFAULT] = ccop_CCACHE_CREATE_DEFAULT; + TypeToOpMapping->operations[ccmsg_CCACHE_CREATE_UNIQUE] = ccop_CCACHE_CREATE_UNIQUE; + TypeToOpMapping->operations[ccmsg_CCACHE_RELEASE] = ccop_CCACHE_RELEASE; + TypeToOpMapping->operations[ccmsg_CCACHE_DESTROY] = ccop_CCACHE_DESTROY; + TypeToOpMapping->operations[ccmsg_CCACHE_SET_DEFAULT] = ccop_CCACHE_SET_DEFAULT; + TypeToOpMapping->operations[ccmsg_CCACHE_GET_CREDS_VERSION] = ccop_CCACHE_GET_CREDS_VERSION; + TypeToOpMapping->operations[ccmsg_CCACHE_GET_NAME] = ccop_CCACHE_GET_NAME; + TypeToOpMapping->operations[ccmsg_CCACHE_GET_PRINCIPAL] = ccop_CCACHE_GET_PRINCIPAL; + TypeToOpMapping->operations[ccmsg_CCACHE_SET_PRINCIPAL] = ccop_CCACHE_SET_PRINCIPAL; + TypeToOpMapping->operations[ccmsg_CCACHE_CREDS_ITERATOR] = ccop_CCACHE_CREDS_ITERATOR; + TypeToOpMapping->operations[ccmsg_CCACHE_STORE_CREDS] = ccop_CCACHE_STORE_CREDS; + TypeToOpMapping->operations[ccmsg_CCACHE_REM_CREDS] = ccop_CCACHE_REM_CREDS; + TypeToOpMapping->operations[ccmsg_CCACHE_GET_LAST_DEFAULT_TIME] = ccop_CCACHE_GET_LAST_DEFAULT_TIME; + TypeToOpMapping->operations[ccmsg_CCACHE_GET_CHANGE_TIME] = ccop_CCACHE_GET_CHANGE_TIME; + TypeToOpMapping->operations[ccmsg_CCACHE_COMPARE] = ccop_CCACHE_COMPARE; + TypeToOpMapping->operations[ccmsg_CCACHE_GET_KDC_TIME_OFFSET] = ccop_CCACHE_GET_KDC_TIME_OFFSET; + TypeToOpMapping->operations[ccmsg_CCACHE_SET_KDC_TIME_OFFSET] = ccop_CCACHE_SET_KDC_TIME_OFFSET; + TypeToOpMapping->operations[ccmsg_CCACHE_CLEAR_KDC_TIME_OFFSET] = ccop_CCACHE_CLEAR_KDC_TIME_OFFSET; + TypeToOpMapping->operations[ccmsg_CCACHE_ITERATOR_RELEASE] = ccop_CCACHE_ITERATOR_RELEASE; + TypeToOpMapping->operations[ccmsg_CCACHE_ITERATOR_NEXT] = ccop_CCACHE_ITERATOR_NEXT; + TypeToOpMapping->operations[ccmsg_CREDS_ITERATOR_RELEASE] = ccop_CREDS_ITERATOR_RELEASE; + TypeToOpMapping->operations[ccmsg_CREDS_ITERATOR_NEXT] = ccop_CREDS_ITERATOR_NEXT; + TypeToOpMapping->operations[ccmsg_CREDS_RELEASE] = ccop_CREDS_RELEASE; + + return ccNoError; +}; + +cc_int32 +cci_serv_process_msg(cc_msg_t * msg, cc_auth_info_t* auth_info, cc_session_info_t* session_info, cc_msg_t** resp_msg) +{ + cc_server_context_t* ctx; + ccmsg_ctx_only_t* header = (ccmsg_ctx_only_t *)msg->header; + cc_int32 code; + + if (msg == NULL || msg->header == NULL || auth_info == NULL || session_info == NULL) + return ccErrBadParam; + + if (AllContexts == NULL) { + code = cci_serv_initialize(); + if ( code != ccNoError ) + return code; + } + + if (msg->type == ccmsg_INIT) { + return TypeToOpMapping->operations[msg->type] (NULL, auth_info, session_info, msg, resp_msg); + } else { + if (msg->header_len < sizeof(ccmsg_ctx_only_t)) { + return ccErrBadParam; + } + + code = cci_serv_find_ctx_by_handle(header->ctx, auth_info, session_info, &ctx); + if (code != ccNoError) { + cci_serv_make_nack(ccErrContextNotFound, auth_info, session_info, resp_msg); + return code; + } + return TypeToOpMapping->operations[msg->type] (ctx, auth_info, session_info, msg, resp_msg); + } +} + +/*deprecated*/ +cc_int32 +cci_serv_find_ctx(cc_auth_info_t* auth_info, cc_session_info_t* session_info, + cc_server_context_t** ctxpp) +{ + cc_context_iterate_t* ctx_iterator; + cc_context_list_node_t* ctx_node; + cc_server_context_t* ctx; + cc_int32 code; + cc_uint32 authorized; + + code = cci_context_list_iterator(AllContexts, &ctx_iterator); + if (code != ccNoError) + return code; + + while (cci_context_iterate_has_next(ctx_iterator)) { + code = cci_context_iterate_next(ctx_iterator, &ctx_node); + if (code != ccNoError) { + cci_context_free_iterator(ctx_iterator); + return code; + } + ctx = (cc_server_context_t *)ctx_node->data; + code = cci_rpc_is_authorized(auth_info, session_info, ctx->auth_info, ctx->session_info, &authorized); + if (code != ccNoError) { + cci_context_free_iterator(ctx_iterator); + return code; + } + + if (authorized) { + cci_context_free_iterator(ctx_iterator); + *ctxpp = ctx; + return ccNoError; + } + } + cci_context_free_iterator(ctx_iterator); + return ccIteratorEnd; +} + +cc_int32 +cci_serv_find_ctx_by_handle(cc_handle ctx_num, cc_auth_info_t* auth, cc_session_info_t* session, cc_server_context_t** ctxpp) +{ + cc_server_context_t* input_ctx = (cc_server_context_t*)ctx_num; + cc_context_iterate_t* ctx_iterator; + cc_context_list_node_t* ctx_node; + cc_server_context_t* ctx; + cc_uint32 authorized; + cc_int32 code; + + code = cci_context_list_iterator(AllContexts, &ctx_iterator); + if (code != ccNoError) + return code; + + while (cci_context_iterate_has_next(ctx_iterator)) { + code = cci_context_iterate_next(ctx_iterator, &ctx_node); + ctx = (cc_server_context_t *)ctx_node->data; + if (code != ccNoError) { + cci_context_free_iterator(ctx_iterator); + return code; + } + + code = cci_rpc_is_authorized(auth, session, ctx->auth_info, ctx->session_info, &authorized); + if (code != ccNoError) { + cci_context_free_iterator(ctx_iterator); + return code; + } + + if (ctx == input_ctx && authorized) { + cci_context_free_iterator(ctx_iterator); + *ctxpp = ctx; + return ccNoError; + } + } + cci_context_free_iterator(ctx_iterator); + return ccIteratorEnd; +} + +cc_int32 +cci_serv_find_ccache_by_handle(cc_server_context_t* ctx, cc_handle ccache, cc_server_ccache_t** ccachepp ) +{ + cc_ccache_iterate_t* ccache_iterator; + cc_ccache_list_node_t* ccache_node; + cc_server_ccache_t* stored_ccache; + cc_server_ccache_t* target_ccache = (cc_server_ccache_t*)ccache; + cc_int32 code; + + code = cci_ccache_list_iterator(ctx->ccaches, &ccache_iterator); + if (code != ccNoError) + return code; + + while (cci_ccache_iterate_has_next(ccache_iterator)) { + code = cci_ccache_iterate_next(ccache_iterator, &ccache_node); + if (code != ccNoError) { + cci_ccache_free_iterator(ccache_iterator); + return code; + } + + stored_ccache = (cc_server_ccache_t *)ccache_node->data; + + if (stored_ccache == target_ccache) { + cci_ccache_free_iterator(ccache_iterator); + *ccachepp = stored_ccache; + return ccNoError; + } + } + cci_ccache_free_iterator(ccache_iterator); + return ccIteratorEnd; +} + +cc_int32 +cci_serv_find_ccache_iterator_by_handle(cc_server_context_t* ctx, cc_handle iterator, cc_generic_list_node_t** nodepp ) +{ + cc_generic_iterate_t* gen_iterator; + cc_generic_list_node_t* gen_node; + cc_ccache_iterate_t* stored_iterator; + cc_ccache_iterate_t* target_iterator = (cc_ccache_iterate_t*)iterator; + cc_int32 code; + + code = cci_generic_list_iterator(ctx->active_iterators, &gen_iterator); + if (code != ccNoError) + return code; + + while (cci_generic_iterate_has_next(gen_iterator)) { + code = cci_generic_iterate_next(gen_iterator, &gen_node); + if (code != ccNoError) { + cci_generic_free_iterator(gen_iterator); + return code; + } + + stored_iterator = (cc_ccache_iterate_t *)gen_node->data; + if (stored_iterator == target_iterator) { + cci_generic_free_iterator(gen_iterator); + *nodepp = gen_node; + return ccNoError; + } + } + cci_generic_free_iterator(gen_iterator); + return ccIteratorEnd; +} + +cc_int32 +cci_serv_find_creds_iterator_by_handle(cc_server_ccache_t* ccache, cc_handle iterator, cc_generic_list_node_t** nodepp) +{ + cc_generic_iterate_t* gen_iterator; + cc_generic_list_node_t* gen_node; + cc_ccache_iterate_t* stored_iterator; + cc_ccache_iterate_t* target_iterator = (cc_ccache_iterate_t*)iterator; + cc_int32 code; + + code = cci_generic_list_iterator(ccache->active_iterators, &gen_iterator); + if (code != ccNoError) + return code; + + while (cci_generic_iterate_has_next(gen_iterator)) { + code = cci_generic_iterate_next(gen_iterator, &gen_node); + if (code != ccNoError) { + cci_generic_free_iterator(gen_iterator); + return code; + } + + stored_iterator = (cc_ccache_iterate_t *)gen_node->data; + if (stored_iterator == target_iterator) { + cci_generic_free_iterator(gen_iterator); + *nodepp = gen_node; + return ccNoError; + } + } + cci_generic_free_iterator(gen_iterator); + return ccIteratorEnd; +} + +cc_int32 +cci_serv_make_nack(cc_int32 err_code, cc_auth_info_t* auth_info, cc_session_info_t* session_info, cc_msg_t** resp_msg) +{ + ccmsg_nack_t* nack_header; + cc_int32 code; + + code = cci_msg_new(ccmsg_NACK, resp_msg); + if (code != ccNoError) + return code; + + nack_header = (ccmsg_nack_t*)malloc(sizeof(ccmsg_nack_t)); + if (nack_header == NULL) { + cci_msg_destroy(*resp_msg); + *resp_msg = 0; + return ccErrNoMem; + } + + nack_header->err_code = err_code;; + code = cci_msg_add_header(*resp_msg, nack_header, sizeof(ccmsg_nack_t)); + if (code != ccNoError) { + cci_msg_destroy(*resp_msg); + *resp_msg = 0; + return code; + } + + return ccNoError; +} + +cc_int32 +cci_serv_make_ack(void * header, cc_int32 header_len, cc_auth_info_t* auth_info, cc_session_info_t* session_info, cc_msg_t** resp_msg) +{ + cc_int32 code; + + code = cci_msg_new(ccmsg_ACK, resp_msg); + if (code != ccNoError) + return code; + + if (header != NULL) { + code = cci_msg_add_header(*resp_msg, header, header_len); + if (code != ccNoError) { + cci_msg_destroy(*resp_msg); + resp_msg = 0; + return code; + } + } + return ccNoError; +} + +cc_int32 +ccop_INIT( cc_server_context_t* ctx, /* not used */ + cc_auth_info_t* auth_info, + cc_session_info_t* session_info, + cc_msg_t *msg, cc_msg_t **resp_msg) +{ + cc_uint32 blob_pos; + cc_server_context_t *new_ctx; + ccmsg_init_resp_t *resp_header; + ccmsg_init_t *header = (ccmsg_init_t *)msg->header; + cc_context_list_node_t* ctx_node; + cc_int32 code; + + *resp_msg = 0; + + if (msg->header_len != sizeof(ccmsg_init_t)) { + return ccErrBadParam; + } + + code = cci_context_new(header->in_version, auth_info, session_info, &new_ctx); + if (code != ccNoError) { + return code; + } + + code = cci_context_list_append(AllContexts, ctx, &ctx_node); + if (code != ccNoError) { + cci_context_destroy(new_ctx); + return code; + } + + resp_header = (ccmsg_init_resp_t*)malloc(sizeof(ccmsg_init_resp_t)); + if (resp_header == NULL) { + cci_context_destroy(new_ctx); + return ccErrNoMem; + } + + code = cci_msg_new(ccmsg_ACK, resp_msg); + if (code != ccNoError) { + free(resp_header); + cci_context_destroy(new_ctx); + return code; + } + code = cci_msg_add_data_blob(*resp_msg, cc_vendor, strlen(cc_vendor) + 1, &blob_pos); + if (code != ccNoError) { + free(resp_header); + cci_context_destroy(new_ctx); + cci_msg_destroy(*resp_msg); + *resp_msg = 0; + return code; + } + + resp_header->out_ctx = new_ctx; + resp_header->out_version = cc_myversion; + resp_header->vendor_offset = blob_pos; + resp_header->vendor_length = strlen(cc_vendor) + 1; + code = cci_msg_add_header(*resp_msg, resp_header, sizeof(ccmsg_init_resp_t)); + if (code != ccNoError) { + free(resp_header); + cci_context_destroy(new_ctx); + cci_msg_destroy(*resp_msg); + *resp_msg = 0; + return code; + } + + return ccNoError; +} + +cc_int32 +ccop_CTX_RELEASE( cc_server_context_t* ctx, + cc_auth_info_t* auth_info, + cc_session_info_t* session_info, + cc_msg_t *msg, cc_msg_t **resp_msg) +{ + ccmsg_ctx_release_t* header = (ccmsg_ctx_release_t *)msg->header; + cc_int32 code; + + *resp_msg = 0; + + if (msg->header_len != sizeof(ccmsg_ctx_release_t)) { + return ccErrBadParam; + } + + code = cci_context_destroy(header->ctx); + return cci_serv_make_ack(NULL, 0, auth_info, session_info, resp_msg); +} + +cc_int32 +ccop_CTX_GET_CHANGE_TIME( cc_server_context_t* ctx, + cc_auth_info_t* auth_info, + cc_session_info_t* session_info, + cc_msg_t *msg, cc_msg_t **resp_msg) +{ + ccmsg_ctx_get_change_time_resp_t* resp_header; + ccmsg_ctx_get_change_time_t *header = (ccmsg_ctx_get_change_time_t *)msg->header; + + *resp_msg = 0; + + if (msg->header_len != sizeof(ccmsg_ctx_get_change_time_t)) { + return ccErrBadParam; + } + + resp_header = (ccmsg_ctx_get_change_time_resp_t*)malloc(sizeof(ccmsg_ctx_get_change_time_resp_t)); + if (resp_header == NULL) { + return ccErrNoMem; + } + + resp_header->time = ctx->changed; + return cci_serv_make_ack(resp_header, sizeof(ccmsg_ctx_get_change_time_resp_t), auth_info, session_info, resp_msg); +} + +cc_int32 +ccop_CTX_GET_DEFAULT_CCACHE_NAME( cc_server_context_t* ctx, + cc_auth_info_t* auth_info, + cc_session_info_t* session_info, + cc_msg_t *msg, cc_msg_t **resp_msg) +{ + char * name; + ccmsg_ctx_get_default_ccache_name_resp_t* resp_header; + ccmsg_ctx_get_default_ccache_name_t* header = (ccmsg_ctx_get_default_ccache_name_t *)msg->header; + cc_int32 code; + + *resp_msg = 0; + + if (msg->header_len != sizeof(ccmsg_ctx_get_default_ccache_name_t)) { + return ccErrBadParam; + } + + code = cci_context_get_default_ccache_name(ctx, &name); + if (code != ccNoError) + return code; + + code = cci_msg_new(ccmsg_ACK, resp_msg); + if (code != ccNoError) + return code; + + resp_header = (ccmsg_ctx_get_default_ccache_name_resp_t*)malloc(sizeof(ccmsg_ctx_get_default_ccache_name_resp_t)); + if (resp_header == NULL) { + cci_msg_destroy(*resp_msg); + *resp_msg = 0; + return ccErrNoMem; + } + + code = cci_msg_add_data_blob(*resp_msg, name, strlen(name) + 1, &resp_header->name_offset); + resp_header->name_len = strlen(name) + 1; + return ccNoError; +} + +cc_int32 +ccop_CTX_COMPARE(cc_server_context_t* ctx, + cc_auth_info_t* auth_info, + cc_session_info_t* session_info, + cc_msg_t *msg, cc_msg_t **resp_msg) +{ + cc_server_context_t *ctx2; + ccmsg_ctx_compare_resp_t* resp_header; + ccmsg_ctx_compare_t* header = (ccmsg_ctx_compare_t *)msg->header; + cc_int32 code; + + *resp_msg = 0; + + if (msg->header_len != sizeof(ccmsg_ctx_compare_t)) + return ccErrBadParam; + + code = cci_serv_find_ctx_by_handle(header->ctx2, auth_info, session_info, &ctx2); + + resp_header = (ccmsg_ctx_compare_resp_t*)malloc(sizeof(ccmsg_ctx_compare_resp_t)); + if (resp_header == NULL) + return ccErrNoMem; + + resp_header->is_equal = cci_context_compare(ctx, ctx2); + return cci_serv_make_ack(resp_header, sizeof(ccmsg_ctx_compare_resp_t), auth_info, session_info, resp_msg); +} + +cc_int32 +ccop_CTX_NEW_CCACHE_ITERATOR(cc_server_context_t* ctx, + cc_auth_info_t* auth_info, + cc_session_info_t* session_info, + cc_msg_t *msg, cc_msg_t **resp_msg) +{ + cc_ccache_iterate_t* ccache_iterator; + ccmsg_ctx_new_ccache_iterator_resp_t* resp_header; + ccmsg_ctx_new_ccache_iterator_t* header = (ccmsg_ctx_new_ccache_iterator_t*)msg->header; + cc_int32 code; + + *resp_msg = 0; + + if (msg->header_len != sizeof(ccmsg_ctx_new_ccache_iterator_t)) + return ccErrBadParam; + + code = cci_context_ccache_iterator(ctx,&ccache_iterator); + + resp_header = (ccmsg_ctx_new_ccache_iterator_resp_t*)malloc(sizeof(ccmsg_ctx_new_ccache_iterator_resp_t)); + if (resp_header == NULL) + return ccErrNoMem; + + resp_header->iterator = ccache_iterator; + + return cci_serv_make_ack(resp_header, sizeof(ccmsg_ctx_new_ccache_iterator_resp_t), auth_info, session_info, resp_msg); +} + +cc_int32 +ccop_CTX_LOCK( cc_server_context_t* ctx, + cc_auth_info_t* auth_info, + cc_session_info_t* session_info, + cc_msg_t *msg, cc_msg_t **resp_msg) +{ + // TODO + return cci_serv_make_nack(ccErrNotImplemented, auth_info, session_info, resp_msg); +} + +cc_int32 +ccop_CTX_UNLOCK( cc_server_context_t* ctx, + cc_auth_info_t* auth_info, + cc_session_info_t* session_info, + cc_msg_t *msg, cc_msg_t **resp_msg) +{ + // TODO + return cci_serv_make_nack(ccErrNotImplemented, auth_info, session_info, resp_msg); +} + +cc_int32 +ccop_CTX_CLONE( cc_server_context_t* ctx, + cc_auth_info_t* auth_info, + cc_session_info_t* session_info, + cc_msg_t *msg, cc_msg_t **resp_msg) +{ + // TODO + return cci_serv_make_nack(ccErrNotImplemented, auth_info, session_info, resp_msg); +} + +cc_int32 +ccop_CCACHE_OPEN(cc_server_context_t* ctx, + cc_auth_info_t* auth_info, + cc_session_info_t* session_info, + cc_msg_t *msg, cc_msg_t **resp_msg) +{ + char *name; + cc_server_ccache_t* ccache; + ccmsg_ccache_open_resp_t* resp_header; + ccmsg_ccache_open_t* header = (ccmsg_ccache_open_t*)msg->header; + cc_int32 code; + + *resp_msg = 0; + + if (msg->header_len != sizeof(ccmsg_ccache_open_t)) + return ccErrBadParam; + + code = cci_msg_retrieve_blob(msg, header->name_offset, header->name_len, &name); + code = cci_context_find_ccache(ctx, name, &ccache); + + free(name); + + if (ccache == NULL) + return cci_serv_make_nack(ccErrCCacheNotFound, auth_info, session_info, resp_msg); + + resp_header = (ccmsg_ccache_open_resp_t*)malloc(sizeof(ccmsg_ccache_open_resp_t)); + if (resp_header == NULL) + return ccErrNoMem; + + resp_header->ccache = ccache; + cci_serv_make_ack(resp_header, sizeof(ccmsg_ccache_open_resp_t), auth_info, session_info, resp_msg); + return ccNoError; +} + +cc_int32 +ccop_CCACHE_OPEN_DEFAULT(cc_server_context_t* ctx, + cc_auth_info_t* auth_info, + cc_session_info_t* session_info, + cc_msg_t *msg, cc_msg_t **resp_msg) +{ + ccmsg_ccache_open_default_t* header = (ccmsg_ccache_open_default_t*)msg->header; + ccmsg_ccache_open_resp_t* resp_header; + cc_server_ccache_t* ccache; + + *resp_msg = 0; + + if (msg->header_len != sizeof(ccmsg_ccache_open_default_t)) + return ccErrBadParam; + + if (ctx->ccaches->head->data == NULL) + return cci_serv_make_nack(ccErrCCacheNotFound, auth_info, session_info, resp_msg); + + ccache = (cc_server_ccache_t*) ctx->ccaches->head->data; + + resp_header = (ccmsg_ccache_open_resp_t*)malloc(sizeof(ccmsg_ccache_open_resp_t)); + if (resp_header == NULL) + return ccErrNoMem; + + resp_header->ccache = ccache; + return cci_serv_make_ack(resp_header, sizeof(ccmsg_ccache_open_resp_t), auth_info, session_info, resp_msg); +} + +cc_int32 +ccop_CCACHE_CREATE(cc_server_context_t* ctx, + cc_auth_info_t* auth_info, + cc_session_info_t* session_info, + cc_msg_t *msg, cc_msg_t **resp_msg) +{ + ccmsg_ccache_create_resp_t* resp_header; + ccmsg_ccache_create_t* header = (ccmsg_ccache_create_t*)msg->header; + cc_server_ccache_t* ccache; + char* principal; + char* name; + cc_int32 code; + + *resp_msg = 0; + + if (msg->header_len != sizeof(ccmsg_ccache_create_t)) + return ccErrBadParam; + + code = cci_msg_retrieve_blob(msg, header->principal_offset, header->principal_len, &principal); + if (code != ccNoError) + return code; + principal[header->principal_len] = '\0'; /*Ensure null termination*/ + + code = cci_msg_retrieve_blob(msg, header->name_offset, header->name_len, &name); + if (code != ccNoError) + return code; + name[header->name_len] = '\0'; /*Ensure null termination*/ + + code = cci_context_create_ccache(ctx, name, header->version, principal, &ccache); + if (code != ccNoError) + return code; + + resp_header = (ccmsg_ccache_create_resp_t*)malloc(sizeof(ccmsg_ccache_create_resp_t)); + if (resp_header == NULL) + return ccErrNoMem; + + resp_header->ccache = ccache; + return cci_serv_make_ack(resp_header, sizeof(ccmsg_ccache_create_resp_t), auth_info, session_info, resp_msg); +} + +cc_int32 +ccop_CCACHE_CREATE_DEFAULT( cc_server_context_t* ctx, + cc_auth_info_t* auth_info, + cc_session_info_t* session_info, + cc_msg_t *msg, cc_msg_t **resp_msg) +{ + ccmsg_ccache_create_resp_t* resp_header; + ccmsg_ccache_create_t* header = (ccmsg_ccache_create_t*)msg->header; + cc_server_ccache_t* ccache; + char* principal; + char* name; + cc_int32 code; + + *resp_msg = 0; + + if (msg->header_len != sizeof(ccmsg_ccache_create_t)) + return ccErrBadParam; + + code = cci_msg_retrieve_blob(msg, header->principal_offset, header->principal_len, &principal); + if (code != ccNoError) + return code; + principal[header->principal_len] = '\0'; /*Ensure null termination*/ + + code = cci_context_get_default_ccache_name(ctx, &name); + if (code != ccNoError) + return code; + + code = cci_context_create_ccache(ctx, name, header->version, principal, &ccache); + if (code != ccNoError) + return code; + + resp_header = (ccmsg_ccache_create_resp_t*)malloc(sizeof(ccmsg_ccache_create_resp_t)); + if (resp_header == NULL) + return ccErrNoMem; + + resp_header->ccache = ccache; + return cci_serv_make_ack(resp_header, sizeof(ccmsg_ccache_create_resp_t), auth_info, session_info, resp_msg); +} + +cc_int32 +ccop_CCACHE_CREATE_UNIQUE( cc_server_context_t* ctx, + cc_auth_info_t* auth_info, + cc_session_info_t* session_info, + cc_msg_t *msg, cc_msg_t **resp_msg) +{ + ccmsg_ccache_create_resp_t* resp_header; + ccmsg_ccache_create_t* header = (ccmsg_ccache_create_t*)msg->header; + cc_server_ccache_t* ccache; + char* principal; + char* name; + cc_int32 code; + + *resp_msg = 0; + + if (msg->header_len != sizeof(ccmsg_ccache_create_t)) + return ccErrBadParam; + + code = cci_msg_retrieve_blob(msg, header->principal_offset, header->principal_len, &principal); + if (code != ccNoError) + return code; + principal[header->principal_len] = '\0'; /*Ensure null termination*/ + + // TODO: Generate a unique ccache name + + code = cci_context_create_ccache(ctx, name, header->version, principal, &ccache); + if (code != ccNoError) + return code; + + resp_header = (ccmsg_ccache_create_resp_t*)malloc(sizeof(ccmsg_ccache_create_resp_t)); + if (resp_header == NULL) + return ccErrNoMem; + + resp_header->ccache = ccache; + return cci_serv_make_ack(resp_header, sizeof(ccmsg_ccache_create_resp_t), auth_info, session_info, resp_msg); +} + +cc_int32 +ccop_CCACHE_RELEASE( cc_server_context_t* ctx, + cc_auth_info_t* auth_info, + cc_session_info_t* session_info, + cc_msg_t *msg, cc_msg_t **resp_msg) +{ + // TODO: This is probably wrong. + return ccop_CCACHE_DESTROY(ctx, auth_info, session_info, msg, resp_msg); +} + +cc_int32 +ccop_CCACHE_DESTROY( cc_server_context_t* ctx, + cc_auth_info_t* auth_info, + cc_session_info_t* session_info, + cc_msg_t *msg, cc_msg_t **resp_msg) +{ + ccmsg_ccache_release_t* header = (ccmsg_ccache_release_t*)msg->header; + cc_server_ccache_t* ccache; + cc_int32 code; + + *resp_msg = 0; + + if (msg->header_len != sizeof(ccmsg_ccache_release_t)) + return ccErrBadParam; + + code = cci_serv_find_ccache_by_handle(ctx, header->ccache, &ccache); + if (code != ccNoError) + return cci_serv_make_nack(ccErrCCacheNotFound, auth_info, session_info, resp_msg); + + cci_ccache_destroy(ccache); + + return cci_serv_make_ack(NULL, 0, auth_info, session_info, resp_msg); +} + +cc_int32 +ccop_CCACHE_SET_DEFAULT(cc_server_context_t* ctx, + cc_auth_info_t* auth_info, + cc_session_info_t* session_info, + cc_msg_t *msg, cc_msg_t **resp_msg) +{ + cc_server_ccache_t* ccache, *stored_ccache, *old_default; + ccmsg_ccache_set_default_t* header = (ccmsg_ccache_set_default_t*)msg->header; + cc_ccache_iterate_t* ccache_iterator; + cc_ccache_list_node_t* ccache_node; + cc_int32 code; + + *resp_msg = 0; + + if (msg->header_len != sizeof(ccmsg_ccache_set_default_t)) + return ccErrBadParam; + + code = cci_serv_find_ccache_by_handle(ctx, header->ccache, &ccache); + if (code != ccNoError) + return cci_serv_make_nack(ccErrCCacheNotFound, auth_info, session_info, resp_msg); + + if (ccache == (cc_server_ccache_t*)ctx->ccaches->head->data) /*already default*/ + return cci_serv_make_ack(NULL, 0, auth_info, session_info, resp_msg); + + old_default = (cc_server_ccache_t*)ctx->ccaches->head->data; + old_default->last_default = time(NULL); + + code = cci_ccache_list_iterator(ctx->ccaches, &ccache_iterator); + if (code != ccNoError) + return cci_serv_make_nack(ccErrCCacheNotFound, auth_info, session_info, resp_msg); + + while (cci_ccache_iterate_has_next(ccache_iterator)) { + code = cci_ccache_iterate_next(ccache_iterator,&ccache_node); + stored_ccache = (cc_server_ccache_t*)ccache_node->data; + + if (stored_ccache == ccache) { + ccache_node->data = NULL; /*don't want list removal code free()ing ccache*/ + cci_ccache_list_remove_element(ctx->ccaches, ccache_node); + cci_ccache_list_prepend(ctx->ccaches, ccache, NULL); + break; + } + } + return cci_serv_make_ack(NULL, 0, auth_info, session_info, resp_msg); +} + +cc_int32 +ccop_CCACHE_GET_CREDS_VERSION(cc_server_context_t* ctx, + cc_auth_info_t* auth_info, + cc_session_info_t* session_info, + cc_msg_t *msg, cc_msg_t **resp_msg) +{ + ccmsg_ccache_get_creds_version_t* header = (ccmsg_ccache_get_creds_version_t*)msg->header; + ccmsg_ccache_get_creds_version_resp_t* resp_header; + cc_server_ccache_t* ccache; + cc_int32 code; + + *resp_msg = 0; + + if (msg->header_len != sizeof(ccmsg_ccache_get_creds_version_t)) + return ccErrBadParam; + + code = cci_serv_find_ccache_by_handle(ctx, header->ccache, &ccache); + if (code != ccNoError) + return cci_serv_make_nack(ccErrCCacheNotFound, auth_info, session_info, resp_msg); + + resp_header = (ccmsg_ccache_get_creds_version_resp_t*)malloc(sizeof(ccmsg_ccache_get_creds_version_resp_t)); + if (resp_header == NULL) + return ccErrNoMem; + + resp_header->version = ccache->versions; + return cci_serv_make_ack(resp_header, sizeof(ccmsg_ccache_get_creds_version_resp_t), auth_info, session_info, resp_msg); +} + +cc_int32 +ccop_CCACHE_GET_NAME(cc_server_context_t* ctx, + cc_auth_info_t* auth_info, + cc_session_info_t* session_info, + cc_msg_t *msg, cc_msg_t **resp_msg) +{ + ccmsg_ccache_get_name_t* header = (ccmsg_ccache_get_name_t*)msg->header; + ccmsg_ccache_get_name_resp_t* resp_header; + cc_server_ccache_t* ccache; + cc_int32 code; + + *resp_msg = 0; + + if (msg->header_len != sizeof(ccmsg_ccache_get_name_resp_t)) + return ccErrBadParam; + + code = cci_serv_find_ccache_by_handle(ctx, header->ccache, &ccache); + if (ccache == NULL) + return cci_serv_make_nack(ccErrCCacheNotFound, auth_info, session_info, resp_msg); + + resp_header = (ccmsg_ccache_get_name_resp_t*)malloc(sizeof(ccmsg_ccache_get_name_resp_t)); + if (resp_header == NULL) + return ccErrNoMem; + + code = cci_msg_new(ccmsg_ACK, resp_msg); + if (code != ccNoError) + return code; + + code = cci_msg_add_data_blob(*resp_msg, ccache->name, strlen(ccache->name) + 1, &resp_header->name_offset); + resp_header->name_len = strlen(ccache->name) + 1; + cci_msg_add_header(*resp_msg, resp_header, sizeof(ccmsg_ccache_get_name_resp_t)); + + return ccNoError; +} + +cc_int32 +ccop_CCACHE_GET_PRINCIPAL(cc_server_context_t* ctx, + cc_auth_info_t* auth_info, + cc_session_info_t* session_info, + cc_msg_t *msg, cc_msg_t **resp_msg) +{ + ccmsg_ccache_get_principal_t* header = (ccmsg_ccache_get_principal_t*)msg->header; + ccmsg_ccache_get_principal_resp_t* resp_header; + cc_server_ccache_t* ccache; + char * principal; + cc_int32 code; + + *resp_msg = 0; + + if (msg->header_len != sizeof(ccmsg_ccache_get_principal_t)) + return ccErrBadParam; + + code = cci_serv_find_ccache_by_handle(ctx, header->ccache, &ccache); + if (code != ccNoError) + return cci_serv_make_nack(ccErrCCacheNotFound, auth_info, session_info, resp_msg); + + code = cci_ccache_get_principal(ccache, header->version, &principal); + if (code != ccNoError) + return cci_serv_make_nack(code, auth_info, session_info, resp_msg); + + code = cci_msg_new(ccmsg_ACK, resp_msg); + if (code != ccNoError) + return code; + + resp_header = (ccmsg_ccache_get_principal_resp_t*)malloc(sizeof(ccmsg_ccache_get_principal_resp_t)); + if (resp_header == NULL) + return ccErrNoMem; + + code = cci_msg_add_data_blob(*resp_msg, principal, strlen(principal) + 1, &resp_header->principal_offset); + cci_msg_add_header(*resp_msg, resp_header, sizeof(ccmsg_ccache_get_principal_resp_t)); + + return ccNoError; +} + +cc_int32 +ccop_CCACHE_SET_PRINCIPAL(cc_server_context_t* ctx, + cc_auth_info_t* auth_info, + cc_session_info_t* session_info, + cc_msg_t *msg, cc_msg_t **resp_msg) +{ + ccmsg_ccache_set_principal_t* header = (ccmsg_ccache_set_principal_t*)msg->header; + cc_server_ccache_t* ccache; + char *principal; + cc_int32 code; + + *resp_msg = 0; + + if (msg->header_len != sizeof(ccmsg_ccache_set_principal_t)) + return ccErrBadParam; + + code = cci_serv_find_ccache_by_handle(ctx, header->ccache, &ccache); + if (code != ccNoError) + return cci_serv_make_nack(ccErrCCacheNotFound, auth_info, session_info, resp_msg); + + code = cci_msg_retrieve_blob(msg, header->principal_offset, header->principal_len, &principal); + if (code != ccNoError) + return cci_serv_make_nack(ccErrBadParam, auth_info, session_info, resp_msg); + + code = cci_ccache_set_principal(ccache, header->version, principal); + if (code != ccNoError) + return cci_serv_make_nack(code, auth_info, session_info, resp_msg); + + return cci_serv_make_ack(NULL, 0, auth_info, session_info, resp_msg); +} + +cc_int32 +ccop_CCACHE_CREDS_ITERATOR(cc_server_context_t* ctx, + cc_auth_info_t* auth_info, + cc_session_info_t* session_info, + cc_msg_t *msg, cc_msg_t **resp_msg) +{ + cc_server_ccache_t* ccache; + cc_credentials_iterate_t* creds_iterator; + ccmsg_ccache_creds_iterator_t* header = (ccmsg_ccache_creds_iterator_t*)msg->header; + ccmsg_ccache_creds_iterator_resp_t* resp_header; + cc_int32 code; + + *resp_msg = 0; + + if (msg->header_len != sizeof(ccmsg_ccache_creds_iterator_t)) + return ccErrBadParam; + + code = cci_serv_find_ccache_by_handle(ctx, header->ccache, &ccache); + if (code != ccNoError) + return cci_serv_make_nack(ccErrCCacheNotFound, auth_info, session_info, resp_msg); + + code = cci_ccache_new_iterator(ccache, &creds_iterator); + if (code != ccNoError) + return code; + + resp_header = (ccmsg_ccache_creds_iterator_resp_t*)malloc(sizeof(ccmsg_ccache_creds_iterator_resp_t)); + if (resp_header == NULL) + return ccErrNoMem; + + resp_header->iterator = creds_iterator; + return cci_serv_make_ack(resp_header, sizeof(ccmsg_ccache_creds_iterator_resp_t), auth_info, session_info, resp_msg); +} + + +static cc_int32 +cci_credentials_union_release( cc_credentials_union * creds ) +{ + int i; + + switch (creds->version) { + case cc_credentials_v4: + free(creds->credentials.credentials_v4); + break; + case cc_credentials_v5: + if ( creds->credentials.credentials_v5->client ) + free(creds->credentials.credentials_v5->client); + if ( creds->credentials.credentials_v5->server ) + free(creds->credentials.credentials_v5->server ); + if ( creds->credentials.credentials_v5->keyblock.data ) + free(creds->credentials.credentials_v5->keyblock.data); + if ( creds->credentials.credentials_v5->ticket.data ) + free(creds->credentials.credentials_v5->ticket.data); + if ( creds->credentials.credentials_v5->second_ticket.data ) + free(creds->credentials.credentials_v5->second_ticket.data); + if ( creds->credentials.credentials_v5->addresses ) { + for ( i=0; creds->credentials.credentials_v5->addresses[i]; i++) { + if (creds->credentials.credentials_v5->addresses[i]->data) + free(creds->credentials.credentials_v5->addresses[i]->data); + } + free(creds->credentials.credentials_v5->addresses); + } + if ( creds->credentials.credentials_v5->authdata ) { + for ( i=0; creds->credentials.credentials_v5->authdata[i]; i++) { + if ( creds->credentials.credentials_v5->authdata[i]->data ) + free(creds->credentials.credentials_v5->authdata[i]->data); + } + free(creds->credentials.credentials_v5->authdata); + } + break; + default: + return ccErrBadCredentialsVersion; + } + return ccNoError; +} + +cc_int32 +ccop_CCACHE_STORE_CREDS(cc_server_context_t* ctx, + cc_auth_info_t* auth_info, + cc_session_info_t* session_info, + cc_msg_t *msg, cc_msg_t **resp_msg) +{ + ccmsg_ccache_store_creds_t* header = (ccmsg_ccache_store_creds_t*)msg->header; + cc_server_ccache_t* ccache; + char *flat_creds; + cc_credentials_union *creds; + cc_int32 code; + + *resp_msg = 0; + + if (msg->header_len != sizeof(ccmsg_ccache_store_creds_t)) + return ccErrBadParam; + + code = cci_serv_find_ccache_by_handle(ctx, header->ccache, &ccache); + if (code != ccNoError) + return cci_serv_make_nack(ccErrCCacheNotFound, auth_info, session_info, resp_msg); + + // TODO: This code is too simplistic. cc_credential_unions are not flat + // structures and must be flattened. That means that although we can + // store a flat blob in the message we will need to decode the blob + // into the actual object. + code = cci_msg_retrieve_blob(msg, header->creds_offset, header->creds_len, &flat_creds); + if (code != ccNoError) + return cci_serv_make_nack(code, auth_info, session_info, resp_msg); + + creds = (cc_credentials_union *)malloc(sizeof(cc_credentials_union)); + if ( creds == NULL ) + return ccErrNoMem; + + switch ( creds->version ) { + case cc_credentials_v4: + code = cci_creds_v4_unmarshall(flat_creds, header->creds_len, creds); + break; + case cc_credentials_v5: + code = cci_creds_v5_unmarshall(flat_creds, header->creds_len, creds); + break; + default: + return cci_serv_make_nack(ccErrBadCredentialsVersion, auth_info, session_info, resp_msg); + } + if (code != ccNoError) + return cci_serv_make_nack(code, auth_info, session_info, resp_msg); + + code = cci_ccache_store_creds(ccache, creds); + cci_credentials_union_release(creds); + if (code != ccNoError) { + return cci_serv_make_nack(code, auth_info, session_info, resp_msg); + } + + return cci_serv_make_ack(NULL, 0, auth_info, session_info, resp_msg); +} + +cc_int32 +ccop_CCACHE_REM_CREDS(cc_server_context_t* ctx, + cc_auth_info_t* auth_info, + cc_session_info_t* session_info, + cc_msg_t *msg, cc_msg_t **resp_msg) +{ + ccmsg_ccache_rem_creds_t* header = (ccmsg_ccache_rem_creds_t*)msg->header; + cc_server_ccache_t* ccache; + cc_credentials_union *creds; + cc_int32 code; + + *resp_msg = 0; + if (msg->header_len != sizeof(ccmsg_ccache_rem_creds_t)) + return ccErrBadParam; + + code = cci_serv_find_ccache_by_handle(ctx, header->ccache, &ccache); + if (code != ccNoError) + return cci_serv_make_nack(ccErrCCacheNotFound, auth_info, session_info, resp_msg); + + code = cci_ccache_rem_creds(ccache, header->creds); + if (code != ccNoError) + return cci_serv_make_nack(code, auth_info, session_info, resp_msg); + + return cci_serv_make_ack(NULL, 0, auth_info, session_info, resp_msg); +} + +cc_int32 +ccop_CCACHE_LOCK( cc_server_context_t* ctx, + cc_auth_info_t* auth_info, + cc_session_info_t* session_info, + cc_msg_t *msg, cc_msg_t **resp_msg) +{ + // TODO + return cci_serv_make_nack(ccErrNotImplemented, auth_info, session_info, resp_msg); +} + +cc_int32 +ccop_CCACHE_UNLOCK( cc_server_context_t* ctx, + cc_auth_info_t* auth_info, + cc_session_info_t* session_info, + cc_msg_t *msg, cc_msg_t **resp_msg) +{ + // TODO + return cci_serv_make_nack(ccErrNotImplemented, auth_info, session_info, resp_msg); +} + +cc_int32 +ccop_CCACHE_MOVE( cc_server_context_t* ctx, + cc_auth_info_t* auth_info, + cc_session_info_t* session_info, + cc_msg_t *msg, cc_msg_t **resp_msg) +{ + // TODO + return cci_serv_make_nack(ccErrNotImplemented, auth_info, session_info, resp_msg); +} + + +cc_int32 +ccop_CCACHE_GET_LAST_DEFAULT_TIME(cc_server_context_t* ctx, + cc_auth_info_t* auth_info, + cc_session_info_t* session_info, + cc_msg_t *msg, cc_msg_t **resp_msg) +{ + ccmsg_ccache_get_last_default_time_t* header = (ccmsg_ccache_get_last_default_time_t*)msg->header; + ccmsg_ccache_get_last_default_time_resp_t* resp_header; + cc_server_ccache_t* ccache; + cc_int32 code; + + *resp_msg = 0; + + if (msg->header_len != sizeof(ccmsg_ccache_get_last_default_time_t)) + return ccErrBadParam; + + code = cci_serv_find_ccache_by_handle(ctx, header->ccache, &ccache); + if (code != ccNoError) + return cci_serv_make_nack(ccErrCCacheNotFound, auth_info, session_info, resp_msg); + + resp_header = (ccmsg_ccache_get_last_default_time_resp_t*)malloc(sizeof(ccmsg_ccache_get_last_default_time_resp_t)); + if (resp_header == NULL) + return ccErrNoMem; + + resp_header->last_default_time = ccache->last_default; + return cci_serv_make_ack(resp_header, sizeof(ccmsg_ccache_get_last_default_time_resp_t), auth_info, session_info, resp_msg); +} + +cc_int32 +ccop_CCACHE_GET_CHANGE_TIME( cc_server_context_t* ctx, + cc_auth_info_t* auth_info, + cc_session_info_t* session_info, + cc_msg_t *msg, cc_msg_t **resp_msg) +{ + ccmsg_ccache_get_change_time_resp_t* resp_header; + ccmsg_ccache_get_change_time_t *header = (ccmsg_ccache_get_change_time_t *)msg->header; + cc_server_ccache_t* ccache = (cc_server_ccache_t *)header->ccache; + + *resp_msg = 0; + + if (msg->header_len != sizeof(ccmsg_ccache_get_change_time_t)) { + return ccErrBadParam; + } + + resp_header = (ccmsg_ccache_get_change_time_resp_t*)malloc(sizeof(ccmsg_ccache_get_change_time_resp_t)); + if (resp_header == NULL) { + return ccErrNoMem; + } + + resp_header->time = ccache->changed; + return cci_serv_make_ack(resp_header, sizeof(ccmsg_ccache_get_change_time_resp_t), auth_info, session_info, resp_msg); +} + +cc_int32 +ccop_CCACHE_COMPARE(cc_server_context_t* ctx, + cc_auth_info_t* auth_info, + cc_session_info_t* session_info, + cc_msg_t *msg, cc_msg_t **resp_msg) +{ + ccmsg_ccache_compare_t* header = (ccmsg_ccache_compare_t*)msg->header; + ccmsg_ccache_compare_resp_t* resp_header; + cc_server_ccache_t* ccache1, *ccache2; + cc_int32 code; + + *resp_msg = 0; + + if (msg->header_len != sizeof(ccmsg_ccache_compare_t)) + return ccErrBadParam; + + code = cci_serv_find_ccache_by_handle(ctx, header->ccache1, &ccache1); + if (code != ccNoError) + return cci_serv_make_nack(ccErrCCacheNotFound, auth_info, session_info, resp_msg); + + code = cci_serv_find_ccache_by_handle(ctx, header->ccache2, &ccache2); + if (code != ccNoError) + return cci_serv_make_nack(ccErrCCacheNotFound, auth_info, session_info, resp_msg); + + resp_header = (ccmsg_ccache_compare_resp_t*)malloc(sizeof(ccmsg_ccache_compare_resp_t)); + if (resp_header == NULL) + return ccErrNoMem; + + cci_ccache_compare(ccache1, ccache2, &resp_header->is_equal); + return cci_serv_make_ack(resp_header, sizeof(ccmsg_ccache_compare_resp_t), auth_info, session_info, resp_msg); +} + +cc_int32 +ccop_CCACHE_GET_KDC_TIME_OFFSET(cc_server_context_t* ctx, + cc_auth_info_t* auth_info, + cc_session_info_t* session_info, + cc_msg_t *msg, cc_msg_t **resp_msg) +{ + ccmsg_ccache_get_kdc_time_offset_t* header = (ccmsg_ccache_get_kdc_time_offset_t*)msg->header; + ccmsg_ccache_get_kdc_time_offset_resp_t* resp_header; + cc_server_ccache_t* ccache; + cc_time_t offset; + cc_int32 code; + + *resp_msg = 0; + + if (msg->header_len != sizeof(ccmsg_ccache_get_kdc_time_offset_t)) + return ccErrBadParam; + + code = cci_serv_find_ccache_by_handle(ctx, header->ccache, &ccache); + if (code != ccNoError) + return cci_serv_make_nack(ccErrCCacheNotFound, auth_info, session_info, resp_msg); + + // TODO How is the header->creds_version supposed to be used? + + code = cci_ccache_get_kdc_time_offset(ccache, &offset); + if (code != ccNoError) + return cci_serv_make_nack(code, auth_info, session_info, resp_msg); + + resp_header = (ccmsg_ccache_get_kdc_time_offset_resp_t*)malloc(sizeof(ccmsg_ccache_get_kdc_time_offset_resp_t)); + if (resp_header == NULL) + return ccErrNoMem; + + resp_header->offset = offset; + return cci_serv_make_ack(resp_header, sizeof(ccmsg_ccache_get_kdc_time_offset_resp_t), auth_info, session_info, resp_msg); +} + +cc_int32 +ccop_CCACHE_SET_KDC_TIME_OFFSET(cc_server_context_t* ctx, + cc_auth_info_t* auth_info, + cc_session_info_t* session_info, + cc_msg_t *msg, cc_msg_t **resp_msg) +{ + ccmsg_ccache_set_kdc_time_offset_t* header = (ccmsg_ccache_set_kdc_time_offset_t*)msg->header; + cc_server_ccache_t* ccache; + cc_int32 code; + + *resp_msg = 0; + + if (msg->header_len != sizeof(ccmsg_ccache_set_kdc_time_offset_t)) + return ccErrBadParam; + + code = cci_serv_find_ccache_by_handle(ctx, header->ccache, &ccache); + if (code != ccNoError) + return cci_serv_make_nack(ccErrCCacheNotFound, auth_info, session_info, resp_msg); + + // TODO How is the header->creds_version supposed to be used? + + cci_ccache_set_kdc_time_offset(ccache, header->offset); + return cci_serv_make_ack(NULL, 0, auth_info, session_info, resp_msg); +} + +cc_int32 +ccop_CCACHE_CLEAR_KDC_TIME_OFFSET(cc_server_context_t* ctx, + cc_auth_info_t* auth_info, + cc_session_info_t* session_info, + cc_msg_t *msg, cc_msg_t **resp_msg) +{ + ccmsg_ccache_clear_kdc_time_offset_t* header = (ccmsg_ccache_clear_kdc_time_offset_t*)msg->header; + cc_server_ccache_t* ccache; + cc_int32 code; + + *resp_msg = 0; + + if (msg->header_len != sizeof(ccmsg_ccache_clear_kdc_time_offset_t)) + return ccErrBadParam; + + code = cci_serv_find_ccache_by_handle(ctx, header->ccache, &ccache); + if (code != ccNoError) + return cci_serv_make_nack(ccErrCCacheNotFound, auth_info, session_info, resp_msg); + + // TODO How is the header->creds_version supposed to be used? + + cci_ccache_clear_kdc_time_offset(ccache); + return cci_serv_make_ack(NULL, 0, auth_info, session_info, resp_msg); +} + +cc_int32 +ccop_CCACHE_ITERATOR_RELEASE(cc_server_context_t* ctx, + cc_auth_info_t* auth_info, + cc_session_info_t* session_info, + cc_msg_t *msg, cc_msg_t **resp_msg) +{ + cc_generic_list_node_t* gen_node; + ccmsg_ccache_iterator_release_t* header = (ccmsg_ccache_iterator_release_t*)msg->header; + cc_int32 code; + + *resp_msg = 0; + + if (msg->header_len != sizeof(ccmsg_ccache_iterator_release_t)) + return ccErrBadParam; + + code = cci_serv_find_ccache_iterator_by_handle(ctx, header->iterator, &gen_node); + if (code != ccNoError) + return cci_serv_make_nack(ccErrBadParam, auth_info, session_info, resp_msg); + + code = cci_generic_list_remove_element(ctx->active_iterators, gen_node); + if (code != ccNoError) + return cci_serv_make_nack(code, auth_info, session_info, resp_msg); + + return cci_serv_make_ack(NULL, 0, auth_info, session_info, resp_msg); +} + +cc_int32 +ccop_CCACHE_ITERATOR_NEXT(cc_server_context_t* ctx, + cc_auth_info_t* auth_info, + cc_session_info_t* session_info, + cc_msg_t *msg, cc_msg_t **resp_msg) +{ + ccmsg_ccache_iterator_release_t* header = (ccmsg_ccache_iterator_release_t*)msg->header; + ccmsg_ccache_iterator_next_resp_t* resp_header; + cc_generic_list_node_t* gen_node; + cc_ccache_iterate_t* ccache_iterator; + cc_ccache_list_node_t *ccache_node; + cc_int32 code; + + *resp_msg = 0; + + if (msg->header_len != sizeof(ccmsg_ccache_iterator_next_t)) + return ccErrBadParam; + + code = cci_serv_find_ccache_iterator_by_handle(ctx, header->iterator, &gen_node); + if (code != ccNoError) + return cci_serv_make_nack(ccErrBadParam, auth_info, session_info, resp_msg); + + ccache_iterator = (cc_ccache_iterate_t*)gen_node->data; + if (cci_ccache_iterate_has_next(ccache_iterator)) { + resp_header = (ccmsg_ccache_iterator_next_resp_t*)malloc(sizeof(ccmsg_ccache_iterator_next_resp_t)); + if (resp_header == NULL) + return ccErrNoMem; + + code = cci_ccache_iterate_next(ccache_iterator, &ccache_node); + if (code != ccNoError) + return cci_serv_make_nack(code, auth_info, session_info, resp_msg); + + resp_header->ccache = ccache_node; + return cci_serv_make_ack(resp_header, sizeof(ccmsg_ccache_iterator_next_resp_t), auth_info, session_info, resp_msg); + } else { + return cci_serv_make_nack(ccIteratorEnd, auth_info, session_info, resp_msg); + } +} + +cc_int32 +ccop_CREDS_ITERATOR_RELEASE(cc_server_context_t* ctx, + cc_auth_info_t* auth_info, + cc_session_info_t* session_info, + cc_msg_t *msg, cc_msg_t **resp_msg) +{ + cc_generic_list_node_t* gen_node; + cc_server_ccache_t* ccache; + ccmsg_creds_iterator_release_t* header = (ccmsg_creds_iterator_release_t*)msg->header; + cc_int32 code; + + *resp_msg = 0; + + if (msg->header_len != sizeof(ccmsg_creds_iterator_release_t)) + return ccErrBadParam; + + code = cci_serv_find_ccache_by_handle(ctx, header->ccache, &ccache); + if (code != ccNoError) + return cci_serv_make_nack(ccErrCCacheNotFound, auth_info, session_info, resp_msg); + + code = cci_serv_find_creds_iterator_by_handle(ccache, header->iterator, &gen_node); + if (code != ccNoError) + return cci_serv_make_nack(ccErrBadParam, auth_info, session_info, resp_msg); + + code = cci_generic_list_remove_element(ccache->active_iterators, gen_node); + if (code != ccNoError) + return cci_serv_make_nack(ccErrBadParam, auth_info, session_info, resp_msg); + + return cci_serv_make_ack(NULL, 0, auth_info, session_info, resp_msg); +} + +cc_int32 +ccop_CREDS_ITERATOR_NEXT(cc_server_context_t* ctx, + cc_auth_info_t* auth_info, + cc_session_info_t* session_info, + cc_msg_t *msg, cc_msg_t **resp_msg) +{ + ccmsg_creds_iterator_next_t* header = (ccmsg_creds_iterator_next_t*)msg->header; + ccmsg_creds_iterator_next_resp_t* resp_header; + cc_credentials_iterate_t* creds_iterator; + cc_generic_list_node_t* gen_node; + cc_credentials_list_node_t* creds_node; + cc_server_ccache_t* ccache; + cc_server_credentials_t* stored_creds; + cc_credentials_union *creds_union; + cc_int32 code; + + *resp_msg = 0; + + if (msg->header_len != sizeof(ccmsg_creds_iterator_next_t)) + return ccErrBadParam; + + code = cci_serv_find_ccache_by_handle(ctx, header->ccache, &ccache); + if (code != ccNoError) + return cci_serv_make_nack(ccErrCCacheNotFound, auth_info, session_info, resp_msg); + + code = cci_serv_find_creds_iterator_by_handle(ccache, header->iterator, &gen_node); + if (code != ccNoError) + return cci_serv_make_nack(ccErrBadParam, auth_info, session_info, resp_msg); + + creds_iterator = (cc_credentials_iterate_t*)gen_node->data; + if (cci_credentials_iterate_has_next(creds_iterator)) { + code = cci_msg_new(ccmsg_ACK, resp_msg); + if (code != ccNoError) + return code; + + resp_header = (ccmsg_creds_iterator_next_resp_t*)malloc(sizeof(ccmsg_creds_iterator_next_resp_t)); + if (resp_header == NULL) + return ccErrNoMem; + + code = cci_credentials_iterate_next(creds_iterator, &creds_node); + stored_creds = (cc_server_credentials_t*)creds_node->data; + creds_union = &stored_creds->creds; + + code = cci_msg_add_data_blob(*resp_msg, creds_union, sizeof(cc_credentials_union), &resp_header->creds_offset); + code = cci_msg_add_header(*resp_msg, resp_header, sizeof(ccmsg_creds_iterator_next_resp_t)); + } else { + cci_serv_make_nack(ccIteratorEnd, auth_info, session_info, resp_msg); + } + return ccNoError; +} + +cc_int32 +ccop_CREDS_RELEASE( cc_server_context_t* ctx, + cc_auth_info_t* auth_info, + cc_session_info_t* session_info, + cc_msg_t *msg, cc_msg_t **resp_msg) +{ + + cci_serv_make_nack(ccErrNotImplemented, auth_info, session_info, resp_msg); + return ccNoError; +} |