* Initial commit of C CCAPI implementation
authorJeffrey Altman <jaltman@secure-endpoints.com>
Wed, 27 Oct 2004 20:48:07 +0000 (20:48 +0000)
committerJeffrey Altman <jaltman@secure-endpoints.com>
Wed, 27 Oct 2004 20:48:07 +0000 (20:48 +0000)
ticket: 2753

git-svn-id: svn://anonsvn.mit.edu/krb5/trunk@16840 dc483132-0cff-0310-8789-dd5450dbe970

46 files changed:
src/lib/ccapi/ChangeLog [new file with mode: 0644]
src/lib/ccapi/client/ChangeLog [new file with mode: 0644]
src/lib/ccapi/client/NTMakefile [new file with mode: 0644]
src/lib/ccapi/client/cacheapi.c [new file with mode: 0644]
src/lib/ccapi/client/ccache.c [new file with mode: 0644]
src/lib/ccapi/client/ccache.h [new file with mode: 0644]
src/lib/ccapi/client/ccache_iterator.c [new file with mode: 0644]
src/lib/ccapi/client/ccache_iterator.h [new file with mode: 0644]
src/lib/ccapi/client/ccstring.c [new file with mode: 0644]
src/lib/ccapi/client/ccstring.h [new file with mode: 0644]
src/lib/ccapi/client/context.c [new file with mode: 0644]
src/lib/ccapi/client/context.h [new file with mode: 0644]
src/lib/ccapi/client/credentials.c [new file with mode: 0644]
src/lib/ccapi/client/credentials.h [new file with mode: 0644]
src/lib/ccapi/client/credentials_iterator.c [new file with mode: 0644]
src/lib/ccapi/client/credentials_iterator.h [new file with mode: 0644]
src/lib/ccapi/client/mac/ChangeLog [new file with mode: 0644]
src/lib/ccapi/client/windows/ChangeLog [new file with mode: 0644]
src/lib/ccapi/include/ChangeLog [new file with mode: 0644]
src/lib/ccapi/include/CredentialsCache.h [new file with mode: 0644]
src/lib/ccapi/include/CredentialsCache2.h [new file with mode: 0644]
src/lib/ccapi/include/marshall.h [new file with mode: 0644]
src/lib/ccapi/include/msg.h [new file with mode: 0644]
src/lib/ccapi/include/msg_headers.h [new file with mode: 0644]
src/lib/ccapi/mac/ChangeLog [new file with mode: 0644]
src/lib/ccapi/marshall.c [new file with mode: 0644]
src/lib/ccapi/msg.c [new file with mode: 0644]
src/lib/ccapi/server/ChangeLog [new file with mode: 0644]
src/lib/ccapi/server/NTMakefile [new file with mode: 0644]
src/lib/ccapi/server/ccache.c [new file with mode: 0644]
src/lib/ccapi/server/context.c [new file with mode: 0644]
src/lib/ccapi/server/datastore.h [new file with mode: 0644]
src/lib/ccapi/server/lists.c [new file with mode: 0644]
src/lib/ccapi/server/mac/ChangeLog [new file with mode: 0644]
src/lib/ccapi/server/rpc_auth.c [new file with mode: 0644]
src/lib/ccapi/server/rpc_auth.h [new file with mode: 0644]
src/lib/ccapi/server/serv_ops.c [new file with mode: 0644]
src/lib/ccapi/server/serv_ops.h [new file with mode: 0644]
src/lib/ccapi/server/windows/ChangeLog [new file with mode: 0644]
src/lib/ccapi/unit-test/ChangeLog [new file with mode: 0644]
src/lib/ccapi/unit-test/t_ccache.c [new file with mode: 0644]
src/lib/ccapi/unit-test/t_context.c [new file with mode: 0644]
src/lib/ccapi/unit-test/t_lists.c [new file with mode: 0644]
src/lib/ccapi/unit-test/t_msg.c [new file with mode: 0644]
src/lib/ccapi/unit-test/t_server.c [new file with mode: 0644]
src/lib/ccapi/windows/ChangeLog [new file with mode: 0644]

diff --git a/src/lib/ccapi/ChangeLog b/src/lib/ccapi/ChangeLog
new file mode 100644 (file)
index 0000000..aaa59da
--- /dev/null
@@ -0,0 +1,4 @@
+2004-10-27   Jeffrey Altman  <jaltman@mit.edu>
+
+ * Initial commit of C CCAPI implementation
+
diff --git a/src/lib/ccapi/client/ChangeLog b/src/lib/ccapi/client/ChangeLog
new file mode 100644 (file)
index 0000000..aaa59da
--- /dev/null
@@ -0,0 +1,4 @@
+2004-10-27   Jeffrey Altman  <jaltman@mit.edu>
+
+ * Initial commit of C CCAPI implementation
+
diff --git a/src/lib/ccapi/client/NTMakefile b/src/lib/ccapi/client/NTMakefile
new file mode 100644 (file)
index 0000000..09ef9df
--- /dev/null
@@ -0,0 +1,22 @@
+!INCLUDE <WIN32.MAK>
+
+CFLAGS = -I../include
+
+CCAPI_OBJS = cacheapi.obj context.obj ccache.obj credentials.obj ccache_iterator.obj \
+             credentials_iterator.obj ccstring.obj marshall.obj msg.obj 
+
+CCAPI_LIB = ccapi.lib
+
+$(CCAPI_LIB): $(CCAPI_OBJS)
+        $(implib) /NOLOGO /OUT:$@ $**
+
+CCAPI_DLLFILE = krbcc32.dll
+
+
+
+$(CCAPI_DLLFILE): $(CCAPI_LIB)
+        $(DLLGUILINK) -def:windows\krbcc32.def
+        $(DLLPREP)
+
+clean:
+        del *.obj *.lib
diff --git a/src/lib/ccapi/client/cacheapi.c b/src/lib/ccapi/client/cacheapi.c
new file mode 100644 (file)
index 0000000..2c874be
--- /dev/null
@@ -0,0 +1,118 @@
+/* $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).
+ * $
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <CredentialsCache.h>
+#include "ccache.h"
+#include "ccache_iterator.h"
+#include "context.h"
+#include "msg.h"
+#include "msg_headers.h"
+
+cc_int32 
+cc_initialize (        cc_context_t*           outContext,
+                cc_int32               inVersion,
+                cc_int32*              outSupportedVersion,
+                char const**           outVendor)
+{
+    static char vendor[128] = "";
+    cc_msg_t     *request;
+    ccmsg_init_t *request_header;
+    cc_msg_t     *response;
+    ccmsg_init_resp_t *response_header;
+    cc_int32 code;
+
+    if ((inVersion != ccapi_version_2) &&
+         (inVersion != ccapi_version_3) &&
+         (inVersion != ccapi_version_4) &&
+         (inVersion != ccapi_version_5)) {
+
+        if (outSupportedVersion != NULL) {
+            *outSupportedVersion = ccapi_version_5;
+        }
+        return ccErrBadAPIVersion;
+    }   
+
+    request_header = (ccmsg_init_t*)malloc(sizeof(ccmsg_init_t));
+    if (request_header == NULL)
+        return ccErrNoMem;
+
+    request_header->in_version = inVersion;
+
+    code = cci_msg_new(ccmsg_INIT, &request);
+    if (code != ccNoError) {
+        free(request_header);
+        return code;
+    }
+
+    code = cci_msg_add_header(request, request_header, sizeof(ccmsg_init_t));
+
+    code = cci_perform_rpc(request, &response);
+
+    if (response->type == ccmsg_NACK) {
+        ccmsg_nack_t * nack_header = (ccmsg_nack_t *)response->header;
+        code = nack_header->err_code;
+    } else if (response->type == ccmsg_ACK) {
+        response_header = (ccmsg_init_resp_t *)response->header;
+        *outSupportedVersion = response_header->out_version;
+        code = cc_context_int_new(outContext, response_header->out_ctx, response_header->out_version);
+
+        if (!vendor[0]) {
+            char * string;
+            code = cci_msg_retrieve_blob(response, response_header->vendor_offset, response_header->vendor_length, &string);
+            strncpy(vendor, string, sizeof(vendor)-1);
+            vendor[sizeof(vendor)-1] = '\0';
+            free(string);
+        } 
+        *outVendor = vendor;
+
+        code = ccNoError;
+    } else {
+        code = ccErrBadInternalMessage;
+    }
+    cci_msg_destroy(request);
+    cci_msg_destroy(response);
+    return code;
+}
+
diff --git a/src/lib/ccapi/client/ccache.c b/src/lib/ccapi/client/ccache.c
new file mode 100644 (file)
index 0000000..5de3880
--- /dev/null
@@ -0,0 +1,1098 @@
+/* $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).
+ * $
+ */
+
+
+/* ccache.c */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <CredentialsCache.h>
+#include "credentials.h"
+#include "ccache.h"
+#include "msg.h"
+#include "msg_headers.h"
+
+cc_int32
+cc_int_ccache_new( cc_ccache_t * pccache, cc_handle hctx, cc_handle hccache )
+{
+    cc_int_ccache_t ccache = (cc_int_ccache_t)malloc(sizeof(cc_int_ccache_d));
+    if ( ccache == NULL )
+        return ccErrNoMem;
+
+    ccache->functions = (cc_ccache_f*)malloc(sizeof(cc_ccache_f));
+    if ( ccache->functions == NULL ) {
+        free(ccache);
+        return ccErrNoMem;
+    }
+
+    ccache->functions->release = cc_int_ccache_release;
+    ccache->functions->destroy = cc_int_ccache_destroy;
+    ccache->functions->set_default = cc_int_ccache_set_default;
+    ccache->functions->get_credentials_version = cc_int_ccache_get_credentials_version;
+    ccache->functions->get_name = cc_int_ccache_get_name;
+    ccache->functions->get_principal = cc_int_ccache_get_principal;
+    ccache->functions->set_principal = cc_int_ccache_set_principal;
+    ccache->functions->store_credentials = cc_int_ccache_store_credentials;
+    ccache->functions->remove_credentials = cc_int_ccache_remove_credentials;
+    ccache->functions->new_credentials_iterator = cc_int_ccache_new_credentials_iterator;
+    ccache->functions->move = cc_int_ccache_move;
+    ccache->functions->lock = cc_int_ccache_lock;
+    ccache->functions->unlock = cc_int_ccache_unlock;
+    ccache->functions->get_last_default_time = cc_int_ccache_get_last_default_time;
+    ccache->functions->get_change_time = cc_int_ccache_get_change_time;
+    ccache->functions->compare = cc_int_ccache_compare;
+    ccache->functions->get_kdc_time_offset = cc_int_ccache_get_kdc_time_offset;
+    ccache->functions->set_kdc_time_offset = cc_int_ccache_set_kdc_time_offset;
+    ccache->functions->clear_kdc_time_offset = cc_int_ccache_clear_kdc_time_offset;
+
+    ccache->magic = CC_CCACHE_MAGIC;
+    ccache->ctx = hctx;
+    ccache->handle = hccache;
+
+    *pccache = (cc_ccache_t)ccache;
+
+    return ccNoError;
+}
+
+cc_int32    
+cc_int_ccache_release( cc_ccache_t ccache )
+{
+    cc_int_ccache_t int_ccache;
+    cc_msg_t        *request;
+    ccmsg_ccache_release_t *request_header;
+    cc_msg_t        *response;
+    cc_int32 code;
+
+    if ( ccache == NULL )
+        return ccErrBadParam;
+
+    int_ccache = (cc_int_ccache_t)ccache;
+
+    if ( int_ccache->magic != CC_CCACHE_MAGIC )
+        return ccErrInvalidCCache;
+
+    request_header = (ccmsg_ccache_release_t*)malloc(sizeof(ccmsg_ccache_release_t));
+    if (request_header == NULL)
+        return ccErrNoMem;
+    request_header->ctx = int_ccache->ctx;
+    request_header->ccache = int_ccache->handle;
+
+    code = cci_msg_new(ccmsg_CCACHE_RELEASE, &request);
+    if (code != ccNoError) {
+        free(request_header);
+        return code;
+    }
+
+    code = cci_msg_add_header(request, request_header, sizeof(ccmsg_ccache_release_t));
+
+    code = cci_perform_rpc(request, &response);
+
+    if (response->type == ccmsg_NACK) {
+        ccmsg_nack_t * nack_header = (ccmsg_nack_t *)response->header;
+        code = nack_header->err_code;
+    } else if (response->type == ccmsg_ACK) {
+        code = ccNoError;
+    } else {
+        code = ccErrBadInternalMessage;
+    }
+    cci_msg_destroy(request);
+    cci_msg_destroy(response);
+    free(int_ccache->functions);
+    free(int_ccache);
+    return code;
+}
+
+
+cc_int32    
+cc_int_ccache_destroy( cc_ccache_t ccache )
+{
+    cc_int_ccache_t int_ccache;
+    cc_msg_t        *request;
+    ccmsg_ccache_destroy_t *request_header;
+    cc_msg_t        *response;
+    cc_int32 code;
+
+    if ( ccache == NULL )
+        return ccErrBadParam;
+
+    int_ccache = (cc_int_ccache_t)ccache;
+
+    if ( int_ccache->magic != CC_CCACHE_MAGIC )
+        return ccErrInvalidCCache;
+
+    request_header = (ccmsg_ccache_destroy_t*)malloc(sizeof(ccmsg_ccache_destroy_t));
+    if (request_header == NULL)
+        return ccErrNoMem;
+    request_header->ctx = int_ccache->ctx;
+    request_header->ccache = int_ccache->handle;
+
+    code = cci_msg_new(ccmsg_CCACHE_DESTROY, &request);
+    if (code != ccNoError) {
+        free(request_header);
+        return code;
+    }
+
+    code = cci_msg_add_header(request, request_header, sizeof(ccmsg_ccache_destroy_t));
+
+    code = cci_perform_rpc(request, &response);
+
+    if (response->type == ccmsg_NACK) {
+        ccmsg_nack_t * nack_header = (ccmsg_nack_t *)response->header;
+        code = nack_header->err_code;
+    } else if (response->type == ccmsg_ACK) {
+        code = ccNoError;
+    } else {
+        code = ccErrBadInternalMessage;
+    }
+    cci_msg_destroy(request);
+    cci_msg_destroy(response);
+    free(ccache);
+    return code;
+}
+
+
+cc_int32
+cc_int_ccache_set_default( cc_ccache_t ccache )
+{
+    cc_int_ccache_t int_ccache;
+    cc_msg_t        *request;
+    ccmsg_ccache_set_default_t *request_header;
+    cc_msg_t        *response;
+    cc_int32 code;
+
+    if ( ccache == NULL )
+        return ccErrBadParam;
+
+    int_ccache = (cc_int_ccache_t)ccache;
+
+    if ( int_ccache->magic != CC_CCACHE_MAGIC )
+        return ccErrInvalidCCache;
+
+    request_header = (ccmsg_ccache_set_default_t*)malloc(sizeof(ccmsg_ccache_set_default_t));
+    if (request_header == NULL)
+        return ccErrNoMem;
+    request_header->ctx = int_ccache->ctx;
+    request_header->ccache = int_ccache->handle;
+
+    code = cci_msg_new(ccmsg_CCACHE_SET_DEFAULT, &request);
+    if (code != ccNoError) {
+        free(request_header);
+        return code;
+    }
+
+    code = cci_msg_add_header(request, request_header, sizeof(ccmsg_ccache_set_default_t));
+
+    code = cci_perform_rpc(request, &response);
+
+    if (response->type == ccmsg_NACK) {
+        ccmsg_nack_t * nack_header = (ccmsg_nack_t *)response->header;
+        code = nack_header->err_code;
+    } else if (response->type == ccmsg_ACK) {
+        code = ccNoError;
+    } else {
+        code = ccErrBadInternalMessage;
+    }
+    cci_msg_destroy(request);
+    cci_msg_destroy(response);
+    return code;
+}
+
+cc_int32
+cc_int_ccache_get_credentials_version( cc_ccache_t ccache,
+                                   cc_uint32* credentials_version)
+{
+    cc_int_ccache_t int_ccache;
+    cc_msg_t        *request;
+    ccmsg_ccache_get_creds_version_t *request_header;
+    cc_msg_t        *response;
+    cc_int32 code;
+
+    if ( ccache == NULL )
+        return ccErrBadParam;
+
+    int_ccache = (cc_int_ccache_t)ccache;
+
+    if ( int_ccache->magic != CC_CCACHE_MAGIC )
+        return ccErrInvalidCCache;
+
+    request_header = (ccmsg_ccache_get_creds_version_t*)malloc(sizeof(ccmsg_ccache_get_creds_version_t));
+    if (request_header == NULL)
+        return ccErrNoMem;
+    request_header->ctx = int_ccache->ctx;
+    request_header->ccache = int_ccache->handle;
+
+    code = cci_msg_new(ccmsg_CCACHE_GET_CREDS_VERSION, &request);
+    if (code != ccNoError) {
+        free(request_header);
+        return code;
+    }
+
+    code = cci_msg_add_header(request, request_header, sizeof(ccmsg_ccache_get_creds_version_t));
+
+    code = cci_perform_rpc(request, &response);
+
+    if (response->type == ccmsg_NACK) {
+        ccmsg_nack_t * nack_header = (ccmsg_nack_t *)response->header;
+        code = nack_header->err_code;
+    } else if (response->type == ccmsg_ACK) {
+        ccmsg_ccache_get_creds_version_resp_t * response_header = (ccmsg_ccache_get_creds_version_resp_t*)response->header;
+        *credentials_version = response_header->version;
+        code = ccNoError;
+    } else {
+        code = ccErrBadInternalMessage;
+    }
+    cci_msg_destroy(request);
+    cci_msg_destroy(response);
+    return code;
+}
+
+cc_int32
+cc_int_ccache_get_name( cc_ccache_t ccache,
+                    cc_string_t* name )
+{
+    cc_int_ccache_t int_ccache;
+    cc_msg_t        *request;
+    ccmsg_ccache_get_name_t *request_header;
+    cc_msg_t        *response;
+    cc_int32 code;
+
+    if ( ccache == NULL )
+        return ccErrBadParam;
+
+    int_ccache = (cc_int_ccache_t)ccache;
+
+    if ( int_ccache->magic != CC_CCACHE_MAGIC )
+        return ccErrInvalidCCache;
+
+    request_header = (ccmsg_ccache_get_name_t*)malloc(sizeof(ccmsg_ccache_get_name_t));
+    if (request_header == NULL)
+        return ccErrNoMem;
+    request_header->ctx = int_ccache->ctx;
+    request_header->ccache = int_ccache->handle;
+
+    code = cci_msg_new(ccmsg_CCACHE_GET_NAME, &request);
+    if (code != ccNoError) {
+        free(request_header);
+        return code;
+    }
+
+    code = cci_msg_add_header(request, request_header, sizeof(ccmsg_ccache_get_name_t));
+
+    code = cci_perform_rpc(request, &response);
+
+    if (response->type == ccmsg_NACK) {
+        ccmsg_nack_t * nack_header = (ccmsg_nack_t *)response->header;
+        code = nack_header->err_code;
+    } else if (response->type == ccmsg_ACK) {
+        char * string;
+        ccmsg_ccache_get_name_resp_t * response_header = (ccmsg_ccache_get_name_resp_t*)response->header;
+        code = cci_msg_retrieve_blob(response, response_header->name_offset, 
+                                      response_header->name_len, &string);
+        if (code == ccNoError) {
+            code = cc_string_new(&name, string);
+            free(string);
+        }
+    } else {
+        code = ccErrBadInternalMessage;
+    }
+    cci_msg_destroy(request);
+    cci_msg_destroy(response);
+    return code;
+}
+
+cc_int32
+cc_int_ccache_get_principal( cc_ccache_t ccache,
+                        cc_uint32 credentials_version,
+                        cc_string_t* principal )
+{
+    cc_int_ccache_t int_ccache;
+    cc_msg_t        *request;
+    ccmsg_ccache_get_principal_t *request_header;
+    cc_msg_t        *response;
+    cc_int32 code;
+
+    if ( ccache == NULL )
+        return ccErrBadParam;
+
+    int_ccache = (cc_int_ccache_t)ccache;
+
+    if ( int_ccache->magic != CC_CCACHE_MAGIC )
+        return ccErrInvalidCCache;
+
+    request_header = (ccmsg_ccache_get_principal_t*)malloc(sizeof(ccmsg_ccache_get_principal_t));
+    if (request_header == NULL)
+        return ccErrNoMem;
+    request_header->ctx = int_ccache->ctx;
+    request_header->ccache = int_ccache->handle;
+    request_header->version = credentials_version;
+
+    code = cci_msg_new(ccmsg_CCACHE_GET_PRINCIPAL, &request);
+    if (code != ccNoError) {
+        free(request_header);
+        return code;
+    }
+
+    code = cci_msg_add_header(request, request_header, sizeof(ccmsg_ccache_get_principal_t));
+
+    code = cci_perform_rpc(request, &response);
+
+    if (response->type == ccmsg_NACK) {
+        ccmsg_nack_t * nack_header = (ccmsg_nack_t *)response->header;
+        code = nack_header->err_code;
+    } else if (response->type == ccmsg_ACK) {
+        char * string;
+        ccmsg_ccache_get_principal_resp_t * response_header = (ccmsg_ccache_get_principal_resp_t*)response->header;
+        code = cci_msg_retrieve_blob(response, response_header->principal_offset, 
+                                      response_header->principal_len, &string);
+        if (code == ccNoError) {
+            code = cc_string_new(&principal, string);
+            free(string);
+        }
+    } else {
+        code = ccErrBadInternalMessage;
+    }
+    cci_msg_destroy(request);
+    cci_msg_destroy(response);
+    return code;
+}
+
+cc_int32
+cc_int_ccache_set_principal( cc_ccache_t ccache,
+                         cc_uint32 credentials_version,
+                         const char* principal )
+{
+    cc_uint32   blob_pos;
+    cc_int_ccache_t int_ccache;
+    cc_msg_t        *request;
+    ccmsg_ccache_set_principal_t *request_header;
+    cc_msg_t        *response;
+    cc_int32 code;
+
+    if ( ccache == NULL )
+        return ccErrBadParam;
+
+    int_ccache = (cc_int_ccache_t)ccache;
+
+    if ( int_ccache->magic != CC_CCACHE_MAGIC )
+        return ccErrInvalidCCache;
+
+    request_header = (ccmsg_ccache_set_principal_t*)malloc(sizeof(ccmsg_ccache_set_principal_t));
+    if (request_header == NULL)
+        return ccErrNoMem;
+    request_header->ctx = int_ccache->ctx;
+    request_header->ccache = int_ccache->handle;
+    request_header->version = credentials_version;
+
+    code = cci_msg_new(ccmsg_CCACHE_GET_PRINCIPAL, &request);
+    if (code != ccNoError) {
+        free(request_header);
+        return code;
+    }
+
+    code = cci_msg_add_data_blob(request, (void*)principal, strlen(principal) + 1, &blob_pos);
+    if (code != ccNoError) {
+        cci_msg_destroy(request);
+        free(request_header);
+        return code;
+    }
+    
+    request_header->principal_offset = blob_pos;
+    request_header->principal_len = strlen(principal) + 1;
+
+    code = cci_msg_add_header(request, request_header, sizeof(ccmsg_ccache_set_principal_t));
+
+    code = cci_perform_rpc(request, &response);
+
+    if (response->type == ccmsg_NACK) {
+        ccmsg_nack_t * nack_header = (ccmsg_nack_t *)response->header;
+        code = nack_header->err_code;
+    } else if (response->type == ccmsg_ACK) {
+        code = ccNoError;
+    } else {
+        code = ccErrBadInternalMessage;
+    }
+    cci_msg_destroy(request);
+    cci_msg_destroy(response);
+    return code;
+}
+
+cc_int32
+cc_int_ccache_new_credentials_iterator( cc_ccache_t ccache,
+                                        cc_credentials_iterator_t* iterator )
+{
+    cc_int_ccache_t int_ccache;
+    cc_msg_t        *request;
+    ccmsg_ccache_creds_iterator_t *request_header;
+    cc_msg_t        *response;
+    cc_int32 code;
+
+    if ( ccache == NULL )
+        return ccErrBadParam;
+
+    int_ccache = (cc_int_ccache_t)ccache;
+
+    if ( int_ccache->magic != CC_CCACHE_MAGIC )
+        return ccErrInvalidCCache;
+
+    request_header = (ccmsg_ccache_creds_iterator_t*)malloc(sizeof(ccmsg_ccache_creds_iterator_t));
+    if (request_header == NULL)
+        return ccErrNoMem;
+    request_header->ctx = int_ccache->ctx;
+    request_header->ccache = int_ccache->handle;
+
+    code = cci_msg_new(ccmsg_CCACHE_CREDS_ITERATOR, &request);
+    if (code != ccNoError) {
+        free(request_header);
+        return code;
+    }
+
+    code = cci_msg_add_header(request, request_header, sizeof(ccmsg_ccache_creds_iterator_t));
+
+    code = cci_perform_rpc(request, &response);
+
+    if (response->type == ccmsg_NACK) {
+        ccmsg_nack_t * nack_header = (ccmsg_nack_t *)response->header;
+        code = nack_header->err_code;
+    } else if (response->type == ccmsg_ACK) {
+        ccmsg_ccache_creds_iterator_resp_t * response_header = (ccmsg_ccache_creds_iterator_resp_t*)response->header;
+        code = cc_int_credentials_iterator_new(iterator, response_header->iterator);
+    } else {
+        code = ccErrBadInternalMessage;
+    }
+    cci_msg_destroy(request);
+    cci_msg_destroy(response);
+    return code;
+}
+
+cc_int32
+cc_int_ccache_store_credentials( cc_ccache_t ccache,
+                             const cc_credentials_union* credentials )
+{
+    cc_int_ccache_t int_ccache;
+    cc_msg_t        *request;
+    ccmsg_ccache_store_creds_t *request_header;
+    cc_msg_t        *response;
+    char            *flat_cred = 0;
+    cc_uint32       flat_cred_len = 0;
+    cc_uint32       blob_pos;
+    cc_int32 code;
+
+    if ( ccache == NULL || credentials == NULL )
+        return ccErrBadParam;
+
+    int_ccache = (cc_int_ccache_t)ccache;
+
+    if ( int_ccache->magic != CC_CCACHE_MAGIC )
+        return ccErrInvalidCCache;
+
+    request_header = (ccmsg_ccache_store_creds_t*)malloc(sizeof(ccmsg_ccache_store_creds_t));
+    if (request_header == NULL)
+        return ccErrNoMem;
+    request_header->ctx = int_ccache->ctx;
+    request_header->ccache = int_ccache->handle;
+
+    code = cci_msg_new(ccmsg_CCACHE_STORE_CREDS, &request);
+    if (code != ccNoError) {
+        free(request_header);
+        return code;
+    }
+
+    switch ( credentials->version ) {
+    case cc_credentials_v4:
+        code = cci_creds_v4_marshall(credentials->credentials.credentials_v4, &flat_cred, &flat_cred_len);
+        break;
+    case cc_credentials_v5:
+        code = cci_creds_v5_marshall(credentials->credentials.credentials_v5, &flat_cred, &flat_cred_len);
+        break;
+    default:
+        cci_msg_destroy(request);
+        free(request_header);
+        return ccErrBadCredentialsVersion;
+    }
+    if (code != ccNoError) {
+        cci_msg_destroy(request);
+        free(request_header);
+        return code;
+    }
+
+    code = cci_msg_add_data_blob(request, (void*)flat_cred, flat_cred_len, &blob_pos);
+    if (code != ccNoError) {
+        cci_msg_destroy(request);
+        free(request_header);
+        return code;
+    }
+    
+    request_header->creds_version = credentials->version;
+    request_header->creds_offset = blob_pos;
+    request_header->creds_len = flat_cred_len;
+
+    code = cci_msg_add_header(request, request_header, sizeof(ccmsg_ccache_store_creds_t));
+
+    code = cci_perform_rpc(request, &response);
+
+    if (response->type == ccmsg_NACK) {
+        ccmsg_nack_t * nack_header = (ccmsg_nack_t *)response->header;
+        code = nack_header->err_code;
+    } else if (response->type == ccmsg_ACK) {
+        code = ccNoError;
+    } else {
+        code = ccErrBadInternalMessage;
+    }
+    free(flat_cred);
+    cci_msg_destroy(request);
+    cci_msg_destroy(response);
+    return code;
+}
+
+cc_int32
+cc_int_ccache_remove_credentials( cc_ccache_t ccache,
+                              cc_credentials_t credentials )
+{
+    cc_int_ccache_t int_ccache;
+    cc_int_credentials_t  int_creds;
+    cc_msg_t        *request;
+    ccmsg_ccache_rem_creds_t *request_header;
+    cc_msg_t        *response;
+    cc_int32 code;
+
+    if ( ccache == NULL || credentials == NULL )
+        return ccErrBadParam;
+
+    int_ccache = (cc_int_ccache_t)ccache;
+    int_creds  = (cc_int_credentials_t)credentials;
+
+    if ( int_ccache->magic != CC_CCACHE_MAGIC )
+        return ccErrInvalidCCache;
+
+    if ( int_creds->magic != CC_CREDS_MAGIC )
+        return ccErrInvalidCredentials;
+
+    request_header = (ccmsg_ccache_rem_creds_t*)malloc(sizeof(ccmsg_ccache_rem_creds_t));
+    if (request_header == NULL)
+        return ccErrNoMem;
+    
+    request_header->ctx = int_ccache->ctx;
+    request_header->ccache = int_ccache->handle;
+    request_header->creds  = int_creds->handle;
+
+    code = cci_msg_new(ccmsg_CCACHE_REM_CREDS, &request);
+    if (code != ccNoError) {
+        free(request_header);
+        return code;
+    }
+
+    code = cci_msg_add_header(request, request_header, sizeof(ccmsg_ccache_rem_creds_t));
+
+    code = cci_perform_rpc(request, &response);
+
+    if (response->type == ccmsg_NACK) {
+        ccmsg_nack_t * nack_header = (ccmsg_nack_t *)response->header;
+        code = nack_header->err_code;
+    } else if (response->type == ccmsg_ACK) {
+        code = ccNoError;
+    } else {
+        code = ccErrBadInternalMessage;
+    }
+    cci_msg_destroy(request);
+    cci_msg_destroy(response);
+    return code;
+}
+
+
+cc_int32
+cc_int_ccache_move( cc_ccache_t source,
+                    cc_ccache_t destination )
+{
+    cc_int_ccache_t int_ccache_source;
+    cc_int_ccache_t int_ccache_dest;
+    cc_msg_t        *request;
+    ccmsg_ccache_move_t *request_header;
+    cc_msg_t        *response;
+    cc_int32 code;
+
+    if ( source == NULL || destination == NULL )
+        return ccErrBadParam;
+
+    int_ccache_source = (cc_int_ccache_t)source;
+    int_ccache_dest = (cc_int_ccache_t)destination;
+
+    if ( int_ccache_source->magic != CC_CCACHE_MAGIC ||
+         int_ccache_dest->magic != CC_CCACHE_MAGIC )
+        return ccErrInvalidCCache;
+
+    if ( int_ccache_source->ctx != int_ccache_dest->ctx )
+        return ccErrInvalidContext;
+
+    request_header = (ccmsg_ccache_move_t*)malloc(sizeof(ccmsg_ccache_move_t));
+    if (request_header == NULL)
+        return ccErrNoMem;
+
+    code = cci_msg_new(ccmsg_CCACHE_MOVE, &request);
+    if (code != ccNoError) {
+        free(request_header);
+        return code;
+    }
+
+    request_header->ctx = int_ccache_source->ctx;
+    request_header->ccache_source = int_ccache_source->handle;
+    request_header->ccache_dest = int_ccache_dest->handle;
+
+    code = cci_msg_add_header(request, request_header, sizeof(ccmsg_ccache_move_t));
+
+    code = cci_perform_rpc(request, &response);
+
+    if (response->type == ccmsg_NACK) {
+        ccmsg_nack_t * nack_header = (ccmsg_nack_t *)response->header;
+        code = nack_header->err_code;
+    } else if (response->type == ccmsg_ACK) {
+        code = ccNoError;
+    } else {
+        code = ccErrBadInternalMessage;
+    }
+    cci_msg_destroy(request);
+    cci_msg_destroy(response);
+    return code;
+}       
+
+cc_int_ccache_lock( cc_ccache_t ccache,
+                cc_uint32 lock_type,
+                cc_uint32 block )
+{
+    cc_int_ccache_t int_ccache;
+    cc_msg_t        *request;
+    ccmsg_ccache_lock_t *request_header;
+    cc_msg_t        *response;
+    cc_int32 code;
+
+    if ( ccache == NULL || 
+         (lock_type != cc_lock_read && lock_type != cc_lock_write) ||
+         (block != cc_lock_block && block != cc_lock_noblock) )
+        return ccErrBadParam;
+
+    int_ccache = (cc_int_ccache_t)ccache;
+
+    if ( int_ccache->magic != CC_CCACHE_MAGIC )
+        return ccErrInvalidCCache;
+
+    request_header = (ccmsg_ccache_lock_t*)malloc(sizeof(ccmsg_ccache_lock_t));
+    if (request_header == NULL)
+        return ccErrNoMem;
+
+    code = cci_msg_new(ccmsg_CCACHE_LOCK, &request);
+    if (code != ccNoError) {
+        free(request_header);
+        return code;
+    }
+
+    request_header->ctx = int_ccache->ctx;
+    request_header->ccache = int_ccache->handle;
+    request_header->lock_type;
+
+    code = cci_msg_add_header(request, request_header, sizeof(ccmsg_ccache_lock_t));
+
+    code = cci_perform_rpc(request, &response);
+
+    if (response->type == ccmsg_NACK) {
+        ccmsg_nack_t * nack_header = (ccmsg_nack_t *)response->header;
+        code = nack_header->err_code;
+
+        // TODO: if (block == cc_lock_block) .....
+    } else if (response->type == ccmsg_ACK) {
+        code = ccNoError;
+    } else {
+        code = ccErrBadInternalMessage;
+    }
+    cci_msg_destroy(request);
+    cci_msg_destroy(response);
+    return code;
+}
+
+cc_int32
+cc_int_ccache_unlock( cc_ccache_t ccache )
+{
+    cc_int_ccache_t int_ccache;
+    cc_msg_t        *request;
+    ccmsg_ccache_unlock_t *request_header;
+    cc_msg_t        *response;
+    cc_int32 code;
+
+    if ( ccache == NULL )
+        return ccErrBadParam;
+
+    int_ccache = (cc_int_ccache_t)ccache;
+
+    if ( int_ccache->magic != CC_CCACHE_MAGIC )
+        return ccErrInvalidCCache;
+
+    request_header = (ccmsg_ccache_unlock_t*)malloc(sizeof(ccmsg_ccache_unlock_t));
+    if (request_header == NULL)
+        return ccErrNoMem;
+
+    code = cci_msg_new(ccmsg_CCACHE_UNLOCK, &request);
+    if (code != ccNoError) {
+        free(request_header);
+        return code;
+    }
+
+    request_header->ctx = int_ccache->ctx;
+    request_header->ccache = int_ccache->handle;
+
+    code = cci_msg_add_header(request, request_header, sizeof(ccmsg_ccache_unlock_t));
+
+    code = cci_perform_rpc(request, &response);
+
+    if (response->type == ccmsg_NACK) {
+        ccmsg_nack_t * nack_header = (ccmsg_nack_t *)response->header;
+        code = nack_header->err_code;
+    } else if (response->type == ccmsg_ACK) {
+        code = ccNoError;
+    } else {
+        code = ccErrBadInternalMessage;
+    }
+    cci_msg_destroy(request);
+    cci_msg_destroy(response);
+    return code;
+}
+
+
+cc_int32
+cc_int_ccache_get_last_default_time( cc_ccache_t ccache,
+                                     cc_time_t* time_offset )
+{
+    cc_int_ccache_t int_ccache;
+    cc_msg_t        *request;
+    ccmsg_ccache_get_last_default_time_t *request_header;
+    cc_msg_t        *response;
+    cc_int32 code;
+
+    if ( ccache == NULL )
+        return ccErrBadParam;
+
+    int_ccache = (cc_int_ccache_t)ccache;
+
+    if ( int_ccache->magic != CC_CCACHE_MAGIC )
+        return ccErrInvalidCCache;
+
+    request_header = (ccmsg_ccache_get_last_default_time_t*)malloc(sizeof(ccmsg_ccache_get_last_default_time_t));
+    if (request_header == NULL)
+        return ccErrNoMem;
+    request_header->ctx = int_ccache->ctx;
+    request_header->ccache = int_ccache->handle;
+
+    code = cci_msg_new(ccmsg_CCACHE_GET_LAST_DEFAULT_TIME, &request);
+    if (code != ccNoError) {
+        free(request_header);
+        return code;
+    }
+
+    code = cci_msg_add_header(request, request_header, sizeof(ccmsg_ccache_get_last_default_time_t));
+
+    code = cci_perform_rpc(request, &response);
+
+    if (response->type == ccmsg_NACK) {
+        ccmsg_nack_t * nack_header = (ccmsg_nack_t *)response->header;
+        code = nack_header->err_code;
+    } else if (response->type == ccmsg_ACK) {
+        ccmsg_ccache_get_last_default_time_resp_t * response_header = (ccmsg_ccache_get_last_default_time_resp_t*)response->header;
+        *time_offset = response_header->last_default_time;
+        code = ccNoError;
+    } else {
+        code = ccErrBadInternalMessage;
+    }
+    cci_msg_destroy(request);
+    cci_msg_destroy(response);
+    return code;
+}
+
+cc_int32
+cc_int_ccache_get_change_time( cc_ccache_t ccache,
+                           cc_time_t* time )
+{
+    cc_int_ccache_t int_ccache;
+    cc_msg_t        *request;
+    ccmsg_ccache_get_change_time_t *request_header;
+    cc_msg_t        *response;
+    cc_int32 code;
+
+    if ( ccache == NULL )
+        return ccErrBadParam;
+
+    int_ccache = (cc_int_ccache_t)ccache;
+
+    if ( int_ccache->magic != CC_CCACHE_MAGIC )
+        return ccErrInvalidCCache;
+
+    request_header = (ccmsg_ccache_get_change_time_t*)malloc(sizeof(ccmsg_ccache_get_change_time_t));
+    if (request_header == NULL)
+        return ccErrNoMem;
+    request_header->ctx = int_ccache->ctx;
+    request_header->ccache = int_ccache->handle;
+
+    code = cci_msg_new(ccmsg_CCACHE_GET_CHANGE_TIME, &request);
+    if (code != ccNoError) {
+        free(request_header);
+        return code;
+    }
+
+    code = cci_msg_add_header(request, request_header, sizeof(ccmsg_ccache_get_change_time_t));
+
+    code = cci_perform_rpc(request, &response);
+
+    if (response->type == ccmsg_NACK) {
+        ccmsg_nack_t * nack_header = (ccmsg_nack_t *)response->header;
+        code = nack_header->err_code;
+    } else if (response->type == ccmsg_ACK) {
+        ccmsg_ccache_get_change_time_resp_t * response_header = (ccmsg_ccache_get_change_time_resp_t*)response->header;
+        *time = response_header->time;
+        code = ccNoError;
+    } else {
+        code = ccErrBadInternalMessage;
+    }
+    cci_msg_destroy(request);
+    cci_msg_destroy(response);
+    return code;
+}
+
+cc_int32
+cc_int_ccache_compare( cc_ccache_t ccache,
+                   cc_ccache_t compare_to,
+                   cc_uint32* equal )
+{
+    cc_int_ccache_t int_ccache;
+    cc_int_ccache_t int_compare_to;
+    cc_msg_t        *request;
+    ccmsg_ccache_compare_t *request_header;
+    cc_msg_t        *response;
+    cc_int32 code;
+
+    if ( ccache == NULL )
+        return ccErrBadParam;
+
+    int_ccache = (cc_int_ccache_t)ccache;
+    int_compare_to = (cc_int_ccache_t)ccache;
+
+    if ( int_ccache->magic != CC_CCACHE_MAGIC ||
+         int_compare_to->magic != CC_CCACHE_MAGIC )
+        return ccErrInvalidCCache;
+
+    request_header = (ccmsg_ccache_compare_t*)malloc(sizeof(ccmsg_ccache_compare_t));
+    if (request_header == NULL)
+        return ccErrNoMem;
+    request_header->ctx = int_ccache->ctx;
+    request_header->ccache1 = int_ccache->handle;
+    request_header->ccache2 = int_compare_to->handle;
+
+    code = cci_msg_new(ccmsg_CCACHE_COMPARE, &request);
+    if (code != ccNoError) {
+        free(request_header);
+        return code;
+    }
+
+    code = cci_msg_add_header(request, request_header, sizeof(ccmsg_ccache_compare_t));
+
+    code = cci_perform_rpc(request, &response);
+
+    if (response->type == ccmsg_NACK) {
+        ccmsg_nack_t * nack_header = (ccmsg_nack_t *)response->header;
+        code = nack_header->err_code;
+    } else if (response->type == ccmsg_ACK) {
+        ccmsg_ccache_compare_resp_t * response_header = (ccmsg_ccache_compare_resp_t*)response->header;
+        *equal = response_header->is_equal;
+        code = ccNoError;
+    } else {
+        code = ccErrBadInternalMessage;
+    }
+    cci_msg_destroy(request);
+    cci_msg_destroy(response);
+    return code;
+}
+
+cc_int32       
+cc_int_ccache_get_kdc_time_offset( cc_ccache_t ccache,
+                               cc_int32        credentials_version,
+                               cc_time_t*      time_offset )
+{
+    cc_int_ccache_t int_ccache;
+    cc_msg_t        *request;
+    ccmsg_ccache_get_kdc_time_offset_t *request_header;
+    cc_msg_t        *response;
+    cc_int32 code;
+
+    if ( ccache == NULL )
+        return ccErrBadParam;
+
+    int_ccache = (cc_int_ccache_t)ccache;
+
+    if ( int_ccache->magic != CC_CCACHE_MAGIC )
+        return ccErrInvalidCCache;
+
+    request_header = (ccmsg_ccache_get_kdc_time_offset_t*)malloc(sizeof(ccmsg_ccache_get_kdc_time_offset_t));
+    if (request_header == NULL)
+        return ccErrNoMem;
+    request_header->ctx = int_ccache->ctx;
+    request_header->ccache = int_ccache->handle;
+    request_header->creds_version = credentials_version;
+
+    code = cci_msg_new(ccmsg_CCACHE_GET_KDC_TIME_OFFSET, &request);
+    if (code != ccNoError) {
+        free(request_header);
+        return code;
+    }
+
+    code = cci_msg_add_header(request, request_header, sizeof(ccmsg_ccache_get_kdc_time_offset_t));
+
+    code = cci_perform_rpc(request, &response);
+
+    if (response->type == ccmsg_NACK) {
+        ccmsg_nack_t * nack_header = (ccmsg_nack_t *)response->header;
+        code = nack_header->err_code;
+    } else if (response->type == ccmsg_ACK) {
+        ccmsg_ccache_get_kdc_time_offset_resp_t * response_header = (ccmsg_ccache_get_kdc_time_offset_resp_t*)response->header;
+        *time_offset = response_header->offset;
+        code = ccNoError;
+    } else {
+        code = ccErrBadInternalMessage;
+    }
+    cci_msg_destroy(request);
+    cci_msg_destroy(response);
+    return code;
+}
+
+cc_int32
+cc_int_ccache_set_kdc_time_offset( cc_ccache_t ccache,
+                               cc_int32        credentials_version,
+                               cc_time_t       time_offset )
+{
+    cc_int_ccache_t int_ccache;
+    cc_msg_t        *request;
+    ccmsg_ccache_set_kdc_time_offset_t *request_header;
+    cc_msg_t        *response;
+    cc_int32 code;
+
+    if ( ccache == NULL )
+        return ccErrBadParam;
+
+    int_ccache = (cc_int_ccache_t)ccache;
+
+    if ( int_ccache->magic != CC_CCACHE_MAGIC )
+        return ccErrInvalidCCache;
+
+    request_header = (ccmsg_ccache_set_kdc_time_offset_t*)malloc(sizeof(ccmsg_ccache_set_kdc_time_offset_t));
+    if (request_header == NULL)
+        return ccErrNoMem;
+    request_header->ctx = int_ccache->ctx;
+    request_header->ccache = int_ccache->handle;
+    request_header->creds_version = credentials_version;
+
+    code = cci_msg_new(ccmsg_CCACHE_SET_KDC_TIME_OFFSET, &request);
+    if (code != ccNoError) {
+        free(request_header);
+        return code;
+    }
+
+    code = cci_msg_add_header(request, request_header, sizeof(ccmsg_ccache_set_kdc_time_offset_t));
+
+    code = cci_perform_rpc(request, &response);
+
+    if (response->type == ccmsg_NACK) {
+        ccmsg_nack_t * nack_header = (ccmsg_nack_t *)response->header;
+        code = nack_header->err_code;
+    } else if (response->type == ccmsg_ACK) {
+        code = ccNoError;
+    } else {
+        code = ccErrBadInternalMessage;
+    }
+    cci_msg_destroy(request);
+    cci_msg_destroy(response);
+    return code;
+}
+                                
+cc_int32
+cc_int_ccache_clear_kdc_time_offset( cc_ccache_t       ccache,
+                                 cc_int32      credentials_version )
+{
+    cc_int_ccache_t int_ccache;
+    cc_msg_t        *request;
+    ccmsg_ccache_clear_kdc_time_offset_t *request_header;
+    cc_msg_t        *response;
+    cc_int32 code;
+
+    if ( ccache == NULL )
+        return ccErrBadParam;
+
+    int_ccache = (cc_int_ccache_t)ccache;
+
+    if ( int_ccache->magic != CC_CCACHE_MAGIC )
+        return ccErrInvalidCCache;
+
+    request_header = (ccmsg_ccache_clear_kdc_time_offset_t*)malloc(sizeof(ccmsg_ccache_clear_kdc_time_offset_t));
+    if (request_header == NULL)
+        return ccErrNoMem;
+    request_header->ctx = int_ccache->ctx;
+    request_header->ccache = int_ccache->handle;
+    request_header->creds_version = credentials_version;
+
+    code = cci_msg_new(ccmsg_CCACHE_CLEAR_KDC_TIME_OFFSET, &request);
+    if (code != ccNoError) {
+        free(request_header);
+        return code;
+    }
+
+    code = cci_msg_add_header(request, request_header, sizeof(ccmsg_ccache_clear_kdc_time_offset_t));
+
+    code = cci_perform_rpc(request, &response);
+
+    if (response->type == ccmsg_NACK) {
+        ccmsg_nack_t * nack_header = (ccmsg_nack_t *)response->header;
+        code = nack_header->err_code;
+    } else if (response->type == ccmsg_ACK) {
+        code = ccNoError;
+    } else {
+        code = ccErrBadInternalMessage;
+    }
+    cci_msg_destroy(request);
+    cci_msg_destroy(response);
+    return code;
+}
+
+
diff --git a/src/lib/ccapi/client/ccache.h b/src/lib/ccapi/client/ccache.h
new file mode 100644 (file)
index 0000000..e3b3993
--- /dev/null
@@ -0,0 +1,146 @@
+/* $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).
+ * $
+ */
+
+/* ccache.h */
+
+#define CC_CCACHE_MAGIC ('C'<<24 | 'C'<<16 | 'A'<<8 | 'C')
+
+struct cc_int_ccache_d {
+    cc_ccache_f*       functions;
+#if TARGET_OS_MAC
+    const cc_ccache_f* otherFunctions;
+#endif
+    cc_uint32           magic;
+    cc_handle           handle;
+    cc_handle           ctx;
+};
+typedef struct cc_int_ccache_d  cc_int_ccache_d;
+typedef cc_int_ccache_d*        cc_int_ccache_t;
+
+
+cc_int32
+cc_int_ccache_new( cc_ccache_t * pccache, cc_handle hctx, cc_handle hccache );
+
+cc_int32    
+cc_int_ccache_release( cc_ccache_t ccache );
+
+cc_int32    
+cc_int_ccache_destroy( cc_ccache_t ccache );
+
+cc_int32
+cc_int_ccache_set_default( cc_ccache_t ccache );
+
+cc_int32
+cc_int_ccache_get_credentials_version( cc_ccache_t ccache,
+                                  cc_uint32* credentials_version);   
+
+cc_int32
+cc_int_ccache_get_name( cc_ccache_t ccache,
+                   cc_string_t* name );
+
+cc_int32
+cc_int_ccache_get_principal( cc_ccache_t ccache,
+                        cc_uint32 credentials_version,
+                        cc_string_t* principal );
+
+cc_int32
+cc_int_ccache_set_principal( cc_ccache_t ccache,
+                        cc_uint32 credentials_version,
+                        const char* principal );
+
+cc_int32
+cc_int_ccache_store_credentials( cc_ccache_t ccache,
+                            const cc_credentials_union* credentials );
+
+cc_int32
+cc_int_ccache_remove_credentials( cc_ccache_t ccache,
+                              cc_credentials_t credentials );
+
+cc_int32
+cc_int_ccache_new_credentials_iterator( cc_ccache_t ccache,
+                                        cc_credentials_iterator_t* iterator );
+
+cc_int32
+cc_int_ccache_move( cc_ccache_t source,
+               cc_ccache_t destination );
+
+cc_int32
+cc_int_ccache_lock( cc_ccache_t ccache,
+               cc_uint32 block,
+               cc_uint32 lock_type );
+
+cc_int32
+cc_int_ccache_unlock( cc_ccache_t ccache );
+
+cc_int32
+cc_int_ccache_get_last_default_time( cc_ccache_t ccache,
+                                cc_time_t* time );
+
+cc_int32
+cc_int_ccache_get_change_time( cc_ccache_t ccache,
+                          cc_time_t* time );
+
+cc_int32
+cc_int_ccache_compare( cc_ccache_t ccache,
+                  cc_ccache_t compare_to,
+                  cc_uint32* equal );
+
+cc_int32       
+cc_int_ccache_get_kdc_time_offset( cc_ccache_t ccache,
+                              cc_int32 credentials_version,
+                              cc_time_t*       time_offset );
+
+cc_int32
+cc_int_ccache_set_kdc_time_offset( cc_ccache_t ccache,
+                              cc_int32 credentials_version,
+                              cc_time_t        time_offset );
+                                
+cc_int32
+cc_int_ccache_clear_kdc_time_offset( cc_ccache_t       ccache,
+                                cc_int32       credentials_version );
+
+
+cc_int32
+cc_int_ccache_compat_clone( cc_int_ccache_t     ccache,
+                            cc_int_ccache_t    *clone );
+
diff --git a/src/lib/ccapi/client/ccache_iterator.c b/src/lib/ccapi/client/ccache_iterator.c
new file mode 100644 (file)
index 0000000..03266b1
--- /dev/null
@@ -0,0 +1,179 @@
+/* $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).
+ * $
+ */
+
+/* ccache_iterator.c */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <CredentialsCache.h>
+#include "ccache_iterator.h"
+#include "msg.h"
+#include "msg_headers.h"
+
+
+cc_int32
+cc_int_ccache_iterator_new( cc_ccache_iterator_t * piter,
+                            cc_handle ctx,
+                            cc_handle handle )
+{
+    cc_int_ccache_iterator_t iter;
+
+    if ( piter == NULL )
+        return ccErrBadParam;
+
+    iter = (cc_int_ccache_iterator_t) malloc( sizeof(cc_int_ccache_iterator_d) );
+    if ( iter == NULL )
+        return ccErrNoMem;
+
+    iter->functions = (cc_ccache_iterator_f*)malloc( sizeof(cc_ccache_iterator_f));
+    if ( iter->functions ) {
+        free(iter);
+        return ccErrNoMem;
+    }
+
+    iter->functions->release = cc_int_ccache_iterator_release;
+    iter->functions->next = cc_int_ccache_iterator_next;
+    iter->magic = CC_CCACHE_ITER_MAGIC;
+    iter->ctx = ctx;
+    iter->handle = handle;
+
+    *piter = (cc_ccache_iterator_t)iter;
+    return ccNoError;
+}
+
+cc_int32
+cc_int_ccache_iterator_release( cc_ccache_iterator_t iter )
+{
+    cc_int_ccache_iterator_t int_iter;
+    cc_msg_t        *request;
+    ccmsg_ccache_iterator_release_t *request_header;
+    cc_msg_t        *response;
+    cc_int32 code;
+
+
+    if ( iter == NULL )
+        return ccErrBadParam;
+
+    int_iter = (cc_int_ccache_iterator_t) iter;
+
+    if ( int_iter->magic != CC_CCACHE_ITER_MAGIC )
+        return ccErrInvalidCCacheIterator;
+
+    request_header = (ccmsg_ccache_iterator_release_t*)malloc(sizeof(ccmsg_ccache_iterator_release_t));
+    if (request_header == NULL)
+        return ccErrNoMem;
+    request_header->ctx = int_iter->ctx;
+    request_header->iterator = int_iter->handle;
+    code = cci_msg_new(ccmsg_CCACHE_ITERATOR_RELEASE, &request);
+    if (code != ccNoError) {
+        free(request_header);
+        return code;
+    }
+
+    code = cci_msg_add_header(request, request_header, sizeof(ccmsg_ccache_iterator_release_t));
+
+    code = cci_perform_rpc(request, &response);
+
+    if (response->type == ccmsg_NACK) {
+        ccmsg_nack_t * nack_header = (ccmsg_nack_t *)response->header;
+        code = nack_header->err_code;
+    } else if (response->type == ccmsg_ACK) {
+        code = ccNoError;
+    } else {
+        code = ccErrBadInternalMessage;
+    }
+    cci_msg_destroy(request);
+    cci_msg_destroy(response);
+
+    free(int_iter->functions);
+    free(int_iter);
+    return ccNoError;
+}
+
+cc_int32
+cc_int_ccache_iterator_next( cc_ccache_iterator_t iter,
+                             cc_ccache_t * ccache )
+{
+    cc_int_ccache_iterator_t int_iter;
+    cc_msg_t        *request;
+    ccmsg_ccache_iterator_next_t *request_header;
+    cc_msg_t        *response;
+    cc_int32 code;
+
+    if ( ccache == NULL )
+        return ccErrBadParam;
+
+    int_iter = (cc_int_ccache_iterator_t)iter;
+
+    if ( int_iter->magic != CC_CCACHE_ITER_MAGIC )
+        return ccErrInvalidCCacheIterator;
+
+    request_header = (ccmsg_ccache_iterator_next_t*)malloc(sizeof(ccmsg_ccache_iterator_next_t));
+    if (request_header == NULL)
+        return ccErrNoMem;
+    request_header->ctx = int_iter->ctx;
+    request_header->iterator = int_iter->handle;
+
+    code = cci_msg_new(ccmsg_CCACHE_ITERATOR_NEXT, &request);
+    if (code != ccNoError) {
+        free(request_header);
+        return code;
+    }
+
+    code = cci_msg_add_header(request, request_header, sizeof(ccmsg_ccache_iterator_next_t));
+
+    code = cci_perform_rpc(request, &response);
+
+    if (response->type == ccmsg_NACK) {
+        ccmsg_nack_t * nack_header = (ccmsg_nack_t *)response->header;
+        code = nack_header->err_code;
+    } else if (response->type == ccmsg_ACK) {
+        ccmsg_ccache_iterator_next_resp_t * response_header = (ccmsg_ccache_iterator_next_resp_t*)response->header;
+        code = cc_ccache_new(ccache, int_iter->ctx, response_header->ccache);
+    } else {
+        code = ccErrBadInternalMessage;
+    }
+    cci_msg_destroy(request);
+    cci_msg_destroy(response);
+    return code;
+}
diff --git a/src/lib/ccapi/client/ccache_iterator.h b/src/lib/ccapi/client/ccache_iterator.h
new file mode 100644 (file)
index 0000000..c55d72e
--- /dev/null
@@ -0,0 +1,85 @@
+/* $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).
+ * $
+ */
+
+/* ccache_iterator.h */
+
+#define CC_CCACHE_ITER_MAGIC ('C'<<24 | 'C'<<16 | 'I'<<8 | 'T')
+
+struct cc_int_ccache_iterator_d {
+    cc_ccache_iterator_f*      functions;
+#if TARGET_OS_MAC
+    cc_ccache_iterator_f*      otherFunctions;
+#endif
+    cc_uint32           magic;
+    cc_handle           handle;
+    cc_handle           ctx;
+
+    cc_uint32           repeat_count;
+    cc_ccache_t         compat_copy;
+};
+typedef struct cc_int_ccache_iterator_d cc_int_ccache_iterator_d;
+typedef cc_int_ccache_iterator_d*      cc_int_ccache_iterator_t;
+
+
+cc_int32
+cc_int_ccache_iterator_new( cc_ccache_iterator_t * piter,
+                            cc_handle ctx,
+                            cc_handle handle );
+
+cc_int32
+cc_int_ccache_iterator_release( cc_ccache_iterator_t iter );
+
+cc_int32
+cc_int_ccache_iterator_next( cc_ccache_iterator_t iter,
+                             cc_ccache_t * ccache );
+
+cc_int32
+cc_int_ccache_iterator_set_repeat_count( cc_int_ccache_iterator_t iter, 
+                                         cc_uint32 count );
+
+cc_int32
+cc_int_ccache_iterator_get_repeat_count( cc_int_ccache_iterator_t iter, 
+                                         cc_uint32 * count );
+
+
+
diff --git a/src/lib/ccapi/client/ccstring.c b/src/lib/ccapi/client/ccstring.c
new file mode 100644 (file)
index 0000000..419bfef
--- /dev/null
@@ -0,0 +1,94 @@
+/* $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).
+ * $
+ */
+
+/* ccstring.c */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <CredentialsCache.h>
+#include "ccstring.h"
+
+cc_int32
+cc_int_string_new( cc_string_t * pstring, char * data )
+{
+    cc_int_string_t string = (cc_int_string_t)malloc(sizeof(cc_int_string_d));
+    if ( string == NULL )
+        return ccErrNoMem;
+
+    string->functions = (cc_string_f *)malloc(sizeof(cc_string_f));
+    if ( string->functions == NULL ) {
+        free(string);
+        return ccErrNoMem;
+    }
+
+    string->magic = CC_STRING_MAGIC;
+    string->functions->release = cc_int_string_release;
+
+    string->data = strdup(data);
+    if ( string->data == NULL ) {
+        free(string->functions);
+        free(string);
+        return ccErrNoMem;
+    }
+
+    *pstring = (cc_string_t)string;
+    return ccNoError;
+}
+
+cc_int32
+cc_int_string_release( cc_string_t str )
+{
+    cc_int_string_t int_string;
+    if ( str == NULL )
+        return ccErrBadParam;
+
+    int_string = (cc_int_string_t)str;
+    if ( int_string->magic != CC_STRING_MAGIC )
+        return ccErrInvalidString;
+
+    free(int_string->functions);
+    free(int_string->data);
+    free(int_string);
+    return ccNoError;
+}
diff --git a/src/lib/ccapi/client/ccstring.h b/src/lib/ccapi/client/ccstring.h
new file mode 100644 (file)
index 0000000..9e0ad22
--- /dev/null
@@ -0,0 +1,65 @@
+/* $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).
+ * $
+ */
+
+/* ccstring.h */
+
+#define CC_STRING_MAGIC ('S'<<24 | 'T'<<16 | 'R'<<8 | 'I')
+
+struct cc_int_string_d {
+    char*         data;
+    cc_string_f*  functions;
+#if TARGET_OS_MAC
+    cc_string_f*  otherFunctions;
+#endif
+    cc_uint32           magic;
+};
+typedef struct cc_int_string_d cc_int_string_d;
+typedef cc_int_string_d*    cc_int_string_t;
+
+cc_int32
+cc_int_string_new( cc_string_t * pstring, char * data );
+
+cc_int32
+cc_int_string_release( cc_string_t string );
+
+
diff --git a/src/lib/ccapi/client/context.c b/src/lib/ccapi/client/context.c
new file mode 100644 (file)
index 0000000..86c41b8
--- /dev/null
@@ -0,0 +1,849 @@
+/* $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).
+ * $
+ */
+
+/* context.c */                                                 
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <CredentialsCache.h>
+#include "context.h"
+#include "msg.h"
+#include "msg_headers.h"
+
+cc_int32
+cc_int_context_new( cc_context_t * pcontext, cc_handle handle, cc_uint32 version )
+{
+    cc_int_context_t context = (cc_int_context_t)malloc(sizeof(cc_int_context_d));
+    if (context == NULL)
+        return ccErrNoMem;
+
+    context->functions = (cc_context_f*)malloc(sizeof(cc_context_f));
+    if (context->functions == NULL) {
+        free(context);
+        return ccErrNoMem;
+    }
+
+    context->functions->release = cc_int_context_release;
+    context->functions->get_change_time = cc_int_context_get_change_time;
+    context->functions->get_default_ccache_name = cc_int_context_get_default_ccache_name;
+    context->functions->open_ccache = cc_int_context_open_ccache;
+    context->functions->open_default_ccache = cc_int_context_open_default_ccache;
+    context->functions->create_ccache = cc_int_context_create_ccache;
+    context->functions->create_default_ccache = cc_int_context_create_default_ccache;
+    context->functions->create_new_ccache = cc_int_context_create_new_ccache;
+    context->functions->new_ccache_iterator = cc_int_context_new_ccache_iterator;
+    context->functions->lock = cc_int_context_lock;
+    context->functions->unlock = cc_int_context_unlock;
+    context->functions->compare = cc_int_context_compare;
+
+    context->magic = CC_CONTEXT_MAGIC;
+    context->handle = handle;
+    context->api_version = version;
+
+    *pcontext = (cc_context_t)context;
+    return ccNoError;
+}
+
+cc_int32    
+cc_int_context_release( cc_context_t context )
+{
+    cc_int_context_t int_context;
+    cc_msg_t        *request;
+    ccmsg_ctx_release_t *request_header;
+    cc_msg_t        *response;
+    cc_int32 code;
+
+    if ( context == NULL )
+        return ccErrBadParam;
+
+    int_context = (cc_int_context_t)context;
+
+    if ( int_context->magic != CC_CONTEXT_MAGIC )
+        return ccErrInvalidContext;
+
+    request_header = (ccmsg_ctx_release_t*)malloc(sizeof(ccmsg_ctx_release_t));
+    if (request_header == NULL)
+        return ccErrNoMem;
+    request_header->ctx = int_context->handle;
+
+    code = cci_msg_new(ccmsg_CTX_RELEASE, &request);
+    if (code != ccNoError) {
+        free(request_header);
+        return code;
+    }
+
+    code = cci_msg_add_header(request, request_header, sizeof(ccmsg_ctx_release_t));
+
+    code = cci_perform_rpc(request, &response);
+
+    if (response->type == ccmsg_NACK) {
+        ccmsg_nack_t * nack_header = (ccmsg_nack_t *)response->header;
+        code = nack_header->err_code;
+    } else if (response->type == ccmsg_ACK) {
+        code = ccNoError;
+    } else {
+        code = ccErrBadInternalMessage;
+    }
+    cci_msg_destroy(request);
+    cci_msg_destroy(response);
+    free(int_context->functions);
+    free(int_context);
+    return code;
+}
+
+cc_int32
+cc_int_context_get_change_time( cc_context_t context,
+                                cc_time_t* time)
+{
+    cc_int_context_t int_context;
+    cc_msg_t        *request;
+    ccmsg_ctx_get_change_time_t *request_header;
+    cc_msg_t        *response;
+    ccmsg_ctx_get_change_time_resp_t *response_header;
+    cc_int32 code;
+
+    if ( context == NULL || time == NULL )
+        return ccErrBadParam;
+
+    int_context = (cc_int_context_t)context;
+
+    if ( int_context->magic != CC_CONTEXT_MAGIC )
+        return ccErrInvalidContext;
+
+    request_header = (ccmsg_ctx_get_change_time_t*)malloc(sizeof(ccmsg_ctx_get_change_time_t));
+    if (request_header == NULL)
+        return ccErrNoMem;
+    request_header->ctx = int_context->handle;
+
+    code = cci_msg_new(ccmsg_CTX_GET_CHANGE_TIME, &request);
+    if (code != ccNoError) {
+        free(request_header);
+        return code;
+    }
+
+    code = cci_msg_add_header(request, request_header, sizeof(ccmsg_ctx_get_change_time_t));
+
+    code = cci_perform_rpc(request, &response);
+
+    if (response->type == ccmsg_NACK) {
+        ccmsg_nack_t * nack_header = (ccmsg_nack_t *)response->header;
+        code = nack_header->err_code;
+    } else if (response->type == ccmsg_ACK) {
+        response_header = (ccmsg_ctx_get_change_time_resp_t*)response->header;
+        *time = response_header->time;
+        code = ccNoError;
+    } else {
+        code = ccErrBadInternalMessage;
+    }
+    cci_msg_destroy(request);
+    cci_msg_destroy(response);
+    return code;
+}
+
+cc_int32
+cc_int_context_get_default_ccache_name( cc_context_t context,
+                                        cc_string_t* name )
+{
+    cc_int_context_t int_context;
+    cc_msg_t        *request;
+    ccmsg_ctx_get_default_ccache_name_t *request_header;
+    cc_msg_t        *response;
+    ccmsg_ctx_get_default_ccache_name_resp_t *response_header;
+    cc_int32 code;
+
+    if ( context == NULL || name == NULL )
+        return ccErrBadParam;
+
+    int_context = (cc_int_context_t)context;
+
+    if ( int_context->magic != CC_CONTEXT_MAGIC )
+        return ccErrInvalidContext;
+
+    request_header = (ccmsg_ctx_get_default_ccache_name_t*)malloc(sizeof(ccmsg_ctx_get_default_ccache_name_t));
+    if (request_header == NULL)
+        return ccErrNoMem;
+    request_header->ctx = int_context->handle;
+
+    code = cci_msg_new(ccmsg_CTX_GET_DEFAULT_CCACHE_NAME, &request);
+    if (code != ccNoError) {
+        free(request_header);
+        return code;
+    }
+
+    code = cci_msg_add_header(request, request_header, sizeof(ccmsg_ctx_get_default_ccache_name_t));
+
+    code = cci_perform_rpc(request, &response);
+
+    if (response->type == ccmsg_NACK) {
+        ccmsg_nack_t * nack_header = (ccmsg_nack_t *)response->header;
+        code = nack_header->err_code;
+    } else if (response->type == ccmsg_ACK) {
+        char * string;
+        response_header = (ccmsg_ctx_get_default_ccache_name_resp_t*)response->header;
+        code = cci_msg_retrieve_blob(response, response_header->name_offset, 
+                                     response_header->name_len, &string);
+        if (code == ccNoError) {
+            code = cc_string_new(&name, string);
+            free(string);
+        }
+    } else {
+        code = ccErrBadInternalMessage;
+    }
+    cci_msg_destroy(request);
+    cci_msg_destroy(response);
+    return code;
+}
+
+cc_int32
+cc_int_context_compare( cc_context_t context,
+                        cc_context_t compare_to,
+                        cc_uint32* equal )
+{
+    cc_int_context_t int_context, int_compare_to;
+    cc_msg_t        *request;
+    ccmsg_ctx_compare_t *request_header;
+    cc_msg_t        *response;
+    ccmsg_ctx_compare_resp_t *response_header;
+    cc_int32 code;
+
+    if ( context == NULL || compare_to == NULL || 
+         equal == NULL )
+        return ccErrBadParam;
+
+    int_context = (cc_int_context_t)context;
+    int_compare_to = (cc_int_context_t)compare_to;
+
+    if ( int_context->magic != CC_CONTEXT_MAGIC ||
+         int_compare_to->magic != CC_CONTEXT_MAGIC )
+        return ccErrInvalidContext;
+
+    request_header = (ccmsg_ctx_compare_t*)malloc(sizeof(ccmsg_ctx_compare_t));
+    if (request_header == NULL)
+        return ccErrNoMem;
+    request_header->ctx1 = int_context->handle;
+    request_header->ctx2 = int_compare_to->handle;
+
+    code = cci_msg_new(ccmsg_CTX_COMPARE, &request);
+    if (code != ccNoError) {
+        free(request_header);
+        return code;
+    }
+
+    code = cci_msg_add_header(request, request_header, sizeof(ccmsg_ctx_compare_t));
+
+    code = cci_perform_rpc(request, &response);
+
+    if (response->type == ccmsg_NACK) {
+        ccmsg_nack_t * nack_header = (ccmsg_nack_t *)response->header;
+        code = nack_header->err_code;
+    } else if (response->type == ccmsg_ACK) {
+        response_header = (ccmsg_ctx_compare_resp_t*)response->header;
+        *equal = response_header->is_equal;
+        code = ccNoError;
+    } else {
+        code = ccErrBadInternalMessage;
+    }
+    cci_msg_destroy(request);
+    cci_msg_destroy(response);
+    return code;
+}
+
+
+cc_int32
+cc_int_context_new_ccache_iterator( cc_context_t context,
+                                    cc_ccache_iterator_t* iterator )
+{
+    cc_int_context_t int_context;
+    cc_msg_t        *request;
+    ccmsg_ctx_new_ccache_iterator_t *request_header;
+    cc_msg_t        *response;
+    ccmsg_ctx_new_ccache_iterator_resp_t *response_header;
+    cc_int32 code;
+
+    if ( context == NULL || iterator == NULL )
+        return ccErrBadParam;
+
+    int_context = (cc_int_context_t)context;
+
+    if ( int_context->magic != CC_CONTEXT_MAGIC )
+        return ccErrInvalidContext;
+
+    request_header = (ccmsg_ctx_new_ccache_iterator_t*)malloc(sizeof(ccmsg_ctx_new_ccache_iterator_t));
+    if (request_header == NULL)
+        return ccErrNoMem;
+    request_header->ctx = int_context->handle;
+
+    code = cci_msg_new(ccmsg_CTX_NEW_CCACHE_ITERATOR, &request);
+    if (code != ccNoError) {
+        free(request_header);
+        return code;
+    }
+
+    code = cci_msg_add_header(request, request_header, sizeof(ccmsg_ctx_new_ccache_iterator_t));
+
+    code = cci_perform_rpc(request, &response);
+
+    if (response->type == ccmsg_NACK) {
+        ccmsg_nack_t * nack_header = (ccmsg_nack_t *)response->header;
+        code = nack_header->err_code;
+    } else if (response->type == ccmsg_ACK) {
+        response_header = (ccmsg_ctx_new_ccache_iterator_resp_t*)response->header;
+        code = cc_int_ccache_iterator_new(iterator, int_context->handle, response_header->iterator);
+    } else {
+        code = ccErrBadInternalMessage;
+    }
+    cci_msg_destroy(request);
+    cci_msg_destroy(response);
+    return code;
+}
+
+cc_int32
+cc_int_context_open_ccache( cc_context_t context,
+                            const char* name,
+                            cc_ccache_t* ccache )
+{
+    cc_uint32 blob_pos;
+    cc_int_context_t int_context;
+    cc_msg_t        *request;
+    ccmsg_ccache_open_t *request_header;
+    cc_msg_t        *response;
+    ccmsg_ccache_open_resp_t *response_header;
+    cc_int32 code;
+
+    if ( context == NULL || name == NULL || ccache == NULL )
+        return ccErrBadParam;
+
+    int_context = (cc_int_context_t)context;
+
+    if ( int_context->magic != CC_CONTEXT_MAGIC )
+        return ccErrInvalidContext;
+
+    request_header = (ccmsg_ccache_open_t*)malloc(sizeof(ccmsg_ccache_open_t));
+    if (request_header == NULL)
+        return ccErrNoMem;
+
+    code = cci_msg_new(ccmsg_CCACHE_OPEN, &request);
+    if (code != ccNoError) {
+        free(request_header);
+        return code;
+    }
+
+    code = cci_msg_add_data_blob(request, (void *)name, strlen(name) + 1, &blob_pos);
+    if (code != ccNoError) {
+        cci_msg_destroy(request);
+        free(request_header);
+        return code;
+    }
+    
+    request_header->ctx = int_context->handle;
+    request_header->name_offset = blob_pos;
+    request_header->name_len = strlen(name) + 1;
+
+    code = cci_msg_add_header(request, request_header, sizeof(ccmsg_ccache_open_t));
+
+    code = cci_perform_rpc(request, &response);
+
+    if (response->type == ccmsg_NACK) {
+        ccmsg_nack_t * nack_header = (ccmsg_nack_t *)response->header;
+        code = nack_header->err_code;
+    } else if (response->type == ccmsg_ACK) {
+        response_header = (ccmsg_ccache_open_resp_t*)response->header;
+        code = cc_cache_new(ccache, response_header->ccache);
+    } else {
+        code = ccErrBadInternalMessage;
+    }
+    cci_msg_destroy(request);
+    cci_msg_destroy(response);
+    return code;
+}
+
+cc_int32
+cc_int_context_open_default_ccache( cc_context_t context,
+                                    cc_ccache_t* ccache)
+{
+    cc_int_context_t int_context;
+    cc_msg_t        *request;
+    ccmsg_ccache_open_default_t *request_header;
+    cc_msg_t        *response;
+    ccmsg_ccache_open_resp_t *response_header;
+    cc_int32 code;
+
+    if ( context == NULL || ccache == NULL )
+        return ccErrBadParam;
+
+    int_context = (cc_int_context_t)context;
+
+    if ( int_context->magic != CC_CONTEXT_MAGIC )
+        return ccErrInvalidContext;
+
+    request_header = (ccmsg_ccache_open_default_t*)malloc(sizeof(ccmsg_ccache_open_default_t));
+    if (request_header == NULL)
+        return ccErrNoMem;
+
+    code = cci_msg_new(ccmsg_CCACHE_OPEN_DEFAULT, &request);
+    if (code != ccNoError) {
+        free(request_header);
+        return code;
+    }
+
+    request_header->ctx = int_context->handle;
+
+    code = cci_msg_add_header(request, request_header, sizeof(ccmsg_ccache_open_default_t));
+
+    code = cci_perform_rpc(request, &response);
+
+    if (response->type == ccmsg_NACK) {
+        ccmsg_nack_t * nack_header = (ccmsg_nack_t *)response->header;
+        code = nack_header->err_code;
+    } else if (response->type == ccmsg_ACK) {
+        response_header = (ccmsg_ccache_open_resp_t*)response->header;
+        code = cc_cache_new(ccache, response_header->ccache);
+    } else {
+        code = ccErrBadInternalMessage;
+    }
+    cci_msg_destroy(request);
+    cci_msg_destroy(response);
+    return code;
+}
+
+cc_int32
+cc_int_context_create_ccache( cc_context_t context,
+                              const char* name,
+                              cc_uint32 cred_vers,
+                              const char* principal, 
+                              cc_ccache_t* ccache )
+{
+    cc_uint32 blob_pos;
+    cc_int_context_t int_context;
+    cc_msg_t        *request;
+    ccmsg_ccache_create_t *request_header;
+    cc_msg_t        *response;
+    ccmsg_ccache_create_resp_t *response_header;
+    cc_int32 code;
+
+    if ( context == NULL || name == NULL || 
+         cred_vers == 0 || cred_vers > cc_credentials_v4_v5 ||
+         principal == NULL || ccache == NULL )
+        return ccErrBadParam;
+
+    int_context = (cc_int_context_t)context;
+
+    if ( int_context->magic != CC_CONTEXT_MAGIC )
+        return ccErrInvalidContext;
+
+    request_header = (ccmsg_ccache_create_t*)malloc(sizeof(ccmsg_ccache_create_t));
+    if (request_header == NULL)
+        return ccErrNoMem;
+
+    code = cci_msg_new(ccmsg_CCACHE_CREATE, &request);
+    if (code != ccNoError) {
+        free(request_header);
+        return code;
+    }
+
+    code = cci_msg_add_data_blob(request, (void *)name, strlen(name) + 1, &blob_pos);
+    if (code != ccNoError) {
+        cci_msg_destroy(request);
+        free(request_header);
+        return code;
+    }
+    
+    request_header->ctx = int_context->handle;
+    request_header->version = cred_vers;
+    request_header->name_offset = blob_pos;
+    request_header->name_len = strlen(name) + 1;
+
+    code = cci_msg_add_data_blob(request, (void *)principal, strlen(principal) + 1, &blob_pos);
+    if (code != ccNoError) {
+        cci_msg_destroy(request);
+        free(request_header);
+        return code;
+    }
+    request_header->principal_offset = blob_pos;
+    request_header->principal_len = strlen(principal) + 1;
+
+    code = cci_msg_add_header(request, request_header, sizeof(ccmsg_ccache_create_t));
+
+    code = cci_perform_rpc(request, &response);
+
+    if (response->type == ccmsg_NACK) {
+        ccmsg_nack_t * nack_header = (ccmsg_nack_t *)response->header;
+        code = nack_header->err_code;
+    } else if (response->type == ccmsg_ACK) {
+        response_header = (ccmsg_ccache_create_resp_t*)response->header;
+        code = cc_cache_new(ccache, response_header->ccache);
+    } else {
+        code = ccErrBadInternalMessage;
+    }
+    cci_msg_destroy(request);
+    cci_msg_destroy(response);
+    return code;
+}
+
+cc_int32
+cc_int_context_create_default_ccache( cc_context_t context,
+                                      cc_uint32 cred_vers,
+                                      const char* principal, 
+                                      cc_ccache_t* ccache )
+{
+    cc_uint32 blob_pos;
+    cc_int_context_t int_context;
+    cc_msg_t        *request;
+    ccmsg_ccache_create_default_t *request_header;
+    cc_msg_t        *response;
+    ccmsg_ccache_create_resp_t *response_header;
+    cc_int32 code;
+
+    if ( context == NULL ||
+         cred_vers == 0 || cred_vers > cc_credentials_v4_v5 ||
+         principal == NULL || ccache == NULL )
+        return ccErrBadParam;
+
+    int_context = (cc_int_context_t)context;
+
+    if ( int_context->magic != CC_CONTEXT_MAGIC )
+        return ccErrInvalidContext;
+
+    request_header = (ccmsg_ccache_create_default_t*)malloc(sizeof(ccmsg_ccache_create_default_t));
+    if (request_header == NULL)
+        return ccErrNoMem;
+
+    code = cci_msg_new(ccmsg_CCACHE_CREATE_DEFAULT, &request);
+    if (code != ccNoError) {
+        free(request_header);
+        return code;
+    }
+
+    request_header->ctx = int_context->handle;
+    request_header->version = cred_vers;
+
+    code = cci_msg_add_data_blob(request, (void *)principal, strlen(principal) + 1, &blob_pos);
+    if (code != ccNoError) {
+        cci_msg_destroy(request);
+        free(request_header);
+        return code;
+    }
+    request_header->principal_offset = blob_pos;
+    request_header->principal_len = strlen(principal) + 1;
+
+    code = cci_msg_add_header(request, request_header, sizeof(ccmsg_ccache_create_default_t));
+
+    code = cci_perform_rpc(request, &response);
+
+    if (response->type == ccmsg_NACK) {
+        ccmsg_nack_t * nack_header = (ccmsg_nack_t *)response->header;
+        code = nack_header->err_code;
+    } else if (response->type == ccmsg_ACK) {
+        response_header = (ccmsg_ccache_create_resp_t*)response->header;
+        code = cc_cache_new(ccache, response_header->ccache);
+    } else {
+        code = ccErrBadInternalMessage;
+    }
+    cci_msg_destroy(request);
+    cci_msg_destroy(response);
+    return code;
+}
+
+cc_int32
+cc_int_context_create_new_ccache( cc_context_t context,
+                                  cc_uint32 cred_vers,
+                                  const char* principal, 
+                                  cc_ccache_t* ccache )
+{
+    cc_uint32 blob_pos;
+    cc_int_context_t int_context;
+    cc_msg_t        *request;
+    ccmsg_ccache_create_unique_t *request_header;
+    cc_msg_t        *response;
+    ccmsg_ccache_create_resp_t *response_header;
+    cc_int32 code;
+
+    if ( context == NULL ||
+         cred_vers == 0 || cred_vers > cc_credentials_v4_v5 ||
+         principal == NULL || ccache == NULL )
+        return ccErrBadParam;
+
+    int_context = (cc_int_context_t)context;
+
+    if ( int_context->magic != CC_CONTEXT_MAGIC )
+        return ccErrInvalidContext;
+
+    request_header = (ccmsg_ccache_create_unique_t*)malloc(sizeof(ccmsg_ccache_create_unique_t));
+    if (request_header == NULL)
+        return ccErrNoMem;
+
+    code = cci_msg_new(ccmsg_CCACHE_CREATE_UNIQUE, &request);
+    if (code != ccNoError) {
+        free(request_header);
+        return code;
+    }
+
+    request_header->ctx = int_context->handle;
+    request_header->version = cred_vers;
+
+    code = cci_msg_add_data_blob(request, (void *)principal, strlen(principal) + 1, &blob_pos);
+    if (code != ccNoError) {
+        cci_msg_destroy(request);
+        free(request_header);
+        return code;
+    }
+    request_header->principal_offset = blob_pos;
+    request_header->principal_len = strlen(principal) + 1;
+
+    code = cci_msg_add_header(request, request_header, sizeof(ccmsg_ccache_create_unique_t));
+
+    code = cci_perform_rpc(request, &response);
+
+    if (response->type == ccmsg_NACK) {
+        ccmsg_nack_t * nack_header = (ccmsg_nack_t *)response->header;
+        code = nack_header->err_code;
+    } else if (response->type == ccmsg_ACK) {
+        response_header = (ccmsg_ccache_create_resp_t*)response-> header;
+        code = cc_cache_new(ccache, response_header->ccache);
+    } else {
+        code = ccErrBadInternalMessage;
+    }
+    cci_msg_destroy(request);
+    cci_msg_destroy(response);
+    return code;
+}
+cc_int32
+cc_int_context_lock( cc_context_t context,
+                     cc_uint32 lock_type,
+                     cc_uint32 block )
+{
+    cc_int_context_t int_context;
+    cc_msg_t        *request;
+    ccmsg_ctx_lock_t *request_header;
+    cc_msg_t        *response;
+    cc_int32 code;
+
+    if ( context == NULL || 
+         (lock_type != cc_lock_read && lock_type != cc_lock_write) ||
+         (block != cc_lock_block && block != cc_lock_noblock) )
+        return ccErrBadParam;
+
+    int_context = (cc_int_context_t)context;
+
+    if ( int_context->magic != CC_CONTEXT_MAGIC )
+        return ccErrInvalidContext;
+
+    request_header = (ccmsg_ctx_lock_t*)malloc(sizeof(ccmsg_ctx_lock_t));
+    if (request_header == NULL)
+        return ccErrNoMem;
+
+    code = cci_msg_new(ccmsg_CTX_LOCK, &request);
+    if (code != ccNoError) {
+        free(request_header);
+        return code;
+    }
+
+    request_header->ctx = int_context->handle;
+    request_header->lock_type;
+
+    code = cci_msg_add_header(request, request_header, sizeof(ccmsg_ctx_lock_t));
+
+    code = cci_perform_rpc(request, &response);
+
+    if (response->type == ccmsg_NACK) {
+        ccmsg_nack_t * nack_header = (ccmsg_nack_t *)response->header;
+        code = nack_header->err_code;
+
+        // TODO: if (block == cc_lock_block) .....
+    } else if (response->type == ccmsg_ACK) {
+        code = ccNoError;
+    } else {
+        code = ccErrBadInternalMessage;
+    }
+    cci_msg_destroy(request);
+    cci_msg_destroy(response);
+    return code;
+}
+
+cc_int32
+cc_int_context_unlock( cc_context_t context )
+{
+    cc_int_context_t int_context;
+    cc_msg_t        *request;
+    ccmsg_ctx_unlock_t *request_header;
+    cc_msg_t        *response;
+    cc_int32 code;
+
+    if ( context == NULL )
+        return ccErrBadParam;
+
+    int_context = (cc_int_context_t)context;
+
+    if ( int_context->magic != CC_CONTEXT_MAGIC )
+        return ccErrInvalidContext;
+
+    request_header = (ccmsg_ctx_unlock_t*)malloc(sizeof(ccmsg_ctx_unlock_t));
+    if (request_header == NULL)
+        return ccErrNoMem;
+
+    code = cci_msg_new(ccmsg_CTX_UNLOCK, &request);
+    if (code != ccNoError) {
+        free(request_header);
+        return code;
+    }
+
+    request_header->ctx = int_context->handle;
+
+    code = cci_msg_add_header(request, request_header, sizeof(ccmsg_ctx_unlock_t));
+
+    code = cci_perform_rpc(request, &response);
+
+    if (response->type == ccmsg_NACK) {
+        ccmsg_nack_t * nack_header = (ccmsg_nack_t *)response->header;
+        code = nack_header->err_code;
+    } else if (response->type == ccmsg_ACK) {
+        code = ccNoError;
+    } else {
+        code = ccErrBadInternalMessage;
+    }
+    cci_msg_destroy(request);
+    cci_msg_destroy(response);
+    return code;
+}
+
+cc_int32
+cc_int_context_clone( cc_context_t      inContext,
+                      cc_context_t*     outContext,
+                      cc_int32          requestedVersion,
+                      cc_int32*         supportedVersion,
+                      char const**      vendor )
+{
+    cc_int_context_t int_context, new_context;
+    static char vendor_st[128] = "";
+    cc_msg_t     *request;
+    ccmsg_clone_t *request_header;
+    cc_msg_t     *response;
+    ccmsg_clone_resp_t *response_header;
+    cc_int32 code;
+
+    if ( inContext == NULL ||
+         outContext == NULL ||
+         supportedVersion == NULL )
+        return ccErrBadParam;
+
+    int_context = (cc_int_context_t)context;
+
+    if ( int_context->magic != CC_CONTEXT_MAGIC )
+        return ccErrInvalidContext;
+
+    if ((requestedVersion != ccapi_version_2) &&
+         (requestedVersion != ccapi_version_3) &&
+         (requestedVersion != ccapi_version_4) &&
+         (requestedVersion != ccapi_version_5)) {
+
+        if (supportedVersion != NULL) {
+            *supportedVersion = ccapi_version_5;
+        }
+        return ccErrBadAPIVersion;
+    }   
+
+    request_header = (ccmsg_clone_t*)malloc(sizeof(ccmsg_clone_t));
+    if (request_header == NULL)
+        return ccErrNoMem;
+
+    request_header->ctx = int_context->handle;
+    request_header->in_version = requestedVersion;
+
+    code = cci_msg_new(ccmsg_INIT, &request);
+    if (code != ccNoError) {
+        free(request_header);
+        return code;
+    }
+
+    code = cci_msg_add_header(request, request_header, sizeof(ccmsg_init_t));
+
+    code = cci_perform_rpc(request, &response);
+
+    if (response->type == ccmsg_NACK) {
+        ccmsg_nack_t * nack_header = (ccmsg_nack_t *)response->header;
+        code = nack_header->err_code;
+    } else if (response->type == ccmsg_ACK) {
+        response_header = (ccmsg_clone_resp_t *)response->header;
+        *supportedVersion = response_header->out_version;
+        code = cc_int_context_new(outContext, response_header->out_ctx, response_header->out_version);
+
+        if (!vendor_st[0]) {
+            char * string;
+            code = cci_msg_retrieve_blob(response, response_header->vendor_offset, response_header->vendor_length, &string);
+            strncpy(vendor_st, string, sizeof(vendor_st)-1);
+            vendor_st[sizeof(vendor_st)-1] = '\0';
+            free(string);
+        } 
+        *vendor = vendor_st;
+
+        code = ccNoError;
+    } else {
+        code = ccErrBadInternalMessage;
+    }
+    cci_msg_destroy(request);
+    cci_msg_destroy(response);
+    return code;
+}
+
+cc_int32
+cc_int_context_get_version( cc_context_t        context,
+                            cc_int32*           version )
+{
+    cc_int_context_t int_context;
+    cc_int32 code;
+
+    if ( context == NULL ||
+         version == NULL )
+        return ccErrBadParam;
+
+    int_context = (cc_int_context_t)context;
+
+    if ( int_context->magic != CC_CONTEXT_MAGIC )
+        return ccErrInvalidContext;
+
+    *version = int_context->api_version;
+    return ccNoError;
+}
+
+
diff --git a/src/lib/ccapi/client/context.h b/src/lib/ccapi/client/context.h
new file mode 100644 (file)
index 0000000..cd5ca67
--- /dev/null
@@ -0,0 +1,131 @@
+/* $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).
+ * $
+ */
+
+/* context.h */
+
+#define CC_CONTEXT_MAGIC ('C'<<24 | 'C'<<16 | 'T'<<8 | 'X')
+
+struct cc_int_context {
+    cc_context_f*      functions;
+
+    cc_uint32           magic;
+#ifdef CCAPI_V2_COMPAT
+    cc_uint32           version;
+#endif
+    cc_uint32           api_version;
+    cc_handle           handle;
+};
+typedef struct cc_int_context cc_int_context_d;
+typedef cc_int_context_d*     cc_int_context_t;
+
+cc_int32
+cc_int_context_new( cc_context_t *pcontext, cc_handle handle, cc_uint32 version );
+
+cc_int32    
+cc_int_context_release( cc_context_t context );
+
+cc_int32
+cc_int_context_get_change_time( cc_context_t context,
+                                cc_time_t* time);
+
+cc_int32
+cc_int_context_get_default_ccache_name( cc_context_t context,
+                                        cc_string_t* name );
+
+cc_int32
+cc_int_context_open_ccache( cc_context_t context,
+                            const char* name,
+                            cc_ccache_t* ccache );
+
+cc_int32
+cc_int_context_open_default_ccache( cc_context_t context,
+                                    cc_ccache_t* ccache );
+
+cc_int32
+cc_int_context_create_ccache( cc_context_t context,
+                              const char* name,
+                              cc_uint32 cred_vers,
+                              const char* principal, 
+                              cc_ccache_t* ccache );
+
+cc_int32
+cc_int_context_create_default_ccache( cc_context_t context,
+                                      cc_uint32 cred_vers,
+                                      const char* principal, 
+                                      cc_ccache_t* ccache );
+
+cc_int32
+cc_int_context_create_new_ccache( cc_context_t context,
+                                  cc_uint32 cred_vers,
+                                  const char* principal, 
+                                  cc_ccache_t* ccache );
+cc_int32
+cc_int_context_new_ccache_iterator( cc_context_t context,
+                                    cc_ccache_iterator_t* iterator );
+
+cc_int32
+cc_int_context_lock( cc_context_t context,
+                     cc_uint32 lock_type,
+                     cc_uint32 block );
+
+cc_int32
+cc_int_context_unlock( cc_context_t context );
+
+cc_int32
+cc_int_context_compare( cc_context_t context,
+                        cc_context_t compare_to,
+                        cc_uint32*   equal );
+
+cc_int32
+cc_int_context_clone( cc_context_t      inContext,
+                      cc_context_t*     outContext,
+                      cc_int32          requestedVersion,
+                      cc_int32*         supportedVersion,
+                      char const**      vendor );
+
+cc_int32
+cc_int_context_get_version( cc_context_t        context,
+                            cc_int32*           version );
+
+
diff --git a/src/lib/ccapi/client/credentials.c b/src/lib/ccapi/client/credentials.c
new file mode 100644 (file)
index 0000000..b0a3df2
--- /dev/null
@@ -0,0 +1,181 @@
+/* $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).
+ * $
+ */
+
+/* credentials.c */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <CredentialsCache.h>
+#include "credentials.h"
+#include "msg.h"
+#include "msg_headers.h"
+
+
+cc_int32
+cc_int_credentials_new( cc_credentials_t *pcredentials, cc_uint32 version, 
+                    cc_handle ctx, cc_handle ccache, cc_handle handle, 
+                    char * data, cc_uint32 len )
+{
+    cc_int_credentials_t credentials;
+    cc_int32 code;
+    
+    if ( pcredentials == NULL )
+        return ccErrBadParam;
+
+    credentials = (cc_int_credentials_t)malloc(sizeof(cc_int_credentials_d));
+    if ( credentials == NULL )
+        return ccErrNoMem;
+
+    credentials->data = (cc_credentials_union *)malloc(sizeof(cc_credentials_union));
+    if ( credentials->data == NULL ) {
+        free(credentials);
+        return ccErrNoMem;
+    }
+
+    credentials->functions = (cc_credentials_f *)malloc(sizeof(cc_credentials_f));
+    if ( credentials->functions == NULL ) {
+        free(credentials->data);
+        free(credentials);
+        return ccErrNoMem;
+    }
+
+    credentials->functions->release = cc_int_credentials_release;
+    credentials->functions->compare = cc_int_credentials_compare;
+    credentials->magic = CC_CREDS_MAGIC;
+    credentials->ctx = ctx;
+    credentials->ccache = ccache;
+    credentials->handle = handle;
+
+    switch ( version ) {
+    case cc_credentials_v4:
+        code = cci_cred_v4_unmarshall(data, len, credentials->data);
+        break;
+    case cc_credentials_v5:
+        code = cci_cred_v5_unmarshall(data, len, credentials->data);
+        break;
+    default:
+        free(credentials);
+        return ccErrBadCredentialsVersion;
+    }
+
+    *pcredentials = (cc_credentials_t)credentials;
+    return ccNoError;
+}
+
+
+cc_int32
+cc_int_credentials_release( cc_credentials_t creds )
+{
+    cc_int_credentials_t int_creds;
+    unsigned short i;
+
+    if ( creds == NULL )
+        return ccErrBadParam;
+
+    int_creds = (cc_int_credentials_t)creds;
+
+    if ( int_creds->magic != CC_CREDS_MAGIC )
+        return ccErrInvalidCredentials;
+
+    switch (int_creds->data->version) {
+    case cc_credentials_v4:
+        free(int_creds->data->credentials.credentials_v4);
+        break;
+    case cc_credentials_v5:
+        if ( int_creds->data->credentials.credentials_v5->client )
+            free(int_creds->data->credentials.credentials_v5->client);
+        if ( int_creds->data->credentials.credentials_v5->server )
+            free(int_creds->data->credentials.credentials_v5->server );
+        if ( int_creds->data->credentials.credentials_v5->keyblock.data )
+            free(int_creds->data->credentials.credentials_v5->keyblock.data);
+        if ( int_creds->data->credentials.credentials_v5->ticket.data )
+            free(int_creds->data->credentials.credentials_v5->ticket.data);
+        if ( int_creds->data->credentials.credentials_v5->second_ticket.data )
+            free(int_creds->data->credentials.credentials_v5->second_ticket.data);
+        if ( int_creds->data->credentials.credentials_v5->addresses ) {
+            for ( i=0; int_creds->data->credentials.credentials_v5->addresses[i]; i++) {
+                if (int_creds->data->credentials.credentials_v5->addresses[i]->data)
+                    free(int_creds->data->credentials.credentials_v5->addresses[i]->data);
+            }
+            free(int_creds->data->credentials.credentials_v5->addresses);
+        }
+        if ( int_creds->data->credentials.credentials_v5->authdata ) {
+            for ( i=0; int_creds->data->credentials.credentials_v5->authdata[i]; i++) {
+                if ( int_creds->data->credentials.credentials_v5->authdata[i]->data )
+                    free(int_creds->data->credentials.credentials_v5->authdata[i]->data);
+            }
+            free(int_creds->data->credentials.credentials_v5->authdata);
+        }
+        break;
+    default:
+        return ccErrBadCredentialsVersion;
+    }
+
+    free(int_creds->functions);
+    free(int_creds->data);
+    free(int_creds);
+    return ccNoError;
+}
+
+cc_int32
+cc_int_credentials_compare( cc_credentials_t credentials,
+                        cc_credentials_t compare_to,
+                        cc_uint32* equal )
+{
+    cc_int_credentials_t int_credentials;
+    cc_int_credentials_t int_compare_to;
+
+    if ( credentials == NULL || compare_to == NULL || equal == NULL )
+        return ccErrBadParam;
+
+    
+    if ( int_credentials->magic != CC_CREDS_MAGIC ||
+         int_compare_to->magic != CC_CREDS_MAGIC )
+        return ccErrInvalidCredentials;
+
+    int_credentials = (cc_int_credentials_t)credentials;
+    int_compare_to  = (cc_int_credentials_t)compare_to;
+
+    *equal = (int_credentials->handle == int_compare_to->handle);
+    return ccNoError;
+}
diff --git a/src/lib/ccapi/client/credentials.h b/src/lib/ccapi/client/credentials.h
new file mode 100644 (file)
index 0000000..320c618
--- /dev/null
@@ -0,0 +1,94 @@
+/* $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).
+ * $
+ */
+
+/* credentials.h */
+
+#define CC_CREDS_MAGIC ('C'<<24 | 'R'<<16 | 'E'<<8 | 'D')
+
+struct cc_int_credentials_d {
+    cc_credentials_union* data;
+    cc_credentials_f* functions;
+#if TARGET_OS_MAC
+    cc_credentials_f*     otherFunctions;
+#endif
+    cc_uint32   magic;
+    cc_handle   ctx;
+    cc_handle   ccache;
+    cc_handle   handle;
+};
+typedef struct cc_int_credentials_d cc_int_credentials_d;
+typedef cc_int_credentials_d* cc_int_credentials_t;
+
+cc_int32
+cc_int_credentials_new( cc_credentials_t * pcredentials, cc_uint32 version, 
+                    cc_handle ctx, cc_handle ccache, cc_handle handle, 
+                    char * data, cc_uint32 len);
+
+cc_int32
+cc_int_credentials_release( cc_credentials_t credentials );
+
+cc_int32
+cc_int_credentials_compare( cc_credentials_t credentials,
+                        cc_credentials_t compare_to,
+                        cc_uint32* equal );
+
+cc_int32
+cci_creds_v4_marshall( cc_credentials_v4_t * creds, 
+                       char ** flat, 
+                       cc_uint32 * len);
+
+cc_int32
+cci_creds_v5_marshall( cc_credentials_v5_t * creds, 
+                       char ** flat, 
+                       cc_uint32 * len);
+
+cc_int32
+cci_creds_v4_unmarshall( char * flat, 
+                             cc_uint32 len,
+                             cc_credentials_union * creds);
+
+cc_int32
+cci_creds_v5_unmarshall( char * flat, 
+                         cc_uint32 len,
+                         cc_credentials_union * creds);
+
diff --git a/src/lib/ccapi/client/credentials_iterator.c b/src/lib/ccapi/client/credentials_iterator.c
new file mode 100644 (file)
index 0000000..b7333da
--- /dev/null
@@ -0,0 +1,187 @@
+/* $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).
+ * $
+ */
+
+/* credentials_iterator.c */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <CredentialsCache.h>
+#include "credentials_iterator.h"
+#include "msg.h"
+#include "msg_headers.h"
+
+
+cc_int32
+cc_int_credentials_iterator_new( cc_credentials_iterator_t * piter, 
+                                 cc_handle ctx,
+                                 cc_handle ccache,
+                                 cc_handle handle )
+{
+    cc_int_credentials_iterator_t iter;
+
+    if ( piter == NULL )
+        return ccErrBadParam;
+
+    iter = (cc_int_credentials_iterator_t) malloc( sizeof(cc_int_credentials_iterator_d) );
+    if ( iter == NULL )
+        return ccErrNoMem;
+
+    iter->functions = (cc_credentials_iterator_f*)malloc(sizeof(cc_credentials_iterator_f));
+    if ( iter->functions == NULL ) {
+        free(iter);
+        return ccErrNoMem;
+    }
+
+    iter->functions->release = cc_int_credentials_iterator_release;
+    iter->functions->next = cc_int_credentials_iterator_next;
+    iter->magic = CC_CREDS_ITER_MAGIC;
+    iter->ctx = ctx;
+    iter->ccache = ccache;
+    iter->handle = handle;
+
+    *piter = (cc_credentials_iterator_t) iter;
+    return ccNoError;
+}
+
+cc_int32
+cc_int_credentials_iterator_release( cc_credentials_iterator_t iter )
+{
+    cc_int_credentials_iterator_t int_iter;
+    cc_msg_t        *request;
+    ccmsg_creds_iterator_release_t *request_header;
+    cc_msg_t        *response;
+    cc_int32 code;
+
+    if ( iter == NULL )
+        return ccErrBadParam;
+
+    int_iter = (cc_int_credentials_iterator_t) iter;
+
+    if ( int_iter->magic != CC_CREDS_ITER_MAGIC )
+        return ccErrInvalidCredentialsIterator;
+
+    request_header = (ccmsg_creds_iterator_release_t*)malloc(sizeof(ccmsg_creds_iterator_release_t));
+    if (request_header == NULL)
+        return ccErrNoMem;
+    request_header->ctx = int_iter->ctx;
+    request_header->ccache = int_iter->ccache;
+    request_header->iterator = int_iter->handle;
+    code = cci_msg_new(ccmsg_CREDS_ITERATOR_RELEASE, &request);
+    if (code != ccNoError) {
+        free(request_header);
+        return code;
+    }
+
+    code = cci_msg_add_header(request, request_header, sizeof(ccmsg_creds_iterator_release_t));
+
+    code = cci_perform_rpc(request, &response);
+
+    if (response->type == ccmsg_NACK) {
+        ccmsg_nack_t * nack_header = (ccmsg_nack_t *)response->header;
+        code = nack_header->err_code;
+    } else if (response->type == ccmsg_ACK) {
+        code = ccNoError;
+    } else {
+        code = ccErrBadInternalMessage;
+    }
+    cci_msg_destroy(request);
+    cci_msg_destroy(response);
+
+    free(int_iter->functions);
+    free(int_iter);
+    return ccNoError;
+}
+
+cc_int32
+cc_int_credentials_iterator_next( cc_credentials_iterator_t iter,
+                                  cc_credentials_t * credentials )
+{
+    cc_int_credentials_iterator_t int_iter;
+    cc_msg_t        *request;
+    ccmsg_creds_iterator_next_t *request_header;
+    cc_msg_t        *response;
+    cc_int32 code;
+
+    if ( credentials == NULL )
+        return ccErrBadParam;
+
+    int_iter = (cc_int_credentials_iterator_t)iter;
+
+    if ( int_iter->magic != CC_CREDS_ITER_MAGIC )
+        return ccErrInvalidCredentialsIterator;
+
+    request_header = (ccmsg_creds_iterator_next_t*)malloc(sizeof(ccmsg_creds_iterator_next_t));
+    if (request_header == NULL)
+        return ccErrNoMem;
+    request_header->ctx = int_iter->ctx;
+    request_header->ccache = int_iter->ccache;
+    request_header->iterator = int_iter->handle;
+
+    code = cci_msg_new(ccmsg_CREDS_ITERATOR_NEXT, &request);
+    if (code != ccNoError) {
+        free(request_header);
+        return code;
+    }
+
+    code = cci_msg_add_header(request, request_header, sizeof(ccmsg_creds_iterator_next_t));
+
+    code = cci_perform_rpc(request, &response);
+
+    if (response->type == ccmsg_NACK) {
+        ccmsg_nack_t * nack_header = (ccmsg_nack_t *)response->header;
+        code = nack_header->err_code;
+    } else if (response->type == ccmsg_ACK) {
+        char * blob;
+        ccmsg_creds_iterator_next_resp_t * response_header = (ccmsg_creds_iterator_next_resp_t*)response->header;
+        code = cci_msg_retrieve_blob(response, response_header->creds_offset, response_header->creds_len, &blob);
+        code = cc_credentials_new(credentials, response_header->version,
+                                  int_iter->ctx, int_iter->ccache, response_header->creds_handle, 
+                                  blob, response_header->creds_len);
+        free(blob);
+    } else {
+        code = ccErrBadInternalMessage;
+    }
+    cci_msg_destroy(request);
+    cci_msg_destroy(response);
+    return code;
+}
diff --git a/src/lib/ccapi/client/credentials_iterator.h b/src/lib/ccapi/client/credentials_iterator.h
new file mode 100644 (file)
index 0000000..2a6f8ed
--- /dev/null
@@ -0,0 +1,72 @@
+/* $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).
+ * $
+ */
+
+/* credentials_iterator.h */
+
+#define CC_CREDS_ITER_MAGIC ('C'<<24 | 'R'<<16 | 'I'<<8 | 'T')
+
+struct cc_int_credentials_iterator_d {
+    cc_credentials_iterator_f* functions;
+#if TARGET_OS_MAC
+    cc_credentials_iterator_f* otherFunctions;
+#endif
+    cc_uint32   magic;
+    cc_handle   handle;
+    cc_handle   ccache;
+    cc_handle   ctx;
+};
+typedef struct cc_int_credentials_iterator_d cc_int_credentials_iterator_d;
+typedef cc_int_credentials_iterator_d* cc_int_credentials_iterator_t;
+
+
+cc_int32
+cc_int_credentials_iterator_new( cc_credentials_iterator_t * piter, cc_handle ctx, cc_handle ccache, cc_handle iter );
+
+cc_int32
+cc_int_credentials_iterator_release( cc_credentials_iterator_t iter );
+
+cc_int32
+cc_int_credentials_iterator_next( cc_credentials_iterator_t iter,
+                                  cc_credentials_t * credentials );
+
+
diff --git a/src/lib/ccapi/client/mac/ChangeLog b/src/lib/ccapi/client/mac/ChangeLog
new file mode 100644 (file)
index 0000000..aaa59da
--- /dev/null
@@ -0,0 +1,4 @@
+2004-10-27   Jeffrey Altman  <jaltman@mit.edu>
+
+ * Initial commit of C CCAPI implementation
+
diff --git a/src/lib/ccapi/client/windows/ChangeLog b/src/lib/ccapi/client/windows/ChangeLog
new file mode 100644 (file)
index 0000000..aaa59da
--- /dev/null
@@ -0,0 +1,4 @@
+2004-10-27   Jeffrey Altman  <jaltman@mit.edu>
+
+ * Initial commit of C CCAPI implementation
+
diff --git a/src/lib/ccapi/include/ChangeLog b/src/lib/ccapi/include/ChangeLog
new file mode 100644 (file)
index 0000000..aaa59da
--- /dev/null
@@ -0,0 +1,4 @@
+2004-10-27   Jeffrey Altman  <jaltman@mit.edu>
+
+ * Initial commit of C CCAPI implementation
+
diff --git a/src/lib/ccapi/include/CredentialsCache.h b/src/lib/ccapi/include/CredentialsCache.h
new file mode 100644 (file)
index 0000000..dd60fa4
--- /dev/null
@@ -0,0 +1,567 @@
+/* $Copyright:
+ *
+ * Copyright 1998-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).
+ * $
+ */
+
+/* $Header$ */
+
+/*
+ * Declarations for Credentials Cache API Library
+ *
+ * API specification: <http://web.mit.edu/pismere/kerberos/ccache-api-v2.html>
+ *
+ *     Revision 1: Frank Dabek, 6/4/1998
+ *     Revision 2: meeroh, 2/24/1999
+ *      Revision 3: meeroh, 11/12/1999
+ *      Revision 4: jaltman, 10/27/2004
+ *
+ */
+#ifndef __CREDENTIALSCACHE__
+#define __CREDENTIALSCACHE__
+
+#if defined(macintosh) || (defined(__MACH__) && defined(__APPLE__))
+       #include <TargetConditionals.h>
+    #if TARGET_RT_MAC_CFM
+        #error "Use KfM 4.0 SDK headers for CFM compilation."
+    #endif
+#endif
+
+#if TARGET_OS_MAC
+    #include <sys/types.h>
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+#if TARGET_OS_MAC
+    #if defined(__MWERKS__)
+        #pragma import on
+        #pragma enumsalwaysint on
+    #endif
+    #pragma options align=mac68k
+#endif
+
+#include <time.h>
+
+/*
+ * Constants
+ */
+/* API versions */
+enum {
+    ccapi_version_2 = 2,
+    ccapi_version_3 = 3,
+    ccapi_version_4 = 4,
+    ccapi_version_5 = 5
+};
+/* Errors */
+enum {
+    ccNoError                                                  = 0,
+
+    ccIteratorEnd                                              = 201,
+    ccErrBadParam,
+    ccErrNoMem,
+    ccErrInvalidContext,
+    ccErrInvalidCCache,
+
+    ccErrInvalidString,                                        /* 206 */
+    ccErrInvalidCredentials,
+    ccErrInvalidCCacheIterator,
+    ccErrInvalidCredentialsIterator,
+    ccErrInvalidLock,
+
+    ccErrBadName,                                              /* 211 */
+    ccErrBadCredentialsVersion,
+    ccErrBadAPIVersion,
+    ccErrContextLocked,
+    ccErrContextUnlocked,
+
+    ccErrCCacheLocked,                                 /* 216 */
+    ccErrCCacheUnlocked,
+    ccErrBadLockType,
+    ccErrNeverDefault,
+    ccErrCredentialsNotFound,
+
+    ccErrCCacheNotFound,                                       /* 221 */
+    ccErrContextNotFound,
+    ccErrServerUnavailable,
+    ccErrServerInsecure,
+    ccErrServerCantBecomeUID,
+    
+    ccErrTimeOffsetNotSet,                             /* 226 */
+    ccErrBadInternalMessage,
+    ccErrNotImplemented
+};
+
+/* Credentials versions */
+enum {
+    cc_credentials_v4 = 1,
+    cc_credentials_v5 = 2,
+    cc_credentials_v4_v5 = 3
+};
+
+/* Lock types */
+enum {
+    cc_lock_read = 1,
+    cc_lock_write = 2
+};
+
+/* Locking Modes */
+enum {
+    cc_lock_noblock = 0,
+    cc_lock_block = 1
+};
+
+/*
+ * Basic types
+ */
+typedef char           cc_int8;
+typedef unsigned char  cc_uint8;
+typedef int            cc_int32;
+typedef unsigned int   cc_uint32;
+typedef time_t         cc_time_t;
+typedef void *         cc_handle;
+
+/*
+ * API types
+ */
+/* Forward declarations */
+struct cc_context_f;
+typedef struct cc_context_f cc_context_f;
+
+struct cc_ccache_f;
+typedef struct cc_ccache_f cc_ccache_f;
+
+struct cc_ccache_iterator_f;
+typedef struct cc_ccache_iterator_f cc_ccache_iterator_f;
+
+struct cc_ccache_iterator_f;
+typedef struct cc_credentials_iterator_f cc_credentials_iterator_f;
+
+struct cc_string_f;
+typedef struct cc_string_f cc_string_f;
+
+struct cc_credentials_f;
+typedef struct cc_credentials_f cc_credentials_f;
+
+/* Credentials types */
+
+enum { /* Make sure all of these are multiples of four (for alignment sanity) */
+    cc_v4_name_size            = 40,
+    cc_v4_instance_size        = 40,
+    cc_v4_realm_size   = 40,
+    cc_v4_ticket_size  = 1254
+};
+
+enum cc_string_to_key_type {
+    cc_v4_stk_afs = 0,
+    cc_v4_stk_des = 1,
+    cc_v4_stk_columbia_special = 2,
+    cc_v4_stk_krb5 = 3,
+    cc_v4_stk_unknown = 4
+};
+
+struct cc_credentials_v4_t {
+    cc_uint32                  version;
+    char                       principal [cc_v4_name_size];
+    char                       principal_instance [cc_v4_instance_size];
+    char                       service [cc_v4_name_size];
+    char                       service_instance [cc_v4_instance_size];
+    char                       realm [cc_v4_realm_size];
+    unsigned char              session_key [8];
+    cc_int32                   kvno;
+    cc_int32                   string_to_key_type;
+    cc_time_t                  issue_date;
+    cc_int32                   lifetime;
+    cc_uint32                  address;
+    cc_int32                   ticket_size;
+    unsigned char              ticket [cc_v4_ticket_size];
+};      
+typedef struct cc_credentials_v4_t cc_credentials_v4_t;
+
+struct cc_data {
+    cc_uint32                  type;
+    cc_uint32                  length;
+    void*                      data;
+};      
+typedef struct cc_data cc_data;
+
+struct cc_credentials_v5_t {
+    char*                      client;
+    char*                      server;
+    cc_data                    keyblock;
+    cc_time_t                  authtime;
+    cc_time_t                  starttime;
+    cc_time_t                  endtime;
+    cc_time_t                  renew_till;
+    cc_uint32                  is_skey;
+    cc_uint32                  ticket_flags;
+    cc_data**                  addresses;
+    cc_data                    ticket;
+    cc_data                    second_ticket;
+    cc_data**                  authdata;
+};      
+typedef struct cc_credentials_v5_t cc_credentials_v5_t;
+
+struct cc_credentials_union {
+    cc_int32                   version;
+    union {
+        cc_credentials_v4_t*   credentials_v4;
+        cc_credentials_v5_t*   credentials_v5;
+    }                          credentials;
+};
+typedef struct cc_credentials_union cc_credentials_union;
+
+/* Exposed parts */
+
+struct cc_context_d {
+    const cc_context_f*        functions;
+#if TARGET_OS_MAC
+    const cc_context_f*        otherFunctions;
+#endif
+};
+typedef struct cc_context_d cc_context_d;
+typedef cc_context_d*  cc_context_t;
+
+struct cc_ccache_d {
+    const cc_ccache_f* functions;
+#if TARGET_OS_MAC
+    const cc_ccache_f* otherFunctions;
+#endif
+};
+typedef struct cc_ccache_d cc_ccache_d;
+typedef cc_ccache_d*   cc_ccache_t;
+
+struct cc_ccache_iterator_d {
+    const cc_ccache_iterator_f*        functions;
+#if TARGET_OS_MAC
+    const cc_ccache_iterator_f*        otherFunctions;
+#endif
+};
+typedef struct cc_ccache_iterator_d cc_ccache_iterator_d;
+typedef cc_ccache_iterator_d*  cc_ccache_iterator_t;
+
+struct cc_credentials_iterator_d {
+    const cc_credentials_iterator_f*   functions;
+#if TARGET_OS_MAC
+    const cc_credentials_iterator_f*   otherFunctions;
+#endif
+};
+typedef struct cc_credentials_iterator_d cc_credentials_iterator_d;
+typedef cc_credentials_iterator_d*     cc_credentials_iterator_t;
+
+struct cc_string_d {
+    const char*                        data;
+    const cc_string_f* functions;
+#if TARGET_OS_MAC
+    const cc_string_f* otherFunctions;
+#endif
+};
+typedef struct cc_string_d cc_string_d;
+typedef cc_string_d*   cc_string_t;
+
+struct cc_credentials_d {
+    const cc_credentials_union* data;
+    const cc_credentials_f* functions;
+#if TARGET_OS_MAC
+    const cc_credentials_f*    otherFunctions;
+#endif
+};
+typedef struct cc_credentials_d cc_credentials_d;
+typedef cc_credentials_d* cc_credentials_t;
+
+/* Function pointer structs */
+
+struct  cc_context_f {
+    cc_int32    (*release) (
+                                cc_context_t context);
+    cc_int32    (*get_change_time) (
+                                cc_context_t context,
+                                cc_time_t* time);
+    cc_int32    (*get_default_ccache_name) (
+                                cc_context_t context,
+                                cc_string_t* name);
+    cc_int32    (*open_ccache) (
+                                cc_context_t context,
+                                const char* name,
+                                cc_ccache_t* ccache);
+    cc_int32    (*open_default_ccache) (
+                                cc_context_t context,
+                                cc_ccache_t* ccache);
+    cc_int32    (*create_ccache) (
+                                cc_context_t context,
+                                const char* name,
+                                cc_uint32 cred_vers,
+                                const char* principal, 
+                                cc_ccache_t* ccache);
+    cc_int32    (*create_default_ccache) (
+                                cc_context_t context,
+                                cc_uint32 cred_vers,
+                                const char* principal, 
+                                cc_ccache_t* ccache);
+    cc_int32    (*create_new_ccache) (
+                                cc_context_t context,
+                                cc_uint32 cred_vers,
+                                const char* principal, 
+                                cc_ccache_t* ccache);
+    cc_int32    (*new_ccache_iterator) (
+                                cc_context_t context,
+                                cc_ccache_iterator_t* iterator);
+    cc_int32    (*lock) (
+                                cc_context_t context,
+                                cc_uint32 lock_type,
+                                cc_uint32 block);
+    cc_int32    (*unlock) (
+                                cc_context_t context);
+    cc_int32    (*compare) (
+                                cc_context_t context,
+                                cc_context_t compare_to,
+                                cc_uint32* equal);
+};
+
+struct cc_ccache_f {
+    cc_int32    (*release) (
+                                 cc_ccache_t ccache);
+    cc_int32    (*destroy) (
+                                 cc_ccache_t ccache);
+    cc_int32    (*set_default) (
+                                 cc_ccache_t ccache);
+    cc_int32    (*get_credentials_version) (
+                                 cc_ccache_t ccache,
+                                 cc_uint32* credentials_version);
+    cc_int32    (*get_name) (
+                                 cc_ccache_t ccache,
+                                 cc_string_t* name);
+    cc_int32    (*get_principal) (
+                                 cc_ccache_t ccache,
+                                 cc_uint32 credentials_version,
+                                 cc_string_t* principal);
+    cc_int32    (*set_principal) (
+                                 cc_ccache_t ccache,
+                                 cc_uint32 credentials_version,
+                                 const char* principal);
+    cc_int32    (*store_credentials) (
+                                 cc_ccache_t ccache,
+                                 const cc_credentials_union* credentials);
+    cc_int32    (*remove_credentials) (
+                                 cc_ccache_t ccache,
+                                 cc_credentials_t credentials);
+    cc_int32    (*new_credentials_iterator) (
+                                 cc_ccache_t ccache,
+                                 cc_credentials_iterator_t* iterator);
+    cc_int32    (*move) (
+                                 cc_ccache_t source,
+                                 cc_ccache_t destination);
+    cc_int32    (*lock) (
+                                 cc_ccache_t ccache,
+                                 cc_uint32 block,
+                                 cc_uint32 lock_type);
+    cc_int32    (*unlock) (
+                                 cc_ccache_t ccache);
+    cc_int32    (*get_last_default_time) (
+                                 cc_ccache_t ccache,
+                                 cc_time_t* time);
+    cc_int32    (*get_change_time) (
+                                 cc_ccache_t ccache,
+                                 cc_time_t* time);
+    cc_int32    (*compare) (
+                                cc_ccache_t ccache,
+                                cc_ccache_t compare_to,
+                                cc_uint32* equal);
+    cc_int32   (*get_kdc_time_offset) (
+                                cc_ccache_t ccache,
+                                cc_int32       credentials_version,
+                                cc_time_t*     time_offset);
+    cc_int32   (*set_kdc_time_offset) (
+                                cc_ccache_t ccache,
+                                cc_int32       credentials_version,
+                                cc_time_t      time_offset);
+                                
+    cc_int32   (*clear_kdc_time_offset) (
+                                cc_ccache_t    ccache,
+                                cc_int32       credentials_version);
+};
+
+struct cc_string_f {
+    cc_int32   (*release) (
+                                cc_string_t string);
+};
+
+struct cc_credentials_f {
+    cc_int32   (*release) (
+                                cc_credentials_t credentials);
+    cc_int32    (*compare) (
+                                cc_credentials_t credentials,
+                                cc_credentials_t compare_to,
+                                cc_uint32* equal);
+};
+
+                          
+struct cc_ccache_iterator_f {
+    cc_int32    (*release) (
+                                 cc_ccache_iterator_t iter);
+    cc_int32    (*next) (
+                                 cc_ccache_iterator_t iter,
+                                 cc_ccache_t* ccache);
+};
+
+struct cc_credentials_iterator_f {
+    cc_int32    (*release) (
+                                 cc_credentials_iterator_t iter);
+    cc_int32    (*next) (
+                                 cc_credentials_iterator_t iter,
+                                 cc_credentials_t* ccache);
+};
+
+/*
+ * API functions
+ */
+cc_int32 cc_initialize (
+       cc_context_t*           outContext,
+       cc_int32                        inVersion,
+       cc_int32*                       outSupportedVersion,
+       char const**            outVendor);
+       
+/*
+ * Convenience macros
+ */
+#define                cc_context_release(context)                                                                                             \
+                       ((context) -> functions -> release (context))
+#define                cc_context_get_change_time(context, time)                                                               \
+                       ((context) -> functions -> get_change_time (context, time))
+#define                cc_context_get_default_ccache_name(context, name)                                               \
+                       ((context) -> functions -> get_default_ccache_name (context, name))
+#define                cc_context_open_ccache(context, name, ccache)                                                   \
+                       ((context) -> functions -> open_ccache (context, name, ccache))
+#define                cc_context_open_default_ccache(context, ccache)                                                 \
+                       ((context) -> functions -> open_default_ccache (context, ccache))
+#define                cc_context_create_ccache(context, name, version, principal, ccache)             \
+                       ((context) -> functions -> create_ccache (context, name, version, principal, ccache))
+#define                cc_context_create_default_ccache(context, version, principal, ccache)   \
+                       ((context) -> functions -> create_default_ccache (context, version, principal, ccache))
+#define                cc_context_create_new_ccache(context, version, principal, ccache)               \
+                       ((context) -> functions -> create_new_ccache (context, version, principal, ccache))
+#define                cc_context_new_ccache_iterator(context, iterator)                                               \
+                       ((context) -> functions -> new_ccache_iterator (context, iterator))
+#define                cc_context_lock(context, type, lock)                                                                    \
+                       ((context) -> functions -> lock (context, type, lock))
+#define                cc_context_unlock(context)                                                                                              \
+                       ((context) -> functions -> unlock (context))
+#define                cc_context_compare(context, compare_to, equal)                                                  \
+                       ((context) -> functions -> compare (context, compare_to, equal))
+
+#define                cc_ccache_release(ccache)                                                                                               \
+                       ((ccache) -> functions -> release (ccache))
+#define                cc_ccache_destroy(ccache)                                                                                               \
+                       ((ccache) -> functions -> destroy (ccache))
+#define                cc_ccache_set_default(ccache)                                                                                   \
+                       ((ccache) -> functions -> set_default (ccache))
+#define                cc_ccache_get_credentials_version(ccache, version)                                              \
+                       ((ccache) -> functions -> get_credentials_version (ccache, version))
+#define                cc_ccache_get_name(ccache, name)                                                                                \
+                       ((ccache) -> functions -> get_name (ccache, name))
+#define                cc_ccache_get_principal(ccache, version, principal)                                             \
+                       ((ccache) -> functions -> get_principal (ccache, version, principal))
+#define                cc_ccache_set_principal(ccache, version, principal)                                             \
+                       ((ccache) -> functions -> set_principal (ccache, version, principal))
+#define                cc_ccache_store_credentials(ccache, credentials)                                                \
+                       ((ccache) -> functions -> store_credentials (ccache, credentials))
+#define                cc_ccache_remove_credentials(ccache, credentials)                                               \
+                       ((ccache) -> functions -> remove_credentials (ccache, credentials))
+#define                cc_ccache_new_credentials_iterator(ccache, iterator)                                    \
+                       ((ccache) -> functions -> new_credentials_iterator (ccache, iterator))
+#define                cc_ccache_lock(ccache, lock)                                                                                    \
+                       ((ccache) -> functions -> lock (ccache, lock))
+#define                cc_ccache_unlock(ccache, unlock)                                                                                \
+                       ((ccache) -> functions -> unlock (ccache, unlock))
+#define                cc_ccache_get_last_default_time(ccache, time)                                                   \
+                       ((ccache) -> functions -> get_last_default_time (ccache, time))
+#define                cc_ccache_get_change_time(ccache, time)                                                                 \
+                       ((ccache) -> functions -> get_change_time (ccache, time))
+#define                cc_ccache_move(source, destination)                                                                             \
+                       ((source) -> functions -> move (source, destination))
+#define                cc_ccache_compare(ccache, compare_to, equal)                                                    \
+                       ((ccache) -> functions -> compare (ccache, compare_to, equal))
+#define                cc_ccache_get_kdc_time_offset(ccache, version, time)                                    \
+            ((ccache) -> functions -> get_kdc_time_offset (version, time))
+#define                cc_ccache_set_kdc_time_offset(ccache, version, time)                                    \
+            ((ccache) -> functions -> set_kdc_time_offset (version, time))
+#define                cc_ccache_clear_kdc_time_offset(ccache, version)                                                \
+            ((ccache) -> functions -> clear_kdc_time_offset (version))
+
+#define                cc_string_release(string)                                                                                               \
+                       ((string) -> functions -> release (string))
+
+#define                cc_credentials_release(credentials)                                                                             \
+                       ((credentials) -> functions -> release (credentials))
+#define                cc_credentials_compare(credentials, compare_to, equal)                                  \
+                       ((credentials) -> functions -> compare (credentials, compare_to, equal))
+
+#define                cc_ccache_iterator_release(iterator)                                                                    \
+                       ((iterator) -> functions -> release (iterator))
+#define                cc_ccache_iterator_next(iterator, ccache)                                                               \
+                       ((iterator) -> functions -> next (iterator, ccache))
+       
+#define                cc_credentials_iterator_release(iterator)                                                               \
+                       ((iterator) -> functions -> release (iterator))
+#define                cc_credentials_iterator_next(iterator, credentials)                                             \
+                       ((iterator) -> functions -> next (iterator, credentials))
+                       
+#if TARGET_OS_MAC
+    #if defined(__MWERKS__)
+        #pragma enumsalwaysint reset
+        #pragma import reset
+    #endif
+       #pragma options align=reset
+#endif
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* __CREDENTIALSCACHE__ */
diff --git a/src/lib/ccapi/include/CredentialsCache2.h b/src/lib/ccapi/include/CredentialsCache2.h
new file mode 100644 (file)
index 0000000..401e093
--- /dev/null
@@ -0,0 +1,308 @@
+/* $Copyright:
+ *
+ * Copyright 1998-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).
+ * $
+ */
+/*
+ * This is backwards compatibility for CCache API v2 clients to be able to run 
+ * against the CCache API v3 library
+ */
+#ifndef __CREDENTIALSCACHE2__
+#define __CREDENTIALSCACHE2__
+#include <Kerberos/CredentialsCache.h>
+#if defined(macintosh) || (defined(__MACH__) && defined(__APPLE__))
+       #include <TargetConditionals.h>
+    #if TARGET_RT_MAC_CFM
+        #error "Use KfM 4.0 SDK headers for CFM compilation."
+    #endif
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+#if TARGET_OS_MAC
+    #if defined(__MWERKS__)
+        #pragma import on
+        #pragma enumsalwaysint on
+    #endif
+    #pragma options align=mac68k
+#endif
+
+/* Some old types get directly mapped to new types */
+
+typedef cc_context_d apiCB;
+typedef cc_ccache_d ccache_p;
+typedef cc_credentials_iterator_d ccache_cit_creds;
+typedef cc_ccache_iterator_d ccache_cit_ccache;
+typedef cc_data cc_data_compat;
+typedef cc_int32 cc_cred_vers;
+typedef cc_int32 cc_result;
+
+/* This doesn't exist in API v3 */
+typedef cc_uint32 cc_flags;
+
+/* Credentials types are visible to the caller so we have to keep binary compatibility */
+
+typedef struct cc_credentials_v5_compat {
+    char*                      client;
+    char*                      server;
+    cc_data_compat             keyblock;
+    cc_time_t                  authtime;
+    cc_time_t                  starttime;
+    cc_time_t                  endtime;
+    cc_time_t                  renew_till;
+    cc_uint32                  is_skey;
+    cc_uint32                  ticket_flags;
+    cc_data_compat**           addresses;
+    cc_data_compat             ticket;
+    cc_data_compat             second_ticket;
+    cc_data_compat**           authdata;
+} cc_credentials_v5_compat;
+enum {
+    MAX_V4_CRED_LEN = 1250
+};
+enum {
+    KRB_NAME_SZ = 40,
+    KRB_INSTANCE_SZ = 40,
+    KRB_REALM_SZ = 40
+};
+typedef struct cc_credentials_v4_compat {
+    unsigned char      kversion;
+    char               principal[KRB_NAME_SZ+1];
+    char               principal_instance[KRB_INSTANCE_SZ+1];
+    char               service[KRB_NAME_SZ+1];
+    char               service_instance[KRB_INSTANCE_SZ+1];
+    char               realm[KRB_REALM_SZ+1];
+    unsigned char      session_key[8];
+    cc_int32           kvno;
+    cc_int32           str_to_key;
+    long               issue_date;
+    cc_int32           lifetime;
+    cc_uint32          address;
+    cc_int32           ticket_sz;
+    unsigned char      ticket[MAX_V4_CRED_LEN];
+    unsigned long      oops;
+} cc_credentials_v4_compat;
+
+typedef union cred_ptr_union_compat {
+    cc_credentials_v4_compat*  pV4Cred;
+    cc_credentials_v5_compat*  pV5Cred;
+} cred_ptr_union_compat;
+typedef struct cred_union {
+    cc_int32                           cred_type;  // cc_cred_vers
+    cred_ptr_union_compat      cred;
+} cred_union;
+
+/* NC info structure is gone in v3 */
+
+struct infoNC {
+    char*      name;
+    char*      principal;
+    cc_int32   vers;
+};
+
+typedef struct infoNC infoNC;
+
+/* Some old type names */
+
+typedef cc_credentials_v4_compat V4Cred_type;
+typedef cc_credentials_v5_compat cc_creds;
+struct ccache_cit;
+typedef struct ccache_cit ccache_cit;
+
+enum {
+    CC_API_VER_2 = ccapi_version_2
+};
+
+enum {
+    CC_NOERROR,
+    CC_BADNAME,
+    CC_NOTFOUND,
+    CC_END,
+    CC_IO,
+    CC_WRITE,
+    CC_NOMEM,
+    CC_FORMAT,
+    CC_LOCKED,
+    CC_BAD_API_VERSION,
+    CC_NO_EXIST,
+    CC_NOT_SUPP,
+    CC_BAD_PARM,
+    CC_ERR_CACHE_ATTACH,
+    CC_ERR_CACHE_RELEASE,
+    CC_ERR_CACHE_FULL,
+    CC_ERR_CRED_VERSION
+};      
+
+enum {
+    CC_CRED_UNKNOWN,
+    CC_CRED_V4,
+    CC_CRED_V5,
+    CC_CRED_MAX
+};
+
+cc_int32 cc_shutdown (
+        apiCB**                                ioContext);
+       
+cc_int32 cc_get_NC_info (
+       apiCB*                          inContext,
+       infoNC***                       outInfo);
+       
+cc_int32 cc_get_change_time (
+       apiCB*                          inContext,
+       cc_time_t*                      outTime);
+       
+cc_int32 cc_open (
+       apiCB*                          inContext,
+       const char*                     inName,
+       cc_int32                        inVersion,
+       cc_uint32                       inFlags,
+       ccache_p**                      outCCache);
+       
+cc_int32 cc_create (
+       apiCB*                          inContext,
+       const char*                     inName,
+       const char*                     inPrincipal,
+       cc_int32                        inVersion,
+       cc_uint32                       inFlags,
+       ccache_p**                      outCCache);
+       
+cc_int32 cc_close (
+       apiCB*                          inContext,
+       ccache_p**                      ioCCache);
+       
+cc_int32 cc_destroy (
+       apiCB*                          inContext,
+       ccache_p**                      ioCCache);
+       
+cc_int32 cc_seq_fetch_NCs_begin (
+       apiCB*                          inContext,
+       ccache_cit**            outIterator);
+
+cc_int32 cc_seq_fetch_NCs_next (
+       apiCB*                          inContext,
+       ccache_p**                      outCCache,
+       ccache_cit*                     inIterator);
+
+cc_int32 cc_seq_fetch_NCs_end (
+       apiCB*                          inContext,
+       ccache_cit**            ioIterator);
+
+cc_int32 cc_get_name (
+       apiCB*                          inContext,
+       ccache_p*                       inCCache,
+       char**                          outName);
+       
+cc_int32 cc_get_cred_version (
+       apiCB*                          inContext,
+       ccache_p*                       inCCache,
+       cc_int32*                       outVersion);
+       
+cc_int32 cc_set_principal (
+       apiCB*                          inContext,
+       ccache_p*                       inCCache,
+       cc_int32                        inVersion,
+       char*                           inPrincipal);
+       
+cc_int32 cc_get_principal (
+       apiCB*                          inContext,
+       ccache_p*                       inCCache,
+       char**                          outPrincipal);
+       
+cc_int32 cc_store (
+       apiCB*                          inContext,
+       ccache_p*                       inCCache,
+       cred_union                      inCredentials);
+
+cc_int32 cc_remove_cred (
+       apiCB*                          inContext,
+       ccache_p*                       inCCache,
+       cred_union                      inCredentials);
+
+cc_int32 cc_seq_fetch_creds_begin (
+       apiCB*                          inContext,
+       const ccache_p*         inCCache,
+       ccache_cit**            outIterator);
+
+cc_int32 cc_seq_fetch_creds_next (
+       apiCB*                          inContext,
+       cred_union**            outCreds,
+       ccache_cit*                     inIterator);
+       
+cc_int32 cc_seq_fetch_creds_end (
+       apiCB*                          inContext,
+       ccache_cit**            ioIterator);
+       
+cc_int32 cc_free_principal (
+       apiCB*                          inContext,
+       char**                          ioPrincipal);
+
+cc_int32 cc_free_name (
+       apiCB*                          inContext,
+       char**                          ioName);
+
+cc_int32 cc_free_creds (
+       apiCB*                          inContext,
+       cred_union**            creds);
+
+cc_int32 cc_free_NC_info (
+       apiCB*                          inContext,
+       infoNC***                       ioInfo);
+       
+#if TARGET_OS_MAC
+    #if defined(__MWERKS__)
+        #pragma enumsalwaysint reset
+        #pragma import reset
+    #endif
+       #pragma options align=reset
+#endif
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* __CREDENTIALSCACHE2__ */
\ No newline at end of file
diff --git a/src/lib/ccapi/include/marshall.h b/src/lib/ccapi/include/marshall.h
new file mode 100644 (file)
index 0000000..19b9463
--- /dev/null
@@ -0,0 +1,93 @@
+/* $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).
+ * $
+ */
+
+#define FLAT_CREDS_V5_VERSION   1
+struct cc_flat_data {
+    cc_uint32                   type;
+    cc_uint32                   length;
+    cc_uint32                   data;
+};
+typedef struct cc_flat_data cc_flat_data;
+
+struct cci_flat_creds_v5 {
+    cc_uint32                   version;        /* version of this structure */
+    cc_flat_data                client;
+    cc_flat_data                server;
+    cc_flat_data               keyblock;
+    cc_time_t                  authtime;
+    cc_time_t                  starttime;
+    cc_time_t                  endtime;
+    cc_time_t                  renew_till;
+    cc_uint32                  is_skey;
+    cc_uint32                  ticket_flags;
+    cc_uint32                   address_count;
+    cc_uint32                   addresses; /* offset to array */
+    cc_flat_data               ticket;
+    cc_flat_data               second_ticket;
+    cc_uint32                   authdata_count;
+    cc_uint32                  authdata;  /* offset to array */
+};
+
+cc_int32
+cci_creds_v4_marshall( cc_credentials_v4_t * creds, 
+                       char ** flat, 
+                       cc_uint32 * len);
+
+cc_int32
+cci_creds_v4_unmarshall( char * flat, 
+                         cc_uint32 len,
+                         cc_credentials_union * creds);
+
+cc_int32
+cci_creds_v5_marshall( cc_credentials_v5_t * creds, 
+                       char ** pflat, 
+                       cc_uint32 * plen);
+
+cc_int32
+cci_creds_v5_unmarshall( char * flat, 
+                         cc_uint32 len,
+                         cc_credentials_union * creds_union);
+
+
+
+
diff --git a/src/lib/ccapi/include/msg.h b/src/lib/ccapi/include/msg.h
new file mode 100644 (file)
index 0000000..0d712d6
--- /dev/null
@@ -0,0 +1,146 @@
+/* $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).
+ * $
+ */
+
+/*
+ * Verifiable, extensible message format.
+ *
+ * Format:
+ * <size of header block (header_len)>
+ * <size of *entire* message, including previous field (flat_len)>
+ * <message type (type)>
+ * <type specific header (header)>
+ * <magic number (magic)>
+ * <data blob 1 length>
+ * <data blob 1>
+ * <data blob 2 length>
+ * <data blob 2>
+ * ...
+ * <magic number (magic)>
+ *
+ * If the header has variable length data it is included in the data blobs. 
+ * The header field has the offset from the beginning of the message of the 1st 
+ * byte of the data and the length of the data.
+ *
+ */
+
+#ifndef __CC_MSG_H__
+#define __CC_MSG_H__
+
+#include "CredentialsCache.h"
+
+struct  cc_msg_t {
+    cc_uint32 type;                    /*type of message*/
+    cc_uint8 *flat;                    /*flattened representation of this message*/
+    cc_uint8 *header;                  /*fixed length header determined by message type*/
+    cc_uint32 flat_len;                        /*length of flat rep*/
+    cc_uint32 header_len;              /*length of header*/
+    cc_uint32 magic;                   /*magic number for verification purposes*/
+    cc_generic_list_head_t* data_blobs;        /*variable length data*/
+};      
+typedef struct cc_msg_t cc_msg_t;
+
+/*Types of messages*/
+enum {
+    ccmsg_ACK,
+    ccmsg_NACK,
+    ccmsg_INIT,
+    ccmsg_CTX_RELEASE,
+    ccmsg_CTX_GET_CHANGE_TIME,
+    ccmsg_CTX_GET_DEFAULT_CCACHE_NAME,
+    ccmsg_CTX_COMPARE,
+    ccmsg_CTX_NEW_CCACHE_ITERATOR,
+    ccmsg_CTX_LOCK,
+    ccmsg_CTX_UNLOCK,
+    ccmsg_CTX_CLONE,
+    ccmsg_CCACHE_OPEN,
+    ccmsg_CCACHE_OPEN_DEFAULT,
+    ccmsg_CCACHE_CREATE,
+    ccmsg_CCACHE_CREATE_DEFAULT,
+    ccmsg_CCACHE_CREATE_UNIQUE,
+    ccmsg_CCACHE_RELEASE,
+    ccmsg_CCACHE_DESTROY,
+    ccmsg_CCACHE_SET_DEFAULT,
+    ccmsg_CCACHE_GET_CREDS_VERSION,
+    ccmsg_CCACHE_GET_NAME,
+    ccmsg_CCACHE_GET_PRINCIPAL,
+    ccmsg_CCACHE_SET_PRINCIPAL,
+    ccmsg_CCACHE_CREDS_ITERATOR,
+    ccmsg_CCACHE_STORE_CREDS,
+    ccmsg_CCACHE_REM_CREDS,
+    ccmsg_CCACHE_GET_LAST_DEFAULT_TIME,
+    ccmsg_CCACHE_GET_CHANGE_TIME,
+    ccmsg_CCACHE_MOVE,
+    ccmsg_CCACHE_COMPARE,
+    ccmsg_CCACHE_GET_KDC_TIME_OFFSET,
+    ccmsg_CCACHE_SET_KDC_TIME_OFFSET,
+    ccmsg_CCACHE_CLEAR_KDC_TIME_OFFSET,
+    ccmsg_CCACHE_ITERATOR_RELEASE,
+    ccmsg_CCACHE_ITERATOR_NEXT,
+    ccmsg_CCACHE_LOCK,
+    ccmsg_CCACHE_UNLOCK,
+    ccmsg_CREDS_ITERATOR_RELEASE,
+    ccmsg_CREDS_ITERATOR_NEXT,
+    ccmsg_CREDS_RELEASE,
+    ccmsg_CREDS_V4,
+    ccmsg_CREDS_V5
+};      
+
+#define CC_MSG_MAX_SIZE        1073741824 /*2^30*/
+#define CC_MSG_MAX_TYPE ccmsg_CREDS_V5
+#define BLOB_LEN (sizeof(cc_uint32))
+#define MAGIC_DATA_LEN (sizeof(cc_uint32))
+#define MAGIC_HEAD_LEN (sizeof(cc_uint32))
+
+cc_int32 cci_msg_new(cc_uint32 type, cc_msg_t** msgpp);
+cc_int32 cci_msg_calc_size(cc_msg_t* msg, cc_uint32 * sizep);
+cc_int32 cci_msg_calc_header_size(cc_msg_t* msg, cc_uint32 * sizep);
+cc_int32 cci_msg_add_data_blob(cc_msg_t* msg, void *data, cc_uint32 len, cc_uint32 * sizep);
+cc_int32 cci_msg_add_header(cc_msg_t* msg, void *header, cc_uint32 header_len);
+cc_int32 cci_msg_calc_blob_pos(cc_msg_t* msg, void *data, cc_uint32 len, cc_uint32 * sizep);
+cc_int32 cci_msg_flatten(cc_msg_t* msg, void **);
+cc_int32 cci_msg_calc_magic(void *flat, int flat_len, cc_uint32 * sizep);
+cc_int32 cci_msg_verify(void* flat, int flat_len, cc_uint32 * sizep);
+cc_int32 cci_msg_unflatten(void *flat, int flat_len, cc_msg_t** msgpp);
+cc_int32 cci_msg_retrieve_blob(cc_msg_t* msg, cc_uint32 blob_offset, cc_uint32 blob_len, void **);
+cc_int32 cci_msg_destroy(cc_msg_t* msg);
+#endif /*__CC_MSG_H__*/
diff --git a/src/lib/ccapi/include/msg_headers.h b/src/lib/ccapi/include/msg_headers.h
new file mode 100644 (file)
index 0000000..a27c2d2
--- /dev/null
@@ -0,0 +1,429 @@
+/* $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).
+ * $
+ */
+
+/*
+ * Message type specific header structures.
+ *
+ */
+
+#ifndef __MSG_HEADERS_H__
+#define __MSG_HEADERS_H__
+
+#include "CredentialsCache.h"
+
+/*
+ * All header structs must have sizes divisible by 4, and
+ * all individual fields within the structs must also have
+ * size divisible by 4. This is to ensure correct alignment
+ * and stop different compilers from inserting padding bytes in
+ * different places.
+ */
+
+struct ccmsg_ctx_only_t {
+    cc_handle ctx;
+};
+typedef struct ccmsg_ctx_only_t ccmsg_ctx_only_t;
+
+struct ccmsg_nack_t {
+    cc_uint32  err_code;       /*error code that caused failure*/
+};
+typedef struct ccmsg_nack_t ccmsg_nack_t;
+
+struct ccmsg_init_t {
+    cc_uint32  in_version;             /*client API version*/
+};
+struct ccmsg_init_resp_t {
+    cc_handle  out_ctx;                /*handle on this ctx*/
+    cc_uint32  out_version;            /*server API version*/
+    cc_uint32  vendor_offset;          /*offset of vendor blob*/
+    cc_uint32  vendor_length;          /*length of vendor blob*/
+};      
+typedef struct ccmsg_init_t ccmsg_init_t;
+typedef struct ccmsg_init_resp_t ccmsg_init_resp_t;
+
+struct ccmsg_clone_t {
+    cc_handle   ctx;
+    cc_uint32  in_version;             /*client API version*/
+};
+struct ccmsg_clone_resp_t {
+    cc_handle  out_ctx;                /*handle on this ctx*/
+    cc_uint32  out_version;            /*server API version*/
+    cc_uint32  vendor_offset;          /*offset of vendor blob*/
+    cc_uint32  vendor_length;          /*length of vendor blob*/
+};      
+typedef struct ccmsg_clone_t ccmsg_clone_t;
+typedef struct ccmsg_clone_resp_t ccmsg_clone_resp_t;
+
+struct ccmsg_ctx_release_t {
+    cc_handle  ctx;    /*# of ctx to release*/
+};
+typedef struct ccmsg_ctx_release_t ccmsg_ctx_release_t;
+
+struct ccmsg_ctx_get_change_time_t {
+    cc_handle  ctx;
+};
+struct ccmsg_ctx_get_change_time_resp_t {
+    cc_time_t  time;
+};
+typedef struct ccmsg_ctx_get_change_time_t ccmsg_ctx_get_change_time_t;
+typedef struct ccmsg_ctx_get_change_time_resp_t ccmsg_ctx_get_change_time_resp_t;
+
+struct ccmsg_ctx_get_default_ccache_name_t {
+    cc_handle  ctx;
+};
+struct ccmsg_ctx_get_default_ccache_name_resp_t {
+    cc_uint32  name_offset;
+    cc_uint32  name_len;
+};
+typedef struct ccmsg_ctx_get_default_ccache_name_t ccmsg_ctx_get_default_ccache_name_t;
+typedef struct ccmsg_ctx_get_default_ccache_name_resp_t ccmsg_ctx_get_default_ccache_name_resp_t;
+
+struct ccmsg_ctx_compare_t {
+    cc_handle  ctx1;
+    cc_handle  ctx2;
+};
+struct ccmsg_ctx_compare_resp_t {
+    cc_uint32  is_equal;       
+};
+typedef struct ccmsg_ctx_compare_t ccmsg_ctx_compare_t;
+typedef struct ccmsg_ctx_compare_resp_t ccmsg_ctx_compare_resp_t;
+
+struct ccmsg_ctx_new_ccache_iterator_t {
+    cc_handle  ctx;
+};
+struct ccmsg_ctx_new_ccache_iterator_resp_t {
+    cc_handle  iterator;
+};
+typedef struct ccmsg_ctx_new_ccache_iterator_t ccmsg_ctx_new_ccache_iterator_t;
+typedef struct ccmsg_ctx_new_ccache_iterator_resp_t ccmsg_ctx_new_ccache_iterator_resp_t;
+
+struct ccmsg_ctx_lock_t {
+    cc_handle   ctx;
+    cc_uint32   lock_type;
+};
+typedef struct ccmsg_ctx_lock_t ccmsg_ctx_lock_t;
+
+struct ccmsg_ctx_unlock_t {
+    cc_handle   ctx;
+};
+typedef struct ccmsg_ctx_unlock_t ccmsg_ctx_unlock_t;
+
+struct ccmsg_ccache_open_t {
+    cc_handle  ctx;
+    cc_uint32  name_offset;
+    cc_uint32  name_len;
+};      
+struct ccmsg_ccache_open_resp_t {
+    cc_handle  ccache;
+};
+typedef struct ccmsg_ccache_open_t ccmsg_ccache_open_t;
+typedef struct ccmsg_ccache_open_resp_t ccmsg_ccache_open_resp_t;
+
+struct ccmsg_ccache_open_default_t {
+    cc_handle  ctx;
+};
+typedef struct ccmsg_ccache_open_default_t ccmsg_ccache_open_default_t;
+
+struct ccmsg_ccache_create_t {
+    cc_handle  ctx;
+    cc_uint32  version;
+    cc_uint32  principal_offset;
+    cc_uint32  principal_len;
+    cc_uint32  name_offset;
+    cc_uint32  name_len;
+};
+struct ccmsg_ccache_create_default_t {
+    cc_handle  ctx;
+    cc_uint32  version;
+    cc_uint32  principal_offset;
+    cc_uint32  principal_len;
+};
+struct ccmsg_ccache_create_unique_t {
+    cc_handle  ctx;
+    cc_uint32  version;
+    cc_uint32  principal_offset;
+    cc_uint32  principal_len;
+};
+
+struct ccmsg_ccache_create_resp_t {
+    cc_handle  ccache;
+};
+typedef struct ccmsg_ccache_create_t ccmsg_ccache_create_t;
+typedef struct ccmsg_ccache_create_default_t ccmsg_ccache_create_default_t;
+typedef struct ccmsg_ccache_create_unique_t ccmsg_ccache_create_unique_t;
+typedef struct ccmsg_ccache_create_resp_t ccmsg_ccache_create_resp_t;
+
+struct ccmsg_ccache_release_t {
+    cc_handle  ctx;
+    cc_handle  ccache;
+};
+typedef struct ccmsg_ccache_release_t ccmsg_ccache_release_t;
+
+struct ccmsg_ccache_destroy_t {
+    cc_handle  ctx;
+    cc_handle  ccache;
+};
+typedef struct ccmsg_ccache_destroy_t ccmsg_ccache_destroy_t;
+
+struct ccmsg_ccache_set_default_t {
+    cc_handle  ctx;
+    cc_handle  ccache;
+};
+typedef struct ccmsg_ccache_set_default_t ccmsg_ccache_set_default_t;
+
+struct ccmsg_ccache_get_creds_version_t {
+    cc_handle  ctx;
+    cc_handle  ccache;
+};
+struct ccmsg_ccache_get_creds_version_resp_t {
+    cc_uint32  version;
+};
+typedef struct ccmsg_ccache_get_creds_version_t ccmsg_ccache_get_creds_version_t;
+typedef struct ccmsg_ccache_get_creds_version_resp_t ccmsg_ccache_get_creds_version_resp_t;
+
+struct ccmsg_ccache_get_name_t {
+    cc_handle  ctx;
+    cc_handle  ccache;
+};
+struct ccmsg_ccache_get_name_resp_t {
+    cc_uint32  name_offset;
+    cc_uint32  name_len;
+};      
+typedef struct ccmsg_ccache_get_name_t ccmsg_ccache_get_name_t;
+typedef struct ccmsg_ccache_get_name_resp_t ccmsg_ccache_get_name_resp_t;
+
+struct ccmsg_ccache_get_principal_t {
+    cc_handle  ctx;
+    cc_handle  ccache;
+    cc_uint32  version;
+};
+struct ccmsg_ccache_get_principal_resp_t {
+    cc_uint32  principal_offset;
+    cc_uint32  principal_len;
+};
+typedef struct ccmsg_ccache_get_principal_t ccmsg_ccache_get_principal_t;
+typedef struct ccmsg_ccache_get_principal_resp_t ccmsg_ccache_get_principal_resp_t;
+
+struct ccmsg_ccache_set_principal_t {
+    cc_handle  ctx;
+    cc_handle  ccache;
+    cc_uint32  version;        
+    cc_uint32  principal_offset;
+    cc_uint32  principal_len;
+};
+typedef struct ccmsg_ccache_set_principal_t ccmsg_ccache_set_principal_t;
+
+struct ccmsg_ccache_creds_iterator_t {
+    cc_handle  ctx;
+    cc_handle  ccache;
+};
+struct ccmsg_ccache_creds_iterator_resp_t {
+    cc_handle  iterator;
+};
+typedef struct ccmsg_ccache_creds_iterator_t ccmsg_ccache_creds_iterator_t;
+typedef struct ccmsg_ccache_creds_iterator_resp_t ccmsg_ccache_creds_iterator_resp_t;
+
+struct ccmsg_ccache_store_creds_t {
+    cc_handle  ctx;
+    cc_handle  ccache;
+    cc_uint32   creds_version;
+    cc_uint32  creds_offset;
+    cc_uint32  creds_len;
+};
+typedef struct ccmsg_ccache_store_creds_t ccmsg_ccache_store_creds_t;
+
+struct ccmsg_ccache_rem_creds_t {
+    cc_handle  ctx;
+    cc_handle  ccache;
+    cc_handle   creds;
+};
+typedef struct ccmsg_ccache_rem_creds_t ccmsg_ccache_rem_creds_t;
+
+struct ccmsg_ccache_lock_t {
+    cc_handle  ctx;
+    cc_handle   ccache;
+    cc_uint32   lock_type;
+};
+typedef struct ccmsg_ccache_lock_t ccmsg_ccache_lock_t;
+
+struct ccmsg_ccache_unlock_t {
+    cc_handle  ctx;
+    cc_handle   ccache;
+};
+typedef struct ccmsg_ccache_unlock_t ccmsg_ccache_unlock_t;
+
+struct ccmsg_ccache_move_t {
+    cc_handle  ctx;
+    cc_handle  ccache_source;
+    cc_handle   ccache_dest;
+};
+typedef struct ccmsg_ccache_move_t ccmsg_ccache_move_t;
+
+struct ccmsg_ccache_get_last_default_time_t {
+    cc_handle  ctx;
+    cc_handle  ccache;
+};
+struct ccmsg_ccache_get_last_default_time_resp_t {
+    cc_time_t  last_default_time;
+};
+typedef struct ccmsg_ccache_get_last_default_time_t ccmsg_ccache_get_last_default_time_t;
+typedef struct ccmsg_ccache_get_last_default_time_resp_t ccmsg_ccache_get_last_default_time_resp_t;
+
+struct ccmsg_ccache_get_change_time_t {
+    cc_handle   ctx;
+    cc_handle  ccache;
+};
+struct ccmsg_ccache_get_change_time_resp_t {
+    cc_time_t  time;
+};
+typedef struct ccmsg_ccache_get_change_time_t ccmsg_ccache_get_change_time_t;
+typedef struct ccmsg_ccache_get_change_time_resp_t ccmsg_ccache_get_change_time_resp_t;
+
+struct ccmsg_ccache_compare_t {
+    cc_handle  ctx;
+    cc_handle  ccache1;
+    cc_handle  ccache2;
+};
+struct ccmsg_ccache_compare_resp_t {
+    cc_uint32  is_equal;
+};
+typedef struct ccmsg_ccache_compare_t ccmsg_ccache_compare_t;
+typedef struct ccmsg_ccache_compare_resp_t ccmsg_ccache_compare_resp_t;
+
+struct ccmsg_ccache_get_kdc_time_offset_t {
+    cc_handle  ctx;
+    cc_handle  ccache;
+    cc_int32    creds_version;
+};      
+struct ccmsg_ccache_get_kdc_time_offset_resp_t {
+    cc_time_t  offset;
+};
+typedef struct ccmsg_ccache_get_kdc_time_offset_t ccmsg_ccache_get_kdc_time_offset_t;
+typedef struct ccmsg_ccache_get_kdc_time_offset_resp_t ccmsg_ccache_get_kdc_time_offset_resp_t;
+
+struct ccmsg_ccache_set_kdc_time_offset_t {
+    cc_handle  ctx;
+    cc_handle  ccache;
+    cc_time_t  offset;
+    cc_int32    creds_version;
+};
+typedef struct ccmsg_ccache_set_kdc_time_offset_t ccmsg_ccache_set_kdc_time_offset_t;
+
+struct ccmsg_ccache_clear_kdc_time_offset_t {
+    cc_handle  ctx;
+    cc_handle  ccache;
+    cc_int32    creds_version;
+};
+typedef struct ccmsg_ccache_clear_kdc_time_offset_t ccmsg_ccache_clear_kdc_time_offset_t;
+
+struct ccmsg_ccache_iterator_release_t {
+    cc_handle  ctx;
+    cc_handle  iterator;
+};
+typedef struct ccmsg_ccache_iterator_release_t ccmsg_ccache_iterator_release_t;
+
+struct ccmsg_ccache_iterator_next_t {
+    cc_handle  ctx;
+    cc_handle  iterator;
+};
+struct ccmsg_ccache_iterator_next_resp_t {
+    cc_handle  ccache;
+};
+typedef struct ccmsg_ccache_iterator_next_t ccmsg_ccache_iterator_next_t;
+typedef struct ccmsg_ccache_iterator_next_resp_t ccmsg_ccache_iterator_next_resp_t;
+
+struct ccmsg_creds_iterator_release_t {
+    cc_handle  ctx;
+    cc_handle  ccache;
+    cc_handle  iterator;
+};
+typedef struct ccmsg_creds_iterator_release_t ccmsg_creds_iterator_release_t;
+
+struct ccmsg_creds_iterator_next_t {
+    cc_handle  ctx;
+    cc_handle  ccache;
+    cc_handle  iterator;
+};
+struct ccmsg_creds_iterator_next_resp_t {
+    cc_uint32  version;
+    cc_handle   creds_handle;
+    cc_uint32  creds_offset;
+    cc_uint32  creds_len;
+};
+typedef struct ccmsg_creds_iterator_next_t ccmsg_creds_iterator_next_t;
+typedef struct ccmsg_creds_iterator_next_resp_t ccmsg_creds_iterator_next_resp_t;
+
+struct ccmsg_creds_v4_t {
+    cc_uint32 offset;
+    cc_uint32 len;
+};
+typedef struct ccmsg_creds_v4_t ccmsg_creds_v4_t;
+
+struct ccmsg_creds_v5_t {
+    cc_uint32 client_offset;
+    cc_uint32 client_len;
+    cc_uint32 server_offset;
+    cc_uint32 server_len;
+    cc_uint32 keyblock_offset;
+    cc_uint32 keyblock_len;
+    cc_time_t authtime;
+    cc_time_t starttime;
+    cc_time_t endtime;
+    cc_time_t renewtime;
+    cc_uint32 is_skey;
+    cc_uint32 ticket_flags;
+    cc_uint32 address_count;
+    cc_uint32 address_offset;
+    cc_uint32 address_len;
+    cc_uint32 ticket_offset;
+    cc_uint32 ticket_len;
+    cc_uint32 ticket2_offset;
+    cc_uint32 ticket2_len;
+    cc_uint32 authdata_count;
+    cc_uint32 authdata_offset;
+    cc_uint32 authdata_len;
+};
+typedef struct ccmsg_creds_v5_t ccmsg_creds_v5_t;
+
+
+#endif /*__MSG_HEADERS_H__*/
diff --git a/src/lib/ccapi/mac/ChangeLog b/src/lib/ccapi/mac/ChangeLog
new file mode 100644 (file)
index 0000000..aaa59da
--- /dev/null
@@ -0,0 +1,4 @@
+2004-10-27   Jeffrey Altman  <jaltman@mit.edu>
+
+ * Initial commit of C CCAPI implementation
+
diff --git a/src/lib/ccapi/marshall.c b/src/lib/ccapi/marshall.c
new file mode 100644 (file)
index 0000000..7027d65
--- /dev/null
@@ -0,0 +1,378 @@
+/* $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).
+ * $
+ */
+
+/* marshall.c */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <CredentialsCache.h>
+#include "msg.h"
+#include "msg_headers.h"
+#include "marshall.h"
+
+cc_int32
+cci_creds_v4_marshall( cc_credentials_v4_t * creds, 
+                       char ** flat, 
+                       cc_uint32 * len)
+{
+    cc_msg_t *  msg;
+    ccmsg_creds_v4_t * header;
+    cc_uint32   blob_pos;
+    cc_int32    code;
+
+    if ( creds == NULL || flat == NULL || len == NULL )
+        return ccErrBadParam;
+
+    header = (ccmsg_creds_v4_t *)malloc(sizeof(ccmsg_creds_v4_t));
+    if ( header == NULL )
+        return ccErrNoMem;
+
+    code = cci_msg_new(ccmsg_CREDS_V4, &msg);
+
+    code = cci_msg_add_header(msg, header, sizeof(ccmsg_creds_v4_t));
+
+    code = cci_msg_add_data_blob(msg, creds, sizeof(cc_credentials_v4_t), &blob_pos);
+
+    header->offset = blob_pos;
+    header->len    = sizeof(cc_credentials_v4_t);
+
+    code = cci_msg_flatten( msg, NULL );
+
+    *flat = msg->flat;
+    *len  = msg->flat_len;
+    msg->flat = NULL;
+    msg->flat_len = 0;
+
+    cci_msg_destroy(msg);
+
+    return ccNoError;
+}
+
+cc_int32
+cci_creds_v4_unmarshall( char * flat, 
+                         cc_uint32 len,
+                         cc_credentials_union * creds)
+{
+    cc_msg_t * msg; 
+    ccmsg_creds_v4_t * header;
+    cc_int32   code;
+
+    if ( flat == NULL || len == 0 || creds == NULL )
+        return ccErrBadParam;
+
+    code = cci_msg_unflatten( flat, len, &msg );
+
+    header = (ccmsg_creds_v4_t *)msg->header;
+
+    creds->version = cc_credentials_v4;
+    code = cci_msg_retrieve_blob(msg, header->offset, header->len, &creds->credentials.credentials_v4);
+
+    cci_msg_destroy(msg);
+
+    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; i<count; i++ ) {
+        len += creds->addresses[i]->length;
+    }
+
+    len += creds->ticket.length;
+    len += creds->second_ticket.length;
+
+    cci_creds_cc_data_array_count_entries( creds->authdata, &count );
+    len += count * sizeof(cc_flat_data);
+    for ( i=0; i<count; i++ ) {
+        len += creds->authdata[i]->length;
+    }
+
+    *plen = len;
+    return ccNoError;
+}
+
+cc_int32
+cci_creds_v5_marshall( cc_credentials_v5_t * creds, 
+                       char ** pflat, 
+                       cc_uint32 * plen)
+{
+    cc_uint32 len;
+    char * flat;
+    struct cci_flat_creds_v5 * header;
+    cc_uint32 offset;
+    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 = FLAT_CREDS_V5_VERSION;
+    if (creds->client) {
+        header->client.length = strlen(creds->client) + 1;
+        header->client.data = offset;
+        memcpy(flat + offset, creds->client, header->client.length);
+        offset += header->client.length;
+    }
+
+    if (creds->server) {
+        header->server.length = strlen(creds->server) + 1;
+        header->server.data = offset;
+        memcpy(flat + offset, creds->server, header->server.length);
+        offset += header->server.length;
+    }
+
+    header->keyblock.type = creds->keyblock.type;
+    if (creds->keyblock.length) {
+        header->keyblock.length = creds->keyblock.length;
+        header->keyblock.data = offset;
+        memcpy(flat + offset, creds->keyblock.data, header->keyblock.length);
+        offset += header->keyblock.length;
+    }           
+
+    header->authtime = creds->authtime;
+    header->starttime = creds->starttime;
+    header->endtime = creds->endtime;
+    header->renew_till = creds->renew_till;
+    header->is_skey = creds->is_skey;
+    header->ticket_flags = creds->ticket_flags;
+
+    cci_creds_cc_data_array_count_entries( creds->addresses, &header->address_count );
+    if ( header->address_count ) {
+        cc_flat_data * addresses = (cc_flat_data *)flat + offset;
+        header->addresses = offset;
+        offset += header->address_count * sizeof(cc_flat_data);
+
+        for ( i=0; i<header->address_count; i++ ) {
+            addresses[i].type = creds->addresses[i]->type;
+            if (creds->addresses[i]->length) {
+                addresses[i].length = creds->addresses[i]->length;
+                addresses[i].data = offset;
+                memcpy(flat + offset, creds->addresses[i]->data, addresses[i].length);
+                offset += addresses[i].length;
+            }
+        }
+    }
+
+    header->ticket.type = creds->ticket.type;
+    if (creds->ticket.length) {
+        header->ticket.length = creds->ticket.length;
+        header->ticket.data = offset;
+        memcpy(flat + offset, creds->ticket.data, header->ticket.length);
+        offset += header->ticket.length;
+    }           
+
+    header->second_ticket.type = creds->second_ticket.type;
+    if (creds->second_ticket.length) {
+        header->second_ticket.length = creds->second_ticket.length;
+        header->second_ticket.data = offset;
+        memcpy(flat + offset, creds->second_ticket.data, header->second_ticket.length);
+        offset += header->second_ticket.length;
+    }           
+
+    cci_creds_cc_data_array_count_entries( creds->authdata, &header->authdata_count );
+    if ( header->authdata_count ) {
+        cc_flat_data * authdata = (cc_flat_data *)flat + offset;
+        header->authdata = offset;
+        offset += header->authdata_count * sizeof(cc_flat_data);
+
+        for ( i=0; i<header->authdata_count; i++ ) {
+            authdata[i].type = creds->authdata[i]->type;
+            if (creds->authdata[i]->length) {
+                authdata[i].length = creds->authdata[i]->length;
+                authdata[i].data = offset;
+                memcpy(flat + offset, creds->authdata[i]->data, authdata[i].length);
+                offset += authdata[i].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_uint32  i;
+    cc_int32   code;
+
+    if ( flat == NULL || len == 0 || creds_union == NULL )
+        return ccErrBadParam;
+
+    creds_union->version = cc_credentials_v5;
+
+    header = (struct cci_flat_creds_v5 *)flat;
+
+    if ( 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(ccmsg_creds_v5_t));
+
+    if ( header->client.length ) {
+        creds->client = (char *)malloc(header->client.length);
+        memcpy(creds->client, flat + header->client.data, header->client.length);
+    }
+
+    if ( header->server.length ) {
+        creds->server = (char *)malloc(header->server.length);
+        memcpy(creds->server, flat + header->server.data, header->server.length);
+    }
+
+    creds->keyblock.type = header->keyblock.type;
+    if ( header->keyblock.length ) {
+        creds->keyblock.length = header->keyblock.length;
+        creds->keyblock.data = malloc(creds->keyblock.length);
+        memcpy(creds->keyblock.data, flat + header->keyblock.data, creds->keyblock.length);
+    }
+
+    creds->authtime = header->authtime;
+    creds->starttime = header->starttime;
+    creds->endtime = header->endtime;
+    creds->renew_till = header->renew_till;
+    creds->is_skey = header->is_skey;
+    creds->ticket_flags = header->ticket_flags;
+
+    creds->addresses = (cc_data **) malloc((header->address_count + 1) * sizeof(cc_data *));
+    flat_data = (cc_flat_data *)flat + header->addresses;
+    for ( i=0 ; i < header->address_count ; i++ ) {
+        creds->addresses[i] = (cc_data *)malloc(sizeof(cc_data));
+        creds->addresses[i]->type = flat_data[i].type;
+        creds->addresses[i]->length = flat_data[i].length;
+        if ( flat_data[i].length ) {
+            creds->addresses[i]->data = malloc(flat_data[i].length);
+            memcpy(creds->addresses[i]->data, flat + flat_data[i].data, flat_data[i].length);
+        } else {
+            creds->addresses[i]->data = NULL;
+        }
+    }
+    creds->addresses[i] = NULL;
+
+    creds->ticket.type = header->ticket.type;
+    if ( header->ticket.length ) {
+        creds->ticket.length = header->ticket.length;
+        creds->ticket.data = malloc(creds->ticket.length);
+        memcpy(creds->ticket.data, flat + header->ticket.data, creds->ticket.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);
+    }
+
+    creds->authdata = (cc_data **) malloc((header->authdata_count + 1) * sizeof(cc_data *));
+    flat_data = (cc_flat_data *)flat + header->authdata;
+    for ( i=0 ; i < header->authdata_count ; i++ ) {
+        creds->authdata[i] = (cc_data *)malloc(sizeof(cc_data));
+        creds->authdata[i]->type = flat_data[i].type;
+        creds->authdata[i]->length = flat_data[i].length;
+        if ( flat_data[i].length ) {
+            creds->authdata[i]->data = malloc(flat_data[i].length);
+            memcpy(creds->authdata[i]->data, flat + flat_data[i].data, flat_data[i].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/msg.c b/src/lib/ccapi/msg.c
new file mode 100644 (file)
index 0000000..f5f074a
--- /dev/null
@@ -0,0 +1,582 @@
+/* $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).
+ * $
+ */
+
+/*
+ * Verifiable, extensible message format.
+ */
+
+#include "CredentialsCache.h"
+#include "msg.h"
+#include "datastore.h"
+
+#include <stdlib.h>
+#include <memory.h>
+#include <stdio.h>
+#include <string.h>
+
+/**
+ * cci_msg_new()
+ *
+ * Purpose: Allocate and initialize a new cc_msg_t structure
+ *
+ * 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_int32 code;
+
+    if (msg == NULL || flatpp == 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;
+
+    memcpy(cur_pos,&msg->header_len,sizeof(cc_uint32));
+    cur_pos+=sizeof(cc_uint32);
+
+    memcpy(cur_pos,&msg->flat_len,sizeof(cc_uint32));
+    cur_pos+=sizeof(cc_uint32);
+
+    memcpy(cur_pos,&msg->type,sizeof(cc_uint32));
+    cur_pos+=sizeof(cc_uint32);
+
+    memcpy(cur_pos, msg->header, msg->header_len);
+    cur_pos += msg->header_len;
+
+    memcpy(cur_pos, &zero, 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;
+        }
+        memcpy(cur_pos, &gen_node->len, sizeof(cc_uint32));
+        cur_pos+=sizeof(cc_uint32);
+               
+        memcpy(cur_pos, gen_node->data, gen_node->len);
+        cur_pos += gen_node->len;
+    }
+    free(gen_iterator);
+
+    memcpy(cur_pos, &zero, sizeof(cc_uint32)); /*magic number will go here later*/
+    cur_pos += sizeof(cc_uint32);
+
+    if (cur_pos - (char *)msg->flat != msg->flat_len) {
+        printf("ERRORR 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 = 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 *ptotal_len;
+    cc_uint32 *pblob_len;
+    cc_uint32 *ptype;
+    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));
+
+    if (*ptotal_len != flat_len) {
+        *validp = 0;
+        return ccNoError;
+    }
+    
+    if (*pheader_len > flat_len) {
+        /*too weak. We could verify header_len against type spec header.*/
+        *validp = 0;
+        return ccNoError;
+    }
+    if (*ptype > CC_MSG_MAX_TYPE) {
+        *validp = 0;
+        return ccNoError;
+    }
+
+    magic1 = (cc_uint32 *)((char *)ptype + sizeof(cc_uint32) + *pheader_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;
+
+        while (*pblob_len + sizeof(cc_uint32) + ((char *)pblob_len - (char *)flat) < (flat_len - sizeof(cc_uint32))) {
+            pblob_len = (cc_uint32 *)((char *)pblob_len + *pblob_len + sizeof(cc_uint32));
+            num_blobs++;
+        }
+
+        if (*pblob_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 + *pblob_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);
+    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 = *(cc_uint32 *)cur_pos;
+    cur_pos += sizeof(cc_uint32);
+
+    msg->flat_len = *(cc_uint32 *)cur_pos;
+    cur_pos += sizeof(cc_uint32);
+
+    msg->type = *(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 = *(cc_uint32 *)cur_pos;
+    cur_pos += sizeof(cc_uint32);
+
+    if (cur_pos - (char *)flat != flat_len - 8) { /*at least 1 blob*/
+        blob_len = *(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 = *(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, void **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->flat);
+    cci_generic_list_destroy(msg->data_blobs);
+    free(msg);
+    return ccNoError;
+}
+
diff --git a/src/lib/ccapi/server/ChangeLog b/src/lib/ccapi/server/ChangeLog
new file mode 100644 (file)
index 0000000..aaa59da
--- /dev/null
@@ -0,0 +1,4 @@
+2004-10-27   Jeffrey Altman  <jaltman@mit.edu>
+
+ * Initial commit of C CCAPI implementation
+
diff --git a/src/lib/ccapi/server/NTMakefile b/src/lib/ccapi/server/NTMakefile
new file mode 100644 (file)
index 0000000..671b690
--- /dev/null
@@ -0,0 +1,30 @@
+# Makefile for the CCAPI Generic Server
+
+!INCLUDE <WIN32.MAK>
+
+CFLAGS = -I../include
+
+CCAPI_LIB = ../lib/ccapi.lib
+WINLIBS = user32.lib advapi32.lib
+CCSOBJS = context.obj ccache.obj lists.obj rpc_auth.obj serv_ops.obj
+
+all: t_lists.exe t_msg.exe t_ccache.exe t_context.exe ccapi_server.exe
+
+t_lists.exe: t_lists.obj $(CCSOBJS) $(CCAPI_LIB)
+        link -out:$@ t_lists.obj $(CCSOBJS) $(CCAPI_LIB) $(WINLIBS)
+
+t_msg.exe: t_msg.obj $(CCSOBJS) $(CCAPI_LIB)
+        link -out:$@ t_msg.obj $(CCSOBJS) $(CCAPI_LIB) $(WINLIBS)
+
+t_ccache.exe: t_ccache.obj $(CCSOBJS) $(CCAPI_LIB)
+        link -out:$@ t_ccache.obj $(CCSOBJS) $(CCAPI_LIB) $(WINLIBS)
+
+t_context.exe: t_context.obj $(CCSOBJS) $(CCAPI_LIB)
+        link -out:$@ t_context.obj $(CCSOBJS) $(CCAPI_LIB) $(WINLIBS)
+
+ccapi_server.exe: main.obj $(CCSOBJS) $(CCAPI_LIB)
+        link -out:$@ main.obj $(CCSOBJS) $(CCAPI_LIB) $(WINLIBS)
+
+clean: 
+       del *.obj *.exe
+
diff --git a/src/lib/ccapi/server/ccache.c b/src/lib/ccapi/server/ccache.c
new file mode 100644 (file)
index 0000000..2c3a745
--- /dev/null
@@ -0,0 +1,703 @@
+/* $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).
+ * $
+ */
+
+/*
+ * Manages ccache objects.
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include "CredentialsCache.h"
+#include "datastore.h"
+
+/**
+ * ccache_new()
+ * 
+ * Purpose: Allocate and initialize new credentials cache for the specified principal
+ *          and version
+ * 
+ * Return:  ccNoError - success
+ *          ccErrInvalidString - name or principal is NULL
+ *          ccErrBadCredentialsVersion - unsupported creds type
+ *          ccErrBadParam - outCcachepp is NULL
+ *          ccErrNoMem - malloc failed
+ */
+cc_int32
+cci_ccache_new( char *name, char *principal, int cred_vers, 
+                cc_server_ccache_t** outCCachepp)
+{
+    cc_server_ccache_t* ccache;
+
+    if (name == NULL || principal == NULL)
+        return ccErrInvalidString;
+
+    if (cred_vers != cc_credentials_v4 && cred_vers != cc_credentials_v5 && 
+         cred_vers != cc_credentials_v4_v5)
+        return ccErrBadCredentialsVersion;
+
+    if (outCCachepp == NULL)
+        return ccErrBadParam;
+
+    ccache = (cc_server_ccache_t*)malloc(sizeof(cc_server_ccache_t));
+    if (ccache == NULL)
+        return ccErrNoMem;
+
+    ccache->name = name;
+    ccache->principal_v4 = NULL;
+    ccache->principal_v5 = NULL;
+    ccache->changed = time(NULL);
+    ccache->kdc_offset = 0;
+    ccache->last_default = 0;
+    cci_generic_list_new(&ccache->active_iterators);
+    cci_credentials_list_new(&ccache->creds);
+    ccache->is_default = 0;
+    ccache->kdc_set = 0;
+    ccache->versions = cred_vers;
+    ccache->mycontext = NULL;
+
+    cci_ccache_set_principal(ccache, cred_vers, principal);
+    *outCCachepp = ccache;
+    return ccNoError;
+}
+
+/**
+ * cci_ccache_check_version()
+ * 
+ * Purpose: Check to see if the ccache and the creds have compatible versions. 
+ * 
+ * Return:  ccNoError and compat = 1 if they are compatible 
+ *          ccNoError and compat = 0 if they are not compatible
+ * 
+ * Errors:  ccErrInvalidCCache - ccache is NULL
+ *          ccErrBadParam - either creds or compat are NULL
+ */
+cc_int32 
+cci_ccache_check_version( const cc_server_ccache_t *ccache,
+                          const cc_credentials_union* creds,
+                          cc_uint32* compat)
+{
+    if (ccache == NULL)
+        return ccErrInvalidCCache;
+
+    if (creds == NULL || compat == NULL)
+        return ccErrBadParam;
+
+    if (ccache->versions == cc_credentials_v4_v5)
+        *compat = 1;
+    else if (ccache->versions == creds->version)
+        *compat = 1;
+    else
+        *compat = 0;
+
+    return ccNoError;
+}
+
+/** 
+cci_ccache_check_principal()
+
+Check to see if the client principal from the credentials matches
+the principal associated with the cache.
+
+* Return:  ccNoError and compat = 1 if they are compatible 
+*          ccNoError and compat = 0 if they are not compatible
+* 
+* Errors:  ccErrInvalidCCache - ccache is NULL
+*          ccErrBadParam - either creds or compat are NULL
+*          ccErrBadCredentialVersion - unsupported credential type
+*/
+cc_int32 
+cci_ccache_check_principal( const cc_server_ccache_t *ccache,
+                            const cc_credentials_union* creds,
+                            cc_uint32* compat)
+{
+    if (ccache == NULL)
+        return ccErrInvalidCCache;
+
+    if (creds == NULL || compat == NULL)
+        return ccErrBadParam;
+
+    if (creds->version == cc_credentials_v4) {
+        if (strcmp(creds->credentials.credentials_v4->principal, ccache->principal_v4) == 0) 
+            *compat = 1;
+        else 
+            *compat = 0;
+    } else if (creds->version == cc_credentials_v5) {
+        if (strcmp(creds->credentials.credentials_v5->client, ccache->principal_v5) == 0)
+            *compat = 1;
+        else 
+            *compat = 0;
+    } else {        
+        return ccErrBadCredentialsVersion;
+    }
+    return ccNoError;
+}
+
+
+/** 
+ * cci_ccache_store_creds()
+ *
+ * Purpose: Stores the provided credentials into the provided cache.  Validates the
+ *          ability of the cache to store credentials of the given version and client
+ *          principal.
+ *
+ * Return:  0 on success
+ *         -1 on error
+ *
+ * Errors: ccErrNoMem
+ *         ccErrBadCredentialsVersion
+ *         ccErrBadInvalidCredentials
+ *         ccErrInvalidCache
+ *         ccErrBadParam
+ */
+cc_int32 
+cci_ccache_store_creds(cc_server_ccache_t *ccache, const cc_credentials_union* credentials) 
+{
+    cc_server_credentials_t* stored_cred=NULL;
+    cc_uint32 valid_version, valid_principal;
+    cc_int32 code;
+
+    if (ccache == NULL)
+        return ccErrInvalidCCache;
+    
+    if (credentials == NULL)
+        return ccErrBadParam;
+
+    code = cci_ccache_check_version(ccache, credentials, &valid_version);
+    if (code != ccNoError) {
+        /* pass error on to caller */
+        goto bad;
+    }
+    code = cci_ccache_check_principal(ccache, credentials, &valid_principal);
+    if (code != ccNoError) {
+        /* pass error on to caller */
+        goto bad;
+    }
+    if (valid_version && valid_principal) {
+        stored_cred = (cc_server_credentials_t*)malloc(sizeof(cc_server_credentials_t));
+        if (stored_cred == NULL) {
+            code = ccErrNoMem;
+            goto bad;
+        }
+        memcpy(&stored_cred->creds, credentials, sizeof(cc_credentials_union));
+
+        if (credentials->version == cc_credentials_v4) {
+            stored_cred->creds.credentials.credentials_v4 = (cc_credentials_v4_t*)malloc(sizeof(cc_credentials_v4_t));
+            if (stored_cred->creds.credentials.credentials_v4 == NULL) {
+                code = ccErrNoMem;
+                goto bad;
+            }
+
+            memcpy(stored_cred->creds.credentials.credentials_v4, credentials->credentials.credentials_v4, sizeof(cc_credentials_v4_t));
+        } else if (credentials->version == cc_credentials_v5) {
+            stored_cred->creds.credentials.credentials_v5 = (cc_credentials_v5_t*)malloc(sizeof(cc_credentials_v5_t));
+            if (stored_cred->creds.credentials.credentials_v5 == NULL) {
+                code = ccErrNoMem;
+                goto bad;
+            }
+
+            memcpy(stored_cred->creds.credentials.credentials_v5, credentials->credentials.credentials_v5, sizeof(cc_credentials_v5_t));
+        } else {
+            code = ccErrBadCredentialsVersion;
+            goto bad;
+        }
+
+        code = cci_credentials_list_append(ccache->creds, stored_cred, NULL);
+        if ( code != ccNoError ) {
+            /* pass error on to caller */
+            goto bad;
+        }
+        if (ccache->creds->head->data == (cc_uint8 *)stored_cred) 
+            stored_cred->is_default = 1; /*we're first on the list, so we're default*/
+
+        cci_ccache_changed(ccache);
+        return ccNoError;
+    } else {
+#ifdef DEBUG
+        printf("vers: %d\tprincipal: %d\n",
+                valid_version, valid_principal);
+#endif /* DEBUG */
+        code = ccErrInvalidCredentials;
+        goto bad;
+    }
+
+  bad:
+    if (stored_cred)
+        free(stored_cred);
+    return code;      /* error */
+}
+
+/**
+ * cci_ccache_changed()
+ *
+ * Purpose: Updates the last update time for the ccache and its associated context.
+ *          Provides a location from which interested parties should be notified
+ *          of cache updates.
+ *
+ * Return:  none
+ *
+ * Errors:  none
+ */
+void 
+cci_ccache_changed(cc_server_ccache_t* ccache) 
+{
+    ccache->changed = time(NULL);
+    if (ccache->mycontext != NULL)
+        ccache->mycontext->changed = time(NULL);
+
+    /* XXX - notify registered listeners when implemented */
+}
+
+/**
+ * cci_ccache_rem_creds()
+ *
+ * Purpose: Removes the specified credential object from the specified cache if
+ *          it exists
+ *
+ * Return:  0 on success (credential is not in the cache)
+ *         -1 on error
+ *
+ * Errors: ccErrBadParam, ccErrNoMem (from cc_credentials_list_iterator)
+ *
+ * Verify: does the memory associated with stored_cred->creds need to be freed?
+ *
+ */
+cc_int32 
+cci_ccache_rem_creds(cc_server_ccache_t *ccache, const cc_credentials_union* credentials) 
+{
+    cc_credentials_iterate_t* credentials_iterator=NULL, *active;
+    cc_generic_iterate_t* generic_iterator=NULL;
+    cc_credentials_list_node_t* credentials_node;
+    cc_generic_list_node_t* generic_node;
+    cc_server_credentials_t* stored_cred;
+    cc_int8 changed = 0;
+    cc_int32 code = 0;
+
+    if (ccache == NULL)
+        return ccErrInvalidCCache;
+
+    if (credentials == NULL)
+        return ccErrBadParam;
+
+    code = cci_credentials_list_iterator(ccache->creds, &credentials_iterator);
+    if (code != ccNoError) {
+        /* pass error to caller */
+        goto cleanup;
+    }
+
+    while (cci_credentials_iterate_has_next(credentials_iterator)) {
+        code = cci_credentials_iterate_next(credentials_iterator, &credentials_node);
+        stored_cred = (cc_server_credentials_t*)credentials_node->data;
+        if (memcmp(&stored_cred->creds,credentials,sizeof(cc_credentials_union)) == 0) {
+            /* XXX - do we need to free(stored_cred->creds) ? */
+            free(credentials_node->data);
+            changed = 1;
+               
+            /*If any iterator's next points to the deleted node, make it point to the next node*/
+            code = cci_generic_list_iterator(ccache->active_iterators, &generic_iterator);
+            while (cci_generic_iterate_has_next(generic_iterator)) {
+                code = cci_generic_iterate_next(generic_iterator, &generic_node);                      
+                active = (cc_credentials_iterate_t*)generic_node->data;
+                if (active->next == credentials_node) 
+                    active->next = active->next->next;
+            }
+            code = cci_generic_free_iterator(generic_iterator);
+            generic_iterator = NULL;
+
+            if (credentials_node == ccache->creds->head) { /*removing the default, must make next cred default*/
+                code = cci_credentials_list_remove_element(ccache->creds, credentials_node);
+
+                if (ccache->creds->head != NULL)
+                    ((cc_server_credentials_t*)ccache->creds->head->data)->is_default = 1;
+            } else {
+                code = cci_credentials_list_remove_element(ccache->creds, credentials_node);
+            }
+            break;
+        }
+    }
+
+  cleanup:
+    if (changed)
+        cci_ccache_changed(ccache);
+    if (credentials_iterator)
+        cci_credentials_free_iterator(credentials_iterator);
+    if (generic_iterator)
+        cci_generic_free_iterator(generic_iterator);
+    return code;
+}
+
+/**
+ * cci_ccache_move()
+ * 
+ * Purpose: Destroys the existing contents of the destination and copies
+ *          all credentials from the source to the destination
+ *
+ * Return:  0 on success
+ *         -1 on error
+ *
+ * Errors:  ccBadNoMem
+ *
+ */
+
+cc_int32 
+cci_ccache_move(cc_server_ccache_t *source, cc_server_ccache_t* destination) 
+{
+    cc_generic_list_node_t* node;
+    cc_generic_iterate_t* iterator;
+    cc_credentials_iterate_t* cur;
+    cc_int32 code;
+
+    if (source == NULL || destination == NULL)
+        return ccErrBadParam;
+       
+    code = cci_credentials_list_destroy(destination->creds);
+    if ( code != ccNoError )
+        return code;
+
+    code = cci_credentials_list_copy(source->creds, &destination->creds);
+    if ( code != ccNoError ) 
+        return code;
+
+    destination->versions = source->versions;
+    destination->kdc_offset = source->kdc_offset;
+    destination->last_default = 0;
+
+    /*reset all active iterators to point to the head of the new creds list*/
+    if (destination->active_iterators->head != NULL) {
+        code = cci_generic_list_iterator(destination->active_iterators, &iterator);
+        while (cci_generic_iterate_has_next(iterator)) {
+            code = cci_generic_iterate_next(iterator, &node);
+            cur = (cc_credentials_iterate_t*)node->data;
+            cur->next = destination->creds->head;
+        }
+        code = cci_generic_free_iterator(iterator);
+    }
+
+    cci_ccache_changed(destination);
+    return code;
+}
+
+/**
+ * cci_ccache_get_kdc_time_offset()
+ * 
+ * Purpose: Retrieves the kdc_time_offset from the ccache if set
+ *
+ * Return:  0 on success
+ *         -1 on error
+ *
+ * Errors:  ccErrBadParam, ccErrTimeOffsetNotSet
+ *
+ */
+cc_int32 
+cci_ccache_get_kdc_time_offset(cc_server_ccache_t* ccache, cc_time_t* offset) 
+{
+    if (ccache == NULL)
+        return ccErrInvalidCCache;
+    
+    if (offset == NULL)
+        return ccErrBadParam;
+
+    if (!ccache->kdc_set)
+        return ccErrTimeOffsetNotSet;
+
+    *offset = ccache->kdc_offset;
+    return ccNoError;
+}
+
+/**
+ * cci_ccache_set_kdc_time_offset()
+ *
+ * Purpose: Sets the kdc time offset in the designated ccache
+ * 
+ * Return:  0 on success
+ *         -1 on error
+ * 
+ * Errors: ccErrBadParam
+ *
+ */
+cc_int32 
+cci_ccache_set_kdc_time_offset(cc_server_ccache_t* ccache, cc_time_t offset) 
+{
+    if (ccache == NULL)
+        return ccErrInvalidCCache;
+
+    ccache->kdc_offset = offset;
+    ccache->kdc_set = 1;
+    cci_ccache_changed(ccache);
+
+    return ccNoError;
+}
+
+/**
+ * cci_ccache_clear_kdc_time_offset()
+ *
+ * Purpose: Clear the kdc time offset in the designated ccache
+ *
+ * Return:  0 on success
+ *         -1 on error
+ *
+ * Errors: ccErrBadParam
+ */
+cc_int32 
+cci_ccache_clear_kdc_time_offset(cc_server_ccache_t* ccache) 
+{
+    if (ccache == NULL)
+        return ccErrInvalidCCache;
+
+    ccache->kdc_offset = 0;
+    ccache->kdc_set = 0;
+    cci_ccache_changed(ccache);
+
+    return ccNoError;
+}
+
+/**
+ * cci_ccache_new_iterator()
+ *
+ * Purpose: Retrieve an iterator for the designated cache
+ *
+ * Return:  0 on success
+ *         -1 on error
+ *
+ * Errors: ccErrBadParam, ccBadNoMem
+ */
+cc_int32 
+cci_ccache_new_iterator(cc_server_ccache_t* ccache, cc_credentials_iterate_t** iterator)
+{
+    cc_int32 code;
+
+    if (ccache == NULL)
+        return ccErrInvalidCCache;
+
+    if (iterator == NULL)
+        return ccErrBadParam;
+
+    code = cci_credentials_list_iterator(ccache->creds, iterator);
+    if (code != ccNoError)
+        return code;
+
+    code = cci_generic_list_prepend(ccache->active_iterators, *iterator, sizeof(cc_credentials_iterate_t), NULL);
+    if (code != ccNoError)
+        return code;
+
+    return ccNoError;
+}
+
+/**
+ * cci_ccache_get_principal()
+ * 
+ * Purpose: Retrieves the client principal associated with the designated cache.
+ *          The value is returned 
+ * Return:
+ *
+ * Errors:
+ */
+cc_int32 
+cci_ccache_get_principal(cc_server_ccache_t* ccache, cc_int32 version, char ** principal) 
+{
+    char *p = NULL;
+    
+    switch ( version ) {
+    case cc_credentials_v4:
+        p = ccache->principal_v4;
+        break;
+    case cc_credentials_v5:
+        p = ccache->principal_v5;
+        break;
+    default:
+        return ccErrBadCredentialsVersion;
+    }
+
+    *principal = (char *)malloc(strlen(p)+1);
+    if ( *principal == NULL )
+        return ccErrNoMem;
+
+    strcpy(*principal, p);
+    return ccNoError;
+}
+
+/**
+ * Purpose: Releases the memory associated with a ccache principal
+ * 
+ * Return:
+ *
+ * Errors:
+ *
+ */
+cc_int32
+cci_ccache_free_principal(char * principal)
+{
+    if ( principal == NULL )
+        return ccErrBadParam;
+
+    free(principal);
+    return ccNoError;
+}
+
+/**
+ * ccache_set_principal()
+ *
+ * Purpose: Assigns a principal to the designated ccache and credential version.
+ *          If the api version is 2, the cache is cleared of all existing
+ *          credentials.
+ *
+ * Return:  0 on success
+ *         -1 on error
+ *
+ * Errors: ccErrNoMem, ccErrBadCredentialsVersion
+ */
+cc_int32 
+cci_ccache_set_principal( cc_server_ccache_t* ccache, cc_int32 cred_version, 
+                          char* principal)
+{
+    cc_generic_iterate_t* generic_iterator;
+    cc_generic_list_node_t* generic_node;
+    cc_ccache_iterate_t* ccache_iterator;
+    cc_int32 code = ccNoError;
+
+    if (ccache == NULL)
+        return ccErrInvalidCCache;
+    
+    if (principal == NULL)
+        return ccErrInvalidString;
+
+    switch (cred_version) {
+    case cc_credentials_v4:
+    case cc_credentials_v4_v5:
+        ccache->principal_v4 = (char *)malloc(strlen(principal) + 1);
+        if (ccache->principal_v4 == NULL)
+            return ccErrNoMem;
+        strcpy(ccache->principal_v4, principal);
+        if (cred_version != cc_credentials_v4_v5)
+            break;
+        /* fall-through if we are v4_v5 */
+    case cc_credentials_v5:
+        ccache->principal_v5 = (char *)malloc(strlen(principal) + 1);
+        if (ccache->principal_v5 == NULL) {
+            if (cred_version == cc_credentials_v4_v5) {
+                free(ccache->principal_v4);
+                ccache->principal_v4 = NULL;
+            }
+            return ccErrNoMem;
+        }
+        strcpy(ccache->principal_v5, principal);
+        break;
+    default:
+        return ccErrBadCredentialsVersion;
+    }
+
+    /*For API version 2 clients set_principal implies a flush of all creds*/
+    if (ccache->mycontext != NULL && ccache->mycontext->api_version == ccapi_version_2) {
+        cci_credentials_list_destroy(ccache->creds);
+        cci_credentials_list_new(&ccache->creds);
+
+        /*clean up active_iterators*/
+        code = cci_generic_list_iterator(ccache->active_iterators, &generic_iterator);
+        if (code == ccNoError) {
+            while (cci_generic_iterate_has_next(generic_iterator)) {
+                code = cci_generic_iterate_next(generic_iterator, &generic_node);
+                ccache_iterator = (cc_ccache_iterate_t*)generic_node->data;
+                ccache_iterator->next = NULL;
+            }
+        }
+    }
+
+    cci_ccache_changed(ccache);
+
+    return code;
+}
+
+/**
+ * cci_ccache_destroy()
+ *
+ * Purpose: Destroys an existing ccache 
+ *
+ * Return:  0 on success
+ *         -1 on errors
+ *
+ * Errors:  ccErrBadParam
+ */
+cc_int32 
+cci_ccache_destroy(cc_server_ccache_t* ccache) 
+{
+    cc_int32 code;
+
+    if ( ccache == NULL )
+        return ccErrInvalidCCache;
+
+    code = cci_generic_list_destroy(ccache->active_iterators);
+    code = cci_credentials_list_destroy(ccache->creds);
+
+    if (ccache->mycontext != NULL)
+        code = cci_context_rem_ccache(ccache->mycontext, ccache);
+
+    return code;
+}
+
+/**
+ * cci_ccache_compare()
+ *
+ * Purpose: Returns a boolean value indicating if two caches are identical
+ *          Implemented as pointer equivalence.
+ *
+ * Return:  1 if TRUE
+ *          0 if FALSE
+ *
+ * Errors:  No errors
+ */
+cc_int32 
+cci_ccache_compare(cc_server_ccache_t* ccache1, cc_server_ccache_t* ccache2, cc_uint32 *result) 
+{
+    if ( ccache1 == NULL || ccache2 == NULL )
+        return ccErrInvalidCCache;
+
+    if (ccache1 == ccache2)
+        *result = 1;
+    else 
+        *result = 0;
+
+    return ccNoError;
+}
+
diff --git a/src/lib/ccapi/server/context.c b/src/lib/ccapi/server/context.c
new file mode 100644 (file)
index 0000000..f405a4d
--- /dev/null
@@ -0,0 +1,325 @@
+/* $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).
+ * $
+ */
+
+/*
+ * Functions to manipulate datastore layer contexts.
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <time.h>
+#include <string.h>
+
+#include "CredentialsCache.h"
+#include "datastore.h"
+
+int cc_myversion = 5;
+char cc_vendor[] = "MIT C lang CCache V5";
+char cc_default_ccache_name[] = "krb5cc";
+
+
+cc_int32
+cci_context_new( int api_version, cc_auth_info_t* auth_info, 
+                 cc_session_info_t* session_info, cc_server_context_t** outContextpp )
+{
+    cc_server_context_t* ctx;
+       
+    if ( outContextpp == NULL )
+        return ccErrBadParam;
+
+       ctx = (cc_server_context_t*)malloc(sizeof(cc_server_context_t));
+    if (ctx == NULL)
+        return ccErrNoMem;
+               
+    cci_ccache_list_new(&ctx->ccaches);
+    cci_generic_list_new(&ctx->active_iterators);      
+    ctx->api_version = api_version;
+    ctx->auth_info = auth_info;
+    ctx->session_info = session_info;
+    ctx->changed = time(NULL);
+
+    *outContextpp = ctx;
+    return ccNoError;
+}
+
+cc_int32
+cci_context_get_default_ccache_name(cc_server_context_t* ctx, char ** outNamepp) 
+{
+    cc_server_ccache_t* default_ccache;
+
+    if (outNamepp == NULL)
+        return ccErrBadParam;
+    
+    if (ctx == NULL)
+        return ccErrInvalidContext;
+
+    if (ctx->ccaches->head != NULL) {
+        default_ccache = (cc_server_ccache_t*)ctx->ccaches->head->data;
+        *outNamepp = default_ccache->name;
+    } else {
+        *outNamepp = cc_default_ccache_name;
+    }
+    return ccNoError;
+}
+
+
+cc_int32
+cci_context_find_ccache( cc_server_context_t* ctx, char *name, 
+                         cc_server_ccache_t** outCcachepp )
+{
+    cc_ccache_iterate_t* ccache_iterator;
+    cc_ccache_list_node_t* ccache_node;
+    cc_server_ccache_t* ccache;
+       cc_int32 code;
+
+    if (ctx == NULL) 
+        return ccErrInvalidContext;
+    
+    if (name == NULL)
+        return ccErrInvalidString;
+
+    if (outCcachepp == NULL)
+        return ccErrBadParam;
+
+    code = cci_ccache_list_iterator(ctx->ccaches, &ccache_iterator);
+    while (cci_ccache_iterate_has_next(ccache_iterator)) {
+        code = cci_ccache_iterate_next(ccache_iterator, &ccache_node);
+        ccache = (cc_server_ccache_t *)ccache_node->data;
+        if (strcmp(ccache->name, name) == 0)  {
+            free(ccache_iterator);
+            *outCcachepp = ccache;
+            return ccNoError;
+        }
+    }
+    free(ccache_iterator);
+    return ccErrCCacheNotFound;
+}       
+
+cc_int32
+cci_context_open_ccache( cc_server_context_t* ctx, char *name, 
+                         cc_server_ccache_t** outCcachepp )
+{
+    return cci_context_find_ccache(ctx, name, outCcachepp);
+}
+
+
+cc_int32
+cci_context_create_ccache( cc_server_context_t* ctx, char *name, int creds_version, 
+                           char *principal, cc_server_ccache_t** outCcachepp )
+{
+    cc_server_ccache_t* ccache;
+    cc_int32 code;
+
+    if (ctx == NULL) 
+        return ccErrInvalidContext;
+    
+    if (outCcachepp == NULL)
+        return ccErrBadParam;
+
+    if (name == NULL || principal == NULL)
+        return ccErrInvalidString;
+
+    if (creds_version != cc_credentials_v4 && creds_version != cc_credentials_v5 && 
+         creds_version != cc_credentials_v4_v5)
+        return ccErrBadCredentialsVersion;
+       
+    code = cci_context_find_ccache(ctx, name, &ccache);
+    if (code == ccNoError) {
+        code = cci_ccache_set_principal(ccache, creds_version, principal);
+    } else {
+        code = cci_ccache_new(name, principal, creds_version, &ccache);
+        if (code != ccNoError)
+            return code;       /*let caller deal with error*/
+
+        ccache->mycontext = ctx;
+        ctx->changed = time(NULL);
+        cci_ccache_list_append(ctx->ccaches, ccache, NULL);
+
+        if (ctx->ccaches->head->data == (cc_uint8 *)ccache) {
+            ccache->is_default = 1;
+        }
+    }
+    *outCcachepp = ccache;
+    return ccNoError;
+}
+
+cc_int32
+cci_context_create_default_ccache( cc_server_context_t* ctx, int creds_version, 
+                                   char *principal, cc_server_ccache_t** outCcachepp )
+{
+    cc_server_ccache_t* ccache, *old_default;
+    cc_int32 code;
+
+    if (ctx == NULL) 
+        return ccErrInvalidContext;
+    
+    if (outCcachepp == NULL)
+        return ccErrBadParam;
+
+    if (principal == NULL)
+        return ccErrInvalidString;
+
+    if (creds_version != cc_credentials_v4 && creds_version != cc_credentials_v5 && 
+         creds_version != cc_credentials_v4_v5)
+        return ccErrBadCredentialsVersion;
+       
+    code = cci_context_find_ccache(ctx, cc_default_ccache_name, &ccache);
+    if (code == ccNoError) {
+        cci_ccache_set_principal(ccache, creds_version, principal);
+    } else {
+        code = cci_ccache_new(cc_default_ccache_name, principal, creds_version, &ccache);
+        if (code != ccNoError)
+            return code;       /*let caller deal with error*/
+
+        ccache->mycontext = ctx;
+        ccache->is_default = 1;
+        ctx->changed = time(NULL);
+       
+        if (ctx->ccaches->head != NULL) {
+            old_default = (cc_server_ccache_t *)ctx->ccaches->head->data;
+            old_default->is_default = 0;
+            old_default->last_default = time(NULL);
+        }
+
+        cci_ccache_list_prepend(ctx->ccaches, ccache, NULL);
+    }
+    *outCcachepp = ccache;
+    return ccNoError;
+}
+
+cc_int32
+cci_context_ccache_iterator(cc_server_context_t* ctx, cc_ccache_iterate_t** iterpp) 
+{
+    cc_ccache_iterate_t* ccache_iterator;
+    cc_int32 code;
+
+    if (ctx == NULL) 
+        return ccErrInvalidContext;
+    
+    if (iterpp == NULL)
+        return ccErrBadParam;
+
+    code = cci_ccache_list_iterator(ctx->ccaches, &ccache_iterator);
+    if (code != ccNoError)
+        return code;
+    cci_generic_list_prepend(ctx->active_iterators, ccache_iterator, sizeof(cc_ccache_iterate_t), NULL);
+
+    *iterpp = ccache_iterator;
+    return ccNoError;
+}
+
+cc_int32 
+cci_context_compare(cc_server_context_t* a, cc_server_context_t* b) 
+{
+    if (a == b)
+        return 1;
+    else
+        return 0;
+}
+
+cc_int32 
+cci_context_destroy(cc_server_context_t* ctx) 
+{
+    cc_ccache_iterate_t* ccache_iterator;
+    cc_ccache_list_node_t* ccache_node;
+    cc_server_ccache_t* ccache;
+    cc_int32 code;
+
+    if (ctx == NULL) 
+        return ccErrInvalidContext;
+
+    cci_generic_list_destroy(ctx->active_iterators);
+       
+    code = cci_ccache_list_iterator(ctx->ccaches, &ccache_iterator);
+    while (cci_ccache_iterate_has_next(ccache_iterator)) {
+        code = cci_ccache_iterate_next(ccache_iterator, &ccache_node);
+        ccache = (cc_server_ccache_t *)ccache_node->data;
+        ccache_node->data = NULL;
+        cci_ccache_destroy(ccache);
+    }
+    cci_ccache_list_destroy(ctx->ccaches);
+
+    return ccNoError;
+}
+
+cc_int32 
+cci_context_rem_ccache(cc_server_context_t* ctx, cc_server_ccache_t* ccache) 
+{
+    cc_ccache_iterate_t* ccache_iterator;
+    cc_ccache_iterate_t* active_ccache_iterator;
+    cc_ccache_list_node_t* ccache_node;
+    cc_server_ccache_t* list_ccache;
+    cc_generic_list_node_t* gen_node;
+    cc_generic_iterate_t* gen_iterator;
+    cc_int32 code;
+
+    if (ctx == NULL) 
+        return ccErrInvalidContext;
+
+    if (ccache == NULL) 
+        return ccErrInvalidCCache;
+
+    code = cci_ccache_list_iterator(ctx->ccaches, &ccache_iterator);
+    while (cci_ccache_iterate_has_next(ccache_iterator)) {
+        code = cci_ccache_iterate_next(ccache_iterator, &ccache_node);
+        list_ccache = (cc_server_ccache_t *)ccache_node->data;
+
+        if (list_ccache == ccache) {
+            code = cci_generic_list_iterator(ctx->active_iterators, &gen_iterator);
+            while (cci_generic_iterate_has_next(gen_iterator)) {
+                code = cci_generic_iterate_next(gen_iterator, &gen_node);
+                active_ccache_iterator = (cc_server_ccache_t *)gen_node->data;
+                if (active_ccache_iterator->next == ccache_node) {
+                    active_ccache_iterator->next = active_ccache_iterator->next->next;
+                }
+            }
+            free(gen_iterator);
+            code = cci_ccache_list_remove_element(ctx->ccaches, ccache_node);
+            break;
+        }
+    }
+    free(ccache_iterator);
+    return ccNoError;
+}
+
diff --git a/src/lib/ccapi/server/datastore.h b/src/lib/ccapi/server/datastore.h
new file mode 100644 (file)
index 0000000..a92c606
--- /dev/null
@@ -0,0 +1,231 @@
+/* $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).
+ * $
+ */
+/*
+ * Prototypes and data structures for datastore.
+ *
+ */
+
+
+#ifndef __CCDATASTOREH__
+#define __CCDATASTOREH__
+
+#include "CredentialsCache.h"
+#include "rpc_auth.h"
+
+enum cc_list_type {
+    generic = 0,
+    context,
+    cache,
+    credentials
+};
+
+struct cc_generic_list_node_t {
+    cc_uint8*                          data;
+    cc_uint32                          len;
+    struct cc_generic_list_node_t*     next;
+    struct cc_generic_list_node_t*     prev;
+};
+typedef struct cc_generic_list_node_t cc_generic_list_node_t;
+
+struct cc_generic_list_head_t {
+    enum cc_list_type                   type;
+    cc_generic_list_node_t*            head;
+    cc_generic_list_node_t*            tail; 
+};      
+typedef struct cc_generic_list_head_t cc_generic_list_head_t;
+
+
+struct cc_generic_iterate_t {
+    cc_generic_list_node_t*            next;
+};
+typedef struct cc_generic_iterate_t cc_generic_iterate_t;
+
+typedef cc_generic_list_head_t cc_context_list_head_t;
+typedef cc_generic_list_node_t cc_context_list_node_t;
+
+typedef cc_generic_list_head_t cc_ccache_list_head_t;
+typedef cc_generic_list_node_t cc_ccache_list_node_t;
+
+typedef cc_generic_list_head_t cc_credentials_list_head_t;
+typedef cc_generic_list_node_t cc_credentials_list_node_t;
+
+struct cc_context_iterate_t {
+    cc_context_list_node_t*    next;
+};
+typedef struct cc_context_iterate_t cc_context_iterate_t;
+
+struct cc_ccache_iterate_t {
+    cc_ccache_list_node_t*     next;
+};
+typedef struct cc_ccache_iterate_t cc_ccache_iterate_t;
+
+struct cc_credentials_iterate_t {
+    cc_credentials_list_node_t*        next;
+};
+typedef struct cc_credentials_iterate_t cc_credentials_iterate_t;
+
+struct cc_lock_t {
+    cc_uint32                           read_locks;             /* count of read locks (>= 0) */
+    cc_uint32                           write_locks;            /* count of write locks (0 or 1) */
+    void *                              platform_data;          /* platform specific implementation data */
+};
+typedef struct cc_lock cc_lock_t;
+
+
+struct cc_server_context_t {
+    cc_ccache_list_head_t*             ccaches;                /*our ccaches*/
+    cc_generic_list_head_t*            active_iterators;       /*active ccache iterators*/
+    cc_int32                           api_version;            /*Version our client passed in on init (ccapi_version_X) */
+    cc_auth_info_t*                    auth_info;              /*auth info passed in from RPC*/
+    cc_session_info_t*                 session_info;           /*session info passed in from RPC*/
+    cc_time_t                          changed;                /*date of last change to this context*/
+    cc_int32                            error;                  /*last error code*/
+    cc_lock_t                           locks;                  /*are we locked?*/
+};                                                              
+typedef struct cc_server_context_t cc_server_context_t;
+
+struct cc_server_ccache_t {
+    char*                              name;                   /*name of this ccache*/
+    char*                              principal_v4;           /*v4 principal associated with this cache*/
+    char*                              principal_v5;           /*v5 principal associated with this cache*/
+    cc_uint32                          versions;               /*versions of creds supported (from cc_credentials enum in CredentialsCache.h)*/
+    cc_time_t                          changed;                /*date of last change to ccache*/
+    cc_int32                           kdc_set;                /*is the KDC time offset initialized?*/
+    cc_time_t                          kdc_offset;             /*offset of our clock relative kdc*/
+    cc_time_t                          last_default;           /*the last date when we were default*/
+    cc_int32                           is_default;             /*is this the default cred on this ccache?*/
+    cc_generic_list_head_t*            active_iterators;       /*iterators which clients have opened on this cache*/
+    cc_credentials_list_head_t*        creds;                          /*list of creds stored in this ccache*/
+    cc_server_context_t*               mycontext;              /*context to which I belong*/
+    cc_lock_t                           locks;                  /*are we locked?*/
+};
+typedef struct cc_server_ccache_t cc_server_ccache_t;
+
+struct cc_server_credentials_t {
+    cc_int32                           is_default;             /*Are we the default cred? (first in list)*/
+    cc_credentials_union               creds;
+};
+typedef struct cc_server_credentials_t cc_server_credentials_t;
+
+
+/*Note: cci means Credential Cache Internal, to differentiate from exported API macros*/
+
+cc_int32 cci_generic_iterate_has_next(cc_generic_iterate_t *iterate);
+cc_int32 cci_generic_iterate_next(cc_generic_iterate_t *iterate, cc_generic_list_node_t**);
+
+cc_int32 cci_generic_list_new(cc_generic_list_head_t **);
+cc_int32 cci_generic_list_append(cc_generic_list_head_t *head, void *data, cc_uint32 len, cc_generic_list_node_t**);
+cc_int32 cci_generic_list_prepend(cc_generic_list_head_t *head, void *data, cc_uint32 len, cc_generic_list_node_t**);
+cc_int32 cci_generic_list_remove_element(cc_generic_list_head_t* head, cc_generic_list_node_t* rem);
+cc_int32 cci_generic_free_element(cc_generic_list_node_t* node);
+cc_int32 cci_generic_list_destroy(cc_generic_list_head_t* head);
+cc_int32 cci_generic_list_copy(cc_generic_list_head_t* head, cc_generic_list_head_t**);
+cc_int32 cci_generic_list_iterator(cc_generic_list_head_t *head, cc_generic_iterate_t**);
+cc_int32 cci_generic_free_iterator(cc_generic_iterate_t* iterator);
+
+cc_int32 cci_context_iterate_has_next(struct cc_context_iterate_t *iterate);
+cc_int32 cci_context_iterate_next(struct cc_context_iterate_t *iterate, cc_context_list_node_t**);
+
+cc_int32 cci_ccache_iterate_has_next(struct cc_ccache_iterate_t *iterate);
+cc_int32 cci_ccache_iterate_next(struct cc_ccache_iterate_t *iterate, cc_ccache_list_node_t**);
+
+cc_int32 cci_credentials_iterate_has_next(cc_credentials_iterate_t *iterate);
+cc_int32 cci_credentials_iterate_next(cc_credentials_iterate_t *iterate, cc_credentials_list_node_t **);
+
+cc_int32 cci_context_list_new(cc_context_list_head_t**);
+cc_int32 cci_context_list_append(cc_context_list_head_t *head, cc_server_context_t *data, cc_context_list_node_t**);
+cc_int32 cci_context_list_prepend(cc_context_list_head_t *head, cc_server_context_t *data, cc_context_list_node_t**);
+cc_int32 cci_context_list_remove_element(cc_context_list_head_t* head, cc_context_list_node_t* rem);
+cc_int32 cci_context_list_iterator(cc_context_list_head_t *head, struct cc_context_iterate_t**);
+cc_int32 cci_context_free_iterator(struct cc_context_iterate_t *iterator);
+cc_int32 cci_context_list_destroy(cc_context_list_head_t* head) ;
+cc_int32 cci_context_list_copy(cc_context_list_head_t* head, cc_context_list_head_t**);
+
+cc_int32 cci_ccache_list_new(cc_ccache_list_head_t**);
+cc_int32 cci_ccache_list_append(cc_ccache_list_head_t *head, cc_server_ccache_t *data, cc_ccache_list_node_t**);
+cc_int32 cci_ccache_list_prepend(cc_ccache_list_head_t *head, cc_server_ccache_t *data, cc_ccache_list_node_t**);
+cc_int32 cci_ccache_list_remove_element(cc_ccache_list_head_t* head, cc_ccache_list_node_t* rem);
+cc_int32 cci_ccache_list_iterator(cc_ccache_list_head_t *head, struct cc_ccache_iterate_t**);
+cc_int32 cci_ccache_free_iterator(struct cc_ccache_iterate_t *iterator);
+cc_int32 cci_ccache_list_destroy(cc_ccache_list_head_t* head) ;
+cc_int32 cci_ccache_list_copy(cc_ccache_list_head_t* head, cc_ccache_list_head_t**);
+
+
+cc_int32 cci_credentials_list_new(cc_credentials_list_head_t**);
+cc_int32 cci_credentials_list_append(cc_credentials_list_head_t *head, cc_server_credentials_t *data, cc_credentials_list_node_t**);
+cc_int32 cci_credentials_list_prepend(cc_credentials_list_head_t *head, cc_server_credentials_t *data, cc_credentials_list_node_t**);
+cc_int32 cci_credentials_list_remove_element(cc_credentials_list_head_t* head, cc_credentials_list_node_t* rem);
+cc_int32 cci_credentials_list_iterator(cc_credentials_list_head_t *head, cc_credentials_iterate_t**);
+cc_int32 cci_credentials_free_iterator(cc_credentials_iterate_t* iterator);
+cc_int32 cci_credentials_list_destroy(cc_credentials_list_head_t* head) ;
+cc_int32 cci_credentials_list_copy(cc_credentials_list_head_t* head, cc_credentials_list_head_t**) ;
+
+
+cc_int32 cci_context_new(int api_version, cc_auth_info_t* auth_info, cc_session_info_t* session_info, cc_server_context_t** ) ;
+cc_int32 cci_context_get_default_ccache_name(cc_server_context_t* ctx, char **);
+cc_int32 cci_context_find_ccache(cc_server_context_t* ctx, char *name, cc_server_ccache_t**);
+cc_int32 cci_context_open_ccache(cc_server_context_t* ctx, char *name, cc_server_ccache_t** );
+cc_int32 cci_context_create_ccache(cc_server_context_t* ctx, char *name, int creds_version, char *principal, cc_server_ccache_t**);
+cc_int32 cci_context_create_default_ccache(cc_server_context_t* ctx, int creds_version, char *principal, cc_server_ccache_t**);
+cc_int32 cci_context_ccache_iterator(cc_server_context_t* ctx, cc_ccache_iterate_t**);
+cc_int32 cci_context_compare(cc_server_context_t* a, cc_server_context_t* b);
+cc_int32 cci_context_destroy(cc_server_context_t* ctx);
+cc_int32 cci_context_rem_ccache(cc_server_context_t* ctx, cc_server_ccache_t* ccache);
+
+cc_int32 cci_ccache_new(char *name, char *principal, int cred_vers, cc_server_ccache_t**);
+cc_int32 cci_ccache_check_version(const cc_server_ccache_t *ccache, const cc_credentials_union* creds, cc_uint32* compat);
+cc_int32 cci_ccache_check_principal(const cc_server_ccache_t *ccache, const cc_credentials_union* creds, cc_uint32* compat);
+cc_int32 cci_ccache_store_creds(cc_server_ccache_t *ccache, const cc_credentials_union* credentials);
+cc_int32 cci_ccache_rem_creds(cc_server_ccache_t *ccache, const cc_credentials_union* credentials);
+cc_int32 cci_ccache_move(cc_server_ccache_t *source, cc_server_ccache_t* destination);
+cc_int32 cci_ccache_get_kdc_time_offset(cc_server_ccache_t* ccache, cc_time_t* offset);
+cc_int32 cci_ccache_set_kdc_time_offset(cc_server_ccache_t* ccache, cc_time_t offset);
+cc_int32 cci_ccache_clear_kdc_time_offset(cc_server_ccache_t* ccache);
+cc_int32 cci_ccache_new_iterator(cc_server_ccache_t* ccache, cc_credentials_iterate_t** iterator);
+cc_int32 cci_ccache_get_principal(cc_server_ccache_t* ccache, cc_int32 version, char ** principal);
+cc_int32 cci_ccache_set_principal(cc_server_ccache_t* ccache, cc_int32 version, char * principal);
+cc_int32 cci_ccache_free_principal(char * principal);
+cc_int32 cci_ccache_destroy(cc_server_ccache_t* ccache);
+void    cci_ccache_changed(cc_server_ccache_t* ccache);
+cc_int32 cci_ccache_compare(cc_server_ccache_t* ccache1, cc_server_ccache_t* ccache2, cc_uint32 *result);
+#endif /*__CCDATASTOREH__*/
diff --git a/src/lib/ccapi/server/lists.c b/src/lib/ccapi/server/lists.c
new file mode 100644 (file)
index 0000000..882ecb7
--- /dev/null
@@ -0,0 +1,996 @@
+/* $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).
+ * $
+ */
+
+
+/*
+ * Lists implementation.
+ * 
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <memory.h>
+
+#include "CredentialsCache.h"
+#include "datastore.h"
+
+/**
+ * cci_generic_iterate_has_next()
+ *
+ * Purpose: Determine if an iterator has a next element
+ *
+ * Return:  1 if another element exists
+ *          0 if no additional elements exist
+ *
+ * Errors:  None
+ *
+ */
+cc_int32 
+cci_generic_iterate_has_next(cc_generic_iterate_t *iterate) 
+{
+    return ((iterate == NULL || iterate->next == NULL) ? 0 : 1);
+}
+
+/**
+ * cci_generic_iterate_next()
+ *
+ * Purpose: Retrieve the next element from an iterator and advance
+ *          the iterator
+ *
+ * Return:  non-NULL, the next element in the iterator
+ *          NULL, the iterator list is empty or iterator is invalid
+ *
+ * Errors:  ccErrBadParam
+ *
+ */
+cc_int32
+cci_generic_iterate_next(cc_generic_iterate_t *iterator, cc_generic_list_node_t** nodepp) 
+{
+    cc_generic_list_node_t* ret;
+    
+    if (iterator == NULL || nodepp == NULL)
+        return ccErrBadParam;
+
+    ret = iterator->next;
+    if (iterator->next != NULL)
+        iterator->next = iterator->next->next;
+
+    *nodepp = ret;
+    return ccNoError;
+}
+
+/**
+ * cci_context_iterate_has_next()
+ *
+ * Purpose: Determine if a context iterator has a next element
+ *
+ * Return:  1 if another element exists
+ *          0 if no additional elements exist
+ */
+cc_int32 
+cci_context_iterate_has_next(cc_context_iterate_t *iterate) 
+{
+    if ( iterate == NULL )
+        return 0;
+    
+    return cci_generic_iterate_has_next((cc_generic_iterate_t*)iterate);
+}
+
+/**
+ * cci_context_iterate_next()
+ *
+ * Purpose: Retrieve the next element from a context iterator and advance
+ *          the iterator
+ *
+ * Return:  non-NULL, the next element in the iterator
+ *          NULL, the iterator list is empty or iterator is invalid
+ *
+ * Errors:  ccErrBadParam
+ *
+ */
+cc_int32
+cci_context_iterate_next(cc_context_iterate_t *iterate, cc_context_list_node_t ** nodepp)
+{
+    if ( iterate == NULL || nodepp == NULL)
+        return ccErrBadParam;
+    
+    return cci_generic_iterate_next((cc_generic_iterate_t*)iterate,(cc_context_list_node_t**)nodepp);
+}
+
+/**
+ * cci_ccache_iterate_has_next()
+ *
+ * Purpose: Determine if a cache iterator has a next element
+ *
+ * Return:  1 if another element exists
+ *          0 if no additional elements exist
+ *         -1 if error
+ *
+ * Errors:  ccErrBadParam
+ *
+ */
+cc_int32 
+cci_ccache_iterate_has_next(cc_ccache_iterate_t *iterate) 
+{
+    if ( iterate == NULL )
+        return 0;
+    return cci_generic_iterate_has_next((cc_generic_iterate_t*)iterate);
+}
+
+/**
+ * cci_ccache_iterate_next()
+ * 
+ * Purpose: Retrieve the next element from a ccache iterator and advance
+ *          the iterator
+ *
+ * Return:  non-NULL, the next element in the iterator
+ *          NULL, the iterator list is empty or iterator is invalid
+ *
+ * Errors:  ccErrBadParam
+ *
+ */
+cc_int32
+cci_ccache_iterate_next(cc_ccache_iterate_t *iterate, cc_ccache_list_node_t ** nodepp)
+{
+    if ( iterate == NULL || nodepp == NULL)
+        return ccErrBadParam;
+    
+    return cci_generic_iterate_next((cc_generic_iterate_t*)iterate, (cc_ccache_list_node_t**)nodepp);
+}
+
+/**
+ * cci_credentials_iterate_has_next()
+ *
+ * Purpose: Determine if a credentials iterator has a next element
+ *
+ * Return:  1 if another element exists
+ *          0 if no additional elements exist
+ *         -1 if error
+ *
+ * Errors:  ccErrBadParam
+ *
+ */
+cc_int32 
+cci_credentials_iterate_has_next(cc_credentials_iterate_t *iterate) 
+{
+    if ( iterate == NULL )
+        return 0;
+    
+    return cci_generic_iterate_has_next((cc_generic_iterate_t*)iterate);
+}
+
+/**
+ * cci_credentials_iterate_next()
+ * 
+ * Purpose: Retrieve the next element from a credentials iterator and advance
+ *          the iterator
+ *
+ * Return:  non-NULL, the next element in the iterator
+ *          NULL, the iterator list is empty or iterator is invalid
+ *
+ * Errors:  ccErrBadParam
+ *
+ */
+cc_int32
+cci_credentials_iterate_next(cc_credentials_iterate_t *iterate, cc_credentials_list_node_t** nodepp) 
+{
+    if ( iterate == NULL || nodepp == NULL )
+        return ccErrBadParam;
+    return cci_generic_iterate_next((cc_generic_iterate_t*)iterate, (cc_credentials_list_node_t**)nodepp);
+}
+
+/**
+ * cci_generic_list_new()
+ *
+ * Purpose: Allocate new generic list
+ *
+ * Return:  non-NULL, an empty list
+ *          NULL, failure
+ *
+ * Errors:  ccErrNoMem
+ *
+ */
+cc_int32
+cci_generic_list_new(cc_generic_list_head_t ** listpp) 
+{
+    cc_generic_list_head_t* ret = (cc_generic_list_head_t *)malloc(sizeof(cc_generic_list_head_t));
+    if (ret == NULL)
+        return ccErrNoMem;
+       
+       ret->type = generic;
+    ret->head = ret->tail = NULL;
+    *listpp = ret;
+
+    return ccNoError;
+}
+
+/**
+ * cci_generic_list_append()
+ *
+ * Purpose: Appends a new node containing a copy of 'len' bytes of 'data' 
+ *
+ * Return:  non-NULL, a pointer to the newly allocated node
+ *          NULL, failure
+ *
+ * Errors:  ccErrNoMem,ccErrBadParam
+ *
+ */
+cc_int32
+cci_generic_list_append(cc_generic_list_head_t *head, void *data, cc_uint32 len, cc_generic_list_node_t** nodepp) 
+{
+    cc_generic_list_node_t* new_node;
+
+    if ( data == NULL || len == 0 )
+        return ccErrBadParam;
+
+    new_node = (cc_generic_list_node_t *)malloc(sizeof(cc_generic_list_node_t));
+    if (new_node == NULL)
+        return ccErrNoMem;
+
+    new_node->data = malloc(len);
+    if ( new_node->data == NULL ) {
+        free(new_node);
+        return ccErrNoMem;         
+    }
+    
+    memcpy(new_node->data,data,len);
+    new_node->len = len;
+
+    if (head->head == NULL) { /*empty list*/
+        head->head = new_node;
+        head->tail = new_node;
+           new_node->next = new_node->prev = NULL;
+    } else {
+        new_node->prev = head->tail;
+        head->tail->next = new_node;
+        head->tail = new_node;
+               new_node->next = NULL;
+    }
+       if (nodepp != NULL)
+           *nodepp = new_node;
+    return ccNoError;
+}
+
+/**
+ * cci_generic_list_prepend()
+ *
+ * Purpose: Prepends a new node containing a copy of 'len' bytes of 'data'
+ *
+ * Return:  non-NULL, a pointer to the newly allocated node
+ *          NULL, failure
+ *
+ * Errors:  ccErrNoMem, ccErrBadParam
+ *
+ */
+cc_int32 
+cci_generic_list_prepend(cc_generic_list_head_t *head, void *data, cc_uint32 len, cc_generic_list_node_t** nodepp) 
+{
+    cc_generic_list_node_t* new_node;
+
+    if ( data == NULL || len == 0 )
+        return ccErrBadParam;
+
+    new_node = (cc_generic_list_node_t *)malloc(sizeof(cc_generic_list_node_t));
+    if (new_node == NULL)
+        return ccErrNoMem;
+
+    new_node->data = malloc(len);
+    if ( new_node->data == NULL ) {
+        free(new_node);
+        return ccErrNoMem;
+    }
+    
+    memcpy(new_node->data,data,len);
+    new_node->len = len;
+       
+    if (head->head == NULL) { /*empty list*/
+        head->head = new_node;
+        head->tail = new_node;
+        new_node->prev = new_node->next = NULL;
+    } else {
+        new_node->next = head->head;
+        head->head->prev = new_node;
+        new_node->prev = NULL;
+        head->head = new_node;
+    }
+
+       if (nodepp != NULL)
+               *nodepp = new_node;
+
+    return ccNoError;
+}
+
+/**
+ * cci_generic_list_remove_element()
+ *
+ * Purpose: Remove a node from the list
+ *
+ * Return:  0, success
+ *         -1, failure
+ *
+ * Errors:  ccErrBadParam
+ *
+ */
+cc_int32 
+cci_generic_list_remove_element(cc_generic_list_head_t* head, cc_generic_list_node_t* rem) 
+{
+    if (head->head == NULL || rem == NULL)
+        return ccErrBadParam;
+
+    if (head->head == rem && head->tail == rem) { /*removing only element of list*/
+        head->head = head->tail = NULL;
+    } else if (head->head == rem) { /*removing head*/
+        head->head = head->head->next;
+    } else if (head->tail == rem) { /*removing tail*/
+        head->tail = head->tail->prev;
+        head->tail->next = NULL;
+    } else {
+        rem->prev->next = rem->next;
+        rem->next->prev = rem->prev;
+    }
+    free(rem);
+    return ccNoError;
+}
+
+/**
+ * cci_generic_free_element()
+ *
+ * Purpose: Free the memory associated with a node
+ *
+ * Return:  0, success
+ *         -1, failure
+ *
+ * Errors:  ccErrBadParam
+ *
+ */
+cc_int32
+cci_generic_free_element(cc_generic_list_node_t* node)
+{
+    if ( node == NULL )
+        return ccErrBadParam;
+
+    if ( node->data ) {
+        free(node->data);
+        node->data = NULL;
+    }
+    node->len = 0;
+    node->next = node->prev = NULL;
+    free(node);
+    return ccNoError;
+}
+
+
+/**
+ * cci_generic_list_destroy()
+ *
+ * Purpose: Deallocate a list and all of its contents
+ *
+ * Return:  0, success
+ *         -1, failure
+ *
+ * Errors:  ccErrBadParam
+ */
+cc_int32
+cci_generic_list_destroy(cc_generic_list_head_t* head) 
+{
+    cc_generic_list_node_t *cur, *next;
+    cc_int32 ret = ccNoError;
+
+    if ( head == NULL )
+        return ccErrBadParam;
+       
+    for (cur = head->head; ret == ccNoError && cur != NULL; cur = next) {
+        next = cur->next;
+        ret = cci_generic_free_element(cur);
+    }       
+    free(head);
+    return(ret);
+}
+
+/**
+ * cci_context_list_destroy()
+ *
+ * Purpose: Deallocate a list and all of its contents
+ *
+ * Return:  0, success
+ *         -1, failure
+ *
+ * Errors:  ccErrBadParam
+ */
+cc_int32
+cci_context_list_destroy(cc_context_list_head_t* head) 
+{
+    return cci_generic_list_destroy((cc_generic_list_head_t*)head);
+}
+
+/**
+ * cci_ccache_list_destroy()
+ *
+ * Purpose: Deallocate a list and all of its contents
+ *
+ * Return:  0, success
+ *         -1, failure
+ *
+ * Errors:  ccErrBadParam
+ */
+cc_int32
+cci_ccache_list_destroy(cc_ccache_list_head_t* head) 
+{
+    return cci_generic_list_destroy((cc_generic_list_head_t*)head);
+}
+
+/**
+ * cci_credentials_list_destroy()
+ *
+ * Purpose: Deallocate a list and all of its contents
+ *
+ * Return:  0, success
+ *         -1, failure
+ *
+ * Errors:  ccErrBadParam
+ */
+cc_int32
+cci_credentials_list_destroy(cc_credentials_list_head_t* head) 
+{
+    return cci_generic_list_destroy((cc_generic_list_head_t*)head);
+}
+
+/**
+ * cci_generic_list_copy()
+ *
+ * Purpose: Copy a list
+ *
+ * Return:  non-NULL, a new list
+ *          NULL, failure
+ *
+ * Errors:  ccErrBadParam, ccErrNoMem
+ *
+ */
+cc_int32
+cci_generic_list_copy(cc_generic_list_head_t* head, cc_generic_list_head_t** headpp) 
+{
+    cc_generic_list_head_t* copy;
+    cc_generic_list_node_t *src_node, *dst_node;
+    cc_int32 code;
+
+    if (head == NULL || headpp == NULL)
+        return ccErrBadParam;
+
+    code = cci_generic_list_new(&copy);
+    if (code != ccNoError)
+        return code;
+
+    for (src_node = head->head; src_node != NULL; src_node = src_node->next) {
+        code = cci_generic_list_append(copy, src_node->data, src_node->len, &dst_node);
+        if (code != ccNoError) {
+            cci_generic_list_destroy(copy);
+            return code;
+        }
+    }
+    *headpp = copy;
+    return ccNoError;
+}
+
+/**
+ * cci_context_list_copy()
+ *
+ * Purpose: Copy a list
+ *
+ * Return:  non-NULL, a new list
+ *          NULL, failure
+ *
+ * Errors:  ccErrBadParam, ccErrNoMem
+ *
+ */
+cc_int32
+cci_context_list_copy(cc_context_list_head_t* head, cc_context_list_head_t** headpp ) 
+{
+    return cci_generic_list_copy((cc_generic_list_head_t*)head, (cc_context_list_head_t **)headpp);
+}
+
+/**
+ * cci_ccache_list_copy()
+ *
+ * Purpose: Copy a list
+ *
+ * Return:  non-NULL, a new list
+ *          NULL, failure
+ *
+ * Errors:  ccErrBadParam, ccErrNoMem
+ */
+cc_int32
+cci_ccache_list_copy(cc_ccache_list_head_t* head, cc_ccache_list_head_t** headpp)
+{
+    return cci_generic_list_copy((cc_generic_list_head_t*)head, (cc_ccache_list_head_t **)headpp);
+}
+
+/**
+ * cci_credentials_list_copy()
+ *
+ * Purpose: Copy a list
+ *
+ * Return:  non-NULL, a new list
+ *          NULL, failure
+ *
+ * Errors:  ccErrBadParam, ccErrNoMem
+ *
+ */
+cc_int32
+cci_credentials_list_copy(cc_credentials_list_head_t* head, cc_credentials_list_head_t** headpp) 
+{
+    return cci_generic_list_copy((cc_generic_list_head_t*)head, (cc_credentials_list_head_t **)headpp);
+}
+
+
+/**
+ * cci_generic_list_iterator()
+ *
+ * Purpose: Allocate an iterator for the specified list
+ *
+ * Return:  non-NULL, an iterator
+ *          NULL, failure
+ *
+ * Errors:  ccErrNoMem
+ *
+ */
+cc_int32
+cci_generic_list_iterator(cc_generic_list_head_t *head, cc_generic_iterate_t** headpp) 
+{
+    cc_generic_iterate_t* iterator;
+
+    if ( head == NULL || headpp == NULL )
+        return ccErrBadParam;
+
+    iterator = (cc_generic_iterate_t*)malloc(sizeof(cc_generic_iterate_t));
+    if (iterator == NULL)
+        return ccErrNoMem;
+    
+    iterator->next = head->head;
+    *headpp = iterator;
+    return ccNoError;
+}
+
+/**
+ * cci_generic_free_iterator()
+ *
+ * Purpose: Deallocate memory associated with an iterator
+ *
+ * Return:  0, success
+ *         -1, failure
+ *
+ * Errors:  ccErrBadParam
+ *
+ */
+cc_int32
+cci_generic_free_iterator(cc_generic_iterate_t* iterator)
+{
+    if ( iterator == NULL )
+        return ccErrBadParam;
+
+    iterator->next = NULL;
+    free(iterator);
+    return ccNoError;
+}
+
+
+/**
+ * cci_context_list_new()
+ *
+ * Purpose: Allocate a new context list
+ *
+ * Return:  non-NULL, a new list
+ *          NULL, failure
+ *
+ * Errors:  ccErrNoMem
+ *
+ */
+cc_int32
+cci_context_list_new(cc_context_list_head_t ** headpp) 
+{
+    cc_context_list_head_t *ret;
+    
+    if ( headpp == NULL )
+        return ccErrBadParam;
+
+    ret = (cc_context_list_head_t *)malloc(sizeof(cc_context_list_head_t));
+    if (ret == NULL)
+        return ccErrNoMem;
+    ret->head = ret->tail = NULL;
+    *headpp = ret;
+    return ccNoError;
+}
+
+/**
+ * cci_context_list_append()
+ *
+ * Purpose: Appends a new node containing a copy of 'len' bytes of 'data' 
+ *
+ * Return:  non-NULL, a pointer to the newly allocated node
+ *          NULL, failure
+ *
+ * Errors:  ccErrNoMem,ccErrBadParam
+ *
+ */
+cc_int32
+cci_context_list_append(cc_context_list_head_t *head, cc_server_context_t *data, cc_context_list_node_t** nodepp) 
+{
+    return cci_generic_list_append((cc_generic_list_head_t *)head, (void *)data, sizeof(cc_server_context_t), (cc_context_list_node_t**)nodepp);
+}
+
+/**
+ * cci_context_list_prepend()
+ *
+ * Purpose: Prepends a new node containing a copy of 'len' bytes of 'data' 
+ *
+ * Return:  non-NULL, a pointer to the newly allocated node
+ *          NULL, failure
+ *
+ * Errors:  ccErrNoMem,ccErrBadParam
+ *
+ */
+cc_int32
+cci_context_list_prepend(cc_context_list_head_t *head, cc_server_context_t *data, cc_context_list_node_t** nodepp ) 
+{
+    return cci_generic_list_prepend((cc_generic_list_head_t *)head, (void *)data, sizeof(cc_server_context_t), (cc_context_list_node_t**)nodepp);
+}
+
+/**
+ * cci_context_list_remove_element
+ *
+ * Purpose: Remove a node from the list
+ *
+ * Return:  0, success
+ *         -1, failure
+ *
+ * Errors:  ccErrBadParam
+ */
+cc_int32
+cci_context_list_remove_element(cc_context_list_head_t* head, cc_context_list_node_t* rem) 
+{
+    return cci_generic_list_remove_element((cc_generic_list_head_t*)head, (cc_generic_list_node_t*)rem);
+}
+
+/**
+ * cci_context_list_iterator()
+ *
+ * Purpose: Allocate an iterator for the specified list
+ *
+ * Return:  non-NULL, an iterator
+ *          NULL, failure
+ *
+ * Errors:  ccErrNoMem
+ *
+ */
+cc_int32
+cci_context_list_iterator(cc_context_list_head_t *head, cc_context_iterate_t** iterpp) 
+{
+    cc_context_iterate_t* iterator;
+    
+    if ( head == NULL || iterpp == NULL )
+        return ccErrBadParam;
+
+    iterator = (cc_context_iterate_t*)malloc(sizeof(cc_context_iterate_t));
+    if (iterator == NULL)
+        return ccErrNoMem;
+
+    iterator->next = head->head;
+    *iterpp = iterator;
+    return ccNoError;
+}
+
+/**
+ * cci_context_free_iterator()
+ *
+ * Purpose: Deallocate memory associated with an iterator
+ *
+ * Return:  0, success
+ *         -1, failure
+ *
+ * Errors:  ccErrBadParam
+ *
+ */
+cc_int32
+cci_context_free_iterator(cc_context_iterate_t* iterator)
+{
+    if ( iterator == NULL )
+        return ccErrBadParam;
+
+    iterator->next = NULL;
+    free(iterator);
+    return ccNoError;
+}
+
+/**
+ * cci_ccache_list_new()
+ *
+ * Purpose: Allocate a new ccache list
+ *
+ * Return:  non-NULL, a new list
+ *          NULL, failure
+ *
+ * Errors:  ccErrNoMem
+ */
+cc_int32
+cci_ccache_list_new(cc_ccache_list_head_t ** listpp)
+{
+    cc_ccache_list_head_t *ret;
+    
+    if ( listpp == NULL )
+        return ccErrBadParam;
+
+    ret = (cc_ccache_list_head_t *)malloc(sizeof(cc_ccache_list_head_t));
+    if (ret == NULL)
+        return ccErrNoMem;
+
+    ret->head = ret->tail = NULL;
+    *listpp = ret;
+    return ccNoError;
+}
+
+/**
+ * cci_ccache_list_append()
+ *
+ * Purpose: Appends a new node containing a copy of 'len' bytes of 'data' 
+ *
+ * Return:  non-NULL, a pointer to the newly allocated node
+ *          NULL, failure
+ *
+ * Errors:  ccErrNoMem,ccErrBadParam
+ *
+ */
+cc_int32
+cci_ccache_list_append(cc_ccache_list_head_t *head, cc_server_ccache_t *data, cc_ccache_list_node_t** nodepp) 
+{
+    return cci_generic_list_append((cc_generic_list_head_t *)head, (void *)data, sizeof(cc_server_ccache_t), (cc_ccache_list_node_t**)nodepp);
+}
+
+/**
+ * cci_ccache_list_prepend()
+ *
+ * Purpose: Prepends a new node containing a copy of 'len' bytes of 'data' 
+ *
+ * Return:  non-NULL, a pointer to the newly allocated node
+ *          NULL, failure
+ *
+ * Errors:  ccErrNoMem,ccErrBadParam
+ *
+ */
+cc_int32
+cci_ccache_list_prepend(cc_ccache_list_head_t *head, cc_server_ccache_t *data, cc_ccache_list_node_t** nodepp) 
+{
+    return cci_generic_list_prepend((cc_generic_list_head_t *)head, (void *)data, sizeof(cc_server_ccache_t), (cc_ccache_list_node_t**)nodepp);
+}
+
+/**
+ * cci_ccache_list_remove_element()
+ *
+ * Purpose: Remove a node from the list
+ *
+ * Return:  0, success
+ *         -1, failure
+ *
+ * Errors:  ccErrBadParam
+ *
+ */
+cc_int32
+cci_ccache_list_remove_element(cc_ccache_list_head_t* head, cc_ccache_list_node_t* rem) 
+{
+    return cci_generic_list_remove_element((cc_generic_list_head_t*)head, (cc_generic_list_node_t*)rem);
+}
+
+/**
+ * cci_ccache_list_iterator()
+ *
+ * Purpose: Allocate an iterator for the specified list
+ *
+ * Return:  non-NULL, an iterator
+ *          NULL, failure
+ *
+ * Errors:  ccErrNoMem
+ *
+ */
+cc_int32
+cci_ccache_list_iterator(cc_ccache_list_head_t *head, cc_ccache_iterate_t** iterpp) 
+{
+    cc_ccache_iterate_t* iterator;
+    
+    if ( head == NULL || iterpp == NULL )
+        return ccErrBadParam;
+
+    iterator = (cc_ccache_iterate_t*)malloc(sizeof(cc_ccache_iterate_t));
+    if (iterator == NULL)
+        return ccErrNoMem;
+
+    iterator->next = head->head;
+    *iterpp = iterator;
+    return ccNoError;
+}
+
+/**
+ * cci_ccache_free_iterator()
+ *
+ * Purpose: Deallocate memory associated with an iterator
+ *
+ * Return:  0, success
+ *         -1, failure
+ *
+ * Errors:  ccErrBadParam
+ *
+ */
+cc_int32
+cci_ccache_free_iterator(cc_ccache_iterate_t* iterator)
+{
+    if ( iterator == NULL )
+        return ccErrBadParam;
+
+    iterator->next = NULL;
+    free(iterator);
+    return ccNoError;
+}
+
+/**
+ * cci_credentials_list_new()
+ *
+ * Purpose: Allocate a new ccache list
+ *
+ * Return:  non-NULL, a new list
+ *          NULL, failure
+ *
+ * Errors:  ccErrNoMem
+ *
+ */
+cc_int32
+cci_credentials_list_new(cc_credentials_list_head_t ** list) 
+{
+    if ( list == NULL )
+        return ccErrBadParam;
+
+    *list = (cc_credentials_list_head_t *)malloc(sizeof(cc_credentials_list_head_t));
+    if (*list == NULL)
+        return ccErrNoMem;
+
+    (*list)->head = (*list)->tail = NULL;
+    return ccNoError;
+}
+
+/**
+ * cci_credentials_list_append()
+ *
+ * Purpose: Appends a new node containing a copy of 'len' bytes of 'data' 
+ *
+ * Return:  non-NULL, a pointer to the newly allocated node
+ *          NULL, failure
+ *
+ * Errors:  ccErrNoMem,ccErrBadParam
+ *
+ */
+cc_int32
+cci_credentials_list_append(cc_credentials_list_head_t *head, cc_server_credentials_t *data, cc_credentials_list_node_t** nodepp ) 
+{
+    return cci_generic_list_append((cc_generic_list_head_t *)head, (void *)data, sizeof(cc_server_credentials_t), (cc_credentials_list_node_t**)nodepp);
+}
+
+/**
+ * cci_credentials_list_prepend()
+ *
+ * Purpose: Prepends a new node containing a copy of 'len' bytes of 'data' 
+ *
+ * Return:  non-NULL, a pointer to the newly allocated node
+ *          NULL, failure
+ *
+ * Errors:  ccErrNoMem,ccErrBadParam
+ *
+ */
+cc_int32
+cci_credentials_list_prepend(cc_credentials_list_head_t *head, cc_server_credentials_t *data, cc_credentials_list_node_t** nodepp) 
+{
+    return cci_generic_list_prepend((cc_generic_list_head_t *)head, (void *)data, sizeof(cc_server_credentials_t), (cc_credentials_list_node_t**)nodepp);
+}
+
+/**
+ * cci_credentials_list_remove_element()
+ *
+ * Purpose: Remove a node from the list
+ *
+ * Return:  0, success
+ *         -1, failure
+ *
+ * Errors:  ccErrBadParam
+ *
+ */
+cc_int32 
+cci_credentials_list_remove_element(cc_credentials_list_head_t* head, cc_credentials_list_node_t* rem) 
+{
+    return cci_generic_list_remove_element((cc_generic_list_head_t*)head, (cc_generic_list_node_t*)rem);
+}
+
+/**
+ * cci_credentials_list_iterator()
+ *
+ * Purpose: Allocate an iterator for the specified list
+ *
+ * Return:  non-NULL, an iterator
+ *          NULL, failure
+ *
+ * Errors:  ccErrNoMem
+ *
+ */
+cc_int32
+cci_credentials_list_iterator(cc_credentials_list_head_t *head, cc_credentials_iterate_t** iterpp) 
+{
+    cc_credentials_iterate_t* iterator;
+    
+    if ( head == NULL || iterpp == NULL )
+        return ccErrBadParam;
+
+    iterator = (cc_credentials_iterate_t*)malloc(sizeof(cc_credentials_iterate_t));
+    if (iterator == NULL)
+        return ccErrNoMem;
+
+    iterator->next = head->head;
+    *iterpp = iterator;
+    return ccNoError;
+}
+
+/**
+ * cci_credentials_free_iterator()
+ *
+ * Purpose: Deallocate memory associated with an iterator
+ *
+ * Return:  0, success
+ *         -1, failure
+ *
+ * Errors:  ccErrBadParam
+ *
+ */
+cc_int32
+cci_credentials_free_iterator(cc_credentials_iterate_t* iterator)
+{
+    if ( iterator == NULL )
+        return ccErrBadParam;
+
+    iterator->next = NULL;
+    free(iterator);
+    return ccNoError;
+}
+
diff --git a/src/lib/ccapi/server/mac/ChangeLog b/src/lib/ccapi/server/mac/ChangeLog
new file mode 100644 (file)
index 0000000..aaa59da
--- /dev/null
@@ -0,0 +1,4 @@
+2004-10-27   Jeffrey Altman  <jaltman@mit.edu>
+
+ * Initial commit of C CCAPI implementation
+
diff --git a/src/lib/ccapi/server/rpc_auth.c b/src/lib/ccapi/server/rpc_auth.c
new file mode 100644 (file)
index 0000000..dd338e0
--- /dev/null
@@ -0,0 +1,63 @@
+/* $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).
+ * $
+ */
+
+/*
+ * Stubs for rpc_auth.
+ */
+
+#include "CredentialsCache.h"
+#include "rpc_auth.h"
+
+cc_int32 
+cci_rpc_is_authorized( cc_auth_info_t* msg_auth, cc_session_info_t* msg_session, cc_auth_info_t* stored_auth, 
+                       cc_session_info_t* stored_session, cc_uint32 * authorizedp) 
+{
+    if (msg_auth == stored_auth && msg_session == stored_session)
+        *authorizedp = 1;
+    else
+        *authorizedp = 0;
+
+    return ccNoError;
+}
+
+
diff --git a/src/lib/ccapi/server/rpc_auth.h b/src/lib/ccapi/server/rpc_auth.h
new file mode 100644 (file)
index 0000000..21d7db5
--- /dev/null
@@ -0,0 +1,71 @@
+/* $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).
+ * $
+ */
+
+
+/*
+ * Types for RPC auth + session info
+ *
+ */
+
+#ifndef __RPC_AUTH_H__
+#define __RPC_AUTH_H__
+
+#include "CredentialsCache.h"
+
+/*preliminary*/
+struct cc_auth_info_t {
+    cc_uint8 *info;
+    cc_uint32  len;
+};
+typedef struct cc_auth_info_t cc_auth_info_t;
+
+/*preliminary*/
+struct cc_session_info_t {
+    cc_uint8 *info;
+    cc_uint32  len;
+};
+typedef struct cc_session_info_t cc_session_info_t;
+
+cc_int32 cci_rpc_is_authorized(cc_auth_info_t* msg_auth, cc_session_info_t* msg_session, cc_auth_info_t* stored_auth, cc_session_info_t* stored_session, cc_uint32 *authorizedp);
+
+#endif /*__RPC_AUTH_H__*/
diff --git a/src/lib/ccapi/server/serv_ops.c b/src/lib/ccapi/server/serv_ops.c
new file mode 100644 (file)
index 0000000..30a108a
--- /dev/null
@@ -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;
+}       
diff --git a/src/lib/ccapi/server/serv_ops.h b/src/lib/ccapi/server/serv_ops.h
new file mode 100644 (file)
index 0000000..f439566
--- /dev/null
@@ -0,0 +1,321 @@
+/* $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).
+ * $
+ */
+
+/*
+ * Prototypes for serv_ops.c
+ */
+
+#ifndef __SERV_OPS_H__
+#define __SERV_OPS_H__
+
+#include "CredentialsCache.h"
+#include "rpc_auth.h"
+#include "msg.h"
+#include "datastore.h"
+
+struct type_to_op_mapping_t {
+    cc_int32 (*operations[CC_MSG_MAX_TYPE]) (
+                        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);
+};
+typedef struct type_to_op_mapping_t type_to_op_mapping_t;
+
+cc_int32 cci_serv_initialize(void);
+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_int32 cci_serv_find_ctx(cc_auth_info_t* auth_info, cc_session_info_t* session_info, cc_server_context_t** contextp);
+cc_int32 cci_serv_find_ctx_by_handle(cc_handle ctx_handle, cc_auth_info_t *auth, cc_session_info_t* session, cc_server_context_t** contextp);
+cc_int32 cci_serv_find_ccache_by_handle(cc_server_context_t* ctx, cc_handle ccache_handle, cc_server_ccache_t** ccachep) ;
+cc_int32 cci_serv_find_ccache_iterator_by_handle(cc_server_context_t* ctx, cc_handle iterator, cc_generic_list_node_t** nodep);
+cc_int32 cci_serv_find_creds_iterator_by_handle(cc_server_ccache_t* ccache, cc_handle iterator, cc_generic_list_node_t** nodep);
+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** msgp);
+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** msgp);
+
+cc_int32 ccop_INIT( 
+        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_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);
+
+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);
+
+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);
+
+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_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_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);
+
+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);
+
+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);
+
+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);
+
+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);
+
+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);
+
+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);
+
+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);
+
+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);
+
+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);
+
+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_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);
+
+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);
+
+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);
+
+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);
+
+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_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);
+
+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);
+
+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);
+
+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) ;
+
+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);
+
+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);
+
+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);
+
+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);
+
+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_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);
+
+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_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);
+
+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);
+#endif /*__SERV_OPS_H__*/
diff --git a/src/lib/ccapi/server/windows/ChangeLog b/src/lib/ccapi/server/windows/ChangeLog
new file mode 100644 (file)
index 0000000..aaa59da
--- /dev/null
@@ -0,0 +1,4 @@
+2004-10-27   Jeffrey Altman  <jaltman@mit.edu>
+
+ * Initial commit of C CCAPI implementation
+
diff --git a/src/lib/ccapi/unit-test/ChangeLog b/src/lib/ccapi/unit-test/ChangeLog
new file mode 100644 (file)
index 0000000..aaa59da
--- /dev/null
@@ -0,0 +1,4 @@
+2004-10-27   Jeffrey Altman  <jaltman@mit.edu>
+
+ * Initial commit of C CCAPI implementation
+
diff --git a/src/lib/ccapi/unit-test/t_ccache.c b/src/lib/ccapi/unit-test/t_ccache.c
new file mode 100644 (file)
index 0000000..6ef33ea
--- /dev/null
@@ -0,0 +1,115 @@
+/* $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).
+ * $
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include "CredentialsCache.h"
+#include "datastore.h"
+
+int main() {
+    cc_server_credentials_t *cred1, *cred2, *cred3;
+    cc_credentials_iterate_t* iterator;
+    cc_server_credentials_t* stored_cred;
+    cc_credentials_list_node_t *node;
+    cc_server_ccache_t *c1, *c2;
+    char p1[] = "Spike";
+    char p2[] = "Jeff";
+    int i;
+    cc_int32 code;
+
+    code = cci_ccache_new("The first", p1, cc_credentials_v4_v5, &c1);
+    code = cci_ccache_new("The 2nd", p2, cc_credentials_v4_v5, &c2);
+
+    cred1 = (cc_server_credentials_t*)malloc(sizeof(cc_server_credentials_t));
+    memset(cred1,0,sizeof(cc_server_credentials_t));
+    cred2 = (cc_server_credentials_t*)malloc(sizeof(cc_server_credentials_t));
+    memset(cred2,0,sizeof(cc_server_credentials_t));
+    cred3 = (cc_server_credentials_t*)malloc(sizeof(cc_server_credentials_t));
+    memset(cred3,0,sizeof(cc_server_credentials_t));
+
+    cred1->creds.version = cred2->creds.version = cc_credentials_v4;
+    cred3->creds.version = cc_credentials_v5;
+
+    cred1->creds.credentials.credentials_v4 = (cc_credentials_v4_t*)malloc(sizeof(cc_credentials_v4_t));
+    memset(cred1->creds.credentials.credentials_v4,0,sizeof(cc_credentials_v4_t));
+    cred2->creds.credentials.credentials_v4 = (cc_credentials_v4_t*)malloc(sizeof(cc_credentials_v4_t));
+    memset(cred2->creds.credentials.credentials_v4,0,sizeof(cc_credentials_v4_t));
+    cred3->creds.credentials.credentials_v5 = (cc_credentials_v5_t*)malloc(sizeof(cc_credentials_v5_t));
+    memset(cred3->creds.credentials.credentials_v5,0,sizeof(cc_credentials_v5_t));
+
+    strncpy(cred1->creds.credentials.credentials_v4->principal, p1, strlen(p1));
+    strncpy(cred2->creds.credentials.credentials_v4->principal, p1, strlen(p1));
+    cred3->creds.credentials.credentials_v5->client = p1;
+
+    code = cci_ccache_store_creds(c1, &cred1->creds);
+    printf("(c1, cred1) -> %d\n",code);
+
+    code = cci_ccache_store_creds(c1, &cred2->creds);
+    printf("(c1, cred2) -> %d\n",code);
+
+    code = cci_ccache_store_creds(c2, &cred3->creds);
+    printf("(c2, cred3) -> %d\n",code);
+
+    code = cci_ccache_store_creds(c1, &cred3->creds);
+    printf("(c1, cred3) -> %d\n",code);
+
+    i = 0;
+    code = cci_ccache_move(c1, c2);
+    code = cci_ccache_destroy(c1);
+    code = cci_ccache_new_iterator(c2, &iterator);
+    while (cci_credentials_iterate_has_next(iterator)) {
+        i++;
+        code = cci_credentials_iterate_next(iterator, &node);
+        stored_cred = (cc_server_credentials_t *)node->data;
+        printf("%d %d %s\n", stored_cred->is_default, stored_cred->creds.version, stored_cred->creds.credentials.credentials_v4->principal);
+
+        if (i == 1) {
+            code = cci_ccache_rem_creds(c2,&cred2->creds);
+            printf("(c2 rem cred2) -> %d\n",code);
+        }
+    }
+    return 0;
+}
+
diff --git a/src/lib/ccapi/unit-test/t_context.c b/src/lib/ccapi/unit-test/t_context.c
new file mode 100644 (file)
index 0000000..9e35d9a
--- /dev/null
@@ -0,0 +1,115 @@
+/* $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).
+ * $
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <time.h>
+#include <string.h>
+
+#include "CredentialsCache.h"
+#include "datastore.h"
+
+
+/*testing code*/
+int main() {
+    int uid = 1;
+    int session = 1;
+    cc_server_ccache_t *ccache;
+    cc_credentials_union* creds;
+    cc_ccache_iterate_t* ccache_iterator;
+    cc_ccache_list_node_t* ccache_node;
+    cc_credentials_iterate_t* creds_iterator;
+    cc_credentials_list_node_t* creds_node;
+    cc_server_credentials_t* server_creds;
+    cc_auth_info_t* auth_info = NULL;
+    cc_session_info_t* session_info = NULL;
+    cc_server_context_t* ctx = NULL;
+    char *name;
+    int i;
+    cc_int32 code;
+
+    code = cci_context_new(5, auth_info, session_info, &ctx);
+    code = cci_context_create_default_ccache(ctx, cc_credentials_v4, "Spike", &ccache);
+    code = cci_context_get_default_ccache_name(ctx, &name);
+    code = cci_context_open_ccache(ctx, name, &ccache);
+       
+    for (i = 0; i < 5; i++) {
+        creds = (cc_credentials_union*)malloc(sizeof(cc_credentials_union));
+        creds->version = cc_credentials_v4;
+        creds->credentials.credentials_v4 = (cc_credentials_v4_t*)malloc(sizeof(cc_credentials_v4_t));
+        strcpy(creds->credentials.credentials_v4->principal, "Spike");
+
+        code = cci_ccache_store_creds(ccache, creds);
+    }
+
+    code = cci_context_create_ccache(ctx, "ccache 2", cc_credentials_v4, "Jeff", &ccache);
+    code = cci_context_open_ccache(ctx, "ccache 2", &ccache);
+       
+    for (i = 0; i < 5; i++) {
+        creds = (cc_credentials_union*)malloc(sizeof(cc_credentials_union));
+        creds->version = cc_credentials_v4;
+        creds->credentials.credentials_v4 = (cc_credentials_v4_t*)malloc(sizeof(cc_credentials_v4_t));
+        strcpy(creds->credentials.credentials_v4->principal, "Jeff");
+
+        cci_ccache_store_creds(ccache, creds);
+    }
+
+    code = cci_context_ccache_iterator(ctx, &ccache_iterator);
+    while (cci_ccache_iterate_has_next(ccache_iterator)) {
+        code = cci_ccache_iterate_next(ccache_iterator, &ccache_node);
+        ccache = (cc_server_ccache_t *)ccache_node->data;
+        printf("%x for %s %s default = %d v %d\n",
+               ccache, ccache->principal_v4, ccache->principal_v5, 
+               ccache->is_default, ccache->versions);
+
+        code = cci_ccache_new_iterator(ccache, &creds_iterator);
+        while (cci_credentials_iterate_has_next(creds_iterator)) {
+            code = cci_credentials_iterate_next(creds_iterator, &creds_node);
+            server_creds = (cc_server_credentials_t *)creds_node->data;        
+            printf("\t%s %d\n", 
+                   server_creds->creds.credentials.credentials_v4->principal, 
+                   creds->version);
+        }
+    }       
+    return 0;
+}
diff --git a/src/lib/ccapi/unit-test/t_lists.c b/src/lib/ccapi/unit-test/t_lists.c
new file mode 100644 (file)
index 0000000..4c8450b
--- /dev/null
@@ -0,0 +1,100 @@
+/* $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).
+ * $
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <memory.h>
+
+#include "CredentialsCache.h"
+#include "datastore.h"
+
+
+int main() {
+    cc_generic_list_head_t* head;
+    cc_generic_list_head_t* copy;// = cc_generic_list_copy(head);
+    cc_generic_list_node_t *head_node,*tail,*middle, *node;
+    cc_generic_iterate_t* iterate;
+    int x1 = 1;
+    int x2 = 2;
+    int x3 = 3;
+    int x4 = 4;
+    int x5 = 5;
+    int x6 = 6;
+    cc_int32 code;
+
+    code = cci_generic_list_new(&head);
+    code = cci_generic_list_append(head,&x4,sizeof(x4),NULL);
+    code = cci_generic_list_append(head,&x5,sizeof(x5),NULL);
+    code = cci_generic_list_append(head,&x6,sizeof(x6),&tail);
+
+    code = cci_generic_list_prepend(head,&x3,sizeof(x3),&middle);
+    code = cci_generic_list_prepend(head,&x2,sizeof(x2),NULL);
+    code = cci_generic_list_prepend(head,&x1,sizeof(x1), &head_node);
+
+    code = cci_generic_list_iterator(head, &iterate);
+    while (cci_generic_iterate_has_next(iterate)) {
+        code = cci_generic_iterate_next(iterate, &node);
+        printf("%d\n",*((int *)(node->data)));
+    }
+    printf("----------\n");
+    cci_generic_list_remove_element(head,head_node);
+    cci_generic_list_remove_element(head,middle);
+    cci_generic_list_remove_element(head,tail);
+
+    code = cci_generic_list_iterator(head, &iterate);
+    while (cci_generic_iterate_has_next(iterate)) {
+        code = cci_generic_iterate_next(iterate, &node);
+        printf("%d\n",*((int *)(node->data)));
+    }
+
+    printf("----------\n");
+    code = cci_generic_list_copy(head, &copy);
+    code = cci_generic_list_iterator(copy, &iterate);
+    while (cci_generic_iterate_has_next(iterate)) {
+        code = cci_generic_iterate_next(iterate, &node);
+        printf("%d\n",*((int *)(node->data)));
+    }
+
+    cci_generic_list_destroy(copy);
+    return 0;
+}       
diff --git a/src/lib/ccapi/unit-test/t_msg.c b/src/lib/ccapi/unit-test/t_msg.c
new file mode 100644 (file)
index 0000000..b3a31a8
--- /dev/null
@@ -0,0 +1,88 @@
+/* $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).
+ * $
+ */
+
+#include "CredentialsCache.h"
+#include "msg.h"
+#include "datastore.h"
+
+#include <stdlib.h>
+#include <memory.h>
+#include <stdio.h>
+#include <string.h>
+
+/*testing code*/
+int main() 
+{
+    cc_msg_t* msg;
+    double header = 4.05;
+    char blob1[] = "This is blob one.1234";
+    int blob2 = 2;
+    char blob3[] = "This is blob 3.";
+    int pos1,pos2,pos3;
+    void *flat;
+    char *p;
+    cc_uint32 valid = 0;
+    cc_int32 code;
+
+    code = cci_msg_new(ccmsg_INIT, &msg);
+    code = cci_msg_add_header(msg, &header, sizeof(double));
+    //cc_msg_add_header(msg, NULL, 0);
+    code = cci_msg_add_data_blob(msg, blob1, strlen(blob1) + 1,&pos1);
+    code = cci_msg_add_data_blob(msg, &blob2, sizeof(int),&pos2);
+    code = cci_msg_add_data_blob(msg, blob3, strlen(blob3) + 1,&pos3);
+
+    cci_msg_flatten(msg,&flat);
+
+    printf("%s\n",(char *)((char *)msg->flat + pos1));
+    printf("%d\n",*(int *)((char *)msg->flat + pos2));
+    printf("%s\n",(char *)((char *)msg->flat + pos3));
+
+    cci_msg_verify(msg->flat, msg->flat_len, &valid);
+    printf("%d\n",valid);
+
+    code = cci_msg_unflatten(msg->flat, msg->flat_len, &msg);
+
+    code = cci_msg_retrieve_blob(msg, pos3, strlen(blob3) + 1, &p);
+    printf("%s PPP\n",p);
+    return 0;
+}
diff --git a/src/lib/ccapi/unit-test/t_server.c b/src/lib/ccapi/unit-test/t_server.c
new file mode 100644 (file)
index 0000000..d4d9984
--- /dev/null
@@ -0,0 +1,185 @@
+/* $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).
+ * $
+ */
+
+
+#include "CredentialsCache.h"
+#include "serv_ops.h"
+#include "datastore.h"
+#include "rpc_auth.h"
+#include "msg_headers.h"
+
+#include <stdlib.h>
+
+static int 
+read_flat_msg(char ** flat_msg, cc_uint32 * flat_len)
+{               
+    
+    /* TODO - read length of message */
+    *flat_len = 999;
+
+    *flat_msg = (char *)malloc(*flat_len);
+
+    /* TODO - read message into buffer */
+
+    return 0;
+}
+
+static int
+send_flat_msg(char * flag_msg, cc_uint32 flat_len)
+{
+        
+    return 0;
+}
+
+static int 
+obtain_auth_info(cc_auth_info_t ** auth)
+{
+    if (auth == NULL)
+        return ccErrBadParam;
+
+    *auth = malloc(sizeof(cc_auth_info_t));
+    if (auth == NULL)
+        return ccErrNoMem;
+    
+    memset(*auth,0,sizeof(cc_auth_info_t));
+
+    /* TODO: obtain real auth data from connection */
+
+    return ccNoError;
+}
+
+static int
+destroy_auth_info(cc_auth_info_t * auth)
+{
+    if (auth == NULL)
+        return ccErrBadParam;
+
+    if (auth->info)
+        free(auth->info);
+
+    free(auth);
+
+    return ccNoError;
+}
+
+static int 
+obtain_session_info(cc_session_info_t ** session)
+{
+    if (session == NULL)
+        return ccErrBadParam;
+
+    *session = malloc(sizeof(cc_session_info_t));
+    if (session == NULL)
+        return ccErrNoMem;
+    
+    memset(*session,0,sizeof(cc_session_info_t));
+
+    /* TODO: obtain real session data from connection */
+
+    return ccNoError;
+}
+
+static int
+destroy_session_info(cc_session_info_t * session)
+{
+    if (session == NULL)
+        return ccErrBadParam;
+
+    if (session->info)
+        free(session->info);
+
+    free(session);
+
+    return ccNoError;
+}
+
+
+int
+main(void)
+{
+    cc_msg_t *          msg;
+    cc_msg_t *          resp;
+    cc_auth_info_t    * auth_info;
+    cc_session_info_t * session_info;
+    cc_int32            code;
+
+    if ( cci_serv_initialize() != ccNoError )
+        return 1;
+
+    while ( 1 ) {
+        msg = (cc_msg_t *)malloc(sizeof(cc_msg_t));
+
+        /* read message */
+        if (read_flat_msg(&msg->flat, &msg->flat_len))
+            continue;
+
+        /* unflatten message */
+        code = cci_msg_unflatten(msg->flat, msg->flat_len, &msg); 
+
+        /* obtain auth info */
+        code = obtain_auth_info(&auth_info);
+
+        /* obtain session info */
+        code = obtain_session_info(&session_info);
+
+        /* process message */
+        code = cci_serv_process_msg(msg, auth_info, session_info, &resp);
+
+        /* flatten response */
+        code = cci_msg_flatten(resp, NULL);
+
+        /* send response */
+        code = send_flat_msg(resp->flat, resp->flat_len);
+
+        code = destroy_auth_info(auth_info);
+
+        code = destroy_session_info(session_info);
+
+        /* free message */
+        code = cci_msg_destroy(msg);
+
+        /* free response */
+        code = cci_msg_destroy(resp);
+    }
+    return 0;
+}
diff --git a/src/lib/ccapi/windows/ChangeLog b/src/lib/ccapi/windows/ChangeLog
new file mode 100644 (file)
index 0000000..aaa59da
--- /dev/null
@@ -0,0 +1,4 @@
+2004-10-27   Jeffrey Altman  <jaltman@mit.edu>
+
+ * Initial commit of C CCAPI implementation
+