aboutsummaryrefslogtreecommitdiffstats
path: root/src/ccapi
diff options
context:
space:
mode:
authorCy Schubert <cy@FreeBSD.org>2017-07-07 17:03:42 +0000
committerCy Schubert <cy@FreeBSD.org>2017-07-07 17:03:42 +0000
commit33a9b234e7087f573ef08cd7318c6497ba08b439 (patch)
treed0ea40ad3bf5463a3c55795977c71bcb7d781b4b /src/ccapi
downloadsrc-33a9b234e7087f573ef08cd7318c6497ba08b439.tar.gz
src-33a9b234e7087f573ef08cd7318c6497ba08b439.zip
Import MIT KRB5 1.15.1, which will gracefully replace KTH Heimdal.vendor/krb5/1.15.1
The tarball used in this import is the same tarball used in ports/krb5-115 r435378. Obtained from: http://web.mit.edu/kerberos/dist/ Thanks to: pfg (for all your tireless behind-the-scenes effort)
Notes
Notes: svn path=/vendor-crypto/krb5/dist/; revision=320790 svn path=/vendor-crypto/krb5/1.15.1/; revision=320791; tag=vendor/krb5/1.15.1
Diffstat (limited to 'src/ccapi')
-rw-r--r--src/ccapi/Makefile.in5
-rw-r--r--src/ccapi/common/Makefile.in65
-rw-r--r--src/ccapi/common/cci_array_internal.c312
-rw-r--r--src/ccapi/common/cci_array_internal.h65
-rw-r--r--src/ccapi/common/cci_common.h56
-rw-r--r--src/ccapi/common/cci_cred_union.c1114
-rw-r--r--src/ccapi/common/cci_cred_union.h52
-rw-r--r--src/ccapi/common/cci_debugging.c54
-rw-r--r--src/ccapi/common/cci_debugging.h43
-rw-r--r--src/ccapi/common/cci_identifier.c290
-rw-r--r--src/ccapi/common/cci_identifier.h64
-rw-r--r--src/ccapi/common/cci_message.c213
-rw-r--r--src/ccapi/common/cci_message.h52
-rw-r--r--src/ccapi/common/cci_os_debugging.h34
-rw-r--r--src/ccapi/common/cci_os_identifier.h33
-rw-r--r--src/ccapi/common/cci_types.h102
-rw-r--r--src/ccapi/common/mac/cci_os_debugging.c35
-rw-r--r--src/ccapi/common/mac/cci_os_identifier.c78
-rw-r--r--src/ccapi/common/unix/Makefile.in13
-rw-r--r--src/ccapi/common/win/OldCC/autolock.hxx66
-rw-r--r--src/ccapi/common/win/OldCC/ccutil.cxx187
-rw-r--r--src/ccapi/common/win/OldCC/ccutil.def5
-rw-r--r--src/ccapi/common/win/OldCC/ccutils.c139
-rw-r--r--src/ccapi/common/win/OldCC/ccutils.h48
-rw-r--r--src/ccapi/common/win/OldCC/init.cxx187
-rw-r--r--src/ccapi/common/win/OldCC/init.hxx102
-rw-r--r--src/ccapi/common/win/OldCC/name.h34
-rw-r--r--src/ccapi/common/win/OldCC/opts.cxx188
-rw-r--r--src/ccapi/common/win/OldCC/opts.hxx56
-rw-r--r--src/ccapi/common/win/OldCC/secure.cxx161
-rw-r--r--src/ccapi/common/win/OldCC/secure.hxx60
-rw-r--r--src/ccapi/common/win/OldCC/util.cxx520
-rw-r--r--src/ccapi/common/win/OldCC/util.h88
-rw-r--r--src/ccapi/common/win/cci_os_debugging.c40
-rw-r--r--src/ccapi/common/win/cci_os_identifier.c57
-rw-r--r--src/ccapi/common/win/ccs_reply.Acf31
-rw-r--r--src/ccapi/common/win/ccs_reply.Idl60
-rw-r--r--src/ccapi/common/win/ccs_request.Acf31
-rw-r--r--src/ccapi/common/win/ccs_request.idl58
-rw-r--r--src/ccapi/common/win/tls.c77
-rw-r--r--src/ccapi/common/win/tls.h71
-rw-r--r--src/ccapi/common/win/win-utils.c68
-rw-r--r--src/ccapi/common/win/win-utils.h55
-rw-r--r--src/ccapi/deps1
-rw-r--r--src/ccapi/doc/CCAPI-Windows-Design.html148
-rw-r--r--src/ccapi/lib/Makefile.in61
-rw-r--r--src/ccapi/lib/ccapi.exports1
-rw-r--r--src/ccapi/lib/ccapi_ccache.c793
-rw-r--r--src/ccapi/lib/ccapi_ccache.h105
-rw-r--r--src/ccapi/lib/ccapi_ccache_iterator.c291
-rw-r--r--src/ccapi/lib/ccapi_ccache_iterator.h51
-rw-r--r--src/ccapi/lib/ccapi_context.c831
-rw-r--r--src/ccapi/lib/ccapi_context.h86
-rw-r--r--src/ccapi/lib/ccapi_context_change_time.c199
-rw-r--r--src/ccapi/lib/ccapi_context_change_time.h41
-rw-r--r--src/ccapi/lib/ccapi_credentials.c165
-rw-r--r--src/ccapi/lib/ccapi_credentials.h43
-rw-r--r--src/ccapi/lib/ccapi_credentials_iterator.c246
-rw-r--r--src/ccapi/lib/ccapi_credentials_iterator.h51
-rw-r--r--src/ccapi/lib/ccapi_err.et74
-rw-r--r--src/ccapi/lib/ccapi_ipc.c119
-rw-r--r--src/ccapi/lib/ccapi_ipc.h45
-rw-r--r--src/ccapi/lib/ccapi_os_ipc.h39
-rw-r--r--src/ccapi/lib/ccapi_string.c101
-rw-r--r--src/ccapi/lib/ccapi_string.h36
-rw-r--r--src/ccapi/lib/ccapi_v2.c917
-rw-r--r--src/ccapi/lib/ccapi_v2.exports23
-rw-r--r--src/ccapi/lib/deps86
-rw-r--r--src/ccapi/lib/libkrb5-ccapi.exports1
-rw-r--r--src/ccapi/lib/mac/ccapi_os_ipc.c50
-rw-r--r--src/ccapi/lib/mac/ccapi_vector.c838
-rw-r--r--src/ccapi/lib/mac/ccapi_vector.exports59
-rw-r--r--src/ccapi/lib/mac/ccapi_vector.h227
-rw-r--r--src/ccapi/lib/unix/Makefile.in12
-rw-r--r--src/ccapi/lib/unix/deps1
-rw-r--r--src/ccapi/lib/unix/stubs.c10
-rw-r--r--src/ccapi/lib/win/Makefile.in123
-rw-r--r--src/ccapi/lib/win/OldCC/ccapi.h280
-rw-r--r--src/ccapi/lib/win/OldCC/client.cxx427
-rw-r--r--src/ccapi/lib/win/OldCC/client.h60
-rw-r--r--src/ccapi/lib/win/WINCCAPI.sln20
-rw-r--r--src/ccapi/lib/win/WINCCAPI.vcproj111
-rw-r--r--src/ccapi/lib/win/ccapi_os_ipc.cxx380
-rw-r--r--src/ccapi/lib/win/ccs_reply_proc.c95
-rw-r--r--src/ccapi/lib/win/debug.exports11
-rw-r--r--src/ccapi/lib/win/dllmain.cxx222
-rw-r--r--src/ccapi/lib/win/dllmain.h41
-rw-r--r--src/ccapi/server/Makefile.in59
-rw-r--r--src/ccapi/server/ccs_array.c309
-rw-r--r--src/ccapi/server/ccs_array.h132
-rw-r--r--src/ccapi/server/ccs_cache_collection.c1109
-rw-r--r--src/ccapi/server/ccs_cache_collection.h72
-rw-r--r--src/ccapi/server/ccs_callback.c238
-rw-r--r--src/ccapi/server/ccs_callback.h61
-rw-r--r--src/ccapi/server/ccs_ccache.c1236
-rw-r--r--src/ccapi/server/ccs_ccache.h82
-rw-r--r--src/ccapi/server/ccs_ccache_iterator.c156
-rw-r--r--src/ccapi/server/ccs_ccache_iterator.h37
-rw-r--r--src/ccapi/server/ccs_client.c236
-rw-r--r--src/ccapi/server/ccs_client.h52
-rw-r--r--src/ccapi/server/ccs_common.h47
-rw-r--r--src/ccapi/server/ccs_credentials.c139
-rw-r--r--src/ccapi/server/ccs_credentials.h46
-rw-r--r--src/ccapi/server/ccs_credentials_iterator.c158
-rw-r--r--src/ccapi/server/ccs_credentials_iterator.h37
-rw-r--r--src/ccapi/server/ccs_list.c361
-rw-r--r--src/ccapi/server/ccs_list.h140
-rw-r--r--src/ccapi/server/ccs_list_internal.c675
-rw-r--r--src/ccapi/server/ccs_list_internal.h94
-rw-r--r--src/ccapi/server/ccs_lock.c248
-rw-r--r--src/ccapi/server/ccs_lock.h61
-rw-r--r--src/ccapi/server/ccs_lock_state.c525
-rw-r--r--src/ccapi/server/ccs_lock_state.h51
-rw-r--r--src/ccapi/server/ccs_os_notify.h37
-rw-r--r--src/ccapi/server/ccs_os_pipe.h42
-rw-r--r--src/ccapi/server/ccs_os_server.h40
-rw-r--r--src/ccapi/server/ccs_pipe.c58
-rw-r--r--src/ccapi/server/ccs_pipe.h42
-rw-r--r--src/ccapi/server/ccs_server.c408
-rw-r--r--src/ccapi/server/ccs_server.h53
-rw-r--r--src/ccapi/server/ccs_types.h120
-rw-r--r--src/ccapi/server/deps170
-rw-r--r--src/ccapi/server/mac/CCacheServerInfo.plist38
-rw-r--r--src/ccapi/server/mac/ccs_os_notify.c79
-rw-r--r--src/ccapi/server/mac/ccs_os_pipe.c79
-rw-r--r--src/ccapi/server/mac/ccs_os_server.c97
-rw-r--r--src/ccapi/server/mac/edu.mit.Kerberos.CCacheServer.plist35
-rw-r--r--src/ccapi/server/unix/Makefile.in12
-rw-r--r--src/ccapi/server/unix/deps1
-rw-r--r--src/ccapi/server/win/Makefile.in114
-rw-r--r--src/ccapi/server/win/Server.sln20
-rw-r--r--src/ccapi/server/win/Server.vcproj227
-rw-r--r--src/ccapi/server/win/WorkItem.cpp142
-rw-r--r--src/ccapi/server/win/WorkQueue.cpp74
-rw-r--r--src/ccapi/server/win/WorkQueue.h51
-rw-r--r--src/ccapi/server/win/ccs_os_pipe.c62
-rw-r--r--src/ccapi/server/win/ccs_os_server.cpp971
-rw-r--r--src/ccapi/server/win/ccs_request_proc.c114
-rw-r--r--src/ccapi/server/win/ccs_win_pipe.c164
-rw-r--r--src/ccapi/server/win/ccs_win_pipe.h68
-rw-r--r--src/ccapi/server/win/workitem.h51
-rw-r--r--src/ccapi/test/Makefile.in225
-rw-r--r--src/ccapi/test/Makefile.w3275
-rw-r--r--src/ccapi/test/Pingtest.sln20
-rw-r--r--src/ccapi/test/deps0
-rw-r--r--src/ccapi/test/main.c90
-rw-r--r--src/ccapi/test/pingtest.c116
-rwxr-xr-xsrc/ccapi/test/setlib.pl10
-rw-r--r--src/ccapi/test/simple_lock_test.c91
-rw-r--r--src/ccapi/test/test_cc_ccache_clear_kdc_time_offset.c15
-rw-r--r--src/ccapi/test/test_cc_ccache_compare.c15
-rw-r--r--src/ccapi/test/test_cc_ccache_destroy.c15
-rw-r--r--src/ccapi/test/test_cc_ccache_get_change_time.c15
-rw-r--r--src/ccapi/test/test_cc_ccache_get_credentials_version.c15
-rw-r--r--src/ccapi/test/test_cc_ccache_get_kdc_time_offset.c15
-rw-r--r--src/ccapi/test/test_cc_ccache_get_last_default_time.c15
-rw-r--r--src/ccapi/test/test_cc_ccache_get_name.c15
-rw-r--r--src/ccapi/test/test_cc_ccache_get_principal.c15
-rw-r--r--src/ccapi/test/test_cc_ccache_iterator_next.c15
-rw-r--r--src/ccapi/test/test_cc_ccache_move.c15
-rw-r--r--src/ccapi/test/test_cc_ccache_new_credentials_iterator.c15
-rw-r--r--src/ccapi/test/test_cc_ccache_release.c15
-rw-r--r--src/ccapi/test/test_cc_ccache_remove_credentials.c15
-rw-r--r--src/ccapi/test/test_cc_ccache_set_default.c15
-rw-r--r--src/ccapi/test/test_cc_ccache_set_kdc_time_offset.c15
-rw-r--r--src/ccapi/test/test_cc_ccache_set_principal.c15
-rw-r--r--src/ccapi/test/test_cc_ccache_store_credentials.c15
-rw-r--r--src/ccapi/test/test_cc_close.c14
-rw-r--r--src/ccapi/test/test_cc_context_compare.c15
-rw-r--r--src/ccapi/test/test_cc_context_create_ccache.c15
-rw-r--r--src/ccapi/test/test_cc_context_create_default_ccache.c15
-rw-r--r--src/ccapi/test/test_cc_context_create_new_ccache.c15
-rw-r--r--src/ccapi/test/test_cc_context_get_change_time.c15
-rw-r--r--src/ccapi/test/test_cc_context_get_default_ccache_name.c15
-rw-r--r--src/ccapi/test/test_cc_context_new_ccache_iterator.c15
-rw-r--r--src/ccapi/test/test_cc_context_open_ccache.c15
-rw-r--r--src/ccapi/test/test_cc_context_open_default_ccache.c15
-rw-r--r--src/ccapi/test/test_cc_context_release.c15
-rw-r--r--src/ccapi/test/test_cc_create.c14
-rw-r--r--src/ccapi/test/test_cc_credentials_iterator_next.c16
-rw-r--r--src/ccapi/test/test_cc_destroy.c14
-rw-r--r--src/ccapi/test/test_cc_get_NC_info.c14
-rw-r--r--src/ccapi/test/test_cc_get_change_time.c14
-rw-r--r--src/ccapi/test/test_cc_get_cred_version.c14
-rw-r--r--src/ccapi/test/test_cc_get_name.c14
-rw-r--r--src/ccapi/test/test_cc_get_principal.c14
-rw-r--r--src/ccapi/test/test_cc_initialize.c15
-rw-r--r--src/ccapi/test/test_cc_open.c14
-rw-r--r--src/ccapi/test/test_cc_remove_cred.c14
-rw-r--r--src/ccapi/test/test_cc_seq_fetch_NCs_begin.c14
-rw-r--r--src/ccapi/test/test_cc_seq_fetch_NCs_next.c14
-rw-r--r--src/ccapi/test/test_cc_seq_fetch_creds_begin.c14
-rw-r--r--src/ccapi/test/test_cc_seq_fetch_creds_next.c14
-rw-r--r--src/ccapi/test/test_cc_set_principal.c14
-rw-r--r--src/ccapi/test/test_cc_shutdown.c14
-rw-r--r--src/ccapi/test/test_cc_store.c14
-rw-r--r--src/ccapi/test/test_ccapi.bat43
-rwxr-xr-xsrc/ccapi/test/test_ccapi.sh76
-rw-r--r--src/ccapi/test/test_ccapi_ccache.c2034
-rw-r--r--src/ccapi/test/test_ccapi_ccache.h49
-rw-r--r--src/ccapi/test/test_ccapi_check.c37
-rw-r--r--src/ccapi/test/test_ccapi_check.h43
-rw-r--r--src/ccapi/test/test_ccapi_constants.c66
-rw-r--r--src/ccapi/test/test_ccapi_constants.h6
-rw-r--r--src/ccapi/test/test_ccapi_context.c990
-rw-r--r--src/ccapi/test/test_ccapi_context.h32
-rw-r--r--src/ccapi/test/test_ccapi_globals.c87
-rw-r--r--src/ccapi/test/test_ccapi_globals.h57
-rw-r--r--src/ccapi/test/test_ccapi_iterators.c246
-rw-r--r--src/ccapi/test/test_ccapi_iterators.h12
-rw-r--r--src/ccapi/test/test_ccapi_log.c45
-rw-r--r--src/ccapi/test/test_ccapi_log.h20
-rw-r--r--src/ccapi/test/test_ccapi_util.c142
-rw-r--r--src/ccapi/test/test_ccapi_util.h13
-rw-r--r--src/ccapi/test/test_ccapi_v2.c1839
-rw-r--r--src/ccapi/test/test_ccapi_v2.h73
-rw-r--r--src/ccapi/test/test_constants.c15
217 files changed, 29561 insertions, 0 deletions
diff --git a/src/ccapi/Makefile.in b/src/ccapi/Makefile.in
new file mode 100644
index 000000000000..3f80d87e1aba
--- /dev/null
+++ b/src/ccapi/Makefile.in
@@ -0,0 +1,5 @@
+mydir=ccapi
+BUILDTOP=$(REL)..
+
+SUBDIRS= lib server test
+WINSUBDIRS= lib\win server\win test
diff --git a/src/ccapi/common/Makefile.in b/src/ccapi/common/Makefile.in
new file mode 100644
index 000000000000..b51cfe2bce34
--- /dev/null
+++ b/src/ccapi/common/Makefile.in
@@ -0,0 +1,65 @@
+mydir=ccapi$(S)common
+BUILDTOP=$(REL)..$(S)..
+SUBDIRS=unix
+
+SRCS= \
+ cci_array_internal.c \
+ cci_cred_union.c \
+ cci_debugging.c \
+ cci_identifier.c \
+ cci_message.c \
+ cci_stream.c
+
+STLIBOBJS= \
+ cci_array_internal.o \
+ cci_cred_union.o \
+ cci_debugging.o \
+ cci_identifier.o \
+ cci_message.o \
+ cci_stream.o
+
+OBJS= \
+ $(OUTPRE)cci_array_internal.$(OBJEXT) \
+ $(OUTPRE)cci_cred_union.$(OBJEXT) \
+ $(OUTPRE)cci_debugging.$(OBJEXT) \
+ $(OUTPRE)cci_identifier.$(OBJEXT) \
+ $(OUTPRE)cci_message.$(OBJEXT) \
+ $(OUTPRE)cci_stream.$(OBJEXT)
+
+all-unix: all-libobjs
+clean-unix:: clean-libobjs
+
+@libobj_frag@
+
+# +++ Dependency line eater +++
+#
+# Makefile dependencies follow. This must be the last section in
+# the Makefile.in file
+#
+cci_array_internal.so cci_array_internal.po $(OUTPRE)cci_array_internal.$(OBJEXT): \
+ $(COM_ERR_DEPS) $(top_srcdir)/include/CredentialsCache.h \
+ cci_array_internal.c cci_array_internal.h cci_common.h \
+ cci_cred_union.h cci_debugging.h cci_identifier.h cci_message.h \
+ cci_stream.h cci_types.h
+cci_cred_union.so cci_cred_union.po $(OUTPRE)cci_cred_union.$(OBJEXT): \
+ $(COM_ERR_DEPS) $(top_srcdir)/include/CredentialsCache.h \
+ cci_common.h cci_cred_union.c cci_cred_union.h cci_debugging.h \
+ cci_identifier.h cci_message.h cci_stream.h cci_types.h
+cci_debugging.so cci_debugging.po $(OUTPRE)cci_debugging.$(OBJEXT): \
+ $(COM_ERR_DEPS) $(top_srcdir)/include/CredentialsCache.h \
+ cci_common.h cci_cred_union.h cci_debugging.c cci_debugging.h \
+ cci_identifier.h cci_message.h cci_os_debugging.h cci_stream.h \
+ cci_types.h
+cci_identifier.so cci_identifier.po $(OUTPRE)cci_identifier.$(OBJEXT): \
+ $(COM_ERR_DEPS) $(top_srcdir)/include/CredentialsCache.h \
+ cci_common.h cci_cred_union.h cci_debugging.h cci_identifier.c \
+ cci_identifier.h cci_message.h cci_os_identifier.h \
+ cci_stream.h cci_types.h
+cci_message.so cci_message.po $(OUTPRE)cci_message.$(OBJEXT): \
+ $(COM_ERR_DEPS) $(top_srcdir)/include/CredentialsCache.h \
+ cci_common.h cci_cred_union.h cci_debugging.h cci_identifier.h \
+ cci_message.c cci_message.h cci_stream.h cci_types.h
+cci_stream.so cci_stream.po $(OUTPRE)cci_stream.$(OBJEXT): \
+ $(COM_ERR_DEPS) $(top_srcdir)/include/CredentialsCache.h \
+ cci_common.h cci_cred_union.h cci_debugging.h cci_identifier.h \
+ cci_message.h cci_stream.c cci_stream.h cci_types.h
diff --git a/src/ccapi/common/cci_array_internal.c b/src/ccapi/common/cci_array_internal.c
new file mode 100644
index 000000000000..7a205d7201cc
--- /dev/null
+++ b/src/ccapi/common/cci_array_internal.c
@@ -0,0 +1,312 @@
+/* ccapi/common/cci_array_internal.c */
+/*
+ * Copyright 2006, 2007 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 M.I.T. 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.
+ */
+
+#include "cci_common.h"
+#include "cci_array_internal.h"
+
+#ifdef WIN32
+#include "k5-platform.h"
+#endif
+
+/* ------------------------------------------------------------------------ */
+
+struct cci_array_d {
+ cci_array_object_t *objects;
+ cc_uint64 count;
+ cc_uint64 max_count;
+
+ cci_array_object_release_t object_release;
+};
+
+struct cci_array_d cci_array_initializer = { NULL, 0, 0, NULL };
+
+#define CCI_ARRAY_COUNT_INCREMENT 16
+
+/* ------------------------------------------------------------------------ */
+
+static cc_int32 cci_array_resize (cci_array_t io_array,
+ cc_uint64 in_new_count)
+{
+ cc_int32 err = ccNoError;
+ cc_uint64 new_max_count = 0;
+
+ if (!io_array) { err = cci_check_error (ccErrBadParam); }
+
+ if (!err) {
+ cc_uint64 old_max_count = io_array->max_count;
+ new_max_count = io_array->max_count;
+
+ if (in_new_count > old_max_count) {
+ /* Expand the array */
+ while (in_new_count > new_max_count) {
+ new_max_count += CCI_ARRAY_COUNT_INCREMENT;
+ }
+
+ } else if ((in_new_count + CCI_ARRAY_COUNT_INCREMENT) < old_max_count) {
+ /* Shrink the array, but never drop below CC_ARRAY_COUNT_INCREMENT */
+ while ((in_new_count + CCI_ARRAY_COUNT_INCREMENT) < new_max_count &&
+ (new_max_count > CCI_ARRAY_COUNT_INCREMENT)) {
+ new_max_count -= CCI_ARRAY_COUNT_INCREMENT;
+ }
+ }
+ }
+
+ if (!err && io_array->max_count != new_max_count) {
+ cci_array_object_t *objects = io_array->objects;
+
+ if (!objects) {
+ objects = malloc (new_max_count * sizeof (*objects));
+ } else {
+ objects = realloc (objects, new_max_count * sizeof (*objects));
+ }
+ if (!objects) { err = cci_check_error (ccErrNoMem); }
+
+ if (!err) {
+ io_array->objects = objects;
+ io_array->max_count = new_max_count;
+ }
+ }
+
+ return cci_check_error (err);
+}
+
+#ifdef TARGET_OS_MAC
+#pragma mark -
+#endif
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 cci_array_new (cci_array_t *out_array,
+ cci_array_object_release_t in_array_object_release)
+{
+ cc_int32 err = ccNoError;
+ cci_array_t array = NULL;
+
+ if (!out_array) { err = cci_check_error (ccErrBadParam); }
+
+ if (!err) {
+ array = malloc (sizeof (*array));
+ if (array) {
+ *array = cci_array_initializer;
+ array->object_release = in_array_object_release;
+ } else {
+ err = cci_check_error (ccErrNoMem);
+ }
+ }
+
+ if (!err) {
+ *out_array = array;
+ array = NULL;
+ }
+
+ cci_array_release (array);
+
+ return cci_check_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 cci_array_release (cci_array_t io_array)
+{
+ cc_int32 err = ccNoError;
+
+ if (!err && io_array) {
+ cc_uint64 i;
+
+ if (io_array->object_release) {
+ for (i = 0; i < io_array->count; i++) {
+ io_array->object_release (io_array->objects[i]);
+ }
+ }
+ free (io_array->objects);
+ free (io_array);
+ }
+
+ return err;
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_uint64 cci_array_count (cci_array_t in_array)
+{
+ return in_array ? in_array->count : 0;
+}
+
+/* ------------------------------------------------------------------------ */
+
+cci_array_object_t cci_array_object_at_index (cci_array_t io_array,
+ cc_uint64 in_position)
+{
+ if (io_array && in_position < io_array->count) {
+ return io_array->objects[in_position];
+ } else {
+ if (!io_array) {
+ cci_debug_printf ("%s() got NULL array", __FUNCTION__);
+ } else {
+ cci_debug_printf ("%s() got bad index %lld (count = %lld)", __FUNCTION__,
+ in_position, io_array->count);
+ }
+ return NULL;
+ }
+}
+
+#ifdef TARGET_OS_MAC
+#pragma mark -
+#endif
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 cci_array_insert (cci_array_t io_array,
+ cci_array_object_t in_object,
+ cc_uint64 in_position)
+{
+ cc_int32 err = ccNoError;
+
+ if (!io_array ) { err = cci_check_error (ccErrBadParam); }
+ if (!in_object) { err = cci_check_error (ccErrBadParam); }
+
+ if (!err) {
+ /* Don't try to insert past the end and don't overflow the array */
+ if (in_position > io_array->count || io_array->count == UINT64_MAX) {
+ err = cci_check_error (ccErrBadParam);
+ }
+ }
+
+ if (!err) {
+ err = cci_array_resize (io_array, io_array->count + 1);
+ }
+
+ if (!err) {
+ cc_uint64 move_count = io_array->count - in_position;
+
+ if (move_count > 0) {
+ memmove (&io_array->objects[in_position + 1], &io_array->objects[in_position],
+ move_count * sizeof (*io_array->objects));
+ }
+
+ io_array->objects[in_position] = in_object;
+ io_array->count++;
+ }
+
+ return cci_check_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 cci_array_remove (cci_array_t io_array,
+ cc_uint64 in_position)
+{
+ cc_int32 err = ccNoError;
+
+ if (!io_array) { err = cci_check_error (ccErrBadParam); }
+
+ if (!err && in_position >= io_array->count) {
+ err = cci_check_error (ccErrBadParam);
+ }
+
+ if (!err) {
+ cc_uint64 move_count = io_array->count - in_position - 1;
+ cci_array_object_t object = io_array->objects[in_position];
+
+ if (move_count > 0) {
+ memmove (&io_array->objects[in_position], &io_array->objects[in_position + 1],
+ move_count * sizeof (*io_array->objects));
+ }
+ io_array->count--;
+
+ if (io_array->object_release) { io_array->object_release (object); }
+
+ cci_array_resize (io_array, io_array->count);
+ }
+
+ return cci_check_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 cci_array_move (cci_array_t io_array,
+ cc_uint64 in_position,
+ cc_uint64 in_new_position,
+ cc_uint64 *out_real_new_position)
+{
+ cc_int32 err = ccNoError;
+
+ if (!io_array ) { err = cci_check_error (ccErrBadParam); }
+ if (!out_real_new_position) { err = cci_check_error (ccErrBadParam); }
+
+ if (!err && in_position >= io_array->count) {
+ err = cci_check_error (ccErrBadParam);
+ }
+
+ if (!err && in_new_position > io_array->count) {
+ err = cci_check_error (ccErrBadParam);
+ }
+ if (!err) {
+ cc_uint64 move_from = 0;
+ cc_uint64 move_to = 0;
+ cc_uint64 move_count = 0;
+ cc_uint64 real_new_position = 0;
+
+ if (in_position < in_new_position) {
+ /* shift right, making an empty space so the
+ * actual new position is one less in_new_position */
+ move_from = in_position + 1;
+ move_to = in_position;
+ move_count = in_new_position - in_position - 1;
+ real_new_position = in_new_position - 1;
+
+ } else if (in_position > in_new_position) {
+ /* shift left */
+ move_from = in_new_position;
+ move_to = in_new_position + 1;
+ move_count = in_position - in_new_position;
+ real_new_position = in_new_position;
+
+ } else {
+ real_new_position = in_new_position;
+ }
+
+ if (move_count > 0) {
+ cci_array_object_t object = io_array->objects[in_position];
+
+ memmove (&io_array->objects[move_to], &io_array->objects[move_from],
+ move_count * sizeof (*io_array->objects));
+ io_array->objects[real_new_position] = object;
+ }
+
+ *out_real_new_position = real_new_position;
+ }
+
+ return cci_check_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 cci_array_push_front (cci_array_t io_array,
+ cc_uint64 in_position)
+{
+ cc_uint64 real_new_position = 0;
+ return cci_array_move (io_array, in_position, 0, &real_new_position);
+}
diff --git a/src/ccapi/common/cci_array_internal.h b/src/ccapi/common/cci_array_internal.h
new file mode 100644
index 000000000000..364de7670543
--- /dev/null
+++ b/src/ccapi/common/cci_array_internal.h
@@ -0,0 +1,65 @@
+/* ccapi/common/cci_array_internal.h */
+/*
+ * Copyright 2006 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 M.I.T. 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.
+ */
+
+#ifndef CCI_ARRAY_INTERNAL_H
+#define CCI_ARRAY_INTERNAL_H
+
+#include "cci_types.h"
+
+struct cci_array_object_d;
+typedef struct cci_array_object_d *cci_array_object_t;
+
+typedef cc_int32 (*cci_array_object_release_t) (cci_array_object_t);
+
+struct cci_array_d;
+typedef struct cci_array_d *cci_array_t;
+
+cc_int32 cci_array_new (cci_array_t *out_array,
+ cci_array_object_release_t in_array_object_release);
+
+cc_int32 cci_array_release (cci_array_t io_array);
+
+cc_uint64 cci_array_count (cci_array_t in_array);
+
+cci_array_object_t cci_array_object_at_index (cci_array_t io_array,
+ cc_uint64 in_position);
+
+cc_int32 cci_array_insert (cci_array_t io_array,
+ cci_array_object_t in_object,
+ cc_uint64 in_position);
+
+cc_int32 cci_array_remove (cci_array_t io_array,
+ cc_uint64 in_position);
+
+cc_int32 cci_array_move (cci_array_t io_array,
+ cc_uint64 in_position,
+ cc_uint64 in_new_position,
+ cc_uint64 *out_real_new_position);
+
+cc_int32 cci_array_push_front (cci_array_t io_array,
+ cc_uint64 in_position);
+
+
+#endif /* CCI_ARRAY_INTERNAL_H */
diff --git a/src/ccapi/common/cci_common.h b/src/ccapi/common/cci_common.h
new file mode 100644
index 000000000000..ec9d10b9409d
--- /dev/null
+++ b/src/ccapi/common/cci_common.h
@@ -0,0 +1,56 @@
+/* ccapi/common/cci_common.h */
+/*
+ * Copyright 2006, 2007 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 M.I.T. 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.
+ */
+
+#ifndef CCI_COMMON_H
+#define CCI_COMMON_H
+
+#include <CredentialsCache.h>
+
+#include <sys/types.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <com_err.h>
+
+#if TARGET_OS_MAC
+#include <unistd.h>
+#define VECTOR_FUNCTIONS_INITIALIZER ,NULL
+#else
+#include "win-mac.h"
+#define VECTOR_FUNCTIONS_INITIALIZER
+#endif
+
+#define k_cci_context_initial_ccache_name "Initial default ccache"
+
+#include "cci_cred_union.h"
+#include "cci_debugging.h"
+#include "cci_identifier.h"
+#include "cci_message.h"
+
+#include "k5-ipc_stream.h"
+
+#endif /* CCI_COMMON_H */
diff --git a/src/ccapi/common/cci_cred_union.c b/src/ccapi/common/cci_cred_union.c
new file mode 100644
index 000000000000..4c8981610771
--- /dev/null
+++ b/src/ccapi/common/cci_cred_union.c
@@ -0,0 +1,1114 @@
+/* ccapi/common/cci_cred_union.c */
+/*
+ * Copyright 2006 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 M.I.T. 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.
+ */
+
+#include "cci_common.h"
+
+#ifdef TARGET_OS_MAC
+#pragma mark -
+#endif
+
+/* ------------------------------------------------------------------------ */
+
+static cc_uint32 cci_credentials_v4_release (cc_credentials_v4_t *io_v4creds)
+{
+ cc_int32 err = ccNoError;
+
+ if (!io_v4creds) { err = ccErrBadParam; }
+
+ if (!err) {
+ memset (io_v4creds, 0, sizeof (*io_v4creds));
+ free (io_v4creds);
+ }
+
+ return err;
+}
+
+/* ------------------------------------------------------------------------ */
+
+static cc_uint32 cci_credentials_v4_read (cc_credentials_v4_t **out_v4creds,
+ k5_ipc_stream io_stream)
+{
+ cc_int32 err = ccNoError;
+ cc_credentials_v4_t *v4creds = NULL;
+
+ if (!io_stream ) { err = cci_check_error (ccErrBadParam); }
+ if (!out_v4creds) { err = cci_check_error (ccErrBadParam); }
+
+ if (!err) {
+ v4creds = malloc (sizeof (*v4creds));
+ if (!v4creds) { err = cci_check_error (ccErrNoMem); }
+ }
+
+ if (!err) {
+ err = krb5int_ipc_stream_read_uint32 (io_stream, &v4creds->version);
+ }
+
+ if (!err) {
+ err = krb5int_ipc_stream_read (io_stream, v4creds->principal, cc_v4_name_size);
+ }
+
+ if (!err) {
+ err = krb5int_ipc_stream_read (io_stream, v4creds->principal_instance, cc_v4_instance_size);
+ }
+
+ if (!err) {
+ err = krb5int_ipc_stream_read (io_stream, v4creds->service, cc_v4_name_size);
+ }
+
+ if (!err) {
+ err = krb5int_ipc_stream_read (io_stream, v4creds->service_instance, cc_v4_instance_size);
+ }
+
+ if (!err) {
+ err = krb5int_ipc_stream_read (io_stream, v4creds->realm, cc_v4_realm_size);
+ }
+
+ if (!err) {
+ err = krb5int_ipc_stream_read (io_stream, v4creds->session_key, cc_v4_key_size);
+ }
+
+ if (!err) {
+ err = krb5int_ipc_stream_read_int32 (io_stream, &v4creds->kvno);
+ }
+
+ if (!err) {
+ err = krb5int_ipc_stream_read_int32 (io_stream, &v4creds->string_to_key_type);
+ }
+
+ if (!err) {
+ err = krb5int_ipc_stream_read_time (io_stream, &v4creds->issue_date);
+ }
+
+ if (!err) {
+ err = krb5int_ipc_stream_read_int32 (io_stream, &v4creds->lifetime);
+ }
+
+ if (!err) {
+ err = krb5int_ipc_stream_read_uint32 (io_stream, &v4creds->address);
+ }
+
+ if (!err) {
+ err = krb5int_ipc_stream_read_int32 (io_stream, &v4creds->ticket_size);
+ }
+
+ if (!err) {
+ err = krb5int_ipc_stream_read (io_stream, v4creds->ticket, cc_v4_ticket_size);
+ }
+
+ if (!err) {
+ *out_v4creds = v4creds;
+ v4creds = NULL;
+ }
+
+ free (v4creds);
+
+ return cci_check_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+static cc_uint32 cci_credentials_v4_write (cc_credentials_v4_t *in_v4creds,
+ k5_ipc_stream io_stream)
+{
+ cc_int32 err = ccNoError;
+
+ if (!io_stream ) { err = cci_check_error (ccErrBadParam); }
+ if (!in_v4creds) { err = cci_check_error (ccErrBadParam); }
+
+ if (!err) {
+ err = krb5int_ipc_stream_write_uint32 (io_stream, in_v4creds->version);
+ }
+
+ if (!err) {
+ err = krb5int_ipc_stream_write (io_stream, in_v4creds->principal, cc_v4_name_size);
+ }
+
+ if (!err) {
+ err = krb5int_ipc_stream_write (io_stream, in_v4creds->principal_instance, cc_v4_instance_size);
+ }
+
+ if (!err) {
+ err = krb5int_ipc_stream_write (io_stream, in_v4creds->service, cc_v4_name_size);
+ }
+
+ if (!err) {
+ err = krb5int_ipc_stream_write (io_stream, in_v4creds->service_instance, cc_v4_instance_size);
+ }
+
+ if (!err) {
+ err = krb5int_ipc_stream_write (io_stream, in_v4creds->realm, cc_v4_realm_size);
+ }
+
+ if (!err) {
+ err = krb5int_ipc_stream_write (io_stream, in_v4creds->session_key, cc_v4_key_size);
+ }
+
+ if (!err) {
+ err = krb5int_ipc_stream_write_int32 (io_stream, in_v4creds->kvno);
+ }
+
+ if (!err) {
+ err = krb5int_ipc_stream_write_int32 (io_stream, in_v4creds->string_to_key_type);
+ }
+
+ if (!err) {
+ err = krb5int_ipc_stream_write_time (io_stream, in_v4creds->issue_date);
+ }
+
+ if (!err) {
+ err = krb5int_ipc_stream_write_int32 (io_stream, in_v4creds->lifetime);
+ }
+
+ if (!err) {
+ err = krb5int_ipc_stream_write_uint32 (io_stream, in_v4creds->address);
+ }
+
+ if (!err) {
+ err = krb5int_ipc_stream_write_int32 (io_stream, in_v4creds->ticket_size);
+ }
+
+ if (!err) {
+ err = krb5int_ipc_stream_write (io_stream, in_v4creds->ticket, cc_v4_ticket_size);
+ }
+
+ return cci_check_error (err);
+}
+
+#ifdef TARGET_OS_MAC
+#pragma mark -
+#endif
+
+/* ------------------------------------------------------------------------ */
+
+static cc_uint32 cci_cc_data_contents_release (cc_data *io_ccdata)
+{
+ cc_int32 err = ccNoError;
+
+ if (!io_ccdata && io_ccdata->data) { err = ccErrBadParam; }
+
+ if (!err) {
+ if (io_ccdata->length) {
+ memset (io_ccdata->data, 0, io_ccdata->length);
+ }
+ free (io_ccdata->data);
+ }
+
+ return err;
+}
+
+/* ------------------------------------------------------------------------ */
+
+static cc_uint32 cci_cc_data_release (cc_data *io_ccdata)
+{
+ cc_int32 err = ccNoError;
+
+ if (!io_ccdata) { err = ccErrBadParam; }
+
+ if (!err) {
+ cci_cc_data_contents_release (io_ccdata);
+ free (io_ccdata);
+ }
+
+ return err;
+}
+
+/* ------------------------------------------------------------------------ */
+
+static cc_uint32 cci_cc_data_read (cc_data *io_ccdata,
+ k5_ipc_stream io_stream)
+{
+ cc_int32 err = ccNoError;
+ cc_uint32 type = 0;
+ cc_uint32 length = 0;
+ char *data = NULL;
+
+ if (!io_stream) { err = cci_check_error (ccErrBadParam); }
+ if (!io_ccdata) { err = cci_check_error (ccErrBadParam); }
+
+ if (!err) {
+ err = krb5int_ipc_stream_read_uint32 (io_stream, &type);
+ }
+
+ if (!err) {
+ err = krb5int_ipc_stream_read_uint32 (io_stream, &length);
+ }
+
+ if (!err && length > 0) {
+ data = malloc (length);
+ if (!data) { err = cci_check_error (ccErrNoMem); }
+
+ if (!err) {
+ err = krb5int_ipc_stream_read (io_stream, data, length);
+ }
+ }
+
+ if (!err) {
+ io_ccdata->type = type;
+ io_ccdata->length = length;
+ io_ccdata->data = data;
+ data = NULL;
+ }
+
+ free (data);
+
+ return cci_check_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+static cc_uint32 cci_cc_data_write (cc_data *in_ccdata,
+ k5_ipc_stream io_stream)
+{
+ cc_int32 err = ccNoError;
+
+ if (!io_stream) { err = cci_check_error (ccErrBadParam); }
+ if (!in_ccdata) { err = cci_check_error (ccErrBadParam); }
+
+ if (!err) {
+ err = krb5int_ipc_stream_write_uint32 (io_stream, in_ccdata->type);
+ }
+
+ if (!err) {
+ err = krb5int_ipc_stream_write_uint32 (io_stream, in_ccdata->length);
+ }
+
+ if (!err && in_ccdata->length > 0) {
+ err = krb5int_ipc_stream_write (io_stream, in_ccdata->data, in_ccdata->length);
+ }
+
+ return cci_check_error (err);
+}
+
+#ifdef TARGET_OS_MAC
+#pragma mark -
+#endif
+
+/* ------------------------------------------------------------------------ */
+
+static cc_uint32 cci_cc_data_array_release (cc_data **io_ccdata_array)
+{
+ cc_int32 err = ccNoError;
+
+ if (!io_ccdata_array) { err = ccErrBadParam; }
+
+ if (!err) {
+ cc_uint32 i;
+
+ for (i = 0; io_ccdata_array && io_ccdata_array[i]; i++) {
+ cci_cc_data_release (io_ccdata_array[i]);
+ }
+ free (io_ccdata_array);
+ }
+
+ return err;
+}
+
+/* ------------------------------------------------------------------------ */
+
+static cc_uint32 cci_cc_data_array_read (cc_data ***io_ccdata_array,
+ k5_ipc_stream io_stream)
+{
+ cc_int32 err = ccNoError;
+ cc_uint32 count = 0;
+ cc_data **array = NULL;
+ cc_uint32 i;
+
+ if (!io_stream ) { err = cci_check_error (ccErrBadParam); }
+ if (!io_ccdata_array) { err = cci_check_error (ccErrBadParam); }
+
+ if (!err) {
+ err = krb5int_ipc_stream_read_uint32 (io_stream, &count);
+ }
+
+ if (!err && count > 0) {
+ array = malloc ((count + 1) * sizeof (*array));
+ if (array) {
+ for (i = 0; i <= count; i++) { array[i] = NULL; }
+ } else {
+ err = cci_check_error (ccErrNoMem);
+ }
+ }
+
+ if (!err) {
+ for (i = 0; !err && i < count; i++) {
+ array[i] = malloc (sizeof (cc_data));
+ if (!array[i]) { err = cci_check_error (ccErrNoMem); }
+
+ if (!err) {
+ err = cci_cc_data_read (array[i], io_stream);
+ }
+ }
+ }
+
+ if (!err) {
+ *io_ccdata_array = array;
+ array = NULL;
+ }
+
+ cci_cc_data_array_release (array);
+
+ return cci_check_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+static cc_uint32 cci_cc_data_array_write (cc_data **in_ccdata_array,
+ k5_ipc_stream io_stream)
+{
+ cc_int32 err = ccNoError;
+ cc_uint32 count = 0;
+
+ if (!io_stream) { err = cci_check_error (ccErrBadParam); }
+ /* in_ccdata_array may be NULL */
+
+ if (!err) {
+ for (count = 0; in_ccdata_array && in_ccdata_array[count]; count++);
+
+ err = krb5int_ipc_stream_write_uint32 (io_stream, count);
+ }
+
+ if (!err) {
+ cc_uint32 i;
+
+ for (i = 0; !err && i < count; i++) {
+ err = cci_cc_data_write (in_ccdata_array[i], io_stream);
+ }
+ }
+
+ return cci_check_error (err);
+}
+
+#ifdef TARGET_OS_MAC
+#pragma mark -
+#endif
+
+/* ------------------------------------------------------------------------ */
+
+cc_credentials_v5_t cci_credentials_v5_initializer = {
+ NULL,
+ NULL,
+ { 0, 0, NULL },
+ 0, 0, 0, 0, 0, 0,
+ NULL,
+ { 0, 0, NULL },
+ { 0, 0, NULL },
+ NULL
+};
+
+/* ------------------------------------------------------------------------ */
+
+static cc_uint32 cci_credentials_v5_release (cc_credentials_v5_t *io_v5creds)
+{
+ cc_int32 err = ccNoError;
+
+ if (!io_v5creds) { err = ccErrBadParam; }
+
+ if (!err) {
+ free (io_v5creds->client);
+ free (io_v5creds->server);
+ cci_cc_data_contents_release (&io_v5creds->keyblock);
+ cci_cc_data_array_release (io_v5creds->addresses);
+ cci_cc_data_contents_release (&io_v5creds->ticket);
+ cci_cc_data_contents_release (&io_v5creds->second_ticket);
+ cci_cc_data_array_release (io_v5creds->authdata);
+ free (io_v5creds);
+ }
+
+ return err;
+}
+
+/* ------------------------------------------------------------------------ */
+
+static cc_uint32 cci_credentials_v5_read (cc_credentials_v5_t **out_v5creds,
+ k5_ipc_stream io_stream)
+{
+ cc_int32 err = ccNoError;
+ cc_credentials_v5_t *v5creds = NULL;
+
+ if (!io_stream ) { err = cci_check_error (ccErrBadParam); }
+ if (!out_v5creds) { err = cci_check_error (ccErrBadParam); }
+
+ if (!err) {
+ v5creds = malloc (sizeof (*v5creds));
+ if (v5creds) {
+ *v5creds = cci_credentials_v5_initializer;
+ } else {
+ err = cci_check_error (ccErrNoMem);
+ }
+ }
+
+ if (!err) {
+ err = krb5int_ipc_stream_read_string (io_stream, &v5creds->client);
+ }
+
+ if (!err) {
+ err = krb5int_ipc_stream_read_string (io_stream, &v5creds->server);
+ }
+
+ if (!err) {
+ err = cci_cc_data_read (&v5creds->keyblock, io_stream);
+ }
+
+ if (!err) {
+ err = krb5int_ipc_stream_read_time (io_stream, &v5creds->authtime);
+ }
+
+ if (!err) {
+ err = krb5int_ipc_stream_read_time (io_stream, &v5creds->starttime);
+ }
+
+ if (!err) {
+ err = krb5int_ipc_stream_read_time (io_stream, &v5creds->endtime);
+ }
+
+ if (!err) {
+ err = krb5int_ipc_stream_read_time (io_stream, &v5creds->renew_till);
+ }
+
+ if (!err) {
+ err = krb5int_ipc_stream_read_uint32 (io_stream, &v5creds->is_skey);
+ }
+
+ if (!err) {
+ err = krb5int_ipc_stream_read_uint32 (io_stream, &v5creds->ticket_flags);
+ }
+
+ if (!err) {
+ err = cci_cc_data_array_read (&v5creds->addresses, io_stream);
+ }
+
+ if (!err) {
+ err = cci_cc_data_read (&v5creds->ticket, io_stream);
+ }
+
+ if (!err) {
+ err = cci_cc_data_read (&v5creds->second_ticket, io_stream);
+ }
+
+ if (!err) {
+ err = cci_cc_data_array_read (&v5creds->authdata, io_stream);
+ }
+
+ if (!err) {
+ *out_v5creds = v5creds;
+ v5creds = NULL;
+ }
+
+ cci_credentials_v5_release (v5creds);
+
+ return cci_check_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+static cc_uint32 cci_credentials_v5_write (cc_credentials_v5_t *in_v5creds,
+ k5_ipc_stream io_stream)
+{
+ cc_int32 err = ccNoError;
+
+ if (!io_stream ) { err = cci_check_error (ccErrBadParam); }
+ if (!in_v5creds) { err = cci_check_error (ccErrBadParam); }
+
+ if (!err) {
+ err = krb5int_ipc_stream_write_string (io_stream, in_v5creds->client);
+ }
+
+ if (!err) {
+ err = krb5int_ipc_stream_write_string (io_stream, in_v5creds->server);
+ }
+
+ if (!err) {
+ err = cci_cc_data_write (&in_v5creds->keyblock, io_stream);
+ }
+
+ if (!err) {
+ err = krb5int_ipc_stream_write_time (io_stream, in_v5creds->authtime);
+ }
+
+ if (!err) {
+ err = krb5int_ipc_stream_write_time (io_stream, in_v5creds->starttime);
+ }
+
+ if (!err) {
+ err = krb5int_ipc_stream_write_time (io_stream, in_v5creds->endtime);
+ }
+
+ if (!err) {
+ err = krb5int_ipc_stream_write_time (io_stream, in_v5creds->renew_till);
+ }
+
+ if (!err) {
+ err = krb5int_ipc_stream_write_uint32 (io_stream, in_v5creds->is_skey);
+ }
+
+ if (!err) {
+ err = krb5int_ipc_stream_write_uint32 (io_stream, in_v5creds->ticket_flags);
+ }
+
+ if (!err) {
+ err = cci_cc_data_array_write (in_v5creds->addresses, io_stream);
+ }
+
+ if (!err) {
+ err = cci_cc_data_write (&in_v5creds->ticket, io_stream);
+ }
+
+ if (!err) {
+ err = cci_cc_data_write (&in_v5creds->second_ticket, io_stream);
+ }
+
+ if (!err) {
+ err = cci_cc_data_array_write (in_v5creds->authdata, io_stream);
+ }
+
+
+ return cci_check_error (err);
+}
+
+#ifdef TARGET_OS_MAC
+#pragma mark -
+#endif
+
+/* ------------------------------------------------------------------------ */
+
+cc_uint32 cci_credentials_union_release (cc_credentials_union *io_cred_union)
+{
+ cc_int32 err = ccNoError;
+
+ if (!io_cred_union) { err = ccErrBadParam; }
+
+ if (!err) {
+ if (io_cred_union->version == cc_credentials_v4) {
+ cci_credentials_v4_release (io_cred_union->credentials.credentials_v4);
+ } else if (io_cred_union->version == cc_credentials_v5) {
+ cci_credentials_v5_release (io_cred_union->credentials.credentials_v5);
+ }
+ free (io_cred_union);
+ }
+
+ return err;
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_uint32 cci_credentials_union_read (cc_credentials_union **out_credentials_union,
+ k5_ipc_stream io_stream)
+{
+ cc_int32 err = ccNoError;
+ cc_credentials_union *credentials_union = NULL;
+
+ if (!io_stream ) { err = cci_check_error (ccErrBadParam); }
+ if (!out_credentials_union) { err = cci_check_error (ccErrBadParam); }
+
+ if (!err) {
+ credentials_union = calloc (1, sizeof (*credentials_union));
+ if (!credentials_union) { err = cci_check_error (ccErrNoMem); }
+ }
+
+ if (!err) {
+ err = krb5int_ipc_stream_read_uint32 (io_stream, &credentials_union->version);
+ }
+
+ if (!err) {
+ if (credentials_union->version == cc_credentials_v4) {
+ err = cci_credentials_v4_read (&credentials_union->credentials.credentials_v4,
+ io_stream);
+
+ } else if (credentials_union->version == cc_credentials_v5) {
+ err = cci_credentials_v5_read (&credentials_union->credentials.credentials_v5,
+ io_stream);
+
+
+ } else {
+ err = ccErrBadCredentialsVersion;
+ }
+ }
+
+ if (!err) {
+ *out_credentials_union = credentials_union;
+ credentials_union = NULL;
+ }
+
+ if (credentials_union) { cci_credentials_union_release (credentials_union); }
+
+ return cci_check_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_uint32 cci_credentials_union_write (const cc_credentials_union *in_credentials_union,
+ k5_ipc_stream io_stream)
+{
+ cc_int32 err = ccNoError;
+
+ if (!io_stream ) { err = cci_check_error (ccErrBadParam); }
+ if (!in_credentials_union) { err = cci_check_error (ccErrBadParam); }
+
+ if (!err) {
+ err = krb5int_ipc_stream_write_uint32 (io_stream, in_credentials_union->version);
+ }
+
+ if (!err) {
+ if (in_credentials_union->version == cc_credentials_v4) {
+ err = cci_credentials_v4_write (in_credentials_union->credentials.credentials_v4,
+ io_stream);
+
+ } else if (in_credentials_union->version == cc_credentials_v5) {
+ err = cci_credentials_v5_write (in_credentials_union->credentials.credentials_v5,
+ io_stream);
+
+ } else {
+ err = ccErrBadCredentialsVersion;
+ }
+ }
+
+ return cci_check_error (err);
+}
+
+#ifdef TARGET_OS_MAC
+#pragma mark -
+#pragma mark -- CCAPI v2 Compat --
+#endif
+
+/* ------------------------------------------------------------------------ */
+
+cc_credentials_v5_compat cci_credentials_v5_compat_initializer = {
+ NULL,
+ NULL,
+ { 0, 0, NULL },
+ 0, 0, 0, 0, 0, 0,
+ NULL,
+ { 0, 0, NULL },
+ { 0, 0, NULL },
+ NULL
+};
+
+/* ------------------------------------------------------------------------ */
+
+cc_uint32 cci_cred_union_release (cred_union *io_cred_union)
+{
+ cc_int32 err = ccNoError;
+
+ if (!io_cred_union) { err = ccErrBadParam; }
+
+ if (!err) {
+ if (io_cred_union->cred_type == CC_CRED_V4) {
+ memset (io_cred_union->cred.pV4Cred, 0, sizeof (cc_credentials_v4_compat));
+ free (io_cred_union->cred.pV4Cred);
+
+ } else if (io_cred_union->cred_type == CC_CRED_V5) {
+ free (io_cred_union->cred.pV5Cred->client);
+ free (io_cred_union->cred.pV5Cred->server);
+ cci_cc_data_contents_release (&io_cred_union->cred.pV5Cred->keyblock);
+ cci_cc_data_array_release (io_cred_union->cred.pV5Cred->addresses);
+ cci_cc_data_contents_release (&io_cred_union->cred.pV5Cred->ticket);
+ cci_cc_data_contents_release (&io_cred_union->cred.pV5Cred->second_ticket);
+ cci_cc_data_array_release (io_cred_union->cred.pV5Cred->authdata);
+ free (io_cred_union->cred.pV5Cred);
+ }
+ free (io_cred_union);
+ }
+
+ return err;
+}
+
+/* ------------------------------------------------------------------------ */
+
+static cc_uint32 cci_cc_data_copy_contents (cc_data *io_ccdata,
+ cc_data *in_ccdata)
+{
+ cc_int32 err = ccNoError;
+ char *data = NULL;
+
+ if (!io_ccdata) { err = cci_check_error (ccErrBadParam); }
+ if (!in_ccdata) { err = cci_check_error (ccErrBadParam); }
+
+ if (!err && in_ccdata->length > 0) {
+ data = malloc (in_ccdata->length);
+ if (data) {
+ memcpy (data, in_ccdata->data, in_ccdata->length);
+ } else {
+ err = cci_check_error (ccErrNoMem);
+ }
+ }
+
+ if (!err) {
+ io_ccdata->type = in_ccdata->type;
+ io_ccdata->length = in_ccdata->length;
+ io_ccdata->data = data;
+ data = NULL;
+ }
+
+ free (data);
+
+ return cci_check_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+static cc_uint32 cci_cc_data_array_copy (cc_data ***io_ccdata_array,
+ cc_data **in_ccdata_array)
+{
+ cc_int32 err = ccNoError;
+ cc_uint32 count = 0;
+ cc_data **array = NULL;
+ cc_uint32 i;
+
+ if (!io_ccdata_array) { err = cci_check_error (ccErrBadParam); }
+
+ if (!err) {
+ for (count = 0; in_ccdata_array && in_ccdata_array[count]; count++);
+ }
+
+ if (!err && count > 0) {
+ array = malloc ((count + 1) * sizeof (*array));
+ if (array) {
+ for (i = 0; i <= count; i++) { array[i] = NULL; }
+ } else {
+ err = cci_check_error (ccErrNoMem);
+ }
+ }
+
+ if (!err) {
+ for (i = 0; !err && i < count; i++) {
+ array[i] = malloc (sizeof (cc_data));
+ if (!array[i]) { err = cci_check_error (ccErrNoMem); }
+
+ if (!err) {
+ err = cci_cc_data_copy_contents (array[i], in_ccdata_array[i]);
+ }
+ }
+ }
+
+ if (!err) {
+ *io_ccdata_array = array;
+ array = NULL;
+ }
+
+ cci_cc_data_array_release (array);
+
+ return cci_check_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_uint32 cci_credentials_union_to_cred_union (const cc_credentials_union *in_credentials_union,
+ cred_union **out_cred_union)
+{
+ cc_int32 err = ccNoError;
+ cred_union *compat_cred_union = NULL;
+
+ if (!in_credentials_union) { err = cci_check_error (ccErrBadParam); }
+ if (!out_cred_union ) { err = cci_check_error (ccErrBadParam); }
+
+ if (!err) {
+ compat_cred_union = calloc (1, sizeof (*compat_cred_union));
+ if (!compat_cred_union) { err = cci_check_error (ccErrNoMem); }
+ }
+
+ if (!err) {
+ if (in_credentials_union->version == cc_credentials_v4) {
+ cc_credentials_v4_compat *compat_v4creds = NULL;
+
+ compat_v4creds = malloc (sizeof (*compat_v4creds));
+ if (!compat_v4creds) { err = cci_check_error (ccErrNoMem); }
+
+ if (!err) {
+ cc_credentials_v4_t *v4creds = in_credentials_union->credentials.credentials_v4;
+
+ compat_cred_union->cred_type = CC_CRED_V4;
+ compat_cred_union->cred.pV4Cred = compat_v4creds;
+
+ compat_v4creds->kversion = v4creds->version;
+ strncpy (compat_v4creds->principal, v4creds->principal, KRB_NAME_SZ+1);
+ strncpy (compat_v4creds->principal_instance, v4creds->principal_instance, KRB_INSTANCE_SZ+1);
+ strncpy (compat_v4creds->service, v4creds->service, KRB_NAME_SZ+1);
+ strncpy (compat_v4creds->service_instance, v4creds->service_instance, KRB_INSTANCE_SZ+1);
+ strncpy (compat_v4creds->realm, v4creds->realm, KRB_REALM_SZ+1);
+ memcpy (compat_v4creds->session_key, v4creds->session_key, 8);
+ compat_v4creds->kvno = v4creds->kvno;
+ compat_v4creds->str_to_key = v4creds->string_to_key_type;
+ compat_v4creds->issue_date = v4creds->issue_date;
+ compat_v4creds->lifetime = v4creds->lifetime;
+ compat_v4creds->address = v4creds->address;
+ compat_v4creds->ticket_sz = v4creds->ticket_size;
+ memcpy (compat_v4creds->ticket, v4creds->ticket, MAX_V4_CRED_LEN);
+ compat_v4creds->oops = 0;
+ }
+
+ } else if (in_credentials_union->version == cc_credentials_v5) {
+ cc_credentials_v5_t *v5creds = in_credentials_union->credentials.credentials_v5;
+ cc_credentials_v5_compat *compat_v5creds = NULL;
+
+ compat_v5creds = malloc (sizeof (*compat_v5creds));
+ if (compat_v5creds) {
+ *compat_v5creds = cci_credentials_v5_compat_initializer;
+ } else {
+ err = cci_check_error (ccErrNoMem);
+ }
+
+ if (!err) {
+ if (!v5creds->client) {
+ err = cci_check_error (ccErrBadParam);
+ } else {
+ compat_v5creds->client = strdup (v5creds->client);
+ if (!compat_v5creds->client) { err = cci_check_error (ccErrNoMem); }
+ }
+ }
+
+ if (!err) {
+ if (!v5creds->server) {
+ err = cci_check_error (ccErrBadParam);
+ } else {
+ compat_v5creds->server = strdup (v5creds->server);
+ if (!compat_v5creds->server) { err = cci_check_error (ccErrNoMem); }
+ }
+ }
+
+ if (!err) {
+ err = cci_cc_data_copy_contents (&compat_v5creds->keyblock, &v5creds->keyblock);
+ }
+
+ if (!err) {
+ err = cci_cc_data_array_copy (&compat_v5creds->addresses, v5creds->addresses);
+ }
+
+ if (!err) {
+ err = cci_cc_data_copy_contents (&compat_v5creds->ticket, &v5creds->ticket);
+ }
+
+ if (!err) {
+ err = cci_cc_data_copy_contents (&compat_v5creds->second_ticket, &v5creds->second_ticket);
+ }
+
+ if (!err) {
+ err = cci_cc_data_array_copy (&compat_v5creds->authdata, v5creds->authdata);
+ }
+
+ if (!err) {
+ compat_cred_union->cred_type = CC_CRED_V5;
+ compat_cred_union->cred.pV5Cred = compat_v5creds;
+
+ compat_v5creds->keyblock = v5creds->keyblock;
+ compat_v5creds->authtime = v5creds->authtime;
+ compat_v5creds->starttime = v5creds->starttime;
+ compat_v5creds->endtime = v5creds->endtime;
+ compat_v5creds->renew_till = v5creds->renew_till;
+ compat_v5creds->is_skey = v5creds->is_skey;
+ compat_v5creds->ticket_flags = v5creds->ticket_flags;
+ }
+ } else {
+ err = cci_check_error (ccErrBadCredentialsVersion);
+ }
+ }
+
+ if (!err) {
+ *out_cred_union = compat_cred_union;
+ compat_cred_union = NULL;
+ }
+
+ if (compat_cred_union) { cci_cred_union_release (compat_cred_union); }
+
+ return cci_check_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_uint32 cci_cred_union_to_credentials_union (const cred_union *in_cred_union,
+ cc_credentials_union **out_credentials_union)
+{
+ cc_int32 err = ccNoError;
+ cc_credentials_union *creds_union = NULL;
+
+ if (!in_cred_union ) { err = cci_check_error (ccErrBadParam); }
+ if (!out_credentials_union) { err = cci_check_error (ccErrBadParam); }
+
+ if (!err) {
+ creds_union = calloc (1, sizeof (*creds_union));
+ if (!creds_union) { err = cci_check_error (ccErrNoMem); }
+ }
+
+ if (!err) {
+ if (in_cred_union->cred_type == CC_CRED_V4) {
+ cc_credentials_v4_compat *compat_v4creds = in_cred_union->cred.pV4Cred;
+ cc_credentials_v4_t *v4creds = NULL;
+
+ if (!err) {
+ v4creds = malloc (sizeof (*v4creds));
+ if (!v4creds) { err = cci_check_error (ccErrNoMem); }
+ }
+
+ if (!err) {
+ creds_union->version = cc_credentials_v4;
+ creds_union->credentials.credentials_v4 = v4creds;
+
+ v4creds->version = compat_v4creds->kversion;
+ strncpy (v4creds->principal, compat_v4creds->principal, KRB_NAME_SZ);
+ strncpy (v4creds->principal_instance, compat_v4creds->principal_instance, KRB_INSTANCE_SZ);
+ strncpy (v4creds->service, compat_v4creds->service, KRB_NAME_SZ);
+ strncpy (v4creds->service_instance, compat_v4creds->service_instance, KRB_INSTANCE_SZ);
+ strncpy (v4creds->realm, compat_v4creds->realm, KRB_REALM_SZ);
+ memcpy (v4creds->session_key, compat_v4creds->session_key, 8);
+ v4creds->kvno = compat_v4creds->kvno;
+ v4creds->string_to_key_type = compat_v4creds->str_to_key;
+ v4creds->issue_date = compat_v4creds->issue_date;
+ v4creds->lifetime = compat_v4creds->lifetime;
+ v4creds->address = compat_v4creds->address;
+ v4creds->ticket_size = compat_v4creds->ticket_sz;
+ memcpy (v4creds->ticket, compat_v4creds->ticket, MAX_V4_CRED_LEN);
+ }
+
+ } else if (in_cred_union->cred_type == CC_CRED_V5) {
+ cc_credentials_v5_compat *compat_v5creds = in_cred_union->cred.pV5Cred;
+ cc_credentials_v5_t *v5creds = NULL;
+
+ if (!err) {
+ v5creds = malloc (sizeof (*v5creds));
+ if (v5creds) {
+ *v5creds = cci_credentials_v5_initializer;
+ } else {
+ err = cci_check_error (ccErrNoMem);
+ }
+ }
+
+ if (!err) {
+ if (!compat_v5creds->client) {
+ err = cci_check_error (ccErrBadParam);
+ } else {
+ v5creds->client = strdup (compat_v5creds->client);
+ if (!v5creds->client) { err = cci_check_error (ccErrNoMem); }
+ }
+ }
+
+ if (!err) {
+ if (!compat_v5creds->server) {
+ err = cci_check_error (ccErrBadParam);
+ } else {
+ v5creds->server = strdup (compat_v5creds->server);
+ if (!v5creds->server) { err = cci_check_error (ccErrNoMem); }
+ }
+ }
+
+ if (!err) {
+ err = cci_cc_data_copy_contents (&v5creds->keyblock, &compat_v5creds->keyblock);
+ }
+
+ if (!err) {
+ err = cci_cc_data_array_copy (&v5creds->addresses, compat_v5creds->addresses);
+ }
+
+ if (!err) {
+ err = cci_cc_data_copy_contents (&v5creds->ticket, &compat_v5creds->ticket);
+ }
+
+ if (!err) {
+ err = cci_cc_data_copy_contents (&v5creds->second_ticket, &compat_v5creds->second_ticket);
+ }
+
+ if (!err) {
+ err = cci_cc_data_array_copy (&v5creds->authdata, compat_v5creds->authdata);
+ }
+
+ if (!err) {
+ creds_union->version = cc_credentials_v5;
+ creds_union->credentials.credentials_v5 = v5creds;
+
+ v5creds->authtime = compat_v5creds->authtime;
+ v5creds->starttime = compat_v5creds->starttime;
+ v5creds->endtime = compat_v5creds->endtime;
+ v5creds->renew_till = compat_v5creds->renew_till;
+ v5creds->is_skey = compat_v5creds->is_skey;
+ v5creds->ticket_flags = compat_v5creds->ticket_flags;
+ }
+
+ } else {
+ err = cci_check_error (ccErrBadCredentialsVersion);
+ }
+ }
+
+ if (!err) {
+ *out_credentials_union = creds_union;
+ creds_union = NULL;
+ }
+
+ if (creds_union) { cci_credentials_union_release (creds_union); }
+
+ return cci_check_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_uint32 cci_cred_union_compare_to_credentials_union (const cred_union *in_cred_union_compat,
+ const cc_credentials_union *in_credentials_union,
+ cc_uint32 *out_equal)
+{
+ cc_int32 err = ccNoError;
+ cc_uint32 equal = 0;
+
+ if (!in_cred_union_compat) { err = cci_check_error (ccErrBadParam); }
+ if (!in_credentials_union) { err = cci_check_error (ccErrBadParam); }
+ if (!out_equal ) { err = cci_check_error (ccErrBadParam); }
+
+ if (!err) {
+ if (in_cred_union_compat->cred_type == CC_CRED_V4 &&
+ in_credentials_union->version == cc_credentials_v4) {
+ cc_credentials_v4_compat *old_creds_v4 = in_cred_union_compat->cred.pV4Cred;
+ cc_credentials_v4_t *new_creds_v4 = in_credentials_union->credentials.credentials_v4;
+
+ if (old_creds_v4 && new_creds_v4 &&
+ !strcmp (old_creds_v4->principal,
+ new_creds_v4->principal) &&
+ !strcmp (old_creds_v4->principal_instance,
+ new_creds_v4->principal_instance) &&
+ !strcmp (old_creds_v4->service,
+ new_creds_v4->service) &&
+ !strcmp (old_creds_v4->service_instance,
+ new_creds_v4->service_instance) &&
+ !strcmp (old_creds_v4->realm, new_creds_v4->realm) &&
+ (old_creds_v4->issue_date == (long) new_creds_v4->issue_date)) {
+ equal = 1;
+ }
+
+ } else if (in_cred_union_compat->cred_type == CC_CRED_V5 &&
+ in_credentials_union->version == cc_credentials_v5) {
+ cc_credentials_v5_compat *old_creds_v5 = in_cred_union_compat->cred.pV5Cred;
+ cc_credentials_v5_t *new_creds_v5 = in_credentials_union->credentials.credentials_v5;
+
+ /* Really should use krb5_parse_name and krb5_principal_compare */
+ if (old_creds_v5 && new_creds_v5 &&
+ !strcmp (old_creds_v5->client, new_creds_v5->client) &&
+ !strcmp (old_creds_v5->server, new_creds_v5->server) &&
+ (old_creds_v5->starttime == new_creds_v5->starttime)) {
+ equal = 1;
+ }
+ }
+ }
+
+ if (!err) {
+ *out_equal = equal;
+ }
+
+ return cci_check_error (err);
+}
diff --git a/src/ccapi/common/cci_cred_union.h b/src/ccapi/common/cci_cred_union.h
new file mode 100644
index 000000000000..2e40476caa52
--- /dev/null
+++ b/src/ccapi/common/cci_cred_union.h
@@ -0,0 +1,52 @@
+/* ccapi/common/cci_cred_union.h */
+/*
+ * Copyright 2006 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 M.I.T. 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.
+ */
+
+#ifndef CCI_CRED_UNION_H
+#define CCI_CRED_UNION_H
+
+#include "cci_types.h"
+#include <CredentialsCache2.h>
+
+cc_uint32 cci_credentials_union_release (cc_credentials_union *io_credentials);
+
+cc_uint32 cci_credentials_union_read (cc_credentials_union **out_credentials_union,
+ k5_ipc_stream io_stream);
+
+cc_uint32 cci_credentials_union_write (const cc_credentials_union *in_credentials_union,
+ k5_ipc_stream io_stream);
+
+cc_uint32 cci_cred_union_release (cred_union *io_cred_union);
+
+cc_uint32 cci_credentials_union_to_cred_union (const cc_credentials_union *in_credentials_union,
+ cred_union **out_cred_union);
+
+cc_uint32 cci_cred_union_to_credentials_union (const cred_union *in_cred_union,
+ cc_credentials_union **out_credentials_union);
+
+cc_uint32 cci_cred_union_compare_to_credentials_union (const cred_union *in_cred_union_compat,
+ const cc_credentials_union *in_credentials_union,
+ cc_uint32 *out_equal);
+
+#endif /* CCI_CRED_UNION_H */
diff --git a/src/ccapi/common/cci_debugging.c b/src/ccapi/common/cci_debugging.c
new file mode 100644
index 000000000000..42d8a7726281
--- /dev/null
+++ b/src/ccapi/common/cci_debugging.c
@@ -0,0 +1,54 @@
+/* ccapi/common/cci_debugging.c */
+/*
+ * Copyright 2006 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 M.I.T. 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.
+ */
+
+#include "cci_common.h"
+#include "cci_os_debugging.h"
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 _cci_check_error (cc_int32 in_error,
+ const char *in_function,
+ const char *in_file,
+ int in_line)
+{
+ /* Do not log for flow control errors or when there is no error at all */
+ if (in_error != ccNoError && in_error != ccIteratorEnd) {
+ cci_debug_printf ("%s() got %d at %s: %d", in_function,
+ in_error, in_file, in_line);
+ }
+
+ return in_error;
+}
+
+/* ------------------------------------------------------------------------ */
+
+void cci_debug_printf (const char *in_format, ...)
+{
+ va_list args;
+
+ va_start (args, in_format);
+ cci_os_debug_vprintf (in_format, args);
+ va_end (args);
+}
diff --git a/src/ccapi/common/cci_debugging.h b/src/ccapi/common/cci_debugging.h
new file mode 100644
index 000000000000..64413e2348ed
--- /dev/null
+++ b/src/ccapi/common/cci_debugging.h
@@ -0,0 +1,43 @@
+/* ccapi/common/cci_debugging.h */
+/*
+ * Copyright 2006 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 M.I.T. 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.
+ */
+
+#ifndef CCI_DEBUGGING_H
+#define CCI_DEBUGGING_H
+
+#include "cci_types.h"
+
+cc_int32 _cci_check_error (cc_int32 in_err,
+ const char *in_function,
+ const char *in_file,
+ int in_line);
+#define cci_check_error(err) _cci_check_error(err, __FUNCTION__, __FILE__, __LINE__)
+
+void cci_debug_printf (const char *in_format, ...)
+#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 7)
+__attribute__ ((__format__ (__printf__, 1, 2)))
+#endif
+;
+
+#endif /* CCI_DEBUGGING_H */
diff --git a/src/ccapi/common/cci_identifier.c b/src/ccapi/common/cci_identifier.c
new file mode 100644
index 000000000000..a672c18f0de6
--- /dev/null
+++ b/src/ccapi/common/cci_identifier.c
@@ -0,0 +1,290 @@
+/* ccapi/common/cci_identifier.c */
+/*
+ * Copyright 2006, 2007 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 M.I.T. 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.
+ */
+
+#include "cci_common.h"
+#include "cci_os_identifier.h"
+
+struct cci_identifier_d {
+ cci_uuid_string_t server_id;
+ cci_uuid_string_t object_id;
+};
+
+struct cci_identifier_d cci_identifier_initializer = { NULL, NULL };
+
+#define cci_uninitialized_server_id "NEEDS_SYNC"
+#define cci_uninitialized_object_id "NEEDS_SYNC"
+
+struct cci_identifier_d cci_identifier_uninitialized_d = {
+ cci_uninitialized_server_id,
+ cci_uninitialized_object_id
+};
+const cci_identifier_t cci_identifier_uninitialized = &cci_identifier_uninitialized_d;
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 cci_identifier_new_uuid (cci_uuid_string_t *out_uuid_string)
+{
+ return cci_os_identifier_new_uuid (out_uuid_string);
+}
+
+/* ------------------------------------------------------------------------ */
+
+static cc_int32 cci_identifier_alloc (cci_identifier_t *out_identifier,
+ cci_uuid_string_t in_server_id,
+ cci_uuid_string_t in_object_id)
+{
+ cc_int32 err = ccNoError;
+ cci_identifier_t identifier = NULL;
+
+ if (!out_identifier) { err = cci_check_error (ccErrBadParam); }
+ if (!in_server_id ) { err = cci_check_error (ccErrBadParam); }
+ if (!in_object_id ) { err = cci_check_error (ccErrBadParam); }
+
+ if (!err) {
+ identifier = malloc (sizeof (*identifier));
+ if (identifier) {
+ *identifier = cci_identifier_initializer;
+ } else {
+ err = cci_check_error (ccErrNoMem);
+ }
+ }
+
+ if (!err) {
+ identifier->server_id = strdup (in_server_id);
+ if (!identifier->server_id) { err = cci_check_error (ccErrNoMem); }
+ }
+
+ if (!err) {
+ identifier->object_id = strdup (in_object_id);
+ if (!identifier->object_id) { err = cci_check_error (ccErrNoMem); }
+ }
+
+ if (!err) {
+ *out_identifier = identifier;
+ identifier = NULL; /* take ownership */
+ }
+
+ cci_identifier_release (identifier);
+
+ return cci_check_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 cci_identifier_new (cci_identifier_t *out_identifier,
+ cci_uuid_string_t in_server_id)
+{
+ cc_int32 err = ccNoError;
+ cci_uuid_string_t object_id = NULL;
+
+ if (!out_identifier) { err = cci_check_error (ccErrBadParam); }
+ if (!in_server_id ) { err = cci_check_error (ccErrBadParam); }
+
+ if (!err) {
+ err = cci_os_identifier_new_uuid (&object_id);
+ }
+
+ if (!err) {
+ err = cci_identifier_alloc (out_identifier, in_server_id, object_id);
+ }
+
+ if (object_id) { free (object_id); }
+
+ return cci_check_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 cci_identifier_copy (cci_identifier_t *out_identifier,
+ cci_identifier_t in_identifier)
+{
+ cc_int32 err = ccNoError;
+
+ if (!out_identifier) { err = cci_check_error (ccErrBadParam); }
+ if (!in_identifier ) { err = cci_check_error (ccErrBadParam); }
+
+ if (!err) {
+ err = cci_identifier_alloc (out_identifier,
+ in_identifier->server_id,
+ in_identifier->object_id);
+ }
+
+ return cci_check_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 cci_identifier_release (cci_identifier_t in_identifier)
+{
+ cc_int32 err = ccNoError;
+
+ /* Do not free the static "uninitialized" identifier */
+ if (!err && in_identifier && in_identifier != cci_identifier_uninitialized) {
+ free (in_identifier->server_id);
+ free (in_identifier->object_id);
+ free (in_identifier);
+ }
+
+ return cci_check_error (err);
+}
+
+#ifdef TARGET_OS_MAC
+#pragma mark -
+#endif
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 cci_identifier_compare (cci_identifier_t in_identifier,
+ cci_identifier_t in_compare_to_identifier,
+ cc_uint32 *out_equal)
+{
+ cc_int32 err = ccNoError;
+
+ if (!in_identifier ) { err = cci_check_error (ccErrBadParam); }
+ if (!in_compare_to_identifier) { err = cci_check_error (ccErrBadParam); }
+ if (!out_equal ) { err = cci_check_error (ccErrBadParam); }
+
+ if (!err) {
+ *out_equal = (!strcmp (in_identifier->object_id,
+ in_compare_to_identifier->object_id) &&
+ !strcmp (in_identifier->server_id,
+ in_compare_to_identifier->server_id));
+ }
+
+ return cci_check_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 cci_identifier_is_for_server (cci_identifier_t in_identifier,
+ cci_uuid_string_t in_server_id,
+ cc_uint32 *out_is_for_server)
+{
+ cc_int32 err = ccNoError;
+
+ if (!in_identifier ) { err = cci_check_error (ccErrBadParam); }
+ if (!in_server_id ) { err = cci_check_error (ccErrBadParam); }
+ if (!out_is_for_server) { err = cci_check_error (ccErrBadParam); }
+
+ if (!err) {
+ *out_is_for_server = (!strcmp (in_identifier->server_id, in_server_id) ||
+ !strcmp (in_identifier->server_id, cci_uninitialized_server_id));
+ }
+
+ return cci_check_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 cci_identifier_compare_server_id (cci_identifier_t in_identifier,
+ cci_identifier_t in_compare_to_identifier,
+ cc_uint32 *out_equal_server_id)
+{
+ cc_int32 err = ccNoError;
+
+ if (!in_identifier ) { err = cci_check_error (ccErrBadParam); }
+ if (!in_compare_to_identifier) { err = cci_check_error (ccErrBadParam); }
+ if (!out_equal_server_id ) { err = cci_check_error (ccErrBadParam); }
+
+ if (!err) {
+ *out_equal_server_id = (!strcmp (in_identifier->server_id,
+ in_compare_to_identifier->server_id));
+ }
+
+ return cci_check_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 cci_identifier_is_initialized (cci_identifier_t in_identifier,
+ cc_uint32 *out_is_initialized)
+{
+ cc_int32 err = ccNoError;
+
+ if (!in_identifier ) { err = cci_check_error (ccErrBadParam); }
+ if (!out_is_initialized) { err = cci_check_error (ccErrBadParam); }
+
+ if (!err) {
+ *out_is_initialized = (strcmp (in_identifier->server_id,
+ cci_uninitialized_server_id) != 0);
+ }
+
+ return cci_check_error (err);
+}
+
+#ifdef TARGET_OS_MAC
+#pragma mark -
+#endif
+
+/* ------------------------------------------------------------------------ */
+
+cc_uint32 cci_identifier_read (cci_identifier_t *out_identifier,
+ k5_ipc_stream io_stream)
+{
+ cc_int32 err = ccNoError;
+ cci_uuid_string_t server_id = NULL;
+ cci_uuid_string_t object_id = NULL;
+
+ if (!out_identifier) { err = cci_check_error (ccErrBadParam); }
+ if (!io_stream ) { err = cci_check_error (ccErrBadParam); }
+
+ if (!err) {
+ err = krb5int_ipc_stream_read_string (io_stream, &server_id);
+ }
+
+ if (!err) {
+ err = krb5int_ipc_stream_read_string (io_stream, &object_id);
+ }
+
+ if (!err) {
+ err = cci_identifier_alloc (out_identifier, server_id, object_id);
+ }
+
+ krb5int_ipc_stream_free_string (server_id);
+ krb5int_ipc_stream_free_string (object_id);
+
+ return cci_check_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_uint32 cci_identifier_write (cci_identifier_t in_identifier,
+ k5_ipc_stream io_stream)
+{
+ cc_int32 err = ccNoError;
+
+ if (!in_identifier) { err = cci_check_error (ccErrBadParam); }
+ if (!io_stream ) { err = cci_check_error (ccErrBadParam); }
+
+ if (!err) {
+ err = krb5int_ipc_stream_write_string (io_stream, in_identifier->server_id);
+ }
+
+ if (!err) {
+ err = krb5int_ipc_stream_write_string (io_stream, in_identifier->object_id);
+ }
+
+ return cci_check_error (err);
+}
diff --git a/src/ccapi/common/cci_identifier.h b/src/ccapi/common/cci_identifier.h
new file mode 100644
index 000000000000..d5e1da4fdd58
--- /dev/null
+++ b/src/ccapi/common/cci_identifier.h
@@ -0,0 +1,64 @@
+/* ccapi/common/cci_identifier.h */
+/*
+ * Copyright 2006 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 M.I.T. 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.
+ */
+
+#ifndef CCI_IDENTIFIER_H
+#define CCI_IDENTIFIER_H
+
+#include "cci_types.h"
+
+extern const cci_identifier_t cci_identifier_uninitialized;
+
+cc_int32 cci_identifier_new_uuid (cci_uuid_string_t *out_uuid_string);
+
+cc_int32 cci_identifier_new (cci_identifier_t *out_identifier,
+ cci_uuid_string_t in_server_id);
+
+cc_int32 cci_identifier_copy (cci_identifier_t *out_identifier,
+ cci_identifier_t in_handle);
+
+cc_int32 cci_identifier_release (cci_identifier_t in_identifier);
+
+cc_int32 cci_identifier_compare (cci_identifier_t in_identifier,
+ cci_identifier_t in_compare_to_identifier,
+ cc_uint32 *out_equal);
+
+cc_int32 cci_identifier_is_for_server (cci_identifier_t in_identifier,
+ cci_uuid_string_t in_server_id,
+ cc_uint32 *out_is_for_server);
+
+cc_int32 cci_identifier_compare_server_id (cci_identifier_t in_identifier,
+ cci_identifier_t in_compare_to_identifier,
+ cc_uint32 *out_equal_server_id);
+
+cc_int32 cci_identifier_is_initialized (cci_identifier_t in_identifier,
+ cc_uint32 *out_is_initialized);
+
+cc_uint32 cci_identifier_read (cci_identifier_t *out_identifier,
+ k5_ipc_stream io_stream);
+
+cc_uint32 cci_identifier_write (cci_identifier_t in_identifier,
+ k5_ipc_stream io_stream);
+
+#endif /* CCI_IDENTIFIER_H */
diff --git a/src/ccapi/common/cci_message.c b/src/ccapi/common/cci_message.c
new file mode 100644
index 000000000000..3f6107594e6e
--- /dev/null
+++ b/src/ccapi/common/cci_message.c
@@ -0,0 +1,213 @@
+/* ccapi/common/cci_message.c */
+/*
+ * Copyright 2006 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 M.I.T. 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.
+ */
+
+#include "cci_common.h"
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 cci_message_invalid_object_err (enum cci_msg_id_t in_request_name)
+{
+ cc_int32 err = ccNoError;
+
+ if (in_request_name > cci_context_first_msg_id &&
+ in_request_name < cci_context_last_msg_id) {
+ err = ccErrInvalidContext;
+
+ } else if (in_request_name > cci_ccache_first_msg_id &&
+ in_request_name < cci_ccache_last_msg_id) {
+ err = ccErrInvalidCCache;
+
+ } else if (in_request_name > cci_ccache_iterator_first_msg_id &&
+ in_request_name < cci_ccache_iterator_last_msg_id) {
+ err = ccErrInvalidCCacheIterator;
+
+ } else if (in_request_name > cci_credentials_iterator_first_msg_id &&
+ in_request_name < cci_credentials_iterator_last_msg_id) {
+ err = ccErrInvalidCredentialsIterator;
+
+ } else {
+ err = ccErrBadInternalMessage;
+ }
+
+ return cci_check_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 cci_message_new_request_header (k5_ipc_stream *out_request,
+ enum cci_msg_id_t in_request_name,
+ cci_identifier_t in_identifier)
+{
+ cc_int32 err = ccNoError;
+ k5_ipc_stream request = NULL;
+
+ if (!out_request) { err = cci_check_error (ccErrBadParam); }
+
+ if (!err) {
+ err = krb5int_ipc_stream_new (&request);
+ }
+
+ if (!err) {
+ err = krb5int_ipc_stream_write_uint32 (request, in_request_name);
+ }
+
+ if (!err) {
+ err = cci_identifier_write (in_identifier, request);
+ }
+
+ if (!err) {
+ *out_request = request;
+ request = NULL;
+ }
+
+ krb5int_ipc_stream_release (request);
+
+ return cci_check_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 cci_message_read_request_header (k5_ipc_stream in_request,
+ enum cci_msg_id_t *out_request_name,
+ cci_identifier_t *out_identifier)
+{
+ cc_int32 err = ccNoError;
+ cc_uint32 request_name;
+ cci_identifier_t identifier = NULL;
+
+ if (!in_request ) { err = cci_check_error (ccErrBadParam); }
+ if (!out_request_name) { err = cci_check_error (ccErrBadParam); }
+ if (!out_identifier ) { err = cci_check_error (ccErrBadParam); }
+
+ if (!err) {
+ err = krb5int_ipc_stream_read_uint32 (in_request, &request_name);
+ }
+
+ if (!err) {
+ err = cci_identifier_read (&identifier, in_request);
+ }
+
+ if (!err) {
+ *out_request_name = request_name;
+ *out_identifier = identifier;
+ identifier = NULL; /* take ownership */
+ }
+
+ cci_identifier_release (identifier);
+
+ return cci_check_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 cci_message_new_reply_header (k5_ipc_stream *out_reply,
+ cc_int32 in_error)
+{
+ cc_int32 err = ccNoError;
+ k5_ipc_stream reply = NULL;
+
+ if (!out_reply) { err = cci_check_error (ccErrBadParam); }
+
+ if (!err) {
+ err = krb5int_ipc_stream_new (&reply);
+ }
+
+ if (!err) {
+ err = krb5int_ipc_stream_write_int32 (reply, in_error);
+ }
+
+ if (!err) {
+ *out_reply = reply;
+ reply = NULL;
+ }
+
+ krb5int_ipc_stream_release (reply);
+
+ return cci_check_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 cci_message_read_reply_header (k5_ipc_stream in_reply,
+ cc_int32 *out_reply_error)
+{
+ cc_int32 err = ccNoError;
+ cc_int32 reply_err = 0;
+
+ if (!in_reply ) { err = cci_check_error (ccErrBadParam); }
+ if (!out_reply_error) { err = cci_check_error (ccErrBadParam); }
+
+ if (!err) {
+ err = krb5int_ipc_stream_read_int32 (in_reply, &reply_err);
+ }
+
+ if (!err) {
+ *out_reply_error = reply_err;
+ }
+
+ return cci_check_error (err);
+}
+
+#ifdef TARGET_OS_MAC
+#pragma mark -
+#endif
+
+/* ------------------------------------------------------------------------ */
+
+uint32_t krb5int_ipc_stream_read_time (k5_ipc_stream io_stream,
+ cc_time_t *out_time)
+{
+ int32_t err = 0;
+ int64_t t = 0;
+
+ if (!io_stream) { err = cci_check_error (ccErrBadParam); }
+ if (!out_time ) { err = cci_check_error (ccErrBadParam); }
+
+ if (!err) {
+ err = krb5int_ipc_stream_read_int64 (io_stream, &t);
+ }
+
+ if (!err) {
+ *out_time = t;
+ }
+
+ return cci_check_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+uint32_t krb5int_ipc_stream_write_time (k5_ipc_stream io_stream,
+ cc_time_t in_time)
+{
+ int32_t err = 0;
+
+ if (!io_stream) { err = cci_check_error (ccErrBadParam); }
+
+ if (!err) {
+ err = krb5int_ipc_stream_write_int64 (io_stream, in_time);
+ }
+
+ return cci_check_error (err);
+}
diff --git a/src/ccapi/common/cci_message.h b/src/ccapi/common/cci_message.h
new file mode 100644
index 000000000000..6babb5606c7f
--- /dev/null
+++ b/src/ccapi/common/cci_message.h
@@ -0,0 +1,52 @@
+/* ccapi/common/cci_message.h */
+/*
+ * Copyright 2006 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 M.I.T. 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.
+ */
+
+#ifndef CCI_MESSAGE_H
+#define CCI_MESSAGE_H
+
+#include "cci_types.h"
+
+cc_int32 cci_message_invalid_object_err (enum cci_msg_id_t in_request_name);
+
+cc_int32 cci_message_new_request_header (k5_ipc_stream *out_request,
+ enum cci_msg_id_t in_request_name,
+ cci_identifier_t in_identifier);
+
+cc_int32 cci_message_read_request_header (k5_ipc_stream in_request,
+ enum cci_msg_id_t *out_request_name,
+ cci_identifier_t *out_identifier);
+
+cc_int32 cci_message_new_reply_header (k5_ipc_stream *out_reply,
+ cc_int32 in_error);
+
+cc_int32 cci_message_read_reply_header (k5_ipc_stream in_reply,
+ cc_int32 *out_reply_error);
+
+uint32_t krb5int_ipc_stream_read_time (k5_ipc_stream io_stream,
+ cc_time_t *out_time);
+uint32_t krb5int_ipc_stream_write_time (k5_ipc_stream io_stream,
+ cc_time_t in_time);
+
+#endif /* CCI_MESSAGE_H */
diff --git a/src/ccapi/common/cci_os_debugging.h b/src/ccapi/common/cci_os_debugging.h
new file mode 100644
index 000000000000..c99c79a91490
--- /dev/null
+++ b/src/ccapi/common/cci_os_debugging.h
@@ -0,0 +1,34 @@
+/* ccapi/common/cci_os_debugging.h */
+/*
+ * Copyright 2006 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 M.I.T. 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.
+ */
+
+#ifndef CCI_OS_DEBUGGING_H
+#define CCI_OS_DEBUGGING_H
+
+#include "cci_types.h"
+#include <stdarg.h>
+
+void cci_os_debug_vprintf (const char *in_format, va_list in_args);
+
+#endif /* CCI_OS_DEBUGGING_H */
diff --git a/src/ccapi/common/cci_os_identifier.h b/src/ccapi/common/cci_os_identifier.h
new file mode 100644
index 000000000000..7ee67eb38c2a
--- /dev/null
+++ b/src/ccapi/common/cci_os_identifier.h
@@ -0,0 +1,33 @@
+/* ccapi/common/cci_os_identifier.h */
+/*
+ * Copyright 2006 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 M.I.T. 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.
+ */
+
+#ifndef CCI_OS_IDENTIFIER_H
+#define CCI_OS_IDENTIFIER_H
+
+#include "cci_types.h"
+
+cc_int32 cci_os_identifier_new_uuid (cci_uuid_string_t *out_uuid_string);
+
+#endif /* CCI_OS_IDENTIFIER_H */
diff --git a/src/ccapi/common/cci_types.h b/src/ccapi/common/cci_types.h
new file mode 100644
index 000000000000..87597d441b6d
--- /dev/null
+++ b/src/ccapi/common/cci_types.h
@@ -0,0 +1,102 @@
+/* ccapi/common/cci_types.h */
+/*
+ * Copyright 2006 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 M.I.T. 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.
+ */
+
+#ifndef CCI_TYPES_H
+#define CCI_TYPES_H
+
+#include <CredentialsCache.h>
+#include <k5-ipc_stream.h>
+
+typedef char *cci_uuid_string_t;
+
+struct cci_identifier_d;
+typedef struct cci_identifier_d *cci_identifier_t;
+
+enum cci_msg_id_t {
+ /* cc_context_t */
+ cci_context_first_msg_id,
+
+ cci_context_unused_release_msg_id, /* Unused. Handle for old clients. */
+ cci_context_sync_msg_id,
+ cci_context_get_change_time_msg_id,
+ cci_context_wait_for_change_msg_id,
+ cci_context_get_default_ccache_name_msg_id,
+ cci_context_open_ccache_msg_id,
+ cci_context_open_default_ccache_msg_id,
+ cci_context_create_ccache_msg_id,
+ cci_context_create_default_ccache_msg_id,
+ cci_context_create_new_ccache_msg_id,
+ cci_context_new_ccache_iterator_msg_id,
+ cci_context_lock_msg_id,
+ cci_context_unlock_msg_id,
+
+ cci_context_last_msg_id,
+
+ /* cc_ccache_t */
+ cci_ccache_first_msg_id,
+
+ cci_ccache_destroy_msg_id,
+ cci_ccache_set_default_msg_id,
+ cci_ccache_get_credentials_version_msg_id,
+ cci_ccache_get_name_msg_id,
+ cci_ccache_get_principal_msg_id,
+ cci_ccache_set_principal_msg_id,
+ cci_ccache_store_credentials_msg_id,
+ cci_ccache_remove_credentials_msg_id,
+ cci_ccache_new_credentials_iterator_msg_id,
+ cci_ccache_move_msg_id,
+ cci_ccache_lock_msg_id,
+ cci_ccache_unlock_msg_id,
+ cci_ccache_get_last_default_time_msg_id,
+ cci_ccache_get_change_time_msg_id,
+ cci_ccache_wait_for_change_msg_id,
+ cci_ccache_get_kdc_time_offset_msg_id,
+ cci_ccache_set_kdc_time_offset_msg_id,
+ cci_ccache_clear_kdc_time_offset_msg_id,
+
+ cci_ccache_last_msg_id,
+
+ /* cc_ccache_iterator_t */
+ cci_ccache_iterator_first_msg_id,
+
+ cci_ccache_iterator_release_msg_id,
+ cci_ccache_iterator_next_msg_id,
+ cci_ccache_iterator_clone_msg_id,
+
+ cci_ccache_iterator_last_msg_id,
+
+ /* cc_credentials_iterator_t */
+ cci_credentials_iterator_first_msg_id,
+
+ cci_credentials_iterator_release_msg_id,
+ cci_credentials_iterator_next_msg_id,
+ cci_credentials_iterator_clone_msg_id,
+
+ cci_credentials_iterator_last_msg_id,
+
+ cci_max_msg_id /* must be last! */
+};
+
+#endif /* CCI_TYPES_H */
diff --git a/src/ccapi/common/mac/cci_os_debugging.c b/src/ccapi/common/mac/cci_os_debugging.c
new file mode 100644
index 000000000000..e5280451bbc4
--- /dev/null
+++ b/src/ccapi/common/mac/cci_os_debugging.c
@@ -0,0 +1,35 @@
+/* ccapi/common/mac/cci_os_debugging.c */
+/*
+ * Copyright 2006 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 M.I.T. 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.
+ */
+
+
+#include "cci_os_debugging.h"
+#include <Kerberos/KerberosDebug.h>
+
+/* ------------------------------------------------------------------------ */
+
+void cci_os_debug_vprintf (const char *in_format, va_list in_args)
+{
+ dvprintf (in_format, in_args);
+}
diff --git a/src/ccapi/common/mac/cci_os_identifier.c b/src/ccapi/common/mac/cci_os_identifier.c
new file mode 100644
index 000000000000..be7b5bdc46f2
--- /dev/null
+++ b/src/ccapi/common/mac/cci_os_identifier.c
@@ -0,0 +1,78 @@
+/* ccapi/common/mac/cci_os_identifier.c */
+/*
+ * Copyright 2006 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 M.I.T. 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.
+ */
+
+#include "cci_common.h"
+#include "cci_os_identifier.h"
+
+#include <CoreFoundation/CoreFoundation.h>
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 cci_os_identifier_new_uuid (cci_uuid_string_t *out_uuid_string)
+{
+ cc_int32 err = ccNoError;
+ cci_uuid_string_t uuid_string = NULL;
+ CFUUIDRef uuid = NULL;
+ CFStringRef uuid_stringref = NULL;
+ CFStringEncoding encoding = kCFStringEncodingUTF8;
+ CFIndex length = 0;
+
+ if (!out_uuid_string) { err = cci_check_error (ccErrBadParam); }
+
+ if (!err) {
+ uuid = CFUUIDCreate (kCFAllocatorDefault);
+ if (!uuid) { err = cci_check_error (ccErrNoMem); }
+ }
+
+ if (!err) {
+ uuid_stringref = CFUUIDCreateString (kCFAllocatorDefault, uuid);
+ if (!uuid_stringref) { err = cci_check_error (ccErrNoMem); }
+ }
+
+ if (!err) {
+ length = CFStringGetMaximumSizeForEncoding (CFStringGetLength (uuid_stringref),
+ encoding) + 1;
+
+ uuid_string = malloc (length);
+ if (!uuid_string) { err = cci_check_error (ccErrNoMem); }
+ }
+
+ if (!err) {
+ if (!CFStringGetCString (uuid_stringref, uuid_string, length, encoding)) {
+ err = cci_check_error (ccErrNoMem);
+ }
+ }
+
+ if (!err) {
+ *out_uuid_string = uuid_string;
+ uuid_string = NULL; /* take ownership */
+ }
+
+ if (uuid_string ) { free (uuid_string); }
+ if (uuid_stringref) { CFRelease (uuid_stringref); }
+ if (uuid ) { CFRelease (uuid); }
+
+ return cci_check_error (err);
+}
diff --git a/src/ccapi/common/unix/Makefile.in b/src/ccapi/common/unix/Makefile.in
new file mode 100644
index 000000000000..ecacabd60f0a
--- /dev/null
+++ b/src/ccapi/common/unix/Makefile.in
@@ -0,0 +1,13 @@
+mydir=ccapi$(S)common$(S)unix
+BUILDTOP=$(REL)..$(S)..$(S)..
+
+STLIBOBJS=
+OBJS=
+SRCS=
+
+all-unix: all-libobjs
+clean-unix:: clean-libobjs
+
+@libobj_frag@
+
+# +++ Dependency line eater +++
diff --git a/src/ccapi/common/win/OldCC/autolock.hxx b/src/ccapi/common/win/OldCC/autolock.hxx
new file mode 100644
index 000000000000..b88172d2ae03
--- /dev/null
+++ b/src/ccapi/common/win/OldCC/autolock.hxx
@@ -0,0 +1,66 @@
+/* ccapi/common/win/OldCC/autolock.hxx */
+/*
+ * Copyright (C) 1998 by Danilo Almeida. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __AUTOLOCK_HXX__
+#define __AUTOLOCK_HXX__
+
+#include <windows.h>
+
+class CcOsLock {
+ CRITICAL_SECTION cs;
+ bool valid;
+public:
+ CcOsLock() {InitializeCriticalSection(&cs); valid = true; }
+ ~CcOsLock() {DeleteCriticalSection(&cs); valid = false;}
+ void lock() {if (valid) EnterCriticalSection(&cs);}
+ void unlock() {if (valid) LeaveCriticalSection(&cs);}
+ bool trylock() {return valid ? (TryEnterCriticalSection(&cs) ? true : false)
+ : false; }
+};
+
+class CcAutoLock {
+ CcOsLock& m_lock;
+public:
+ static void Start(CcAutoLock*& a, CcOsLock& lock) { a = new CcAutoLock(lock); };
+ static void Stop (CcAutoLock*& a) { delete a; a = 0; };
+ CcAutoLock(CcOsLock& lock):m_lock(lock) { m_lock.lock(); }
+ ~CcAutoLock() { m_lock.unlock(); }
+};
+
+class CcAutoTryLock {
+ CcOsLock& m_lock;
+ bool m_locked;
+public:
+ CcAutoTryLock(CcOsLock& lock):m_lock(lock) { m_locked = m_lock.trylock(); }
+ ~CcAutoTryLock() { if (m_locked) m_lock.unlock(); m_locked = false; }
+ bool IsLocked() const { return m_locked; }
+};
+
+#endif /* __AUTOLOCK_HXX */
diff --git a/src/ccapi/common/win/OldCC/ccutil.cxx b/src/ccapi/common/win/OldCC/ccutil.cxx
new file mode 100644
index 000000000000..729104de7ed3
--- /dev/null
+++ b/src/ccapi/common/win/OldCC/ccutil.cxx
@@ -0,0 +1,187 @@
+/*
+ * $Header$
+ *
+ * Copyright 2008 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 M.I.T. 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.
+ */
+
+#include <windows.h>
+#include "init.hxx"
+#include "secure.hxx"
+
+extern "C" {
+#include "cci_debugging.h"
+ }
+
+
+CcOsLock Init::s_lock;
+DWORD Init::s_refcount = 0;
+DWORD Init::s_error = ERROR_INVALID_HANDLE;
+bool Init::s_init = false;
+Init::InitInfo Init::s_info = { 0 };
+HINSTANCE Init::s_hRpcDll = 0;
+
+#define INIT "INIT: "
+
+static
+void
+ShowInfo(
+ Init::InitInfo& info
+ );
+
+DWORD
+Init::Info(
+ InitInfo& info
+ )
+{
+ // This funciton will not do automatic initialization.
+ CcAutoLock AL(s_lock);
+ if (!s_init) {
+ memset(&info, 0, sizeof(info));
+ return s_error ? s_error : ERROR_INVALID_HANDLE;
+ } else {
+ info = s_info;
+ return 0;
+ }
+}
+
+DWORD
+Init::Initialize() {
+ CcAutoLock AL(s_lock);
+ cci_debug_printf("%s s_init:%d", __FUNCTION__, s_init);
+ if (s_init) {
+ s_refcount++;
+ return 0;
+ }
+ SecureClient s;
+ DWORD status = 0;
+ OSVERSIONINFO osvi;
+ BOOL isSupportedVersion = FALSE;
+ memset(&s_info, 0, sizeof(s_info));
+ memset(&osvi, 0, sizeof(osvi));
+ osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
+
+ status = !GetVersionEx(&osvi); // Returns a boolean. Invert to 0 is OK.
+
+ if (!status) {
+ switch(osvi.dwPlatformId) {
+ case VER_PLATFORM_WIN32_WINDOWS:
+ s_info.isNT = FALSE;
+ isSupportedVersion = TRUE;
+ break;
+ case VER_PLATFORM_WIN32_NT:
+ s_info.isNT = TRUE;
+ isSupportedVersion = TRUE;
+ break;
+ case VER_PLATFORM_WIN32s:
+ default:
+ s_info.isNT = FALSE;
+ break;
+ }
+
+ if (!isSupportedVersion) {
+ cci_debug_printf("%s Trying to run on an unsupported version of Windows", __FUNCTION__);
+ status = 1;
+ }
+ }
+
+ if (!status) {status = !s_info.isNT;}
+
+ if (!status) {status = !(s_hRpcDll = LoadLibrary(TEXT("rpcrt4.dll")));}
+
+ if (!status) {
+ s_info.fRpcBindingSetAuthInfoEx = (FP_RpcBindingSetAuthInfoEx)
+ GetProcAddress(s_hRpcDll, TEXT(FN_RpcBindingSetAuthInfoEx));
+ if (!s_info.fRpcBindingSetAuthInfoEx) {
+ cci_debug_printf(" Running on NT but could not find RpcBindinSetAuthInfoEx");
+ status = 1;
+ }
+ }
+
+ if (!status) {
+ s_info.fRpcServerRegisterIfEx = (FP_RpcServerRegisterIfEx)
+ GetProcAddress(s_hRpcDll, TEXT(FN_RpcServerRegisterIfEx));
+ if (!s_info.fRpcServerRegisterIfEx) {
+ cci_debug_printf(" Running on NT but could not find RpcServerRegisterIfEx");
+ status = 1;
+ }
+ }
+
+ if (!status) {
+ status = SecureClient::Attach();
+ if (status) {
+ cci_debug_printf(" SecureClient::Attach() failed (%u)", status);
+ }
+ }
+
+ if (status) {
+ memset(&s_info, 0, sizeof(s_info));
+ if (s_hRpcDll) {
+ FreeLibrary(s_hRpcDll);
+ s_hRpcDll = 0;
+ }
+ cci_debug_printf(" Init::Attach() failed (%u)", status);
+ } else {
+ s_refcount++;
+ s_init = true;
+ ShowInfo(s_info);
+ }
+ s_error = status;
+ return status;
+}
+
+DWORD
+Init::Cleanup(
+ )
+{
+ CcAutoLock AL(s_lock);
+ s_refcount--;
+ if (s_refcount) return 0;
+ if (!s_init) return 0;
+ DWORD error = 0;
+ if (s_hRpcDll) {
+ FreeLibrary(s_hRpcDll);
+ s_hRpcDll = 0;
+ }
+ error = SecureClient::Detach();
+ memset(&s_info, 0, sizeof(s_info));
+ s_init = false;
+ s_error = 0;
+ if (error) {
+ cci_debug_printf(" Init::Detach() had an error (%u)", error);
+ }
+ return error;
+}
+
+static
+void
+ShowInfo(
+ Init::InitInfo& info
+ )
+{
+ if (info.isNT) {
+ cci_debug_printf(" Running on Windows NT using secure mode");
+ } else {
+ cci_debug_printf(" Running insecurely on non-NT Windows");
+ }
+ return;
+}
diff --git a/src/ccapi/common/win/OldCC/ccutil.def b/src/ccapi/common/win/OldCC/ccutil.def
new file mode 100644
index 000000000000..57113f094ea3
--- /dev/null
+++ b/src/ccapi/common/win/OldCC/ccutil.def
@@ -0,0 +1,5 @@
+;LIBRARY COMERR32
+HEAPSIZE 8192
+
+EXPORTS
+ \ No newline at end of file
diff --git a/src/ccapi/common/win/OldCC/ccutils.c b/src/ccapi/common/win/OldCC/ccutils.c
new file mode 100644
index 000000000000..13f72cbe09d1
--- /dev/null
+++ b/src/ccapi/common/win/OldCC/ccutils.c
@@ -0,0 +1,139 @@
+/* ccapi/common/win/OldCC/ccutils.c */
+/*
+ * Copyright 2008 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 M.I.T. 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.
+ */
+
+#include <windows.h>
+#include <stdlib.h>
+#include <malloc.h>
+
+#include "cci_debugging.h"
+#include "util.h"
+
+BOOL isNT() {
+ OSVERSIONINFO osvi;
+ DWORD status = 0;
+ BOOL bSupportedVersion = FALSE;
+ BOOL bIsNT = FALSE;
+
+ memset(&osvi, 0, sizeof(osvi));
+ osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
+
+ status = !GetVersionEx(&osvi); // Returns a boolean. Invert to 0 is OK.
+
+ if (!status) {
+ switch(osvi.dwPlatformId) {
+ case VER_PLATFORM_WIN32_WINDOWS:
+ bIsNT = FALSE;
+ bSupportedVersion = TRUE;
+ break;
+ case VER_PLATFORM_WIN32_NT:
+ bIsNT = TRUE;
+ bSupportedVersion = TRUE;
+ break;
+ case VER_PLATFORM_WIN32s:
+ default:
+ bIsNT = FALSE;
+ break;
+ }
+
+ if (!bSupportedVersion) {
+ cci_debug_printf("%s Running on an unsupported version of Windows", __FUNCTION__);
+ status = 1;
+ }
+ }
+
+ return (!status && bIsNT && bSupportedVersion);
+ }
+
+char* allocEventName(char* uuid_string, char* suffix) {
+ LPSTR event_name = NULL;
+ cc_int32 err = ccNoError;
+
+ event_name = malloc(strlen(uuid_string) + strlen(suffix) + 3);
+ if (!event_name) err = cci_check_error(ccErrNoMem);
+
+ if (!err) {
+ strcpy(event_name, uuid_string);
+ strcat(event_name, "_");
+ strcat(event_name, suffix);
+ }
+
+ return event_name;
+ }
+
+HANDLE createThreadEvent(char* uuid, char* suffix) {
+ LPSTR event_name = NULL;
+ HANDLE hEvent = NULL;
+ PSECURITY_ATTRIBUTES psa = 0; // Everything having to do with
+ SECURITY_ATTRIBUTES sa = { 0 }; // sa, psa, security is copied
+ DWORD status = 0; // from the previous implementation.
+
+ psa = isNT() ? &sa : 0;
+
+ if (isNT()) {
+ sa.nLength = sizeof(sa);
+ status = alloc_own_security_descriptor_NT(&sa.lpSecurityDescriptor);
+ cci_check_error(status);
+ }
+
+ if (!status) {
+ event_name = allocEventName(uuid, suffix);
+ if (!event_name) status = cci_check_error(ccErrNoMem);
+ }
+#if 0
+ cci_debug_printf("%s event_name:%s", __FUNCTION__, event_name);
+#endif
+ if (!status) {
+ hEvent = CreateEvent(psa, FALSE, FALSE, event_name);
+ if (!hEvent) status = cci_check_error(GetLastError());
+ }
+
+ if (!status) ResetEvent(hEvent);
+
+
+ if (event_name) free(event_name);
+ if (isNT()) free(sa.lpSecurityDescriptor);
+
+ return hEvent;
+ }
+
+HANDLE openThreadEvent(char* uuid, char* suffix) {
+ LPSTR event_name = NULL;
+ HANDLE hEvent = NULL;
+ DWORD status = 0;
+
+ event_name = allocEventName(uuid, suffix);
+ if (!event_name) status = cci_check_error(ccErrNoMem);
+#if 0
+ cci_debug_printf("%s event_name:%s", __FUNCTION__, event_name);
+#endif
+ if (!status) {
+ hEvent = OpenEvent(EVENT_MODIFY_STATE, FALSE, event_name);
+ if (!hEvent) status = cci_check_error(GetLastError());
+ }
+
+ if (event_name) free(event_name);
+
+ return hEvent;
+ }
diff --git a/src/ccapi/common/win/OldCC/ccutils.h b/src/ccapi/common/win/OldCC/ccutils.h
new file mode 100644
index 000000000000..f91c7770214e
--- /dev/null
+++ b/src/ccapi/common/win/OldCC/ccutils.h
@@ -0,0 +1,48 @@
+/* ccapi/common/win/OldCC/ccutils.h */
+/*
+ * Copyright 2008 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 M.I.T. 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.
+ */
+
+#ifndef __CCUTILS_H__
+#define __CCUTILS_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+#if 0
+}
+#endif
+
+#define REPLY_SUFFIX (char*)"reply"
+#define LISTEN_SUFFIX (char*)"listen"
+
+BOOL isNT();
+char* allocEventName (char* uuid, char* suffix);
+HANDLE createThreadEvent(char* uuid, char* suffix);
+HANDLE openThreadEvent (char* uuid, char* suffix);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __CCUTILS_H__ */
diff --git a/src/ccapi/common/win/OldCC/init.cxx b/src/ccapi/common/win/OldCC/init.cxx
new file mode 100644
index 000000000000..feb7ad3ad957
--- /dev/null
+++ b/src/ccapi/common/win/OldCC/init.cxx
@@ -0,0 +1,187 @@
+/*
+ * $Header$
+ *
+ * Copyright 2008 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 M.I.T. 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.
+ */
+
+#include <windows.h>
+#include "init.hxx"
+#include "secure.hxx"
+
+extern "C" {
+#include "cci_debugging.h"
+ }
+
+
+CcOsLock Init::s_lock;
+DWORD Init::s_refcount = 0;
+DWORD Init::s_error = ERROR_INVALID_HANDLE;
+bool Init::s_init = false;
+Init::InitInfo Init::s_info = { 0 };
+HINSTANCE Init::s_hRpcDll = 0;
+
+#define INIT "INIT: "
+
+static
+void
+ShowInfo(
+ Init::InitInfo& info
+ );
+
+DWORD
+Init::Info(
+ InitInfo& info
+ )
+{
+ // This funciton will not do automatic initialization.
+ CcAutoLock AL(s_lock);
+ if (!s_init) {
+ memset(&info, 0, sizeof(info));
+ return s_error ? s_error : ERROR_INVALID_HANDLE;
+ } else {
+ info = s_info;
+ return 0;
+ }
+}
+
+DWORD
+Init::Initialize() {
+ CcAutoLock AL(s_lock);
+// cci_debug_printf("%s s_init:%d", __FUNCTION__, s_init);
+ if (s_init) {
+ s_refcount++;
+ return 0;
+ }
+ SecureClient s;
+ DWORD status = 0;
+ OSVERSIONINFO osvi;
+ BOOL isSupportedVersion = FALSE;
+ memset(&s_info, 0, sizeof(s_info));
+ memset(&osvi, 0, sizeof(osvi));
+ osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
+
+ status = !GetVersionEx(&osvi); // Returns a boolean. Invert to 0 is OK.
+
+ if (!status) {
+ switch(osvi.dwPlatformId) {
+ case VER_PLATFORM_WIN32_WINDOWS:
+ s_info.isNT = FALSE;
+ isSupportedVersion = TRUE;
+ break;
+ case VER_PLATFORM_WIN32_NT:
+ s_info.isNT = TRUE;
+ isSupportedVersion = TRUE;
+ break;
+ case VER_PLATFORM_WIN32s:
+ default:
+ s_info.isNT = FALSE;
+ break;
+ }
+
+ if (!isSupportedVersion) {
+ cci_debug_printf("%s Trying to run on an unsupported version of Windows", __FUNCTION__);
+ status = 1;
+ }
+ }
+
+ if (!status) {status = !s_info.isNT;}
+
+ if (!status) {status = !(s_hRpcDll = LoadLibrary(TEXT("rpcrt4.dll")));}
+
+ if (!status) {
+ s_info.fRpcBindingSetAuthInfoEx = (FP_RpcBindingSetAuthInfoEx)
+ GetProcAddress(s_hRpcDll, TEXT(FN_RpcBindingSetAuthInfoEx));
+ if (!s_info.fRpcBindingSetAuthInfoEx) {
+ cci_debug_printf(" Running on NT but could not find RpcBindinSetAuthInfoEx");
+ status = 1;
+ }
+ }
+
+ if (!status) {
+ s_info.fRpcServerRegisterIfEx = (FP_RpcServerRegisterIfEx)
+ GetProcAddress(s_hRpcDll, TEXT(FN_RpcServerRegisterIfEx));
+ if (!s_info.fRpcServerRegisterIfEx) {
+ cci_debug_printf(" Running on NT but could not find RpcServerRegisterIfEx");
+ status = 1;
+ }
+ }
+
+ if (!status) {
+ status = SecureClient::Attach();
+ if (status) {
+ cci_debug_printf(" SecureClient::Attach() failed (%u)", status);
+ }
+ }
+
+ if (status) {
+ memset(&s_info, 0, sizeof(s_info));
+ if (s_hRpcDll) {
+ FreeLibrary(s_hRpcDll);
+ s_hRpcDll = 0;
+ }
+ cci_debug_printf(" Init::Attach() failed (%u)", status);
+ } else {
+ s_refcount++;
+ s_init = true;
+ ShowInfo(s_info);
+ }
+ s_error = status;
+ return status;
+}
+
+DWORD
+Init::Cleanup(
+ )
+{
+ CcAutoLock AL(s_lock);
+ s_refcount--;
+ if (s_refcount) return 0;
+ if (!s_init) return 0;
+ DWORD error = 0;
+ if (s_hRpcDll) {
+ FreeLibrary(s_hRpcDll);
+ s_hRpcDll = 0;
+ }
+ error = SecureClient::Detach();
+ memset(&s_info, 0, sizeof(s_info));
+ s_init = false;
+ s_error = 0;
+ if (error) {
+ cci_debug_printf(" Init::Detach() had an error (%u)", error);
+ }
+ return error;
+}
+
+static
+void
+ShowInfo(
+ Init::InitInfo& info
+ )
+{
+ if (info.isNT) {
+ cci_debug_printf(" Running on Windows NT using secure mode");
+ } else {
+ cci_debug_printf(" Running insecurely on non-NT Windows");
+ }
+ return;
+}
diff --git a/src/ccapi/common/win/OldCC/init.hxx b/src/ccapi/common/win/OldCC/init.hxx
new file mode 100644
index 000000000000..9bac7f8f9e25
--- /dev/null
+++ b/src/ccapi/common/win/OldCC/init.hxx
@@ -0,0 +1,102 @@
+/*
+ * $Header$
+ *
+ * Copyright 2008 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 M.I.T. 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.
+ */
+
+#pragma once
+#include "autolock.hxx"
+#include <rpc.h>
+
+typedef RPC_STATUS (RPC_ENTRY *FP_RpcBindingSetAuthInfoExA)(
+ IN RPC_BINDING_HANDLE Binding,
+ IN unsigned char __RPC_FAR * ServerPrincName,
+ IN unsigned long AuthnLevel,
+ IN unsigned long AuthnSvc,
+ IN RPC_AUTH_IDENTITY_HANDLE AuthIdentity, OPTIONAL
+ IN unsigned long AuthzSvc,
+ IN RPC_SECURITY_QOS *SecurityQos OPTIONAL
+ );
+
+typedef RPC_STATUS (RPC_ENTRY *FP_RpcBindingSetAuthInfoExW)(
+ IN RPC_BINDING_HANDLE Binding,
+ IN unsigned short __RPC_FAR * ServerPrincName,
+ IN unsigned long AuthnLevel,
+ IN unsigned long AuthnSvc,
+ IN RPC_AUTH_IDENTITY_HANDLE AuthIdentity, OPTIONAL
+ IN unsigned long AuthzSvc, OPTIONAL
+ IN RPC_SECURITY_QOS *SecurityQOS
+ );
+
+typedef RPC_STATUS (RPC_ENTRY *FP_RpcServerRegisterIfEx)(
+ IN RPC_IF_HANDLE IfSpec,
+ IN UUID __RPC_FAR * MgrTypeUuid,
+ IN RPC_MGR_EPV __RPC_FAR * MgrEpv,
+ IN unsigned int Flags,
+ IN unsigned int MaxCalls,
+ IN RPC_IF_CALLBACK_FN __RPC_FAR *IfCallback
+ );
+
+#ifdef UNICODE
+#define FP_RpcBindingSetAuthInfoEx FP_RpcBindingSetAuthInfoExW
+#define FN_RpcBindingSetAuthInfoEx "RpcBindingSetAuthInfoExW"
+#else
+#define FP_RpcBindingSetAuthInfoEx FP_RpcBindingSetAuthInfoExA
+#define FN_RpcBindingSetAuthInfoEx "RpcBindingSetAuthInfoExA"
+#endif
+
+#define FN_RpcServerRegisterIfEx "RpcServerRegisterIfEx"
+
+class Init
+{
+public:
+ struct InitInfo {
+ BOOL isNT;
+ FP_RpcBindingSetAuthInfoEx fRpcBindingSetAuthInfoEx;
+ FP_RpcServerRegisterIfEx fRpcServerRegisterIfEx;
+ };
+
+ static DWORD Initialize();
+ static DWORD Cleanup();
+ static DWORD Info(InitInfo& info);
+
+ static bool Initialized() { return s_init; }
+
+private:
+ static CcOsLock s_lock;
+ static DWORD s_refcount;
+ static DWORD s_error;
+ static bool s_init;
+ static InitInfo s_info;
+ static HINSTANCE s_hRpcDll;
+};
+
+#define INIT_INIT_EX(trap, error) \
+do \
+{ \
+ if (!Init::Initialized()) \
+ { \
+ DWORD rc = Init::Initialize(); \
+ if (rc) return (trap) ? (error) : rc; \
+ } \
+} while(0)
diff --git a/src/ccapi/common/win/OldCC/name.h b/src/ccapi/common/win/OldCC/name.h
new file mode 100644
index 000000000000..66ca3a9f86b5
--- /dev/null
+++ b/src/ccapi/common/win/OldCC/name.h
@@ -0,0 +1,34 @@
+/* ccapi/common/win/OldCC/name.h */
+/*
+ * Copyright 2008 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 M.I.T. 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.
+ */
+
+#pragma once
+
+#ifdef _WIN64
+#define CCAPI_MODULE "krbcc64"
+#else
+#define CCAPI_MODULE "krbcc32"
+#endif
+#define CCAPI_DLL CCAPI_MODULE ".dll"
+#define CCAPI_EXE "ccapiserver.exe" \ No newline at end of file
diff --git a/src/ccapi/common/win/OldCC/opts.cxx b/src/ccapi/common/win/OldCC/opts.cxx
new file mode 100644
index 000000000000..bd5f503ea63f
--- /dev/null
+++ b/src/ccapi/common/win/OldCC/opts.cxx
@@ -0,0 +1,188 @@
+/*
+ * $Header$
+ *
+ * Copyright 2008 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 M.I.T. 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.
+ */
+
+#include <windows.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <opts.hxx>
+
+#if 0
+const struct Opts*
+GetOpts(
+ )
+{
+ bool done = false;
+ struct Opts* o;
+ if (!(o = new Opts))
+ goto cleanup;
+ if (!(o->pszString = new char[lstrlenA(opts.pszString) + 1]))
+ goto cleanup;
+ if (!(o->pszEndpoint = new char[lstrlenA(opts.pszEndpoint) + 1]))
+ goto cleanup;
+ strcpy(o->pszString, opts.pszString);
+ strcpy(o->pszEndpoint, opts.pszEndpoint);
+ done = true;
+ cleanup:
+ if (!done) {
+ FreeOpts(o);
+ o = 0;
+ }
+ return o;
+}
+
+void
+FreeOpts(
+ struct Opts* o
+ )
+{
+ if (o) {
+ if (o->pszString)
+ delete [] o->pszString;
+ if (o->pszEndpoint)
+ delete [] o->pszEndpoint;
+ delete o;
+ }
+}
+#endif
+
+bool
+ParseOpts::IsValidOpt(
+ char ch
+ )
+{
+ return (m_ValidOpts[ch % 256] != 0);
+}
+
+void
+ParseOpts::PrintOpt(
+ char ch,
+ char* text
+ )
+{
+ if (IsValidOpt(ch))
+ fprintf(stderr, " -%c %s\n", ch, text);
+}
+
+void
+ParseOpts::UsageOpts(
+ char * program,
+ int code
+ )
+{
+ fprintf(stderr, "Usage: %s [options]\n", program);
+ PrintOpt('k', "stop server");
+#ifdef CCAPI_TEST_OPTIONS
+ PrintOpt('s', "string");
+ PrintOpt('e', "endpoint");
+ PrintOpt('m', "maxcalls");
+ PrintOpt('n', "mincalls");
+ PrintOpt('f', "flag_wait_op");
+ PrintOpt('u', "unprotected");
+ PrintOpt('b', "use security callback");
+#endif
+ PrintOpt('c', "output debug info to console");
+ exit(code);
+}
+
+void
+ParseOpts::SetValidOpts(
+ char* valid_opts
+ )
+{
+ memset(m_ValidOpts, 0, sizeof(m_ValidOpts));
+ char *p = valid_opts;
+ for (p = valid_opts; *p; p++) {
+ m_ValidOpts[*p % sizeof(m_ValidOpts)] = 1;
+ }
+}
+
+void
+ParseOpts::Parse(
+ Opts& opts,
+ int argc,
+ char **argv
+ )
+{
+ int i;
+ for (i = 1; i < argc; i++) {
+ if ((*argv[i] == '-') || (*argv[i] == '/')) {
+ char ch = tolower(*(argv[i]+1));
+ if (!IsValidOpt(ch))
+ UsageOpts(argv[0]);
+ switch (ch) {
+ case 'k':
+ opts.bShutdown = TRUE;
+ break;
+#ifdef CCAPI_TEST_OPTIONS
+ case 's':
+ opts.pszString = argv[++i];
+ break;
+ case 'e':
+ opts.pszEndpoint = argv[++i];
+ break;
+ case 'm':
+ opts.cMaxCalls = (unsigned int) atoi(argv[++i]);
+ break;
+ case 'n':
+ opts.cMinCalls = (unsigned int) atoi(argv[++i]);
+ break;
+ case 'f':
+ opts.fDontWait = (unsigned int) atoi(argv[++i]);
+ break;
+ case 'u':
+ opts.bDontProtect = TRUE;
+ break;
+ case 'b':
+ opts.bSecCallback = TRUE;
+ break;
+#endif
+ case 'c':
+ opts.bConsole = TRUE;
+ break;
+ case 'h':
+ case '?':
+ default:
+ UsageOpts(argv[0]);
+ }
+ }
+ else
+ UsageOpts(argv[0]);
+ }
+
+}
+
+ParseOpts::ParseOpts(char* valid_opts)
+{
+ SetValidOpts(valid_opts);
+}
+
+ParseOpts::ParseOpts()
+{
+}
+
+ParseOpts::~ParseOpts()
+{
+}
diff --git a/src/ccapi/common/win/OldCC/opts.hxx b/src/ccapi/common/win/OldCC/opts.hxx
new file mode 100644
index 000000000000..755ce4ae609a
--- /dev/null
+++ b/src/ccapi/common/win/OldCC/opts.hxx
@@ -0,0 +1,56 @@
+/*
+ * $Header$
+ *
+ * Copyright 2008 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 M.I.T. 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.
+ */
+
+#pragma once
+
+class ParseOpts
+{
+public:
+ struct Opts {
+ char* pszString;
+ char* pszEndpoint;
+ unsigned int cMinCalls;
+ unsigned int cMaxCalls;
+ unsigned int fDontWait;
+ bool bDontProtect;
+ bool bShutdown;
+ bool bSecCallback;
+ bool bConsole;
+ };
+
+ ParseOpts(char* valid_opts);
+ ParseOpts();
+ ~ParseOpts();
+ void SetValidOpts(char* valid_opts);
+ void Parse(Opts& opts, int argc, char **argv);
+
+private:
+ bool IsValidOpt(char ch);
+ void PrintOpt(char ch, char* text);
+ void UsageOpts(char* program, int code = 0);
+
+ char m_ValidOpts[256];
+};
diff --git a/src/ccapi/common/win/OldCC/secure.cxx b/src/ccapi/common/win/OldCC/secure.cxx
new file mode 100644
index 000000000000..99ba08a25dd4
--- /dev/null
+++ b/src/ccapi/common/win/OldCC/secure.cxx
@@ -0,0 +1,161 @@
+/*
+ * $Header$
+ *
+ * Copyright 2008 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 M.I.T. 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.
+ */
+
+#include <windows.h>
+#include "secure.hxx"
+
+extern "C" {
+#include "cci_debugging.h"
+ }
+
+CcOsLock SecureClient::s_lock;
+DWORD SecureClient::s_refcount = 0;
+DWORD SecureClient::s_error = 0;
+HANDLE SecureClient::s_hToken = 0;
+
+#include "util.h"
+
+#define SC "SecureClient::"
+
+DWORD
+SecureClient::Attach(
+ )
+{
+ CcAutoLock AL(s_lock);
+ if (s_hToken) {
+ s_refcount++;
+ return 0;
+ }
+ if (OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY,
+ &s_hToken)) {
+ s_refcount++;
+ s_error = 0;
+ } else {
+ s_hToken = 0;
+ s_error = GetLastError();
+ }
+ return s_error;
+}
+
+DWORD
+SecureClient::Detach(
+ )
+{
+ CcAutoLock AL(s_lock);
+ s_refcount--;
+ if (s_refcount) return 0;
+ if (!s_hToken) return 0;
+ DWORD error = 0;
+ if (!CloseHandle(s_hToken))
+ error = GetLastError();
+ s_hToken = 0;
+ s_error = 0;
+ return error;
+}
+
+DWORD SecureClient::Token(HANDLE& hToken) {
+ // This function will not do automatic initialization.
+ CcAutoLock AL(s_lock);
+ hToken = 0;
+ if (!s_hToken) {
+ cci_debug_printf("%s no process token initialized (%u)", __FUNCTION__, s_error);
+ return s_error ? s_error : ERROR_INVALID_HANDLE;
+ }
+ else {
+ DWORD status = 0;
+ if (!DuplicateHandle(GetCurrentProcess(), s_hToken,
+ GetCurrentProcess(), &hToken, 0, FALSE,
+ DUPLICATE_SAME_ACCESS)) {
+ status = GetLastError();
+ cci_debug_printf(" Could not duplicate handle (%u)", status);
+ }
+ return status;
+ }
+ }
+
+void
+SecureClient::Start(SecureClient*& s) {
+ s = new SecureClient;
+}
+
+void
+SecureClient::Stop(SecureClient*& s) {
+ delete s;
+ s = 0;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+/* This constructor turns off impersonation.
+ * It is OK for OpenThreadToken to return an error -- that just means impersonation
+ * is off.
+ */
+SecureClient::SecureClient():
+ m_Error(0),
+ m_hToken(0),
+ m_NeedRestore(false) {
+
+ HANDLE hThread = GetCurrentThread();
+ HANDLE hThDuplicate;
+
+ int status = DuplicateHandle( GetCurrentProcess(),
+ hThread,
+ GetCurrentProcess(),
+ &hThDuplicate,
+ TOKEN_ALL_ACCESS,
+ FALSE,
+ 0);
+ if (!status) return;
+
+ if (!OpenThreadToken(hThDuplicate, TOKEN_ALL_ACCESS, FALSE, &m_hToken)) {
+ m_Error = GetLastError();
+ return;
+ }
+ if (SetThreadToken(&hThDuplicate, NULL)) {
+ m_NeedRestore = true;
+ } else {
+ m_Error = GetLastError();
+ }
+ CloseHandle(hThDuplicate);
+ }
+
+SecureClient::~SecureClient() {
+ if (m_NeedRestore) {
+ HANDLE hThread = GetCurrentThread();
+ if (!SetThreadToken(&hThread, m_hToken)) {
+ m_Error = cci_check_error(GetLastError());
+ }
+ }
+ if (m_hToken) {
+ if (!CloseHandle(m_hToken)) {
+ m_Error = cci_check_error(GetLastError());
+ }
+ }
+ }
+
+DWORD SecureClient::Error() {
+ return m_Error;
+ } \ No newline at end of file
diff --git a/src/ccapi/common/win/OldCC/secure.hxx b/src/ccapi/common/win/OldCC/secure.hxx
new file mode 100644
index 000000000000..3714c6f84723
--- /dev/null
+++ b/src/ccapi/common/win/OldCC/secure.hxx
@@ -0,0 +1,60 @@
+/*
+ * $Header$
+ *
+ * Copyright 2008 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 M.I.T. 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.
+ */
+
+#pragma once
+
+#include <windows.h>
+#include "autolock.hxx"
+
+class SecureClient
+{
+public:
+ static DWORD Attach();
+ static DWORD Detach();
+ static DWORD Token(HANDLE& hToken);
+ static void Start(SecureClient*& s);
+ static void Stop(SecureClient*& s);
+
+#if 0
+ static DWORD CheckImpersonation();
+ static bool IsImp();
+ static DWORD DuplicateImpAsPrimary(HANDLE& hPrimary);
+#endif
+
+ SecureClient();
+ ~SecureClient();
+ DWORD Error();
+
+private:
+ static CcOsLock s_lock;
+ static DWORD s_refcount;
+ static DWORD s_error;
+ static HANDLE s_hToken;
+
+ DWORD m_Error;
+ HANDLE m_hToken;
+ bool m_NeedRestore;
+};
diff --git a/src/ccapi/common/win/OldCC/util.cxx b/src/ccapi/common/win/OldCC/util.cxx
new file mode 100644
index 000000000000..dd4a2694ac6b
--- /dev/null
+++ b/src/ccapi/common/win/OldCC/util.cxx
@@ -0,0 +1,520 @@
+/*
+ * $Header$
+ *
+ * Copyright 2008 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 M.I.T. 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.
+ */
+
+#include <windows.h>
+#include <stdio.h> // for _snprintf
+#include <malloc.h>
+#include <stdlib.h>
+
+extern "C" {
+#include "cci_debugging.h"
+#include "ccutils.h"
+ }
+
+#include "util.h"
+#include "secure.hxx"
+
+
+void* malloc_alloc_p(size_t size) {
+ return malloc(size);
+ }
+
+void free_alloc_p(void *pptr) {
+ void **real_pptr = (void**)pptr;
+ if (*real_pptr) {
+ free(*real_pptr);
+ *real_pptr = 0;
+ }
+ }
+
+extern "C" DWORD alloc_textual_sid(
+ PSID pSid, // binary Sid
+ LPSTR *pTextualSid // buffer for Textual representaion of Sid
+ ) {
+ PSID_IDENTIFIER_AUTHORITY psia;
+ DWORD dwSubAuthorities;
+ DWORD dwSidRev = SID_REVISION;
+ DWORD dwCounter;
+ DWORD dwSidSize;
+
+ *pTextualSid = 0;
+
+ //
+ // test if Sid passed in is valid
+ //
+ if(!IsValidSid(pSid)) return ERROR_INVALID_PARAMETER;
+
+ // obtain SidIdentifierAuthority
+ psia = GetSidIdentifierAuthority(pSid);
+
+ // obtain sidsubauthority count
+ dwSubAuthorities =* GetSidSubAuthorityCount(pSid);
+
+ //
+ // compute buffer length
+ // S-SID_REVISION- + identifierauthority- + subauthorities- + NULL
+ //
+ dwSidSize = (15 + 12 + (12 * dwSubAuthorities) + 1) * sizeof(TCHAR);
+ *pTextualSid = (LPSTR)malloc_alloc_p(dwSidSize);
+ if (!*pTextualSid)
+ return GetLastError();
+
+ LPSTR TextualSid = *pTextualSid;
+
+ //
+ // prepare S-SID_REVISION-
+ //
+ wsprintf(TextualSid, TEXT("S-%lu-"), dwSidRev );
+
+ //
+ // prepare SidIdentifierAuthority
+ //
+ if ( (psia->Value[0] != 0) || (psia->Value[1] != 0) )
+ {
+ wsprintf(TextualSid + lstrlen(TextualSid),
+ TEXT("0x%02hx%02hx%02hx%02hx%02hx%02hx"),
+ (USHORT)psia->Value[0],
+ (USHORT)psia->Value[1],
+ (USHORT)psia->Value[2],
+ (USHORT)psia->Value[3],
+ (USHORT)psia->Value[4],
+ (USHORT)psia->Value[5]);
+ }
+ else
+ {
+ wsprintf(TextualSid + lstrlen(TextualSid), TEXT("%lu"),
+ (ULONG)(psia->Value[5] ) +
+ (ULONG)(psia->Value[4] << 8) +
+ (ULONG)(psia->Value[3] << 16) +
+ (ULONG)(psia->Value[2] << 24) );
+ }
+
+ //
+ // loop through SidSubAuthorities
+ //
+ for (dwCounter=0 ; dwCounter < dwSubAuthorities ; dwCounter++)
+ {
+ wsprintf(TextualSid + lstrlen(TextualSid), TEXT("-%lu"),
+ *GetSidSubAuthority(pSid, dwCounter) );
+ }
+ return 0;
+}
+
+DWORD alloc_token_user(HANDLE hToken, PTOKEN_USER *pptu) {
+ DWORD status = 0;
+ DWORD size = 0;
+ *pptu = 0;
+
+ GetTokenInformation(hToken, TokenUser, *pptu, 0, &size);
+ if (size == 0) status = GetLastError();
+
+ if (!status) {
+ if (!(*pptu = (PTOKEN_USER)malloc_alloc_p(size)))
+ status = GetLastError();
+ }
+
+ if (!status) {
+ if (!GetTokenInformation(hToken, TokenUser, *pptu, size, &size))
+ status = GetLastError();
+ }
+
+ if (status && *pptu) {
+ free_alloc_p(pptu);
+ }
+ return status;
+ }
+
+DWORD
+alloc_username(
+ PSID Sid,
+ LPSTR* pname,
+ LPSTR* pdomain = 0
+ )
+{
+ DWORD status = 0;
+ DWORD name_len = 0;
+ DWORD domain_len = 0;
+ SID_NAME_USE snu;
+ LPSTR name = 0;
+ LPSTR domain = 0;
+
+ *pname = 0;
+ if (pdomain) *pdomain = 0;
+
+ LookupAccountSidA(NULL, Sid, 0, &name_len, 0, &domain_len, &snu);
+ if ((name_len == 0) || (domain_len == 0)) status = GetLastError();
+
+ if (!status) {
+ if (!(name = (LPSTR)malloc_alloc_p(name_len))) status = GetLastError();
+ }
+
+ if (!status) {
+ if (!(domain = (LPSTR)malloc_alloc_p(domain_len))) status = GetLastError();
+ }
+
+ if (!status) {
+ if (!LookupAccountSidA(NULL, Sid, name, &name_len, domain, &domain_len, &snu)) status = GetLastError();
+ }
+
+ if (status) {
+ if (name) free_alloc_p(&name);
+ if (domain) free_alloc_p(&domain);
+ }
+ else {
+ if (pdomain) {
+ *pname = name;
+ *pdomain = domain;
+ }
+ else {
+ DWORD size = name_len + domain_len + 1;
+ *pname = (LPSTR)malloc_alloc_p(size);
+ if (!*pname) status = GetLastError();
+ else _snprintf(*pname, size, "%s\\%s", name, domain);
+ }
+ }
+ return status;
+ }
+
+DWORD get_authentication_id(HANDLE hToken, LUID* pAuthId) {
+ TOKEN_STATISTICS ts;
+ DWORD len;
+
+ if (!GetTokenInformation(hToken, TokenStatistics, &ts, sizeof(ts), &len))
+ return GetLastError();
+ *pAuthId = ts.AuthenticationId;
+ return 0;
+ }
+
+DWORD
+alloc_name_9x(
+ LPSTR* pname,
+ LPSTR postfix
+ )
+{
+ char prefix[] = "krbcc";
+ DWORD len = (sizeof(prefix) - 1) + 1 + strlen(postfix) + 1;
+
+ *pname = (LPSTR)malloc_alloc_p(len);
+ if (!*pname) return GetLastError();
+ _snprintf(*pname, len, "%s.%s", prefix, postfix);
+ return 0;
+}
+
+DWORD alloc_name_NT(LPSTR* pname, LPSTR postfix) {
+ DWORD status = 0;
+ HANDLE hToken = 0;
+ LUID auth_id;
+#ifdef _DEBUG
+ PTOKEN_USER ptu = 0;
+ LPSTR name = 0;
+ LPSTR domain = 0;
+ LPSTR sid = 0;
+#endif
+ char prefix[] = "krbcc";
+ // Play it safe and say 3 characters are needed per 8 bits (byte).
+ // Note that 20 characters are needed for a 64-bit number in
+ // decimal (plus one for the string termination.
+ // and include room for sessionId.
+ char lid[3*sizeof(LUID)+1+5];
+ DWORD sessionId;
+ DWORD len = 0;
+
+ *pname = 0;
+
+ status = SecureClient::Token(hToken);
+
+ if (!status) {
+ status = get_authentication_id(hToken, &auth_id);
+ }
+
+ if (!status) {
+ if (!ProcessIdToSessionId(GetCurrentProcessId(), &sessionId))
+ sessionId = 0;
+ }
+
+#ifdef _DEBUG
+ if (!status) {status = alloc_token_user(hToken, &ptu);}
+ if (!status) {status = alloc_username(ptu->User.Sid, &name, &domain);}
+ if (!status) {status = alloc_textual_sid(ptu->User.Sid, &sid);}
+#endif
+
+ if (!status) {
+ _snprintf(lid, sizeof(lid), "%I64u.%u", auth_id, sessionId);
+ lid[sizeof(lid)-1] = 0; // be safe
+
+ len = (sizeof(prefix) - 1) + 1 + strlen(lid) + 1 + strlen(postfix) + 1;
+ *pname = (LPSTR)malloc_alloc_p(len);
+ if (!*pname) status = GetLastError();
+ }
+
+ //
+ // We used to allocate a name of the form:
+ // "prefix.domain.name.sid.lid.postfix" (usually under 80
+ // characters, depending on username). However, XP thought this
+ // was "invalid" (too long?) for some reason.
+ //
+ // Therefore, we now use "prefix.lid.postfix"
+ // and for Terminal server we use "prefix.lid.sessionId.postfix"
+ //
+
+ if (!status) {
+ _snprintf(*pname, len, "%s.%s.%s", prefix, lid, postfix);
+ }
+
+#ifdef _DEBUG
+ if (sid)
+ free_alloc_p(&sid);
+ if (name)
+ free_alloc_p(&name);
+ if (domain)
+ free_alloc_p(&domain);
+ if (ptu)
+ free_alloc_p(&ptu);
+#endif
+ if (hToken && hToken != INVALID_HANDLE_VALUE)
+ CloseHandle(hToken);
+ if (status && *pname)
+ free_alloc_p(pname);
+ return status;
+}
+
+extern "C" DWORD alloc_name(LPSTR* pname, LPSTR postfix, BOOL isNT) {
+ return isNT ? alloc_name_NT(pname, postfix) :
+ alloc_name_9x(pname, postfix);
+ }
+
+extern "C" DWORD alloc_own_security_descriptor_NT(PSECURITY_DESCRIPTOR* ppsd) {
+ DWORD status = 0;
+ HANDLE hToken = 0;
+ PTOKEN_USER ptu = 0;
+ PSID pSid = 0;
+ PACL pAcl = 0;
+ DWORD size = 0;
+ SECURITY_DESCRIPTOR sd;
+
+ *ppsd = 0;
+
+ if (!status) {status = SecureClient::Token(hToken);}
+
+ // Get SID:
+ if (!status) {status = alloc_token_user(hToken, &ptu);}
+
+ if (!status) {
+ size = GetLengthSid(ptu->User.Sid);
+ pSid = (PSID) malloc_alloc_p(size);
+ if (!pSid) status = GetLastError();
+ }
+ if (!status) {
+ if (!CopySid(size, pSid, ptu->User.Sid)) status = GetLastError();
+ }
+
+ if (!status) {
+ // Prepare ACL:
+ size = sizeof(ACL);
+ // Add an ACE:
+ size += sizeof(ACCESS_ALLOWED_ACE) - sizeof(DWORD) + GetLengthSid(pSid);
+ pAcl = (PACL) malloc_alloc_p(size);
+ if (!pAcl) status = GetLastError();
+ }
+
+ if (!status) {
+ if (!InitializeAcl(pAcl, size, ACL_REVISION)) status = GetLastError();
+ }
+
+ if (!status) {
+ if (!AddAccessAllowedAce(pAcl, ACL_REVISION, GENERIC_ALL, pSid)) status = GetLastError();
+ }
+
+ if (!status) {
+ // Prepare SD itself:
+ if (!InitializeSecurityDescriptor(&sd, SECURITY_DESCRIPTOR_REVISION)) status = GetLastError();
+ }
+
+ if (!status) {
+ if (!SetSecurityDescriptorDacl(&sd, TRUE, pAcl, FALSE)) status = GetLastError();
+ }
+
+ if (!status) {
+ if (!SetSecurityDescriptorOwner(&sd, pSid, FALSE)) status = GetLastError();
+ }
+
+ if (!status) {
+ if (!IsValidSecurityDescriptor(&sd)) status = ERROR_INVALID_PARAMETER;
+ }
+
+ if (!status) {
+ // We now have a SD. Let's copy it.
+ {
+ // This should not succeed. Instead it should give us the size.
+ BOOL ok = MakeSelfRelativeSD(&sd, 0, &size);
+ }
+ if (size == 0) status = GetLastError();
+ }
+
+ if (!status) {
+ *ppsd = (PSECURITY_DESCRIPTOR) malloc_alloc_p(size);
+ if (!*ppsd) status = GetLastError();
+ }
+
+ if (!status) {
+ if (!MakeSelfRelativeSD(&sd, *ppsd, &size)) status = GetLastError();
+ }
+
+ if (ptu) free_alloc_p(&ptu);
+ if (pSid) free_alloc_p(&pSid);
+ if (pAcl) free_alloc_p(&pAcl);
+ if (hToken && hToken != INVALID_HANDLE_VALUE) CloseHandle(hToken);
+ if (status && *ppsd) free_alloc_p(ppsd);
+ return status;
+}
+
+DWORD
+alloc_module_file_name(
+ char* module,
+ char** pname
+ )
+{
+ const DWORD max = 8192;
+ DWORD status = 0;
+ DWORD got = 0;
+ DWORD size = 512; // use low number to test...
+ HMODULE h = 0;
+ BOOL ok = FALSE;
+ char* name = 0;
+
+ if (!pname)
+ return ERROR_INVALID_PARAMETER;
+ *pname = 0;
+
+ h = GetModuleHandle(module);
+
+ if (!h) return GetLastError();
+
+ // We assume size < max and size > 0
+ while (!status && !ok) {
+ if (size > max) {
+ // XXX - Assert?
+ status = ERROR_INVALID_DATA;
+ continue;
+ }
+ if (name) free_alloc_p(&name);
+ name = (char*)malloc_alloc_p(size + 1);
+ if (!name) {
+ status = ERROR_NOT_ENOUGH_MEMORY;
+ continue;
+ }
+ name[size] = 0;
+ got = GetModuleFileName(h, name, size);
+ if (!got) {
+ status = GetLastError();
+ // sanity check:
+ if (!status) {
+ // XXX - print nasty message...assert?
+ status = ERROR_INVALID_DATA;
+ }
+ continue;
+ }
+ // To know we're ok, we need to verify that what we got
+ // was bigger than GetModuleSize thought it got.
+ ok = got && (got < size) && !name[got];
+ size *= 2;
+ }
+ if (status && name)
+ free_alloc_p(&name);
+ else
+ *pname = name;
+ return status;
+}
+
+DWORD
+alloc_module_dir_name(
+ char* module,
+ char** pname
+ )
+{
+ DWORD status = alloc_module_file_name(module, pname);
+ if (!status) {
+ char* name = *pname;
+ char* p = name + strlen(name);
+ while ((p >= name) && (*p != '\\') && (*p != '/')) p--;
+ if (p < name) {
+ free_alloc_p(pname);
+ status = ERROR_INVALID_DATA;
+ } else {
+ *p = 0;
+ }
+ }
+ return status;
+}
+
+DWORD
+alloc_module_dir_name_with_file(
+ char* module,
+ char* file,
+ char** pname
+ )
+{
+ DWORD status = alloc_module_dir_name(module, pname);
+ if (!status) {
+ char* name = *pname;
+ size_t name_size = strlen(name);
+ size_t size = name_size + 1 + strlen(file) + 1;
+ char* result = (char*)malloc_alloc_p(size);
+ if (!result) {
+ status = ERROR_NOT_ENOUGH_MEMORY;
+ free_alloc_p(pname);
+ } else {
+ strcpy(result, name);
+ result[name_size] = '\\';
+ strcpy(result + name_size + 1, file);
+ free_alloc_p(pname);
+ *pname = result;
+ }
+ }
+ return status;
+}
+
+DWORD alloc_cmdline_2_args(char* prog,
+ char* arg1,
+ char* arg2,
+ char** pname) {
+ DWORD status = 0;
+ size_t size = strlen(prog) + strlen(arg1) + strlen(arg2) + 4;
+ char* result = (char*)malloc_alloc_p(size);
+ if (!result) {
+ status = ERROR_NOT_ENOUGH_MEMORY;
+ }
+ else {
+ strcpy(result, prog);
+ strcat(result, " ");
+ strcat(result, arg1);
+ strcat(result, " ");
+ strcat(result, arg2);
+ *pname = result;
+ }
+ cci_debug_printf("%s made <%s>", __FUNCTION__, result);
+ return status;
+ }
diff --git a/src/ccapi/common/win/OldCC/util.h b/src/ccapi/common/win/OldCC/util.h
new file mode 100644
index 000000000000..082f6080b2dd
--- /dev/null
+++ b/src/ccapi/common/win/OldCC/util.h
@@ -0,0 +1,88 @@
+/* ccapi/common/win/OldCC/util.h */
+/*
+ * Copyright 2008 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 M.I.T. 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.
+ */
+
+#ifndef __UTIL_H__
+#define __UTIL_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+#if 0
+}
+#endif
+
+BOOL isNT();
+
+void*
+user_allocate(
+ size_t size
+ );
+
+void
+user_free(
+ void* ptr
+ );
+
+void
+free_alloc_p(
+ void* pptr
+ );
+
+DWORD
+alloc_name(
+ LPSTR* pname,
+ LPSTR postfix,
+ BOOL isNT
+ );
+
+DWORD
+alloc_own_security_descriptor_NT(
+ PSECURITY_DESCRIPTOR* ppsd
+ );
+
+DWORD
+alloc_module_dir_name(
+ char* module,
+ char** pname
+ );
+
+DWORD
+alloc_module_dir_name_with_file(
+ char* module,
+ char* file,
+ char** pname
+ );
+
+DWORD alloc_cmdline_2_args(
+ char* prog,
+ char* arg1,
+ char* arg2,
+ char** pname);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __UTIL_H__ */
diff --git a/src/ccapi/common/win/cci_os_debugging.c b/src/ccapi/common/win/cci_os_debugging.c
new file mode 100644
index 000000000000..597ac8560534
--- /dev/null
+++ b/src/ccapi/common/win/cci_os_debugging.c
@@ -0,0 +1,40 @@
+/* ccapi/common/win/cci_os_debugging.c */
+/*
+ * Copyright 2008 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 M.I.T. 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.
+ */
+
+#include <stdio.h>
+#include <stdarg.h>
+
+#include "cci_os_debugging.h"
+#include "win-utils.h"
+
+/* ------------------------------------------------------------------------ */
+
+void cci_os_debug_vprintf (const char *in_format, va_list in_args) {
+#ifdef DEBUG
+ printf ( "%s %ld ", timestamp(), GetCurrentThreadId() );
+ vprintf ( in_format, in_args );
+ printf ( "\n" );
+#endif
+ }
diff --git a/src/ccapi/common/win/cci_os_identifier.c b/src/ccapi/common/win/cci_os_identifier.c
new file mode 100644
index 000000000000..4be2638bd0ee
--- /dev/null
+++ b/src/ccapi/common/win/cci_os_identifier.c
@@ -0,0 +1,57 @@
+/* ccapi/common/win/cci_os_identifier.c */
+/*
+ * Copyright 2008 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 M.I.T. 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.
+ */
+
+#include "cci_common.h"
+#include "cci_os_identifier.h"
+
+#include <rpc.h>
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 cci_os_identifier_new_uuid (cci_uuid_string_t *out_uuid_string) {
+ cc_int32 err = ccNoError;
+ UUID uuid;
+ char* uuidStringTemp;
+
+ err = UuidCreate(&uuid);
+
+ if (!err) {
+ err = UuidToString(&uuid, &uuidStringTemp);
+ }
+
+ if (!err) {
+ *out_uuid_string = malloc(1+strlen(uuidStringTemp));
+
+ if (*out_uuid_string) {
+ strcpy(*out_uuid_string, uuidStringTemp);
+ }
+
+ RpcStringFree(&uuidStringTemp);
+ }
+
+ cci_debug_printf("cci_os_identifier_new_uuid returning %s", *out_uuid_string);
+
+ return cci_check_error (err);
+ } \ No newline at end of file
diff --git a/src/ccapi/common/win/ccs_reply.Acf b/src/ccapi/common/win/ccs_reply.Acf
new file mode 100644
index 000000000000..aea44d74c62f
--- /dev/null
+++ b/src/ccapi/common/win/ccs_reply.Acf
@@ -0,0 +1,31 @@
+/*
+ * $Header$
+ *
+ * Copyright 2008 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 M.I.T. 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.
+ */
+
+[implicit_handle(handle_t ccs_reply_IfHandle)]
+
+interface ccs_reply {
+ [async] ccapi_listen();
+ }
diff --git a/src/ccapi/common/win/ccs_reply.Idl b/src/ccapi/common/win/ccs_reply.Idl
new file mode 100644
index 000000000000..73e818682eb7
--- /dev/null
+++ b/src/ccapi/common/win/ccs_reply.Idl
@@ -0,0 +1,60 @@
+/*
+ * $Header$
+ *
+ * Copyright 2008 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 M.I.T. 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.
+ */
+
+[ uuid (6E3B5060-CA46-1067-B31A-00DD010662DA),
+ version(1.0),
+ pointer_default(unique)
+]
+
+/* This interface sends a cci_stream via rpc.
+ */
+
+interface ccs_reply {
+ const long HSIZE = 8;
+
+/* The reply from the server to a request from the client: */
+void ccs_rpc_request_reply(
+ [in] const long rpcmsg, /* Message type */
+ [in, size_is(HSIZE)] const char tsphandle[],
+ [in, string] const char* uuid,
+ [in] const long srvStartTime, /* Server Start Time */
+ [in] const long cbIn, /* Length of buffer */
+ [in, size_is(cbIn)] const unsigned char chIn[], /* Data buffer */
+ [out] long* status ); /* Return code */
+
+void ccs_rpc_connect_reply(
+ [in] const long rpcmsg, /* Message type */
+ [in, size_is(HSIZE)] const char tsphandle[],
+ [in, string] const char* uuid,
+ [in] const long srvStartTime, /* Server Start Time */
+ [out] long* status ); /* Return code */
+
+void ccapi_listen(
+ handle_t hBinding,
+ [in] const long rpcmsg, /* Message type */
+ [out] long* status ); /* Return code */
+
+ }
diff --git a/src/ccapi/common/win/ccs_request.Acf b/src/ccapi/common/win/ccs_request.Acf
new file mode 100644
index 000000000000..625bcce6532b
--- /dev/null
+++ b/src/ccapi/common/win/ccs_request.Acf
@@ -0,0 +1,31 @@
+/*
+ * $Header$
+ *
+ * Copyright 2008 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 M.I.T. 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.
+ */
+
+[implicit_handle(handle_t ccs_request_IfHandle)]
+interface ccs_request
+{
+
+}
diff --git a/src/ccapi/common/win/ccs_request.idl b/src/ccapi/common/win/ccs_request.idl
new file mode 100644
index 000000000000..cad5e4444860
--- /dev/null
+++ b/src/ccapi/common/win/ccs_request.idl
@@ -0,0 +1,58 @@
+/*
+ * $Header$
+ *
+ * Copyright 2008 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 M.I.T. 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.
+ */
+
+[ uuid (906B0CE0-C70B-1067-B317-00DD010662DA),
+ version(1.0),
+ pointer_default(unique)
+]
+
+interface ccs_request {
+
+typedef char CC_CHAR;
+typedef unsigned char CC_UCHAR;
+typedef int CC_INT32;
+typedef unsigned int CC_UINT32;
+
+const long HSIZE = 8;
+
+void ccs_rpc_request(
+ [in] const long rpcmsg, /* Message type */
+ [in, size_is(HSIZE)] const char tsphandle[],
+ [in, string] const char* pszUUID, /* Requestor's UUID */
+ [in] const long lenRequest, /* Length of buffer */
+ [in, size_is(lenRequest)] const char* pszRequest, /* Data buffer */
+ [in] const long serverStartTime,/* Which server session we're talking to */
+ [out] long* status ); /* Return code */
+
+void ccs_rpc_connect(
+ [in] const long rpcmsg, /* Message type */
+ [in, size_is(HSIZE)] const char tsphandle[],
+ [in, string] const char* pszUUID, /* Requestor's UUID */
+ [out] long* status ); /* Return code */
+
+CC_UINT32 ccs_authenticate(
+ [in, string] const CC_CHAR* name );
+}
diff --git a/src/ccapi/common/win/tls.c b/src/ccapi/common/win/tls.c
new file mode 100644
index 000000000000..6c13d5a98151
--- /dev/null
+++ b/src/ccapi/common/win/tls.c
@@ -0,0 +1,77 @@
+/* ccapi/common/win/tls.c */
+/*
+ * Copyright 2008 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 M.I.T. 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.
+ */
+
+#include "string.h"
+#include <stdlib.h>
+#include <malloc.h>
+
+#include "tls.h"
+
+void tspdata_setUUID(struct tspdata* p, unsigned char __RPC_FAR* uuidString) {
+ strncpy(p->_uuid, uuidString, UUID_SIZE-1);
+ };
+
+void tspdata_setListening (struct tspdata* p, BOOL b) {p->_listening = b;}
+
+void tspdata_setConnected (struct tspdata* p, BOOL b) {p->_CCAPI_Connected = b;}
+
+void tspdata_setReplyEvent(struct tspdata* p, HANDLE h) {p->_replyEvent = h;}
+
+void tspdata_setRpcAState (struct tspdata* p, RPC_ASYNC_STATE* rpcState) {
+ p->_rpcState = rpcState;}
+
+void tspdata_setSST (struct tspdata* p, time_t t) {p->_sst = t;}
+
+void tspdata_setStream (struct tspdata* p, k5_ipc_stream s) {p->_stream = s;}
+
+BOOL tspdata_getListening (const struct tspdata* p) {return p->_listening;}
+
+BOOL tspdata_getConnected (const struct tspdata* p) {return p->_CCAPI_Connected;}
+
+HANDLE tspdata_getReplyEvent(const struct tspdata* p) {return p->_replyEvent;}
+
+time_t tspdata_getSST (const struct tspdata* p) {return p->_sst;}
+
+k5_ipc_stream tspdata_getStream (const struct tspdata* p) {return p->_stream;}
+
+char* tspdata_getUUID (const struct tspdata* p) {return p->_uuid;}
+
+RPC_ASYNC_STATE* tspdata_getRpcAState (const struct tspdata* p) {return p->_rpcState;}
+
+
+BOOL WINAPI GetTspData(DWORD dwTlsIndex, struct tspdata** pdw) {
+ struct tspdata* pData; // The stored memory pointer
+
+ pData = (struct tspdata*)TlsGetValue(dwTlsIndex);
+ if (pData == NULL) {
+ pData = malloc(sizeof(*pData));
+ if (pData == NULL)
+ return FALSE;
+ memset(pData, 0, sizeof(*pData));
+ TlsSetValue(dwTlsIndex, pData);
+ }
+ (*pdw) = pData;
+ return TRUE;
+ }
diff --git a/src/ccapi/common/win/tls.h b/src/ccapi/common/win/tls.h
new file mode 100644
index 000000000000..bd2bb9e1e0d4
--- /dev/null
+++ b/src/ccapi/common/win/tls.h
@@ -0,0 +1,71 @@
+/* ccapi/common/win/tls.h */
+/*
+ * Copyright 2008 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 M.I.T. 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.
+ */
+
+/* Thread local storage for client threads. */
+
+#ifndef _tls_h
+#define _tls_h
+
+#include "windows.h"
+#include "time.h"
+#include "rpc.h"
+
+#include "k5-ipc_stream.h"
+
+#define UUID_SIZE 128
+
+/* The client code can be run in any client thread.
+ The thread-specific data is defined here.
+ */
+
+struct tspdata {
+ BOOL _listening;
+ BOOL _CCAPI_Connected;
+ RPC_ASYNC_STATE* _rpcState;
+ HANDLE _replyEvent;
+ time_t _sst;
+ k5_ipc_stream _stream;
+ char _uuid[UUID_SIZE];
+ };
+
+void tspdata_setListening (struct tspdata* p, BOOL b);
+void tspdata_setConnected (struct tspdata* p, BOOL b);
+void tspdata_setReplyEvent(struct tspdata* p, HANDLE h);
+void tspdata_setRpcAState (struct tspdata* p, RPC_ASYNC_STATE* rpcState);
+void tspdata_setSST (struct tspdata* p, time_t t);
+void tspdata_setStream (struct tspdata* p, k5_ipc_stream s);
+void tspdata_setUUID (struct tspdata* p, unsigned char __RPC_FAR* uuidString);
+HANDLE tspdata_getReplyEvent(const struct tspdata* p);
+
+BOOL tspdata_getListening(const struct tspdata* p);
+BOOL tspdata_getConnected(const struct tspdata* p);
+RPC_ASYNC_STATE* tspdata_getRpcAState(const struct tspdata* p);
+time_t tspdata_getSST (const struct tspdata* p);
+k5_ipc_stream tspdata_getStream (const struct tspdata* p);
+char* tspdata_getUUID (const struct tspdata* p);
+
+BOOL WINAPI GetTspData(DWORD tlsIndex, struct tspdata** pdw);
+
+#endif _tls_h
diff --git a/src/ccapi/common/win/win-utils.c b/src/ccapi/common/win/win-utils.c
new file mode 100644
index 000000000000..b49cca85f037
--- /dev/null
+++ b/src/ccapi/common/win/win-utils.c
@@ -0,0 +1,68 @@
+/* ccapi/common/win/win-utils.c */
+/*
+ * Copyright 2008 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 M.I.T. 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.
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <time.h>
+#include "windows.h"
+#include <stdlib.h>
+#include <malloc.h>
+
+
+#include "win-utils.h"
+#include "cci_debugging.h"
+
+#pragma warning (disable : 4996)
+
+#define UUID_SIZE 128
+
+char* clientPrefix = "CCAPI_CLIENT_";
+char* serverPrefix = "CCS_LISTEN_";
+unsigned char* pszProtocolSequence = "ncalrpc";
+
+#define MAX_TIMESTAMP 40
+char _ts[MAX_TIMESTAMP];
+
+char* clientEndpoint(const char* UUID) {
+ char* _clientEndpoint = (char*)malloc(strlen(UUID) + strlen(clientPrefix) + 2);
+ strcpy(_clientEndpoint, clientPrefix);
+ strncat(_clientEndpoint, UUID, UUID_SIZE);
+// cci_debug_printf("%s returning %s", __FUNCTION__, _clientEndpoint);
+ return _clientEndpoint;
+ }
+
+char* serverEndpoint(const char* user) {
+ char* _serverEndpoint = (char*)malloc(strlen(user) + strlen(serverPrefix) + 2);
+ strcpy(_serverEndpoint, serverPrefix);
+ strncat(_serverEndpoint, user, UUID_SIZE);
+ return _serverEndpoint;
+ }
+
+char* timestamp() {
+ SYSTEMTIME _stime;
+ GetSystemTime(&_stime);
+ GetTimeFormat(LOCALE_SYSTEM_DEFAULT, 0, &_stime, "HH:mm:ss", _ts, sizeof(_ts)-1);
+ return _ts;
+ }
diff --git a/src/ccapi/common/win/win-utils.h b/src/ccapi/common/win/win-utils.h
new file mode 100644
index 000000000000..41cab24dcdff
--- /dev/null
+++ b/src/ccapi/common/win/win-utils.h
@@ -0,0 +1,55 @@
+/* ccapi/common/win/win-utils.h */
+/*
+ * Copyright 2008 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 M.I.T. 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.
+ */
+
+#ifndef _win_utils_h
+#define _win_utils_h
+
+#ifndef TRUE
+#define TRUE (1==1)
+#endif
+
+#ifndef FALSE
+#define FALSE (1==0)
+#endif
+
+static enum ccapiMsgType {
+ CCMSG_INVALID = 0,
+ CCMSG_CONNECT,
+ CCMSG_REQUEST,
+ CCMSG_CONNECT_REPLY,
+ CCMSG_REQUEST_REPLY,
+ CCMSG_DISCONNECT,
+ CCMSG_LISTEN,
+ CCMSG_PING,
+ CCMSG_QUIT
+ };
+
+char* clientEndpoint(const char* UUID);
+char* serverEndpoint(const char* UUID);
+extern unsigned char* pszProtocolSequence;
+
+char* timestamp();
+
+#endif // _win_utils_h \ No newline at end of file
diff --git a/src/ccapi/deps b/src/ccapi/deps
new file mode 100644
index 000000000000..2feac3c9d388
--- /dev/null
+++ b/src/ccapi/deps
@@ -0,0 +1 @@
+# No dependencies here.
diff --git a/src/ccapi/doc/CCAPI-Windows-Design.html b/src/ccapi/doc/CCAPI-Windows-Design.html
new file mode 100644
index 000000000000..72af7e92a7ba
--- /dev/null
+++ b/src/ccapi/doc/CCAPI-Windows-Design.html
@@ -0,0 +1,148 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
+<title>Windows CCAPI RPC design</title>
+<style type="text/css">
+<!--
+.style2 {color: 0}
+.style3 {font-family: "Courier New", Courier, monospace}
+.style5 {color: #CC3300}
+.style6 {color: #999999}
+.style7 {color: #000099}
+-->
+</style>
+</head>
+
+<body>
+<h2 class="style5">Proposed RPC design for Windows CCAPI clients and server</h2>
+<p>The proposal is for a single user; the solution is replicated for each user logged onto the PC.</p>
+<h2>Conventions &amp; clarifications </h2>
+<p>&quot;Client&quot; and &quot;server&quot; refer to the CCAPI client and server. </p>
+<p>The CCAPI client acts as both an RPC client and RPC server and the CCAPI server acts as both an RPC client and RPC server. </p>
+<ul>
+ <li class="style2">The RPC call from the CCAPI client to the CCAPI server is called the &quot;request.&quot; In this mode, the CCAPI client is the RPC client and the CCAPI server is the RPC server.</li>
+ <li class="style2">The RPC call from the CCAPI server to the CCAPI client is called the &quot;reply.&quot; In this mode, the CCAPI client is the RPC server and the CCAPI server is the RPC client. </li>
+</ul>
+<p>The Windows username is referred to below as &quot;&lt;USER&gt;.&quot; </p>
+<p>The Windows Logon Security Identifier is referred to as &quot;&lt;LSID&gt;.&quot; </p>
+<p>&lt;UUID&gt; means a thread-specific UUID.</p>
+<p>&lt;SST&gt; means <strong>s</strong>erver <strong>s</strong>tart <strong>t</strong>ime, a time_t. </p>
+<p>A description of client and server authentication has not been added yet.</p>
+<h2>Design Requirements </h2>
+<ul>
+ <li>The server's OS-independent code is single threaded, because it must operate on platforms that do not allow multiple threads. </li>
+ <li>The client and server must be able to maintain connections, where state is maintained between individual messages.</li>
+ <li>Individual messages must be handled in a single threaded server. </li>
+ <li>The server must be able to detect when a client dies, so that any connection state can be cleaned up. </li>
+</ul>
+<h2>Design</h2>
+<p>The server and each client create an RPC endpoint. The server's endpoint is CCS_&lt;LSID&gt; and the client's endpoint is CCAPI_&lt;UUID&gt;, where each client geta a UUID. </p>
+<p>On Windows, the server's ccs_pipe_t type is a char* and is set to the client UUID.</p>
+<h3>How is the request handled in the server and the reply sent to the client? </h3>
+<p>One straightforward way is for the reply to be the returned data in the request RPC call (an [out] parameter). That is, data passed from the RPC server to the RPC client. The request handler calls <span class="style3">ccs_server_handle_request</span>. Eventually, the server code calls <span class="style3">ccs_os_server_send_reply, </span>which saves the reply somewhere. When the server eventually returns to the request handler, the handler returns the saved reply to the client.</p>
+<p>But this doesn't work. If two clients A and B ask for the same lock, A will acquire the lock and B will have to wait. But if the single threaded server waits for B's lock, it will never handle A's unlock message. Therefore the server must return to B's request handler and <em>not </em>send a reply to B. So this method will not work. </p>
+<p>Instead, there are listener and worker threads in Windows-specific code. </p>
+<p>The client's <span class="style3">cci_os_ipc </span>function waits for <span class="style3">ccs_reply</span>. The client sends the request, including <em>it's UUID, </em>from which the server can construct the endpoint on which to call <span class="style3">ccs_reply</span>. </p>
+<p>The server's listener thread listens for RPC requests. The request handler puts each request/<em>reply</em> endpoint in a queue and returns to the client.</p>
+<p>The server's worker thread removes items from the queue, calls <span class="style3">ccs_server_handle_request</span>. <span class="style3">ccs_server_handle_request</span> takes both the request data and the client UUID . Eventually <span class="style3">ccs_os_server_send_reply</span> is called, with the reply data and client UUID in the reply_pipe. <span class="style3">ccs_os_server_send_reply</span> calls <span class="style3">ccs_reply </span>on the client's endpoint, which sends the reply to the client. </p>
+<p>Is there any security issue with the client listening for RPC calls from the server?</p>
+<h3>Connections</h3>
+<p>If the client wants state to be maintained on the server, the client creates a connection. When the connection is closed, the server cleans up any state associated with the connection. </p>
+<p>Any given thread in an application process could want to create a connection. When cci_ipc_thread_init is called, the connection thread-local variables are initialized. New connections are created when cci_os_ipc() (via _cci_ipc_send) is called and no connection was previously established. Basically we lazily establish connections so the client doesn't talk to the server until it has to.</p>
+<h3>Detecting client exit</h3>
+<p>The server must be able to detect when clients disappear, so the server can free any resources that had been held for the client. </p>
+<p>The Windows RPC API does not appear to provide a notification for an endpoint disappearing. It does provide a way to ask if an endpoint is listening. This is useful for polling, but we want a better performing solution than that. </p>
+<p>The client has an <em>isAlive </em>function on its endpoint. </p>
+<p>To detect the client disappearing without using polling, the server makes an asynchronous call to the <em>isAlive </em>function on the client's endpoint. The <em>isAlive </em>function never returns. When the client exits for any reason, it's <em></em>endpoint will be closed and the server's function call will return an error. The asynchronous call on the server means no additional threads are used. </p>
+<p>Windows provides a number of notification methods to signal I/O completion. Among them are I/O completion ports and callback functions. I chose callback functions because they appear to consume fewer resources. </p>
+<h3>RPC Endpoint / Function summary</h3>
+<ul>
+ <li>The server creates one CCS_&lt;LSID&gt; endpoint to listen for connection requests and client requests.
+ It has the functions
+ <ul>
+ <li>ccs_rpc_connect(msgtype, UUIDlen, &lt;UUID&gt;, status)</li>
+ <li>ccs_rpc_request(msgtype, UUIDlen, &lt;UUID&gt;, msglen, msg, SST, status) called by client. NB: The windows server sets the <span class="style3">in_client_pipe </span>to the <span class="style3">in_reply_pipe</span>.<br />
+ </li>
+ </ul>
+ </li>
+ <li>Each client thread creates a CCAPI_&lt;UUID&gt; endpoint. It has the functions
+ <ul>
+ <li>isAlive [function never returns.] </li>
+ <li>ccs_rpc_request_reply(msgtype, SST, replylen, reply, status)</li>
+ <li>ccs_rpc_connect_reply(msgtype, SST, status</li>
+ </ul>
+ </li>
+</ul>
+<h2>Windows-specific implementation details </h2>
+<h3>Client CCAPI library initialization:</h3>
+<p>This code runs when the CCAPI DLL is loaded. </p>
+<ul>
+ <li>?</li>
+</ul>
+<h3>Client initialization: </h3>
+<p>This code runs when cci_os_ipc_thread_init is called: </p>
+<ul>
+ <li>Generate &lt;UUID&gt; and save in thread-specific storage. This serves as the client ID / ccs_pipe_t. </li>
+ <li>Create client endpoint.</li>
+ <li>Listen on client <em></em>endpoint.</li>
+ <li>Create canonical server connection endpoint from the &lt;LSID&gt;, which the client and server should have in common. </li>
+ <li>Test if server is listening to the CCS_&lt;LSID&gt; endpoint.
+ <ul>
+ <li>If not, quit. (! Start it?) </li>
+ </ul>
+ </li>
+ <li>Call ccs_connect(&lt;UUID&gt;) on the CCS_&lt;LSID&gt; endpoint.</li>
+ <li>Save SST in thread-specific storage. </li>
+</ul>
+<h3>Server initialization:</h3>
+<p class="style6">[old]</p>
+<ul>
+ <li class="style6">Server is initialized by client starting a new process. There should be only one server process per Windows username. </li>
+</ul>
+<p class="style7">[new]</p>
+<ul>
+ <li class="style7">Server is started by kfwlogon (as is done currently). </li>
+ <li>Capture <strong>s</strong>erver <strong>s</strong>tart <strong>t</strong>ime (SST). </li>
+ <li>Start listener thread, create listener endpoint, listen on CCS_&lt;LSID&gt; endpoint. </li>
+</ul>
+<h3>Establishing a connection: </h3>
+<ul>
+ <li>Client calls ccs_connect(&lt;UUID&gt;) on server's CCS_&lt;LSID&gt; endpoint.</li>
+ <li>Client gets back and stores SST in thread-specific storage.</li>
+ <li>If new connection, server ...
+ <ul>
+ <li>adds connection to connection table</li>
+ <li>calls isAlive on CCAPI_&lt;UUID&gt;.
+ <ul>
+ <li>NB: isAlive never returns. </li>
+ </ul>
+ </li>
+ </ul>
+ </li>
+</ul>
+<h3>Client request:</h3>
+<p>The server's reply to the client's request is not synchronous.</p>
+<ul>
+ <li>Client calls ccs_rpc_request(msglen, msg, msgtype, UUIDlen, &lt;UUID&gt;, SST, status) on server's endpoint.</li>
+ <li>Server listen thread receives message, queues request.</li>
+ <li>Server worker thread dequeues request, processes, calls ccs_rpc_reply(replylen, reply, msgtype, status) on CCAPI_&lt;UUID&gt;.</li>
+ <li>Server checks SST. If server's SST is different, it means server has restarted since client created connection. </li>
+ <li>Client receives reply. </li>
+</ul>
+<h3>Detecting client exit</h3>
+<ul>
+ <li>When connection created, client created an endpoint.</li>
+ <li>Server calls isAlive on client's endpoint. </li>
+ <li>When isAlive returns, the server's notification callback will be called. Call back routine queues a DISCONNECT pseudo-message. When the server's worker thread handles the DISCONNECT, it will release connection resources.</li>
+</ul>
+<h3>Detecting server exit </h3>
+<ul>
+ <li>Client's call to ccs_rpc_request will return an error if the server has gone away. </li>
+</ul>
+<p>&nbsp;</p>
+<p>------<br />
+ Stop: <br />
+Start: </p>
+</body>
+</html>
diff --git a/src/ccapi/lib/Makefile.in b/src/ccapi/lib/Makefile.in
new file mode 100644
index 000000000000..14e7d7b6ea18
--- /dev/null
+++ b/src/ccapi/lib/Makefile.in
@@ -0,0 +1,61 @@
+mydir=ccapi$(S)lib
+BUILDTOP=$(REL)..$(S)..
+SUBDIRS=unix
+LOCALINCLUDES=-I$(srcdir)/../common -I.
+
+SHLIB_EXPDEPS= $(COM_ERR_DEPLIB) $(SUPPORT_DEPLIB)
+SHLIB_EXPLIBS=-lcom_err $(SUPPORT_LIB)
+RELDIR=../ccapi/lib
+
+LIBBASE=krb5-ccapi
+LIBMAJOR=1
+LIBMINOR=0
+
+STOBJLISTS= \
+ OBJS.ST \
+ unix/OBJS.ST
+
+STLIBOBJS= \
+ ccapi_ccache.o \
+ ccapi_ccache_iterator.o \
+ ccapi_context.o \
+ ccapi_context_change_time.o \
+ ccapi_credentials.o \
+ ccapi_credentials_iterator.o \
+ ccapi_err.o \
+ ccapi_ipc.o \
+ ccapi_string.o \
+ ccapi_v2.o
+
+OBJS= \
+ $(OUTPRE)ccapi_ccache.$(OUTPRE) \
+ $(OUTPRE)ccapi_ccache_iterator.$(OUTPRE) \
+ $(OUTPRE)ccapi_context.$(OUTPRE) \
+ $(OUTPRE)ccapi_context_change_time.$(OUTPRE) \
+ $(OUTPRE)ccapi_credentials.$(OUTPRE) \
+ $(OUTPRE)ccapi_credentials_iterator.$(OUTPRE) \
+ $(OUTPRE)ccapi_err.$(OUTPRE) \
+ $(OUTPRE)ccapi_ipc.$(OUTPRE) \
+ $(OUTPRE)ccapi_string.$(OUTPRE) \
+ $(OUTPRE)ccapi_v2.$(OUTPRE)
+
+SRCS= \
+ ccapi_ccache.c \
+ ccapi_ccache_iterator.c \
+ ccapi_context.c \
+ ccapi_context_change_time.c \
+ ccapi_credentials.c \
+ ccapi_credentials_iterator.c \
+ ccapi_err.c \
+ ccapi_ipc.c \
+ ccapi_string.c \
+ ccapi_v2.c
+
+ccapi_err.c ccapi_err.h : ccapi_err.et
+
+all-unix: all-libobjs all-liblinks
+clean-unix:: clean-libobjs clean-liblinks clean-libs
+
+@lib_frag@
+@libobj_frag@
+
diff --git a/src/ccapi/lib/ccapi.exports b/src/ccapi/lib/ccapi.exports
new file mode 100644
index 000000000000..92c859bd745f
--- /dev/null
+++ b/src/ccapi/lib/ccapi.exports
@@ -0,0 +1 @@
+cc_initialize
diff --git a/src/ccapi/lib/ccapi_ccache.c b/src/ccapi/lib/ccapi_ccache.c
new file mode 100644
index 000000000000..9e8ba36c5c4e
--- /dev/null
+++ b/src/ccapi/lib/ccapi_ccache.c
@@ -0,0 +1,793 @@
+/* ccapi/lib/ccapi_ccache.c */
+/*
+ * Copyright 2006, 2007 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 M.I.T. 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.
+ */
+
+#include "ccapi_ccache.h"
+
+#include "ccapi_string.h"
+#include "ccapi_credentials.h"
+#include "ccapi_credentials_iterator.h"
+#include "ccapi_ipc.h"
+
+/* ------------------------------------------------------------------------ */
+
+typedef struct cci_ccache_d {
+ cc_ccache_f *functions;
+#if TARGET_OS_MAC
+ cc_ccache_f *vector_functions;
+#endif
+ cci_identifier_t identifier;
+ cc_time_t last_wait_for_change_time;
+ cc_uint32 compat_version;
+} *cci_ccache_t;
+
+/* ------------------------------------------------------------------------ */
+
+struct cci_ccache_d cci_ccache_initializer = {
+ NULL
+ VECTOR_FUNCTIONS_INITIALIZER,
+ NULL,
+ 0
+};
+
+cc_ccache_f cci_ccache_f_initializer = {
+ ccapi_ccache_release,
+ ccapi_ccache_destroy,
+ ccapi_ccache_set_default,
+ ccapi_ccache_get_credentials_version,
+ ccapi_ccache_get_name,
+ ccapi_ccache_get_principal,
+ ccapi_ccache_set_principal,
+ ccapi_ccache_store_credentials,
+ ccapi_ccache_remove_credentials,
+ ccapi_ccache_new_credentials_iterator,
+ ccapi_ccache_move,
+ ccapi_ccache_lock,
+ ccapi_ccache_unlock,
+ ccapi_ccache_get_last_default_time,
+ ccapi_ccache_get_change_time,
+ ccapi_ccache_compare,
+ ccapi_ccache_get_kdc_time_offset,
+ ccapi_ccache_set_kdc_time_offset,
+ ccapi_ccache_clear_kdc_time_offset,
+ ccapi_ccache_wait_for_change
+};
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 cci_ccache_new (cc_ccache_t *out_ccache,
+ cci_identifier_t in_identifier)
+{
+ cc_int32 err = ccNoError;
+ cci_ccache_t ccache = NULL;
+
+ if (!out_ccache ) { err = cci_check_error (ccErrBadParam); }
+ if (!in_identifier) { err = cci_check_error (ccErrBadParam); }
+
+ if (!err) {
+ ccache = malloc (sizeof (*ccache));
+ if (ccache) {
+ *ccache = cci_ccache_initializer;
+ } else {
+ err = cci_check_error (ccErrNoMem);
+ }
+ }
+
+ if (!err) {
+ ccache->functions = malloc (sizeof (*ccache->functions));
+ if (ccache->functions) {
+ *ccache->functions = cci_ccache_f_initializer;
+ } else {
+ err = cci_check_error (ccErrNoMem);
+ }
+ }
+
+ if (!err) {
+ err = cci_identifier_copy (&ccache->identifier, in_identifier);
+ }
+
+ if (!err) {
+ *out_ccache = (cc_ccache_t) ccache;
+ ccache = NULL; /* take ownership */
+ }
+
+ ccapi_ccache_release ((cc_ccache_t) ccache);
+
+ return cci_check_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 cci_ccache_write (cc_ccache_t in_ccache,
+ k5_ipc_stream in_stream)
+{
+ cc_int32 err = ccNoError;
+ cci_ccache_t ccache = (cci_ccache_t) in_ccache;
+
+ if (!in_ccache) { err = cci_check_error (ccErrBadParam); }
+ if (!in_stream) { err = cci_check_error (ccErrBadParam); }
+
+ if (!err) {
+ err = cci_identifier_write (ccache->identifier, in_stream);
+ }
+
+ return cci_check_error (err);
+}
+
+#ifdef TARGET_OS_MAC
+#pragma mark -
+#endif
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 ccapi_ccache_release (cc_ccache_t io_ccache)
+{
+ cc_int32 err = ccNoError;
+ cci_ccache_t ccache = (cci_ccache_t) io_ccache;
+
+ if (!io_ccache) { err = ccErrBadParam; }
+
+ if (!err) {
+ cci_identifier_release (ccache->identifier);
+
+ free ((char *) ccache->functions);
+ free (ccache);
+ }
+
+ return err;
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 ccapi_ccache_destroy (cc_ccache_t io_ccache)
+{
+ cc_int32 err = ccNoError;
+ cci_ccache_t ccache = (cci_ccache_t) io_ccache;
+
+ if (!io_ccache) { err = cci_check_error (ccErrBadParam); }
+
+ if (!err) {
+ err = cci_ipc_send (cci_ccache_destroy_msg_id,
+ ccache->identifier,
+ NULL,
+ NULL);
+ }
+
+ if (!err) {
+ err = ccapi_ccache_release (io_ccache);
+ }
+
+ return cci_check_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 ccapi_ccache_set_default (cc_ccache_t io_ccache)
+{
+ cc_int32 err = ccNoError;
+ cci_ccache_t ccache = (cci_ccache_t) io_ccache;
+
+ if (!io_ccache) { err = cci_check_error (ccErrBadParam); }
+
+ if (!err) {
+ err = cci_ipc_send (cci_ccache_set_default_msg_id,
+ ccache->identifier,
+ NULL,
+ NULL);
+ }
+
+ return cci_check_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 ccapi_ccache_get_credentials_version (cc_ccache_t in_ccache,
+ cc_uint32 *out_credentials_version)
+{
+ cc_int32 err = ccNoError;
+ cci_ccache_t ccache = (cci_ccache_t) in_ccache;
+ k5_ipc_stream reply = NULL;
+
+ if (!in_ccache ) { err = cci_check_error (ccErrBadParam); }
+ if (!out_credentials_version) { err = cci_check_error (ccErrBadParam); }
+
+ if (!err) {
+ err = cci_ipc_send (cci_ccache_get_credentials_version_msg_id,
+ ccache->identifier,
+ NULL,
+ &reply);
+ }
+
+ if (!err) {
+ err = krb5int_ipc_stream_read_uint32 (reply, out_credentials_version);
+ }
+
+ krb5int_ipc_stream_release (reply);
+
+ return cci_check_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 ccapi_ccache_get_name (cc_ccache_t in_ccache,
+ cc_string_t *out_name)
+{
+ cc_int32 err = ccNoError;
+ cci_ccache_t ccache = (cci_ccache_t) in_ccache;
+ k5_ipc_stream reply = NULL;
+ char *name = NULL;
+
+ if (!in_ccache) { err = cci_check_error (ccErrBadParam); }
+ if (!out_name ) { err = cci_check_error (ccErrBadParam); }
+
+ if (!err) {
+ err = cci_ipc_send (cci_ccache_get_name_msg_id,
+ ccache->identifier,
+ NULL,
+ &reply);
+ }
+
+ if (!err) {
+ err = krb5int_ipc_stream_read_string (reply, &name);
+ }
+
+ if (!err) {
+ err = cci_string_new (out_name, name);
+ }
+
+ krb5int_ipc_stream_release (reply);
+ krb5int_ipc_stream_free_string (name);
+
+ return cci_check_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 ccapi_ccache_get_principal (cc_ccache_t in_ccache,
+ cc_uint32 in_credentials_version,
+ cc_string_t *out_principal)
+{
+ cc_int32 err = ccNoError;
+ cci_ccache_t ccache = (cci_ccache_t) in_ccache;
+ k5_ipc_stream request = NULL;
+ k5_ipc_stream reply = NULL;
+ char *principal = NULL;
+
+ if (!in_ccache ) { err = cci_check_error (ccErrBadParam); }
+ if (!out_principal) { err = cci_check_error (ccErrBadParam); }
+
+ if (!err) {
+ err = krb5int_ipc_stream_new (&request);
+ }
+
+ if (!err) {
+ err = krb5int_ipc_stream_write_uint32 (request, in_credentials_version);
+ }
+
+ if (!err) {
+ err = cci_ipc_send (cci_ccache_get_principal_msg_id,
+ ccache->identifier,
+ request,
+ &reply);
+ }
+
+ if (!err) {
+ err = krb5int_ipc_stream_read_string (reply, &principal);
+ }
+
+ if (!err) {
+ err = cci_string_new (out_principal, principal);
+ }
+
+ krb5int_ipc_stream_release (request);
+ krb5int_ipc_stream_release (reply);
+ krb5int_ipc_stream_free_string (principal);
+
+ return cci_check_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 ccapi_ccache_set_principal (cc_ccache_t io_ccache,
+ cc_uint32 in_credentials_version,
+ const char *in_principal)
+{
+ cc_int32 err = ccNoError;
+ cci_ccache_t ccache = (cci_ccache_t) io_ccache;
+ k5_ipc_stream request = NULL;
+
+ if (!io_ccache ) { err = cci_check_error (ccErrBadParam); }
+ if (!in_principal) { err = cci_check_error (ccErrBadParam); }
+
+ if (!err) {
+ err = krb5int_ipc_stream_new (&request);
+ }
+
+ if (!err) {
+ err = krb5int_ipc_stream_write_uint32 (request, in_credentials_version);
+ }
+
+ if (!err) {
+ err = krb5int_ipc_stream_write_string (request, in_principal);
+ }
+
+ if (!err) {
+ err = cci_ipc_send (cci_ccache_set_principal_msg_id,
+ ccache->identifier,
+ request,
+ NULL);
+ }
+
+ krb5int_ipc_stream_release (request);
+
+ return cci_check_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 ccapi_ccache_store_credentials (cc_ccache_t io_ccache,
+ const cc_credentials_union *in_credentials_union)
+{
+ cc_int32 err = ccNoError;
+ cci_ccache_t ccache = (cci_ccache_t) io_ccache;
+ k5_ipc_stream request = NULL;
+
+ if (!io_ccache ) { err = cci_check_error (ccErrBadParam); }
+ if (!in_credentials_union) { err = cci_check_error (ccErrBadParam); }
+
+ if (!err) {
+ err = krb5int_ipc_stream_new (&request);
+ }
+
+ if (!err) {
+ err = cci_credentials_union_write (in_credentials_union, request);
+ }
+
+ if (!err) {
+ err = cci_ipc_send (cci_ccache_store_credentials_msg_id,
+ ccache->identifier,
+ request,
+ NULL);
+ }
+
+ krb5int_ipc_stream_release (request);
+
+ return cci_check_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 ccapi_ccache_remove_credentials (cc_ccache_t io_ccache,
+ cc_credentials_t in_credentials)
+{
+ cc_int32 err = ccNoError;
+ cci_ccache_t ccache = (cci_ccache_t) io_ccache;
+ k5_ipc_stream request = NULL;
+
+ if (!io_ccache ) { err = cci_check_error (ccErrBadParam); }
+ if (!in_credentials) { err = cci_check_error (ccErrBadParam); }
+
+ if (!err) {
+ err = krb5int_ipc_stream_new (&request);
+ }
+
+ if (!err) {
+ err = cci_credentials_write (in_credentials, request);
+ }
+
+ if (!err) {
+ err = cci_ipc_send (cci_ccache_remove_credentials_msg_id,
+ ccache->identifier,
+ request,
+ NULL);
+ }
+
+ krb5int_ipc_stream_release (request);
+
+ return cci_check_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 ccapi_ccache_new_credentials_iterator (cc_ccache_t in_ccache,
+ cc_credentials_iterator_t *out_credentials_iterator)
+{
+ cc_int32 err = ccNoError;
+ cci_ccache_t ccache = (cci_ccache_t) in_ccache;
+ k5_ipc_stream reply = NULL;
+ cci_identifier_t identifier = NULL;
+
+ if (!in_ccache ) { err = cci_check_error (ccErrBadParam); }
+ if (!out_credentials_iterator) { err = cci_check_error (ccErrBadParam); }
+
+ if (!err) {
+ err = cci_ipc_send (cci_ccache_new_credentials_iterator_msg_id,
+ ccache->identifier,
+ NULL,
+ &reply);
+ }
+
+ if (!err) {
+ err = cci_identifier_read (&identifier, reply);
+ }
+
+ if (!err) {
+ err = cci_credentials_iterator_new (out_credentials_iterator, identifier);
+ }
+
+ krb5int_ipc_stream_release (reply);
+ cci_identifier_release (identifier);
+
+ return cci_check_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+/* Note: message is sent as the destination to avoid extra work on the */
+/* server when deleting it the source ccache. */
+
+cc_int32 ccapi_ccache_move (cc_ccache_t io_source_ccache,
+ cc_ccache_t io_destination_ccache)
+{
+ cc_int32 err = ccNoError;
+ cci_ccache_t source_ccache = (cci_ccache_t) io_source_ccache;
+ cci_ccache_t destination_ccache = (cci_ccache_t) io_destination_ccache;
+ k5_ipc_stream request = NULL;
+
+ if (!io_source_ccache ) { err = cci_check_error (ccErrBadParam); }
+ if (!io_destination_ccache) { err = cci_check_error (ccErrBadParam); }
+
+ if (!err) {
+ err = krb5int_ipc_stream_new (&request);
+ }
+
+ if (!err) {
+ err = cci_identifier_write (source_ccache->identifier, request);
+ }
+
+ if (!err) {
+ err = cci_ipc_send (cci_ccache_move_msg_id,
+ destination_ccache->identifier,
+ request,
+ NULL);
+ }
+
+ krb5int_ipc_stream_release (request);
+
+ return cci_check_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 ccapi_ccache_lock (cc_ccache_t io_ccache,
+ cc_uint32 in_lock_type,
+ cc_uint32 in_block)
+{
+ cc_int32 err = ccNoError;
+ cci_ccache_t ccache = (cci_ccache_t) io_ccache;
+ k5_ipc_stream request = NULL;
+
+ if (!io_ccache) { err = cci_check_error (ccErrBadParam); }
+
+ if (!err) {
+ err = krb5int_ipc_stream_new (&request);
+ }
+
+ if (!err) {
+ err = krb5int_ipc_stream_write_uint32 (request, in_lock_type);
+ }
+
+ if (!err) {
+ err = krb5int_ipc_stream_write_uint32 (request, in_block);
+ }
+
+ if (!err) {
+ err = cci_ipc_send (cci_ccache_lock_msg_id,
+ ccache->identifier,
+ request,
+ NULL);
+ }
+
+ krb5int_ipc_stream_release (request);
+
+ return cci_check_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 ccapi_ccache_unlock (cc_ccache_t io_ccache)
+{
+ cc_int32 err = ccNoError;
+ cci_ccache_t ccache = (cci_ccache_t) io_ccache;
+
+ if (!io_ccache) { err = cci_check_error (ccErrBadParam); }
+
+ if (!err) {
+ err = cci_ipc_send (cci_ccache_unlock_msg_id,
+ ccache->identifier,
+ NULL,
+ NULL);
+ }
+
+ return cci_check_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 ccapi_ccache_get_last_default_time (cc_ccache_t in_ccache,
+ cc_time_t *out_last_default_time)
+{
+ cc_int32 err = ccNoError;
+ cci_ccache_t ccache = (cci_ccache_t) in_ccache;
+ k5_ipc_stream reply = NULL;
+
+ if (!in_ccache ) { err = cci_check_error (ccErrBadParam); }
+ if (!out_last_default_time) { err = cci_check_error (ccErrBadParam); }
+
+ if (!err) {
+ err = cci_ipc_send (cci_ccache_get_last_default_time_msg_id,
+ ccache->identifier,
+ NULL,
+ &reply);
+ }
+
+ if (!err) {
+ err = krb5int_ipc_stream_read_time (reply, out_last_default_time);
+ }
+
+ krb5int_ipc_stream_release (reply);
+
+ return cci_check_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 ccapi_ccache_get_change_time (cc_ccache_t in_ccache,
+ cc_time_t *out_change_time)
+{
+ cc_int32 err = ccNoError;
+ cci_ccache_t ccache = (cci_ccache_t) in_ccache;
+ k5_ipc_stream reply = NULL;
+
+ if (!in_ccache ) { err = cci_check_error (ccErrBadParam); }
+ if (!out_change_time) { err = cci_check_error (ccErrBadParam); }
+
+ if (!err) {
+ err = cci_ipc_send (cci_ccache_get_change_time_msg_id,
+ ccache->identifier,
+ NULL,
+ &reply);
+ }
+
+ if (!err) {
+ err = krb5int_ipc_stream_read_time (reply, out_change_time);
+ }
+
+ krb5int_ipc_stream_release (reply);
+
+ return cci_check_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 ccapi_ccache_wait_for_change (cc_ccache_t in_ccache)
+{
+ cc_int32 err = ccNoError;
+ cci_ccache_t ccache = (cci_ccache_t) in_ccache;
+ k5_ipc_stream request = NULL;
+ k5_ipc_stream reply = NULL;
+
+ if (!in_ccache) { err = cci_check_error (ccErrBadParam); }
+
+ if (!err) {
+ err = krb5int_ipc_stream_new (&request);
+ }
+
+ if (!err) {
+ err = krb5int_ipc_stream_write_time (request, ccache->last_wait_for_change_time);
+ }
+
+ if (!err) {
+ err = cci_ipc_send (cci_ccache_wait_for_change_msg_id,
+ ccache->identifier,
+ request,
+ &reply);
+ }
+
+ if (!err) {
+ err = krb5int_ipc_stream_read_time (reply, &ccache->last_wait_for_change_time);
+ }
+
+ krb5int_ipc_stream_release (request);
+ krb5int_ipc_stream_release (reply);
+
+ return cci_check_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 ccapi_ccache_compare (cc_ccache_t in_ccache,
+ cc_ccache_t in_compare_to_ccache,
+ cc_uint32 *out_equal)
+{
+ cc_int32 err = ccNoError;
+ cci_ccache_t ccache = (cci_ccache_t) in_ccache;
+ cci_ccache_t compare_to_ccache = (cci_ccache_t) in_compare_to_ccache;
+
+ if (!in_ccache ) { err = cci_check_error (ccErrBadParam); }
+ if (!in_compare_to_ccache) { err = cci_check_error (ccErrBadParam); }
+ if (!out_equal ) { err = cci_check_error (ccErrBadParam); }
+
+ if (!err) {
+ err = cci_identifier_compare (ccache->identifier,
+ compare_to_ccache->identifier,
+ out_equal);
+ }
+
+ return cci_check_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 ccapi_ccache_get_kdc_time_offset (cc_ccache_t in_ccache,
+ cc_uint32 in_credentials_version,
+ cc_time_t *out_time_offset)
+{
+ cc_int32 err = ccNoError;
+ cci_ccache_t ccache = (cci_ccache_t) in_ccache;
+ k5_ipc_stream request = NULL;
+ k5_ipc_stream reply = NULL;
+
+ if (!in_ccache ) { err = cci_check_error (ccErrBadParam); }
+ if (!out_time_offset) { err = cci_check_error (ccErrBadParam); }
+
+ if (!err) {
+ err = krb5int_ipc_stream_new (&request);
+ }
+
+ if (!err) {
+ err = krb5int_ipc_stream_write_uint32 (request, in_credentials_version);
+ }
+
+ if (!err) {
+ err = cci_ipc_send (cci_ccache_get_kdc_time_offset_msg_id,
+ ccache->identifier,
+ request,
+ &reply);
+ }
+
+ if (!err) {
+ err = krb5int_ipc_stream_read_time (reply, out_time_offset);
+ }
+
+ krb5int_ipc_stream_release (request);
+ krb5int_ipc_stream_release (reply);
+
+ return cci_check_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 ccapi_ccache_set_kdc_time_offset (cc_ccache_t io_ccache,
+ cc_uint32 in_credentials_version,
+ cc_time_t in_time_offset)
+{
+ cc_int32 err = ccNoError;
+ cci_ccache_t ccache = (cci_ccache_t) io_ccache;
+ k5_ipc_stream request = NULL;
+
+ if (!io_ccache) { err = cci_check_error (ccErrBadParam); }
+
+ if (!err) {
+ err = krb5int_ipc_stream_new (&request);
+ }
+
+ if (!err) {
+ err = krb5int_ipc_stream_write_uint32 (request, in_credentials_version);
+ }
+
+ if (!err) {
+ err = krb5int_ipc_stream_write_time (request, in_time_offset);
+ }
+
+ if (!err) {
+ err = cci_ipc_send (cci_ccache_set_kdc_time_offset_msg_id,
+ ccache->identifier,
+ request,
+ NULL);
+ }
+
+ krb5int_ipc_stream_release (request);
+
+ return cci_check_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 ccapi_ccache_clear_kdc_time_offset (cc_ccache_t io_ccache,
+ cc_uint32 in_credentials_version)
+{
+ cc_int32 err = ccNoError;
+ cci_ccache_t ccache = (cci_ccache_t) io_ccache;
+ k5_ipc_stream request = NULL;
+
+ if (!io_ccache) { err = cci_check_error (ccErrBadParam); }
+
+ if (!err) {
+ err = krb5int_ipc_stream_new (&request);
+ }
+
+ if (!err) {
+ err = krb5int_ipc_stream_write_uint32 (request, in_credentials_version);
+ }
+
+ if (!err) {
+ err = cci_ipc_send (cci_ccache_clear_kdc_time_offset_msg_id,
+ ccache->identifier,
+ request,
+ NULL);
+ }
+
+ krb5int_ipc_stream_release (request);
+
+ return cci_check_error (err);
+}
+
+#ifdef TARGET_OS_MAC
+#pragma mark -
+#endif
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 cci_ccache_get_compat_version (cc_ccache_t in_ccache,
+ cc_uint32 *out_compat_version)
+{
+ cc_int32 err = ccNoError;
+ cci_ccache_t ccache = (cci_ccache_t) in_ccache;
+
+ if (!in_ccache ) { err = cci_check_error (ccErrBadParam); }
+ if (!out_compat_version) { err = cci_check_error (ccErrBadParam); }
+
+ if (!err) {
+ *out_compat_version = ccache->compat_version;
+ }
+
+ return cci_check_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 cci_ccache_set_compat_version (cc_ccache_t io_ccache,
+ cc_uint32 in_compat_version)
+{
+ cc_int32 err = ccNoError;
+ cci_ccache_t ccache = (cci_ccache_t) io_ccache;
+
+ if (!io_ccache) { err = cci_check_error (ccErrBadParam); }
+
+ if (!err) {
+ ccache->compat_version = in_compat_version;
+ }
+
+ return cci_check_error (err);
+}
diff --git a/src/ccapi/lib/ccapi_ccache.h b/src/ccapi/lib/ccapi_ccache.h
new file mode 100644
index 000000000000..e6fc129abbe8
--- /dev/null
+++ b/src/ccapi/lib/ccapi_ccache.h
@@ -0,0 +1,105 @@
+/* ccapi/lib/ccapi_ccache.h */
+/*
+ * Copyright 2006 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 M.I.T. 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.
+ */
+
+#ifndef CCAPI_CCACHE_H
+#define CCAPI_CCACHE_H
+
+#include "cci_common.h"
+
+cc_int32 cci_ccache_new (cc_ccache_t *out_ccache,
+ cci_identifier_t in_identifier);
+
+cc_int32 ccapi_ccache_release (cc_ccache_t io_ccache);
+
+cc_int32 cci_ccache_write (cc_ccache_t in_ccache,
+ k5_ipc_stream in_stream);
+
+cc_int32 ccapi_ccache_destroy (cc_ccache_t io_ccache);
+
+cc_int32 ccapi_ccache_set_default (cc_ccache_t io_ccache);
+
+cc_int32 ccapi_ccache_get_credentials_version (cc_ccache_t in_ccache,
+ cc_uint32 *out_credentials_version);
+
+cc_int32 ccapi_ccache_get_name (cc_ccache_t in_ccache,
+ cc_string_t *out_name);
+
+cc_int32 ccapi_ccache_get_principal (cc_ccache_t in_ccache,
+ cc_uint32 in_credentials_version,
+ cc_string_t *out_principal);
+
+cc_int32 ccapi_ccache_set_principal (cc_ccache_t io_ccache,
+ cc_uint32 in_credentials_version,
+ const char *in_principal);
+
+cc_int32 ccapi_ccache_store_credentials (cc_ccache_t io_ccache,
+ const cc_credentials_union *in_credentials_union);
+
+cc_int32 ccapi_ccache_remove_credentials (cc_ccache_t io_ccache,
+ cc_credentials_t in_credentials);
+
+cc_int32 ccapi_ccache_new_credentials_iterator (cc_ccache_t in_ccache,
+ cc_credentials_iterator_t *out_credentials_iterator);
+
+cc_int32 ccapi_ccache_move (cc_ccache_t io_source_ccache,
+ cc_ccache_t io_destination_ccache);
+
+cc_int32 ccapi_ccache_lock (cc_ccache_t io_ccache,
+ cc_uint32 in_lock_type,
+ cc_uint32 in_block);
+
+cc_int32 ccapi_ccache_unlock (cc_ccache_t io_ccache);
+
+cc_int32 ccapi_ccache_get_last_default_time (cc_ccache_t in_ccache,
+ cc_time_t *out_last_default_time);
+
+cc_int32 ccapi_ccache_get_change_time (cc_ccache_t in_ccache,
+ cc_time_t *out_change_time);
+
+cc_int32 ccapi_ccache_wait_for_change (cc_ccache_t in_ccache);
+
+cc_int32 ccapi_ccache_compare (cc_ccache_t in_ccache,
+ cc_ccache_t in_compare_to_ccache,
+ cc_uint32 *out_equal);
+
+cc_int32 ccapi_ccache_get_kdc_time_offset (cc_ccache_t in_ccache,
+ cc_uint32 in_credentials_version,
+ cc_time_t *out_time_offset);
+
+cc_int32 ccapi_ccache_set_kdc_time_offset (cc_ccache_t io_ccache,
+ cc_uint32 in_credentials_version,
+ cc_time_t in_time_offset);
+
+cc_int32 ccapi_ccache_clear_kdc_time_offset (cc_ccache_t io_ccache,
+ cc_uint32 in_credentials_version);
+
+cc_int32 cci_ccache_get_compat_version (cc_ccache_t in_ccache,
+ cc_uint32 *out_compat_version);
+
+cc_int32 cci_ccache_set_compat_version (cc_ccache_t io_ccache,
+ cc_uint32 in_compat_version);
+
+
+#endif /* CCAPI_CCACHE_H */
diff --git a/src/ccapi/lib/ccapi_ccache_iterator.c b/src/ccapi/lib/ccapi_ccache_iterator.c
new file mode 100644
index 000000000000..795610d974f8
--- /dev/null
+++ b/src/ccapi/lib/ccapi_ccache_iterator.c
@@ -0,0 +1,291 @@
+/* ccapi/lib/ccapi_ccache_iterator.c */
+/*
+ * Copyright 2006 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 M.I.T. 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.
+ */
+
+#include "ccapi_ccache_iterator.h"
+#include "ccapi_ccache.h"
+#include "ccapi_ipc.h"
+
+/* ------------------------------------------------------------------------ */
+
+typedef struct cci_ccache_iterator_d {
+ cc_ccache_iterator_f *functions;
+#if TARGET_OS_MAC
+ cc_ccache_iterator_f *vector_functions;
+#endif
+ cci_identifier_t identifier;
+ char *saved_ccache_name;
+} *cci_ccache_iterator_t;
+
+/* ------------------------------------------------------------------------ */
+
+struct cci_ccache_iterator_d cci_ccache_iterator_initializer = {
+ NULL
+ VECTOR_FUNCTIONS_INITIALIZER,
+ NULL,
+ NULL
+};
+
+cc_ccache_iterator_f cci_ccache_iterator_f_initializer = {
+ ccapi_ccache_iterator_release,
+ ccapi_ccache_iterator_next,
+ ccapi_ccache_iterator_clone
+};
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 cci_ccache_iterator_new (cc_ccache_iterator_t *out_ccache_iterator,
+ cci_identifier_t in_identifier)
+{
+ cc_int32 err = ccNoError;
+ cci_ccache_iterator_t ccache_iterator = NULL;
+
+ if (!in_identifier ) { err = cci_check_error (ccErrBadParam); }
+ if (!out_ccache_iterator) { err = cci_check_error (ccErrBadParam); }
+
+ if (!err) {
+ ccache_iterator = malloc (sizeof (*ccache_iterator));
+ if (ccache_iterator) {
+ *ccache_iterator = cci_ccache_iterator_initializer;
+ } else {
+ err = cci_check_error (ccErrNoMem);
+ }
+ }
+
+ if (!err) {
+ ccache_iterator->functions = malloc (sizeof (*ccache_iterator->functions));
+ if (ccache_iterator->functions) {
+ *ccache_iterator->functions = cci_ccache_iterator_f_initializer;
+ } else {
+ err = cci_check_error (ccErrNoMem);
+ }
+ }
+
+ if (!err) {
+ err = cci_identifier_copy (&ccache_iterator->identifier, in_identifier);
+ }
+
+ if (!err) {
+ *out_ccache_iterator = (cc_ccache_iterator_t) ccache_iterator;
+ ccache_iterator = NULL; /* take ownership */
+ }
+
+ ccapi_ccache_iterator_release ((cc_ccache_iterator_t) ccache_iterator);
+
+ return cci_check_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 cci_ccache_iterator_write (cc_ccache_iterator_t in_ccache_iterator,
+ k5_ipc_stream in_stream)
+{
+ cc_int32 err = ccNoError;
+ cci_ccache_iterator_t ccache_iterator = (cci_ccache_iterator_t) in_ccache_iterator;
+
+ if (!in_ccache_iterator) { err = cci_check_error (ccErrBadParam); }
+ if (!in_stream ) { err = cci_check_error (ccErrBadParam); }
+
+ if (!err) {
+ err = cci_identifier_write (ccache_iterator->identifier, in_stream);
+ }
+
+ return cci_check_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 ccapi_ccache_iterator_release (cc_ccache_iterator_t io_ccache_iterator)
+{
+ cc_int32 err = ccNoError;
+ cci_ccache_iterator_t ccache_iterator = (cci_ccache_iterator_t) io_ccache_iterator;
+
+ if (!io_ccache_iterator) { err = ccErrBadParam; }
+
+ if (!err) {
+ cc_uint32 initialized = 0;
+
+ err = cci_identifier_is_initialized (ccache_iterator->identifier,
+ &initialized);
+
+ if (!err && initialized) {
+ err = cci_ipc_send (cci_ccache_iterator_release_msg_id,
+ ccache_iterator->identifier,
+ NULL,
+ NULL);
+ if (err) {
+ cci_debug_printf ("%s: cci_ipc_send failed with error %d",
+ __FUNCTION__, err);
+ err = ccNoError;
+ }
+ }
+ }
+
+ if (!err) {
+ free ((char *) ccache_iterator->functions);
+ cci_identifier_release (ccache_iterator->identifier);
+ free (ccache_iterator->saved_ccache_name);
+ free (ccache_iterator);
+ }
+
+ return err;
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 ccapi_ccache_iterator_next (cc_ccache_iterator_t in_ccache_iterator,
+ cc_ccache_t *out_ccache)
+{
+ cc_int32 err = ccNoError;
+ cci_ccache_iterator_t ccache_iterator = (cci_ccache_iterator_t) in_ccache_iterator;
+ k5_ipc_stream reply = NULL;
+ cci_identifier_t identifier = NULL;
+
+ if (!in_ccache_iterator) { err = cci_check_error (ccErrBadParam); }
+ if (!out_ccache ) { err = cci_check_error (ccErrBadParam); }
+
+ if (!err) {
+ cc_uint32 initialized = 0;
+
+ err = cci_identifier_is_initialized (ccache_iterator->identifier,
+ &initialized);
+
+ if (!err && !initialized) {
+ /* server doesn't actually exist. Pretend we're empty. */
+ err = cci_check_error (ccIteratorEnd);
+ }
+ }
+
+ if (!err) {
+ err = cci_ipc_send (cci_ccache_iterator_next_msg_id,
+ ccache_iterator->identifier,
+ NULL,
+ &reply);
+ }
+
+ if (!err) {
+ err = cci_identifier_read (&identifier, reply);
+ }
+
+ if (!err) {
+ err = cci_ccache_new (out_ccache, identifier);
+ }
+
+ krb5int_ipc_stream_release (reply);
+ cci_identifier_release (identifier);
+
+ return cci_check_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 ccapi_ccache_iterator_clone (cc_ccache_iterator_t in_ccache_iterator,
+ cc_ccache_iterator_t *out_ccache_iterator)
+{
+ cc_int32 err = ccNoError;
+ cci_ccache_iterator_t ccache_iterator = (cci_ccache_iterator_t) in_ccache_iterator;
+ k5_ipc_stream reply = NULL;
+ cc_uint32 initialized = 0;
+ cci_identifier_t identifier = NULL;
+
+ if (!in_ccache_iterator ) { err = cci_check_error (ccErrBadParam); }
+ if (!out_ccache_iterator) { err = cci_check_error (ccErrBadParam); }
+
+ if (!err) {
+ err = cci_identifier_is_initialized (ccache_iterator->identifier,
+ &initialized);
+ }
+
+ if (!err) {
+ if (initialized) {
+ err = cci_ipc_send (cci_ccache_iterator_next_msg_id,
+ ccache_iterator->identifier,
+ NULL,
+ &reply);
+
+ if (!err) {
+ err = cci_identifier_read (&identifier, reply);
+ }
+
+ } else {
+ /* server doesn't actually exist. Make another dummy one. */
+ identifier = cci_identifier_uninitialized;
+ }
+ }
+
+ if (!err) {
+ err = cci_ccache_iterator_new (out_ccache_iterator, identifier);
+ }
+
+ cci_identifier_release (identifier);
+ krb5int_ipc_stream_release (reply);
+
+ return cci_check_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 cci_ccache_iterator_get_saved_ccache_name (cc_ccache_iterator_t in_ccache_iterator,
+ const char **out_saved_ccache_name)
+{
+ cc_int32 err = ccNoError;
+ cci_ccache_iterator_t ccache_iterator = (cci_ccache_iterator_t) in_ccache_iterator;
+
+ if (!in_ccache_iterator ) { err = cci_check_error (ccErrBadParam); }
+ if (!out_saved_ccache_name) { err = cci_check_error (ccErrBadParam); }
+
+ if (!err) {
+ *out_saved_ccache_name = ccache_iterator->saved_ccache_name;
+ }
+
+ return cci_check_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 cci_ccache_iterator_set_saved_ccache_name (cc_ccache_iterator_t io_ccache_iterator,
+ const char *in_saved_ccache_name)
+{
+ cc_int32 err = ccNoError;
+ cci_ccache_iterator_t ccache_iterator = (cci_ccache_iterator_t) io_ccache_iterator;
+ char *new_saved_ccache_name = NULL;
+
+ if (!io_ccache_iterator) { err = cci_check_error (ccErrBadParam); }
+
+ if (!err && in_saved_ccache_name) {
+ new_saved_ccache_name = strdup (in_saved_ccache_name);
+ if (!new_saved_ccache_name) { err = ccErrNoMem; }
+ }
+
+ if (!err) {
+ free (ccache_iterator->saved_ccache_name);
+
+ ccache_iterator->saved_ccache_name = new_saved_ccache_name;
+ new_saved_ccache_name = NULL; /* take ownership */
+ }
+
+ free (new_saved_ccache_name);
+
+ return cci_check_error (err);
+}
diff --git a/src/ccapi/lib/ccapi_ccache_iterator.h b/src/ccapi/lib/ccapi_ccache_iterator.h
new file mode 100644
index 000000000000..88947eafd9d6
--- /dev/null
+++ b/src/ccapi/lib/ccapi_ccache_iterator.h
@@ -0,0 +1,51 @@
+/* ccapi/lib/ccapi_ccache_iterator.h */
+/*
+ * Copyright 2006 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 M.I.T. 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.
+ */
+
+#ifndef CCAPI_CCACHE_ITERATOR_H
+#define CCAPI_CCACHE_ITERATOR_H
+
+#include "cci_common.h"
+
+cc_int32 cci_ccache_iterator_new (cc_ccache_iterator_t *out_ccache_iterator,
+ cci_identifier_t in_identifier);
+
+cc_int32 cci_ccache_iterator_write (cc_ccache_iterator_t in_ccache_iterator,
+ k5_ipc_stream in_stream);
+
+cc_int32 ccapi_ccache_iterator_release (cc_ccache_iterator_t io_ccache_iterator);
+
+cc_int32 ccapi_ccache_iterator_next (cc_ccache_iterator_t in_ccache_iterator,
+ cc_ccache_t *out_ccache);
+
+cc_int32 ccapi_ccache_iterator_clone (cc_ccache_iterator_t in_ccache_iterator,
+ cc_ccache_iterator_t *out_ccache_iterator);
+
+cc_int32 cci_ccache_iterator_get_saved_ccache_name (cc_ccache_iterator_t in_ccache_iterator,
+ const char **out_saved_ccache_name);
+
+cc_int32 cci_ccache_iterator_set_saved_ccache_name (cc_ccache_iterator_t io_ccache_iterator,
+ const char *in_saved_ccache_name);
+
+#endif /* CCAPI_CCACHE_ITERATOR_H */
diff --git a/src/ccapi/lib/ccapi_context.c b/src/ccapi/lib/ccapi_context.c
new file mode 100644
index 000000000000..cf677fc55142
--- /dev/null
+++ b/src/ccapi/lib/ccapi_context.c
@@ -0,0 +1,831 @@
+/* ccapi/lib/ccapi_context.c */
+/*
+ * Copyright 2006, 2007 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 M.I.T. 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.
+ */
+
+#include "ccapi_context.h"
+
+#include "k5-platform.h"
+
+#include "ccapi_ccache.h"
+#include "ccapi_ccache_iterator.h"
+#include "ccapi_string.h"
+#include "ccapi_ipc.h"
+#include "ccapi_context_change_time.h"
+#include "ccapi_err.h"
+
+#include <CredentialsCache2.h>
+
+typedef struct cci_context_d {
+ cc_context_f *functions;
+#if TARGET_OS_MAC
+ cc_context_f *vector_functions;
+#endif
+ cci_identifier_t identifier;
+ cc_uint32 synchronized;
+ cc_time_t last_wait_for_change_time;
+} *cci_context_t;
+
+/* ------------------------------------------------------------------------ */
+
+struct cci_context_d cci_context_initializer = {
+ NULL
+ VECTOR_FUNCTIONS_INITIALIZER,
+ NULL,
+ 0,
+ 0
+};
+
+cc_context_f cci_context_f_initializer = {
+ ccapi_context_release,
+ ccapi_context_get_change_time,
+ ccapi_context_get_default_ccache_name,
+ ccapi_context_open_ccache,
+ ccapi_context_open_default_ccache,
+ ccapi_context_create_ccache,
+ ccapi_context_create_default_ccache,
+ ccapi_context_create_new_ccache,
+ ccapi_context_new_ccache_iterator,
+ ccapi_context_lock,
+ ccapi_context_unlock,
+ ccapi_context_compare,
+ ccapi_context_wait_for_change
+};
+
+static cc_int32 cci_context_sync (cci_context_t in_context,
+ cc_uint32 in_launch);
+
+#ifdef TARGET_OS_MAC
+#pragma mark -
+#endif
+
+MAKE_INIT_FUNCTION(cci_process_init);
+MAKE_FINI_FUNCTION(cci_process_fini);
+
+/* ------------------------------------------------------------------------ */
+
+static int cci_process_init (void)
+{
+ cc_int32 err = ccNoError;
+
+ if (!err) {
+ err = cci_context_change_time_thread_init ();
+ }
+
+ if (!err) {
+ err = cci_ipc_process_init ();
+ }
+
+ if (!err) {
+ add_error_table (&et_CAPI_error_table);
+ }
+
+ return err;
+}
+
+/* ------------------------------------------------------------------------ */
+
+static void cci_process_fini (void)
+{
+ if (!INITIALIZER_RAN (cci_process_init) || PROGRAM_EXITING ()) {
+ return;
+ }
+
+ remove_error_table(&et_CAPI_error_table);
+ cci_context_change_time_thread_fini ();
+}
+
+
+#ifdef TARGET_OS_MAC
+#pragma mark -
+#endif
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 cc_initialize (cc_context_t *out_context,
+ cc_int32 in_version,
+ cc_int32 *out_supported_version,
+ char const **out_vendor)
+{
+ cc_int32 err = ccNoError;
+ cci_context_t context = NULL;
+ static char *vendor_string = "MIT Kerberos CCAPI";
+
+ if (!out_context) { err = cci_check_error (ccErrBadParam); }
+
+ if (!err) {
+ err = CALL_INIT_FUNCTION (cci_process_init);
+ }
+
+ if (!err) {
+ switch (in_version) {
+ case ccapi_version_2:
+ case ccapi_version_3:
+ case ccapi_version_4:
+ case ccapi_version_5:
+ case ccapi_version_6:
+ case ccapi_version_7:
+ break;
+
+ default:
+ err = ccErrBadAPIVersion;
+ break;
+ }
+ }
+
+ if (!err) {
+ context = malloc (sizeof (*context));
+ if (context) {
+ *context = cci_context_initializer;
+ } else {
+ err = cci_check_error (ccErrNoMem);
+ }
+ }
+
+ if (!err) {
+ context->functions = malloc (sizeof (*context->functions));
+ if (context->functions) {
+ *context->functions = cci_context_f_initializer;
+ } else {
+ err = cci_check_error (ccErrNoMem);
+ }
+ }
+
+ if (!err) {
+ context->identifier = cci_identifier_uninitialized;
+
+ *out_context = (cc_context_t) context;
+ context = NULL; /* take ownership */
+
+ if (out_supported_version) {
+ *out_supported_version = ccapi_version_max;
+ }
+
+ if (out_vendor) {
+ *out_vendor = vendor_string;
+ }
+ }
+
+ ccapi_context_release ((cc_context_t) context);
+
+ return cci_check_error (err);
+}
+
+#ifdef TARGET_OS_MAC
+#pragma mark -
+#endif
+
+/* ------------------------------------------------------------------------ */
+/*
+ * Currently does not need to talk to the server since the server must
+ * handle cleaning up resources from crashed clients anyway.
+ *
+ * NOTE: if server communication is ever added here, make sure that
+ * krb5_stdcc_shutdown calls an internal function which does not talk to the
+ * server. krb5_stdcc_shutdown is called from thread fini functions and may
+ * crash talking to the server depending on what order the OS calls the fini
+ * functions (ie: if the ipc layer fini function is called first).
+ */
+
+cc_int32 ccapi_context_release (cc_context_t in_context)
+{
+ cc_int32 err = ccNoError;
+ cci_context_t context = (cci_context_t) in_context;
+
+ if (!in_context) { err = ccErrBadParam; }
+
+ if (!err) {
+ cci_identifier_release (context->identifier);
+ free (context->functions);
+ free (context);
+ }
+
+ return err;
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 ccapi_context_get_change_time (cc_context_t in_context,
+ cc_time_t *out_change_time)
+{
+ cc_int32 err = ccNoError;
+ cci_context_t context = (cci_context_t) in_context;
+ k5_ipc_stream reply = NULL;
+
+ if (!in_context ) { err = cci_check_error (ccErrBadParam); }
+ if (!out_change_time) { err = cci_check_error (ccErrBadParam); }
+
+ if (!err) {
+ err = cci_context_sync (context, 0);
+ }
+
+ if (!err) {
+ err = cci_ipc_send_no_launch (cci_context_get_change_time_msg_id,
+ context->identifier,
+ NULL, &reply);
+ }
+
+ if (!err && krb5int_ipc_stream_size (reply) > 0) {
+ cc_time_t change_time = 0;
+
+ /* got a response from the server */
+ err = krb5int_ipc_stream_read_time (reply, &change_time);
+
+ if (!err) {
+ err = cci_context_change_time_update (context->identifier,
+ change_time);
+ }
+ }
+
+ if (!err) {
+ err = cci_context_change_time_get (out_change_time);
+ }
+
+ krb5int_ipc_stream_release (reply);
+
+ return cci_check_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 ccapi_context_wait_for_change (cc_context_t in_context)
+{
+ cc_int32 err = ccNoError;
+ cci_context_t context = (cci_context_t) in_context;
+ k5_ipc_stream request = NULL;
+ k5_ipc_stream reply = NULL;
+
+ if (!in_context) { err = cci_check_error (ccErrBadParam); }
+
+ if (!err) {
+ err = krb5int_ipc_stream_new (&request);
+ }
+
+ if (!err) {
+ err = krb5int_ipc_stream_write_time (request, context->last_wait_for_change_time);
+ }
+
+ if (!err) {
+ err = cci_context_sync (context, 1);
+ }
+
+ if (!err) {
+ err = cci_ipc_send (cci_context_wait_for_change_msg_id,
+ context->identifier,
+ request,
+ &reply);
+ }
+
+ if (!err) {
+ err = krb5int_ipc_stream_read_time (reply, &context->last_wait_for_change_time);
+ }
+
+ krb5int_ipc_stream_release (request);
+ krb5int_ipc_stream_release (reply);
+
+ return cci_check_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 ccapi_context_get_default_ccache_name (cc_context_t in_context,
+ cc_string_t *out_name)
+{
+ cc_int32 err = ccNoError;
+ cci_context_t context = (cci_context_t) in_context;
+ k5_ipc_stream reply = NULL;
+ char *reply_name = NULL;
+ char *name = NULL;
+
+ if (!in_context) { err = cci_check_error (ccErrBadParam); }
+ if (!out_name ) { err = cci_check_error (ccErrBadParam); }
+
+ if (!err) {
+ err = cci_context_sync (context, 0);
+ }
+
+ if (!err) {
+ err = cci_ipc_send_no_launch (cci_context_get_default_ccache_name_msg_id,
+ context->identifier,
+ NULL,
+ &reply);
+ }
+
+ if (!err) {
+ if (krb5int_ipc_stream_size (reply) > 0) {
+ /* got a response from the server */
+ err = krb5int_ipc_stream_read_string (reply, &reply_name);
+
+ if (!err) {
+ name = reply_name;
+ }
+ } else {
+ name = k_cci_context_initial_ccache_name;
+ }
+ }
+
+ if (!err) {
+ err = cci_string_new (out_name, name);
+ }
+
+ krb5int_ipc_stream_release (reply);
+ krb5int_ipc_stream_free_string (reply_name);
+
+ return cci_check_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 ccapi_context_open_ccache (cc_context_t in_context,
+ const char *in_name,
+ cc_ccache_t *out_ccache)
+{
+ cc_int32 err = ccNoError;
+ cci_context_t context = (cci_context_t) in_context;
+ k5_ipc_stream request = NULL;
+ k5_ipc_stream reply = NULL;
+ cci_identifier_t identifier = NULL;
+
+ if (!in_context ) { err = cci_check_error (ccErrBadParam); }
+ if (!in_name ) { err = cci_check_error (ccErrBadParam); }
+ if (!out_ccache ) { err = cci_check_error (ccErrBadParam); }
+
+ if (!err) {
+ err = krb5int_ipc_stream_new (&request);
+ }
+
+ if (!err) {
+ err = krb5int_ipc_stream_write_string (request, in_name);
+ }
+
+ if (!err) {
+ err = cci_context_sync (context, 0);
+ }
+
+ if (!err) {
+ err = cci_ipc_send_no_launch (cci_context_open_ccache_msg_id,
+ context->identifier,
+ request,
+ &reply);
+ }
+
+ if (!err && !(krb5int_ipc_stream_size (reply) > 0)) {
+ err = ccErrCCacheNotFound;
+ }
+
+ if (!err) {
+ err = cci_identifier_read (&identifier, reply);
+ }
+
+ if (!err) {
+ err = cci_ccache_new (out_ccache, identifier);
+ }
+
+ cci_identifier_release (identifier);
+ krb5int_ipc_stream_release (reply);
+ krb5int_ipc_stream_release (request);
+
+ return cci_check_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 ccapi_context_open_default_ccache (cc_context_t in_context,
+ cc_ccache_t *out_ccache)
+{
+ cc_int32 err = ccNoError;
+ cci_context_t context = (cci_context_t) in_context;
+ k5_ipc_stream reply = NULL;
+ cci_identifier_t identifier = NULL;
+
+ if (!in_context) { err = cci_check_error (ccErrBadParam); }
+ if (!out_ccache) { err = cci_check_error (ccErrBadParam); }
+
+ if (!err) {
+ err = cci_context_sync (context, 0);
+ }
+
+ if (!err) {
+ err = cci_ipc_send_no_launch (cci_context_open_default_ccache_msg_id,
+ context->identifier,
+ NULL,
+ &reply);
+ }
+
+ if (!err && !(krb5int_ipc_stream_size (reply) > 0)) {
+ err = ccErrCCacheNotFound;
+ }
+
+ if (!err) {
+ err = cci_identifier_read (&identifier, reply);
+ }
+
+ if (!err) {
+ err = cci_ccache_new (out_ccache, identifier);
+ }
+
+ cci_identifier_release (identifier);
+ krb5int_ipc_stream_release (reply);
+
+ return cci_check_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 ccapi_context_create_ccache (cc_context_t in_context,
+ const char *in_name,
+ cc_uint32 in_cred_vers,
+ const char *in_principal,
+ cc_ccache_t *out_ccache)
+{
+ cc_int32 err = ccNoError;
+ cci_context_t context = (cci_context_t) in_context;
+ k5_ipc_stream request = NULL;
+ k5_ipc_stream reply = NULL;
+ cci_identifier_t identifier = NULL;
+
+ if (!in_context ) { err = cci_check_error (ccErrBadParam); }
+ if (!in_name ) { err = cci_check_error (ccErrBadParam); }
+ if (!in_principal) { err = cci_check_error (ccErrBadParam); }
+ if (!out_ccache ) { err = cci_check_error (ccErrBadParam); }
+
+ if (!err) {
+ err = krb5int_ipc_stream_new (&request);
+ }
+
+ if (!err) {
+ err = krb5int_ipc_stream_write_string (request, in_name);
+ }
+
+ if (!err) {
+ err = krb5int_ipc_stream_write_uint32 (request, in_cred_vers);
+ }
+
+ if (!err) {
+ err = krb5int_ipc_stream_write_string (request, in_principal);
+ }
+
+ if (!err) {
+ err = cci_context_sync (context, 1);
+ }
+
+ if (!err) {
+ err = cci_ipc_send (cci_context_create_ccache_msg_id,
+ context->identifier,
+ request,
+ &reply);
+ }
+
+ if (!err) {
+ err = cci_identifier_read (&identifier, reply);
+ }
+
+ if (!err) {
+ err = cci_ccache_new (out_ccache, identifier);
+ }
+
+ cci_identifier_release (identifier);
+ krb5int_ipc_stream_release (reply);
+ krb5int_ipc_stream_release (request);
+
+ return cci_check_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 ccapi_context_create_default_ccache (cc_context_t in_context,
+ cc_uint32 in_cred_vers,
+ const char *in_principal,
+ cc_ccache_t *out_ccache)
+{
+ cc_int32 err = ccNoError;
+ cci_context_t context = (cci_context_t) in_context;
+ k5_ipc_stream request = NULL;
+ k5_ipc_stream reply = NULL;
+ cci_identifier_t identifier = NULL;
+
+ if (!in_context ) { err = cci_check_error (ccErrBadParam); }
+ if (!in_principal) { err = cci_check_error (ccErrBadParam); }
+ if (!out_ccache ) { err = cci_check_error (ccErrBadParam); }
+
+ if (!err) {
+ err = krb5int_ipc_stream_new (&request);
+ }
+
+ if (!err) {
+ err = krb5int_ipc_stream_write_uint32 (request, in_cred_vers);
+ }
+
+ if (!err) {
+ err = krb5int_ipc_stream_write_string (request, in_principal);
+ }
+
+ if (!err) {
+ err = cci_context_sync (context, 1);
+ }
+
+ if (!err) {
+ err = cci_ipc_send (cci_context_create_default_ccache_msg_id,
+ context->identifier,
+ request,
+ &reply);
+ }
+
+ if (!err) {
+ err = cci_identifier_read (&identifier, reply);
+ }
+
+ if (!err) {
+ err = cci_ccache_new (out_ccache, identifier);
+ }
+
+ cci_identifier_release (identifier);
+ krb5int_ipc_stream_release (reply);
+ krb5int_ipc_stream_release (request);
+
+ return cci_check_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 ccapi_context_create_new_ccache (cc_context_t in_context,
+ cc_uint32 in_cred_vers,
+ const char *in_principal,
+ cc_ccache_t *out_ccache)
+{
+ cc_int32 err = ccNoError;
+ cci_context_t context = (cci_context_t) in_context;
+ k5_ipc_stream request = NULL;
+ k5_ipc_stream reply = NULL;
+ cci_identifier_t identifier = NULL;
+
+ if (!in_context ) { err = cci_check_error (ccErrBadParam); }
+ if (!in_principal) { err = cci_check_error (ccErrBadParam); }
+ if (!out_ccache ) { err = cci_check_error (ccErrBadParam); }
+
+ if (!err) {
+ err = krb5int_ipc_stream_new (&request);
+ }
+
+ if (!err) {
+ err = krb5int_ipc_stream_write_uint32 (request, in_cred_vers);
+ }
+
+ if (!err) {
+ err = krb5int_ipc_stream_write_string (request, in_principal);
+ }
+
+ if (!err) {
+ err = cci_context_sync (context, 1);
+ }
+
+ if (!err) {
+ err = cci_ipc_send (cci_context_create_new_ccache_msg_id,
+ context->identifier,
+ request,
+ &reply);
+ }
+
+ if (!err) {
+ err = cci_identifier_read (&identifier, reply);
+ }
+
+ if (!err) {
+ err = cci_ccache_new (out_ccache, identifier);
+ }
+
+ cci_identifier_release (identifier);
+ krb5int_ipc_stream_release (reply);
+ krb5int_ipc_stream_release (request);
+
+ return cci_check_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 ccapi_context_new_ccache_iterator (cc_context_t in_context,
+ cc_ccache_iterator_t *out_iterator)
+{
+ cc_int32 err = ccNoError;
+ cci_context_t context = (cci_context_t) in_context;
+ k5_ipc_stream reply = NULL;
+ cci_identifier_t identifier = NULL;
+
+ if (!in_context ) { err = cci_check_error (ccErrBadParam); }
+ if (!out_iterator) { err = cci_check_error (ccErrBadParam); }
+
+ if (!err) {
+ err = cci_context_sync (context, 0);
+ }
+
+ if (!err) {
+ err = cci_ipc_send_no_launch (cci_context_new_ccache_iterator_msg_id,
+ context->identifier,
+ NULL,
+ &reply);
+ }
+
+ if (!err) {
+ if (krb5int_ipc_stream_size (reply) > 0) {
+ err = cci_identifier_read (&identifier, reply);
+ } else {
+ identifier = cci_identifier_uninitialized;
+ }
+ }
+
+ if (!err) {
+ err = cci_ccache_iterator_new (out_iterator, identifier);
+ }
+
+ krb5int_ipc_stream_release (reply);
+ cci_identifier_release (identifier);
+
+ return cci_check_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 ccapi_context_lock (cc_context_t in_context,
+ cc_uint32 in_lock_type,
+ cc_uint32 in_block)
+{
+ cc_int32 err = ccNoError;
+ cci_context_t context = (cci_context_t) in_context;
+ k5_ipc_stream request = NULL;
+
+ if (!in_context) { err = cci_check_error (ccErrBadParam); }
+
+ if (!err) {
+ err = krb5int_ipc_stream_new (&request);
+ }
+
+ if (!err) {
+ err = krb5int_ipc_stream_write_uint32 (request, in_lock_type);
+ }
+
+ if (!err) {
+ err = krb5int_ipc_stream_write_uint32 (request, in_block);
+ }
+
+ if (!err) {
+ err = cci_context_sync (context, 1);
+ }
+
+ if (!err) {
+ err = cci_ipc_send (cci_context_lock_msg_id,
+ context->identifier,
+ request,
+ NULL);
+ }
+
+ krb5int_ipc_stream_release (request);
+
+ return cci_check_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 ccapi_context_unlock (cc_context_t in_context)
+{
+ cc_int32 err = ccNoError;
+ cci_context_t context = (cci_context_t) in_context;
+
+ if (!in_context) { err = cci_check_error (ccErrBadParam); }
+
+ if (!err) {
+ err = cci_context_sync (context, 1);
+ }
+
+ if (!err) {
+ err = cci_ipc_send (cci_context_unlock_msg_id,
+ context->identifier,
+ NULL,
+ NULL);
+ }
+
+ return cci_check_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 ccapi_context_compare (cc_context_t in_context,
+ cc_context_t in_compare_to_context,
+ cc_uint32 *out_equal)
+{
+ cc_int32 err = ccNoError;
+ cci_context_t context = (cci_context_t) in_context;
+ cci_context_t compare_to_context = (cci_context_t) in_compare_to_context;
+
+ if (!in_context ) { err = cci_check_error (ccErrBadParam); }
+ if (!in_compare_to_context) { err = cci_check_error (ccErrBadParam); }
+ if (!out_equal ) { err = cci_check_error (ccErrBadParam); }
+
+ if (!err) {
+ err = cci_context_sync (context, 0);
+ }
+
+ if (!err) {
+ err = cci_context_sync (compare_to_context, 0);
+ }
+
+ if (!err) {
+ /* If both contexts can't talk to the server, then
+ * we assume they are equivalent */
+ err = cci_identifier_compare (context->identifier,
+ compare_to_context->identifier,
+ out_equal);
+ }
+
+ return cci_check_error (err);
+}
+
+#ifdef TARGET_OS_MAC
+#pragma mark -
+#endif
+
+/* ------------------------------------------------------------------------ */
+
+static cc_int32 cci_context_sync (cci_context_t in_context,
+ cc_uint32 in_launch)
+{
+ cc_int32 err = ccNoError;
+ cci_context_t context = (cci_context_t) in_context;
+ k5_ipc_stream reply = NULL;
+ cci_identifier_t new_identifier = NULL;
+
+ if (!in_context) { err = cci_check_error (ccErrBadParam); }
+
+ if (!err) {
+ /* Use the uninitialized identifier because we may be talking */
+ /* to a different server which would reject our identifier and */
+ /* the point of this message is to sync with the server's id */
+ if (in_launch) {
+ err = cci_ipc_send (cci_context_sync_msg_id,
+ cci_identifier_uninitialized,
+ NULL,
+ &reply);
+ } else {
+ err = cci_ipc_send_no_launch (cci_context_sync_msg_id,
+ cci_identifier_uninitialized,
+ NULL,
+ &reply);
+ }
+ }
+
+ if (!err) {
+ if (krb5int_ipc_stream_size (reply) > 0) {
+ err = cci_identifier_read (&new_identifier, reply);
+ } else {
+ new_identifier = cci_identifier_uninitialized;
+ }
+ }
+
+ if (!err) {
+ cc_uint32 equal = 0;
+
+ err = cci_identifier_compare (context->identifier, new_identifier, &equal);
+
+ if (!err && !equal) {
+ if (context->identifier) {
+ cci_identifier_release (context->identifier);
+ }
+ context->identifier = new_identifier;
+ new_identifier = NULL; /* take ownership */
+ }
+ }
+
+ if (!err && context->synchronized) {
+ err = cci_context_change_time_sync (context->identifier);
+ }
+
+ if (!err && !context->synchronized) {
+ /* Keep state about whether this is the first call to avoid always */
+ /* modifying the global change time on the context's first ipc call. */
+ context->synchronized = 1;
+ }
+
+ cci_identifier_release (new_identifier);
+ krb5int_ipc_stream_release (reply);
+
+ return cci_check_error (err);
+}
diff --git a/src/ccapi/lib/ccapi_context.h b/src/ccapi/lib/ccapi_context.h
new file mode 100644
index 000000000000..51b8982e6bdd
--- /dev/null
+++ b/src/ccapi/lib/ccapi_context.h
@@ -0,0 +1,86 @@
+/* ccapi/lib/ccapi_context.h */
+/*
+ * Copyright 2006 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 M.I.T. 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.
+ */
+
+#ifndef CCAPI_CONTEXT_H
+#define CCAPI_CONTEXT_H
+
+#include "cci_common.h"
+
+/* Used for freeing ccapi context in thread fini calls
+ * Does not tell the server you are exiting. */
+cc_int32 cci_context_destroy (cc_context_t in_context);
+
+cc_int32 ccapi_context_release (cc_context_t in_context);
+
+cc_int32 ccapi_context_get_change_time (cc_context_t in_context,
+ cc_time_t *out_time);
+
+cc_int32 ccapi_context_wait_for_change (cc_context_t in_context);
+
+cc_int32 ccapi_context_get_default_ccache_name (cc_context_t in_context,
+ cc_string_t *out_name);
+
+cc_int32 ccapi_context_open_ccache (cc_context_t in_context,
+ const char *in_name,
+ cc_ccache_t *out_ccache);
+
+cc_int32 ccapi_context_open_default_ccache (cc_context_t in_context,
+ cc_ccache_t *out_ccache);
+
+cc_int32 ccapi_context_create_ccache (cc_context_t in_context,
+ const char *in_name,
+ cc_uint32 in_cred_vers,
+ const char *in_principal,
+ cc_ccache_t *out_ccache);
+
+cc_int32 ccapi_context_create_default_ccache (cc_context_t in_context,
+ cc_uint32 in_cred_vers,
+ const char *in_principal,
+ cc_ccache_t *out_ccache);
+
+cc_int32 ccapi_context_create_new_ccache (cc_context_t in_context,
+ cc_uint32 in_cred_vers,
+ const char *in_principal,
+ cc_ccache_t *out_ccache);
+
+cc_int32 ccapi_context_new_ccache_iterator (cc_context_t in_context,
+ cc_ccache_iterator_t *out_iterator);
+
+cc_int32 ccapi_context_lock (cc_context_t in_context,
+ cc_uint32 in_lock_type,
+ cc_uint32 in_block);
+
+cc_int32 ccapi_context_unlock (cc_context_t in_context);
+
+cc_int32 ccapi_context_compare (cc_context_t in_context,
+ cc_context_t in_compare_to_context,
+ cc_uint32 *out_equal);
+
+#ifdef WIN32
+void cci_thread_init__auxinit();
+#endif
+
+
+#endif /* CCAPI_CONTEXT_H */
diff --git a/src/ccapi/lib/ccapi_context_change_time.c b/src/ccapi/lib/ccapi_context_change_time.c
new file mode 100644
index 000000000000..ec6b955e9f7d
--- /dev/null
+++ b/src/ccapi/lib/ccapi_context_change_time.c
@@ -0,0 +1,199 @@
+/* ccapi/lib/ccapi_context_change_time.c */
+/*
+ * Copyright 2006, 2007 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 M.I.T. 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.
+ */
+
+#include "ccapi_context_change_time.h"
+#include "cci_common.h"
+
+#include "k5-thread.h"
+
+static cci_identifier_t g_change_time_identifer = NULL;
+static cc_time_t g_change_time = 0;
+static cc_time_t g_change_time_offset = 0;
+static k5_mutex_t g_change_time_mutex = K5_MUTEX_PARTIAL_INITIALIZER;
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 cci_context_change_time_thread_init (void)
+{
+ return k5_mutex_finish_init(&g_change_time_mutex);
+}
+
+/* ------------------------------------------------------------------------ */
+
+void cci_context_change_time_thread_fini (void)
+{
+ k5_mutex_destroy(&g_change_time_mutex);
+}
+
+/* ------------------------------------------------------------------------ */
+/* WARNING! Mutex must be locked when calling this! */
+
+static cc_int32 cci_context_change_time_update_identifier (cci_identifier_t in_new_identifier,
+ cc_uint32 *out_server_ids_match,
+ cc_uint32 *out_old_server_running,
+ cc_uint32 *out_new_server_running)
+{
+ cc_int32 err = ccNoError;
+ cc_uint32 server_ids_match = 0;
+ cc_uint32 old_server_running = 0;
+ cc_uint32 new_server_running = 0;
+
+ if (!in_new_identifier) { err = cci_check_error (err); }
+
+ if (!err && !g_change_time_identifer) {
+ g_change_time_identifer = cci_identifier_uninitialized;
+ }
+
+ if (!err) {
+ err = cci_identifier_compare_server_id (g_change_time_identifer,
+ in_new_identifier,
+ &server_ids_match);
+ }
+
+ if (!err && out_old_server_running) {
+ err = cci_identifier_is_initialized (g_change_time_identifer, &old_server_running);
+ }
+
+ if (!err && out_new_server_running) {
+ err = cci_identifier_is_initialized (in_new_identifier, &new_server_running);
+ }
+
+ if (!err && !server_ids_match) {
+ cci_identifier_t new_change_time_identifer = NULL;
+
+ err = cci_identifier_copy (&new_change_time_identifer, in_new_identifier);
+
+ if (!err) {
+ /* Save the new identifier */
+ if (g_change_time_identifer) {
+ cci_identifier_release (g_change_time_identifer);
+ }
+ g_change_time_identifer = new_change_time_identifer;
+ }
+ }
+
+ if (!err) {
+ if (out_server_ids_match ) { *out_server_ids_match = server_ids_match; }
+ if (out_old_server_running) { *out_old_server_running = old_server_running; }
+ if (out_new_server_running) { *out_new_server_running = new_server_running; }
+ }
+
+
+ return cci_check_error (err);
+}
+
+#ifdef TARGET_OS_MAC
+#pragma mark -
+#endif
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 cci_context_change_time_get (cc_time_t *out_change_time)
+{
+ cc_int32 err = ccNoError;
+
+ k5_mutex_lock (&g_change_time_mutex);
+
+ *out_change_time = g_change_time + g_change_time_offset;
+ k5_mutex_unlock (&g_change_time_mutex);
+
+ return err;
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 cci_context_change_time_update (cci_identifier_t in_identifier,
+ cc_time_t in_new_change_time)
+{
+ cc_int32 err = ccNoError;
+ k5_mutex_lock (&g_change_time_mutex);
+
+ if (!in_identifier) { err = cci_check_error (err); }
+
+ if (!err) {
+ if (g_change_time < in_new_change_time) {
+ /* Only update if it increases the time. May be a different server. */
+ g_change_time = in_new_change_time;
+ cci_debug_printf ("%s: setting change time to %d",
+ __FUNCTION__, in_new_change_time);
+ }
+ }
+
+ if (!err) {
+ err = cci_context_change_time_update_identifier (in_identifier,
+ NULL, NULL, NULL);
+ }
+
+ k5_mutex_unlock (&g_change_time_mutex);
+
+ return err;
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 cci_context_change_time_sync (cci_identifier_t in_new_identifier)
+{
+ cc_int32 err = ccNoError;
+ cc_uint32 server_ids_match = 0;
+ cc_uint32 server_was_running = 0;
+ cc_uint32 server_is_running = 0;
+
+ k5_mutex_lock (&g_change_time_mutex);
+
+ if (!in_new_identifier) { err = cci_check_error (err); }
+
+ if (!err) {
+ err = cci_context_change_time_update_identifier (in_new_identifier,
+ &server_ids_match,
+ &server_was_running,
+ &server_is_running);
+ }
+
+ if (!err && !server_ids_match) {
+ /* Increment the change time so callers re-read */
+ g_change_time_offset++;
+
+ /* If the server died, absorb the offset */
+ if (server_was_running && !server_is_running) {
+ cc_time_t now = time (NULL);
+
+ g_change_time += g_change_time_offset;
+ g_change_time_offset = 0;
+
+ /* Make sure the change time increases, ideally with the current time */
+ g_change_time = (g_change_time < now) ? now : g_change_time;
+ }
+
+ cci_debug_printf ("%s noticed server changed ("
+ "server_was_running = %d; server_is_running = %d; "
+ "g_change_time = %d; g_change_time_offset = %d",
+ __FUNCTION__, server_was_running, server_is_running,
+ g_change_time, g_change_time_offset);
+ }
+
+ k5_mutex_unlock (&g_change_time_mutex);
+
+ return err;
+}
diff --git a/src/ccapi/lib/ccapi_context_change_time.h b/src/ccapi/lib/ccapi_context_change_time.h
new file mode 100644
index 000000000000..b1fa110e3451
--- /dev/null
+++ b/src/ccapi/lib/ccapi_context_change_time.h
@@ -0,0 +1,41 @@
+/* ccapi/lib/ccapi_context_change_time.h */
+/*
+ * Copyright 2006 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 M.I.T. 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.
+ */
+
+#ifndef CCAPI_CONTEXT_CHANGE_TIME_H
+#define CCAPI_CONTEXT_CHANGE_TIME_H
+
+#include "cci_common.h"
+
+cc_int32 cci_context_change_time_thread_init (void);
+void cci_context_change_time_thread_fini (void);
+
+cc_int32 cci_context_change_time_get (cc_time_t *out_change_time);
+
+cc_int32 cci_context_change_time_update (cci_identifier_t in_identifier,
+ cc_time_t in_new_change_time);
+
+cc_int32 cci_context_change_time_sync (cci_identifier_t in_new_identifier);
+
+#endif /* CCAPI_CONTEXT_CHANGE_TIME_H */
diff --git a/src/ccapi/lib/ccapi_credentials.c b/src/ccapi/lib/ccapi_credentials.c
new file mode 100644
index 000000000000..cb175a31bdc7
--- /dev/null
+++ b/src/ccapi/lib/ccapi_credentials.c
@@ -0,0 +1,165 @@
+/* ccapi/lib/ccapi_credentials.c */
+/*
+ * Copyright 2006 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 M.I.T. 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.
+ */
+
+#include "ccapi_credentials.h"
+
+#include "ccapi_string.h"
+
+/* ------------------------------------------------------------------------ */
+
+typedef struct cci_credentials_d {
+ cc_credentials_union *data;
+ cc_credentials_f *functions;
+#if TARGET_OS_MAC
+ cc_credentials_f *vector_functions;
+#endif
+ cci_identifier_t identifier;
+} *cci_credentials_t;
+
+/* ------------------------------------------------------------------------ */
+
+struct cci_credentials_d cci_credentials_initializer = {
+ NULL,
+ NULL
+ VECTOR_FUNCTIONS_INITIALIZER,
+ NULL
+};
+
+cc_credentials_f cci_credentials_f_initializer = {
+ ccapi_credentials_release,
+ ccapi_credentials_compare
+};
+
+cc_credentials_union cci_credentials_union_initializer = {
+ 0,
+ { NULL }
+};
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 cci_credentials_read (cc_credentials_t *out_credentials,
+ k5_ipc_stream in_stream)
+{
+ cc_int32 err = ccNoError;
+ cci_credentials_t credentials = NULL;
+
+ if (!out_credentials) { err = cci_check_error (ccErrBadParam); }
+ if (!in_stream ) { err = cci_check_error (ccErrBadParam); }
+
+ if (!err) {
+ credentials = malloc (sizeof (*credentials));
+ if (credentials) {
+ *credentials = cci_credentials_initializer;
+ } else {
+ err = cci_check_error (ccErrNoMem);
+ }
+ }
+
+ if (!err) {
+ credentials->functions = malloc (sizeof (*credentials->functions));
+ if (credentials->functions) {
+ *credentials->functions = cci_credentials_f_initializer;
+ } else {
+ err = cci_check_error (ccErrNoMem);
+ }
+ }
+
+ if (!err) {
+ err = cci_identifier_read (&credentials->identifier, in_stream);
+ }
+
+ if (!err) {
+ err = cci_credentials_union_read (&credentials->data, in_stream);
+ }
+
+ if (!err) {
+ *out_credentials = (cc_credentials_t) credentials;
+ credentials = NULL; /* take ownership */
+ }
+
+ if (credentials) { ccapi_credentials_release ((cc_credentials_t) credentials); }
+
+ return cci_check_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 cci_credentials_write (cc_credentials_t in_credentials,
+ k5_ipc_stream in_stream)
+{
+ cc_int32 err = ccNoError;
+ cci_credentials_t credentials = (cci_credentials_t) in_credentials;
+
+ if (!in_credentials) { err = cci_check_error (ccErrBadParam); }
+ if (!in_stream ) { err = cci_check_error (ccErrBadParam); }
+
+ if (!err) {
+ err = cci_identifier_write (credentials->identifier, in_stream);
+ }
+
+ return cci_check_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 ccapi_credentials_compare (cc_credentials_t in_credentials,
+ cc_credentials_t in_compare_to_credentials,
+ cc_uint32 *out_equal)
+{
+ cc_int32 err = ccNoError;
+ cci_credentials_t credentials = (cci_credentials_t) in_credentials;
+ cci_credentials_t compare_to_credentials = (cci_credentials_t) in_compare_to_credentials;
+
+ if (!in_credentials ) { err = cci_check_error (ccErrBadParam); }
+ if (!in_compare_to_credentials) { err = cci_check_error (ccErrBadParam); }
+ if (!out_equal ) { err = cci_check_error (ccErrBadParam); }
+
+ if (!err) {
+ err = cci_identifier_compare (credentials->identifier,
+ compare_to_credentials->identifier,
+ out_equal);
+ }
+
+ return cci_check_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 ccapi_credentials_release (cc_credentials_t io_credentials)
+{
+ cc_int32 err = ccNoError;
+ cci_credentials_t credentials = (cci_credentials_t) io_credentials;
+
+ if (!io_credentials) { err = ccErrBadParam; }
+
+ if (!err) {
+ cci_credentials_union_release (credentials->data);
+ free ((char *) credentials->functions);
+ cci_identifier_release (credentials->identifier);
+ free (credentials);
+ }
+
+ return err;
+}
diff --git a/src/ccapi/lib/ccapi_credentials.h b/src/ccapi/lib/ccapi_credentials.h
new file mode 100644
index 000000000000..aea6a412ecb7
--- /dev/null
+++ b/src/ccapi/lib/ccapi_credentials.h
@@ -0,0 +1,43 @@
+/* ccapi/lib/ccapi_credentials.h */
+/*
+ * Copyright 2006 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 M.I.T. 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.
+ */
+
+#ifndef CCAPI_CREDENTIALS_H
+#define CCAPI_CREDENTIALS_H
+
+#include "cci_common.h"
+
+cc_int32 cci_credentials_read (cc_credentials_t *out_credentials,
+ k5_ipc_stream in_stream);
+
+cc_int32 cci_credentials_write (cc_credentials_t in_credentials,
+ k5_ipc_stream in_stream);
+
+cc_int32 ccapi_credentials_compare (cc_credentials_t in_credentials,
+ cc_credentials_t in_compare_to_credentials,
+ cc_uint32 *out_equal);
+
+cc_int32 ccapi_credentials_release (cc_credentials_t io_credentials);
+
+#endif /* CCAPI_CREDENTIALS_H */
diff --git a/src/ccapi/lib/ccapi_credentials_iterator.c b/src/ccapi/lib/ccapi_credentials_iterator.c
new file mode 100644
index 000000000000..f1efc7f8d0ed
--- /dev/null
+++ b/src/ccapi/lib/ccapi_credentials_iterator.c
@@ -0,0 +1,246 @@
+/* ccapi/lib/ccapi_credentials_iterator.c */
+/*
+ * Copyright 2006 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 M.I.T. 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.
+ */
+
+#include "ccapi_credentials_iterator.h"
+#include "ccapi_credentials.h"
+#include "ccapi_ipc.h"
+
+/* ------------------------------------------------------------------------ */
+
+typedef struct cci_credentials_iterator_d {
+ cc_credentials_iterator_f *functions;
+#if TARGET_OS_MAC
+ cc_credentials_iterator_f *vector_functions;
+#endif
+ cci_identifier_t identifier;
+ cc_uint32 compat_version;
+} *cci_credentials_iterator_t;
+
+/* ------------------------------------------------------------------------ */
+
+struct cci_credentials_iterator_d cci_credentials_iterator_initializer = {
+ NULL
+ VECTOR_FUNCTIONS_INITIALIZER,
+ NULL,
+ 0
+};
+
+cc_credentials_iterator_f cci_credentials_iterator_f_initializer = {
+ ccapi_credentials_iterator_release,
+ ccapi_credentials_iterator_next,
+ ccapi_credentials_iterator_clone
+};
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 cci_credentials_iterator_new (cc_credentials_iterator_t *out_credentials_iterator,
+ cci_identifier_t in_identifier)
+{
+ cc_int32 err = ccNoError;
+ cci_credentials_iterator_t credentials_iterator = NULL;
+
+ if (!out_credentials_iterator) { err = cci_check_error (ccErrBadParam); }
+ if (!in_identifier ) { err = cci_check_error (ccErrBadParam); }
+
+ if (!err) {
+ credentials_iterator = malloc (sizeof (*credentials_iterator));
+ if (credentials_iterator) {
+ *credentials_iterator = cci_credentials_iterator_initializer;
+ } else {
+ err = cci_check_error (ccErrNoMem);
+ }
+ }
+
+ if (!err) {
+ credentials_iterator->functions = malloc (sizeof (*credentials_iterator->functions));
+ if (credentials_iterator->functions) {
+ *credentials_iterator->functions = cci_credentials_iterator_f_initializer;
+ } else {
+ err = cci_check_error (ccErrNoMem);
+ }
+ }
+
+ if (!err) {
+ err = cci_identifier_copy (&credentials_iterator->identifier, in_identifier);
+ }
+
+ if (!err) {
+ *out_credentials_iterator = (cc_credentials_iterator_t) credentials_iterator;
+ credentials_iterator = NULL; /* take ownership */
+ }
+
+ if (credentials_iterator) { ccapi_credentials_iterator_release ((cc_credentials_iterator_t) credentials_iterator); }
+
+ return cci_check_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 cci_credentials_iterator_write (cc_credentials_iterator_t in_credentials_iterator,
+ k5_ipc_stream in_stream)
+{
+ cc_int32 err = ccNoError;
+ cci_credentials_iterator_t credentials_iterator = (cci_credentials_iterator_t) in_credentials_iterator;
+
+ if (!in_credentials_iterator) { err = cci_check_error (ccErrBadParam); }
+ if (!in_stream ) { err = cci_check_error (ccErrBadParam); }
+
+ if (!err) {
+ err = cci_identifier_write (credentials_iterator->identifier, in_stream);
+ }
+
+ return cci_check_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 ccapi_credentials_iterator_release (cc_credentials_iterator_t io_credentials_iterator)
+{
+ cc_int32 err = ccNoError;
+ cci_credentials_iterator_t credentials_iterator = (cci_credentials_iterator_t) io_credentials_iterator;
+
+ if (!io_credentials_iterator) { err = ccErrBadParam; }
+
+ if (!err) {
+ err = cci_ipc_send (cci_credentials_iterator_release_msg_id,
+ credentials_iterator->identifier,
+ NULL,
+ NULL);
+ if (err) {
+ cci_debug_printf ("%s: cci_ipc_send failed with error %d",
+ __FUNCTION__, err);
+ err = ccNoError;
+ }
+ }
+
+ if (!err) {
+ free ((char *) credentials_iterator->functions);
+ cci_identifier_release (credentials_iterator->identifier);
+ free (credentials_iterator);
+ }
+
+ return err;
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 ccapi_credentials_iterator_next (cc_credentials_iterator_t in_credentials_iterator,
+ cc_credentials_t *out_credentials)
+{
+ cc_int32 err = ccNoError;
+ cci_credentials_iterator_t credentials_iterator = (cci_credentials_iterator_t) in_credentials_iterator;
+ k5_ipc_stream reply = NULL;
+
+ if (!in_credentials_iterator) { err = cci_check_error (ccErrBadParam); }
+ if (!out_credentials ) { err = cci_check_error (ccErrBadParam); }
+
+ if (!err) {
+ err = cci_ipc_send (cci_credentials_iterator_next_msg_id,
+ credentials_iterator->identifier,
+ NULL,
+ &reply);
+ }
+
+ if (!err) {
+ err = cci_credentials_read (out_credentials, reply);
+ }
+
+ krb5int_ipc_stream_release (reply);
+
+ return cci_check_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 ccapi_credentials_iterator_clone (cc_credentials_iterator_t in_credentials_iterator,
+ cc_credentials_iterator_t *out_credentials_iterator)
+{
+ cc_int32 err = ccNoError;
+ cci_credentials_iterator_t credentials_iterator = (cci_credentials_iterator_t) in_credentials_iterator;
+ k5_ipc_stream reply = NULL;
+ cci_identifier_t identifier = NULL;
+
+ if (!in_credentials_iterator ) { err = cci_check_error (ccErrBadParam); }
+ if (!out_credentials_iterator) { err = cci_check_error (ccErrBadParam); }
+
+ if (!err) {
+ err = cci_ipc_send (cci_credentials_iterator_next_msg_id,
+ credentials_iterator->identifier,
+ NULL,
+ &reply);
+ }
+
+ if (!err) {
+ err = cci_identifier_read (&identifier, reply);
+ }
+
+ if (!err) {
+ err = cci_credentials_iterator_new (out_credentials_iterator, identifier);
+ }
+
+ krb5int_ipc_stream_release (reply);
+ cci_identifier_release (identifier);
+
+ return cci_check_error (err);
+}
+
+#ifdef TARGET_OS_MAC
+#pragma mark -
+#endif
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 cci_credentials_iterator_get_compat_version (cc_credentials_iterator_t in_credentials_iterator,
+ cc_uint32 *out_compat_version)
+{
+ cc_int32 err = ccNoError;
+ cci_credentials_iterator_t credentials_iterator = (cci_credentials_iterator_t) in_credentials_iterator;
+
+ if (!in_credentials_iterator) { err = cci_check_error (ccErrBadParam); }
+ if (!out_compat_version ) { err = cci_check_error (ccErrBadParam); }
+
+ if (!err) {
+ *out_compat_version = credentials_iterator->compat_version;
+ }
+
+ return cci_check_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 cci_credentials_iterator_set_compat_version (cc_credentials_iterator_t io_credentials_iterator,
+ cc_uint32 in_compat_version)
+{
+ cc_int32 err = ccNoError;
+ cci_credentials_iterator_t credentials_iterator = (cci_credentials_iterator_t) io_credentials_iterator;
+
+ if (!io_credentials_iterator) { err = cci_check_error (ccErrBadParam); }
+
+ if (!err) {
+ credentials_iterator->compat_version = in_compat_version;
+ }
+
+ return cci_check_error (err);
+}
diff --git a/src/ccapi/lib/ccapi_credentials_iterator.h b/src/ccapi/lib/ccapi_credentials_iterator.h
new file mode 100644
index 000000000000..56c4505d9590
--- /dev/null
+++ b/src/ccapi/lib/ccapi_credentials_iterator.h
@@ -0,0 +1,51 @@
+/* ccapi/lib/ccapi_credentials_iterator.h */
+/*
+ * Copyright 2006 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 M.I.T. 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.
+ */
+
+#ifndef CCAPI_CREDENTIALS_ITERATOR_H
+#define CCAPI_CREDENTIALS_ITERATOR_H
+
+#include "cci_common.h"
+
+cc_int32 cci_credentials_iterator_new (cc_credentials_iterator_t *out_credentials_iterator,
+ cci_identifier_t in_identifier);
+
+cc_int32 cci_credentials_iterator_write (cc_credentials_iterator_t in_credentials_iterator,
+ k5_ipc_stream in_stream);
+
+cc_int32 ccapi_credentials_iterator_release (cc_credentials_iterator_t io_credentials_iterator);
+
+cc_int32 ccapi_credentials_iterator_next (cc_credentials_iterator_t in_credentials_iterator,
+ cc_credentials_t *out_credentials);
+
+cc_int32 ccapi_credentials_iterator_clone (cc_credentials_iterator_t in_credentials_iterator,
+ cc_credentials_iterator_t *out_credentials_iterator);
+
+cc_int32 cci_credentials_iterator_get_compat_version (cc_credentials_iterator_t in_credentials_iterator,
+ cc_uint32 *out_compat_version);
+
+cc_int32 cci_credentials_iterator_set_compat_version (cc_credentials_iterator_t io_credentials_iterator,
+ cc_uint32 in_compat_version);
+
+#endif /* CCAPI_CREDENTIALS_ITERATOR_H */
diff --git a/src/ccapi/lib/ccapi_err.et b/src/ccapi/lib/ccapi_err.et
new file mode 100644
index 000000000000..44cd2d0b5e53
--- /dev/null
+++ b/src/ccapi/lib/ccapi_err.et
@@ -0,0 +1,74 @@
+#
+# $Header$
+#
+# Copyright 1998-2006 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 M.I.T. 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.
+#
+
+error_table_base 201
+error_table_manager "Credentials Cache"
+error_table CAPI
+
+# 201
+error_code ccIteratorEnd, "Reached end of iterator"
+error_code ccErrBadParam, "Invalid argument"
+error_code ccErrNoMem, "Out of memory"
+error_code ccErrInvalidContext, "Invalid credentials cache context"
+error_code ccErrInvalidCCache, "Invalid credentials cache"
+
+# 206
+index 5
+error_code ccErrInvalidString, "Invalid credentials cache string"
+error_code ccErrInvalidCredentials, "Invalid credentials"
+error_code ccErrInvalidCCacheIterator, "Invalid credentials cache iterator"
+error_code ccErrInvalidCredentialsIterator, "Invalid credentials iterator"
+error_code ccErrInvalidLock, "Invalid iterator"
+
+# 211
+index 10
+error_code ccErrBadName, "Invalid credentials cache name"
+error_code ccErrBadCredentialsVersion, "Invalid credentials cache version (not 4 or 5)"
+error_code ccErrBadAPIVersion, "Invalid CCAPI version"
+error_code ccErrContextLocked, "Credentials cache context is already locked"
+error_code ccErrContextUnlocked, "Credentials cache context is already unlocked"
+
+# 216
+index 15
+error_code ccErrCCacheLocked, "Credentials cache is already locked"
+error_code ccErrCCacheUnlocked, "Credentials cache is already unlocked"
+error_code ccErrBadLockType, "Invalid credentials cache lock type"
+error_code ccErrNeverDefault, "Credentials cache has never been the default cache"
+error_code ccErrCredentialsNotFound, "Credentials not found"
+
+# 221
+index 20
+error_code ccErrCCacheNotFound, "Credentials cache not found"
+error_code ccErrContextNotFound, "Credentials cache context not found"
+error_code ccErrServerUnavailable, "Credentials cache server unavailable"
+error_code ccErrServerInsecure, "Credentials cache server in this bootstrap is owned by another user"
+error_code ccErrServerCantBecomeUID, "Credentials cache server failed to change effective uids"
+
+# 226
+index 25
+error_code ccErrTimeOffsetNotSet, "Credentials cache time offset not set"
+
+end
diff --git a/src/ccapi/lib/ccapi_ipc.c b/src/ccapi/lib/ccapi_ipc.c
new file mode 100644
index 000000000000..2c1fcba61029
--- /dev/null
+++ b/src/ccapi/lib/ccapi_ipc.c
@@ -0,0 +1,119 @@
+/* ccapi/lib/ccapi_ipc.c */
+/*
+ * Copyright 2006 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 M.I.T. 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.
+ */
+
+#include "ccapi_ipc.h"
+#include "ccapi_os_ipc.h"
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 cci_ipc_process_init (void)
+{
+ return cci_os_ipc_process_init ();
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 cci_ipc_thread_init (void)
+{
+ return cci_os_ipc_thread_init ();
+}
+
+/* ------------------------------------------------------------------------ */
+
+static cc_int32 _cci_ipc_send (enum cci_msg_id_t in_request_name,
+ cc_int32 in_launch_server,
+ cci_identifier_t in_identifier,
+ k5_ipc_stream in_request_data,
+ k5_ipc_stream *out_reply_data)
+{
+ cc_int32 err = ccNoError;
+ k5_ipc_stream request = NULL;
+ k5_ipc_stream reply = NULL;
+ cc_int32 reply_error = 0;
+
+ if (!in_identifier) { err = cci_check_error (ccErrBadParam); }
+ /* in_request_data may be NULL */
+ /* out_reply_data may be NULL */
+
+ if (!err) {
+ err = cci_message_new_request_header (&request,
+ in_request_name,
+ in_identifier);
+ }
+
+ if (!err && in_request_data) {
+ err = krb5int_ipc_stream_write (request,
+ krb5int_ipc_stream_data (in_request_data),
+ krb5int_ipc_stream_size (in_request_data));
+ }
+
+ if (!err) {
+ err = cci_os_ipc (in_launch_server, request, &reply);
+
+ if (!err && krb5int_ipc_stream_size (reply) > 0) {
+ err = cci_message_read_reply_header (reply, &reply_error);
+ }
+ }
+
+ if (!err && reply_error) {
+ err = reply_error;
+ }
+
+ if (!err && out_reply_data) {
+ *out_reply_data = reply;
+ reply = NULL; /* take ownership */
+ }
+
+ krb5int_ipc_stream_release (request);
+ krb5int_ipc_stream_release (reply);
+
+ return cci_check_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 cci_ipc_send (enum cci_msg_id_t in_request_name,
+ cci_identifier_t in_identifier,
+ k5_ipc_stream in_request_data,
+ k5_ipc_stream *out_reply_data)
+{
+ return cci_check_error (_cci_ipc_send (in_request_name, 1,
+ in_identifier,
+ in_request_data,
+ out_reply_data));
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 cci_ipc_send_no_launch (enum cci_msg_id_t in_request_name,
+ cci_identifier_t in_identifier,
+ k5_ipc_stream in_request_data,
+ k5_ipc_stream *out_reply_data)
+{
+ return cci_check_error (_cci_ipc_send (in_request_name, 0,
+ in_identifier,
+ in_request_data,
+ out_reply_data));
+}
diff --git a/src/ccapi/lib/ccapi_ipc.h b/src/ccapi/lib/ccapi_ipc.h
new file mode 100644
index 000000000000..a23772b29f7b
--- /dev/null
+++ b/src/ccapi/lib/ccapi_ipc.h
@@ -0,0 +1,45 @@
+/* ccapi/lib/ccapi_ipc.h */
+/*
+ * Copyright 2006 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 M.I.T. 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.
+ */
+
+#ifndef CCAPI_IPC_H
+#define CCAPI_IPC_H
+
+#include "cci_common.h"
+
+cc_int32 cci_ipc_process_init (void);
+
+cc_int32 cci_ipc_thread_init (void);
+
+cc_int32 cci_ipc_send (enum cci_msg_id_t in_request_name,
+ cci_identifier_t in_identifier,
+ k5_ipc_stream in_request_data,
+ k5_ipc_stream *out_reply_data);
+
+cc_int32 cci_ipc_send_no_launch (enum cci_msg_id_t in_request_name,
+ cci_identifier_t in_identifier,
+ k5_ipc_stream in_request_data,
+ k5_ipc_stream *out_reply_data);
+
+#endif /* CCAPI_IPC_H */
diff --git a/src/ccapi/lib/ccapi_os_ipc.h b/src/ccapi/lib/ccapi_os_ipc.h
new file mode 100644
index 000000000000..fe7c87a08c9b
--- /dev/null
+++ b/src/ccapi/lib/ccapi_os_ipc.h
@@ -0,0 +1,39 @@
+/* ccapi/lib/ccapi_os_ipc.h */
+/*
+ * Copyright 2006 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 M.I.T. 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.
+ */
+
+#ifndef CCAPI_OS_IPC_H
+#define CCAPI_OS_IPC_H
+
+#include "cci_common.h"
+
+cc_int32 cci_os_ipc_process_init (void);
+
+cc_int32 cci_os_ipc_thread_init (void);
+
+cc_int32 cci_os_ipc (cc_int32 in_launch_server,
+ k5_ipc_stream in_request_stream,
+ k5_ipc_stream *out_reply_stream);
+
+#endif /* CCAPI_OS_IPC_H */
diff --git a/src/ccapi/lib/ccapi_string.c b/src/ccapi/lib/ccapi_string.c
new file mode 100644
index 000000000000..ab84dfe39aff
--- /dev/null
+++ b/src/ccapi/lib/ccapi_string.c
@@ -0,0 +1,101 @@
+/* ccapi/lib/ccapi_string.c */
+/*
+ * Copyright 2006 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 M.I.T. 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.
+ */
+
+#include "ccapi_string.h"
+
+/* ------------------------------------------------------------------------ */
+
+cc_string_d cci_string_d_initializer = {
+ NULL,
+ NULL
+ VECTOR_FUNCTIONS_INITIALIZER };
+
+cc_string_f cci_string_f_initializer = {
+ ccapi_string_release
+};
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 cci_string_new (cc_string_t *out_string,
+ char *in_cstring)
+{
+ cc_int32 err = ccNoError;
+ cc_string_t string = NULL;
+
+ if (!out_string) { err = cci_check_error (ccErrBadParam); }
+ if (!in_cstring) { err = cci_check_error (ccErrBadParam); }
+
+ if (!err) {
+ string = malloc (sizeof (*string));
+ if (string) {
+ *string = cci_string_d_initializer;
+ } else {
+ err = cci_check_error (ccErrNoMem);
+ }
+ }
+
+ if (!err) {
+ string->functions = malloc (sizeof (*string->functions));
+ if (string->functions) {
+ *((cc_string_f *) string->functions) = cci_string_f_initializer;
+ } else {
+ err = cci_check_error (ccErrNoMem);
+ }
+ }
+
+ if (!err) {
+ string->data = strdup (in_cstring);
+ if (!string->data) {
+ err = cci_check_error (ccErrNoMem);
+ }
+
+ }
+
+ if (!err) {
+ *out_string = string;
+ string = NULL; /* take ownership */
+ }
+
+ if (string) { ccapi_string_release (string); }
+
+ return cci_check_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 ccapi_string_release (cc_string_t in_string)
+{
+ cc_int32 err = ccNoError;
+
+ if (!in_string) { err = ccErrBadParam; }
+
+ if (!err) {
+ free ((char *) in_string->data);
+ free ((char *) in_string->functions);
+ free (in_string);
+ }
+
+ return err;
+}
diff --git a/src/ccapi/lib/ccapi_string.h b/src/ccapi/lib/ccapi_string.h
new file mode 100644
index 000000000000..02debde9d1f3
--- /dev/null
+++ b/src/ccapi/lib/ccapi_string.h
@@ -0,0 +1,36 @@
+/* ccapi/lib/ccapi_string.h */
+/*
+ * Copyright 2006 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 M.I.T. 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.
+ */
+
+#ifndef CCAPI_STRING_H
+#define CCAPI_STRING_H
+
+#include "cci_common.h"
+
+cc_int32 cci_string_new (cc_string_t *out_string,
+ char *in_cstring);
+
+cc_int32 ccapi_string_release (cc_string_t in_string);
+
+#endif /* CCAPI_STRING_H */
diff --git a/src/ccapi/lib/ccapi_v2.c b/src/ccapi/lib/ccapi_v2.c
new file mode 100644
index 000000000000..8a831d796abb
--- /dev/null
+++ b/src/ccapi/lib/ccapi_v2.c
@@ -0,0 +1,917 @@
+/* ccapi/lib/ccapi_v2.c */
+/*
+ * Copyright 2006 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 M.I.T. 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.
+ */
+
+#include "cci_common.h"
+#include "ccapi_string.h"
+#include "ccapi_context.h"
+#include "ccapi_ccache.h"
+#include "ccapi_ccache_iterator.h"
+#include "ccapi_credentials.h"
+#include "ccapi_credentials_iterator.h"
+#include <CredentialsCache2.h>
+
+infoNC infoNC_initializer = { NULL, NULL, CC_CRED_UNKNOWN };
+
+/* ------------------------------------------------------------------------ */
+
+static cc_int32 cci_remap_version (cc_int32 in_v2_version,
+ cc_uint32 *out_v3_version)
+{
+ cc_result err = ccNoError;
+
+ if (!out_v3_version) { err = cci_check_error (ccErrBadParam); }
+
+ if (!err) {
+ if (in_v2_version == CC_CRED_V4) {
+ *out_v3_version = cc_credentials_v4;
+
+ } else if (in_v2_version == CC_CRED_V5) {
+ *out_v3_version = cc_credentials_v5;
+
+ } else {
+ err = ccErrBadCredentialsVersion;
+ }
+ }
+
+ return cci_check_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+static cc_result _cci_remap_error (cc_result in_error,
+ const char *in_function,
+ const char *in_file,
+ int in_line)
+{
+ _cci_check_error (in_error, in_function, in_file, in_line);
+
+ if (in_error >= CC_NOERROR && in_error <= CC_ERR_CRED_VERSION) {
+ return in_error;
+ }
+
+ switch (in_error) {
+ case ccNoError:
+ return CC_NOERROR;
+
+ case ccIteratorEnd:
+ return CC_END;
+
+ case ccErrBadParam:
+ case ccErrContextNotFound:
+ case ccErrInvalidContext:
+ case ccErrInvalidCredentials:
+ case ccErrInvalidCCacheIterator:
+ case ccErrInvalidCredentialsIterator:
+ case ccErrInvalidLock:
+ case ccErrBadLockType:
+ return CC_BAD_PARM;
+
+ case ccErrNoMem:
+ return CC_NOMEM;
+
+ case ccErrInvalidCCache:
+ case ccErrCCacheNotFound:
+ return CC_NO_EXIST;
+
+ case ccErrCredentialsNotFound:
+ return CC_NOTFOUND;
+
+ case ccErrBadName:
+ return CC_BADNAME;
+
+ case ccErrBadCredentialsVersion:
+ return CC_ERR_CRED_VERSION;
+
+ case ccErrBadAPIVersion:
+ return CC_BAD_API_VERSION;
+
+ case ccErrContextLocked:
+ case ccErrContextUnlocked:
+ case ccErrCCacheLocked:
+ case ccErrCCacheUnlocked:
+ return CC_LOCKED;
+
+ case ccErrServerUnavailable:
+ case ccErrServerInsecure:
+ case ccErrServerCantBecomeUID:
+ case ccErrBadInternalMessage:
+ case ccErrClientNotFound:
+ return CC_IO;
+
+ case ccErrNotImplemented:
+ return CC_NOT_SUPP;
+
+ default:
+ cci_debug_printf ("%s(): Unhandled error", __FUNCTION__);
+ return CC_BAD_PARM;
+ }
+}
+#define cci_remap_error(err) _cci_remap_error(err, __FUNCTION__, __FILE__, __LINE__)
+
+
+#if TARGET_OS_MAC
+#pragma mark -
+#endif
+
+/* ------------------------------------------------------------------------ */
+
+cc_result cc_shutdown (apiCB **io_context)
+{
+ cc_result err = ccNoError;
+
+ if (!io_context) { err = cci_check_error (ccErrBadParam); }
+
+ if (!err) {
+ err = ccapi_context_release (*io_context);
+ }
+
+ if (!err) {
+ *io_context = NULL;
+ }
+
+ return cci_remap_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_result cc_get_change_time (apiCB *in_context,
+ cc_time_t *out_change_time)
+{
+ cc_result err = ccNoError;
+
+ if (!in_context ) { err = cci_check_error (ccErrBadParam); }
+ if (!out_change_time) { err = cci_check_error (ccErrBadParam); }
+
+ if (!err) {
+ err = ccapi_context_get_change_time (in_context, out_change_time);
+ }
+
+ return cci_remap_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_result cc_get_NC_info (apiCB *in_context,
+ infoNC ***out_info)
+{
+ cc_result err = CC_NOERROR;
+ infoNC **info = NULL;
+ cc_uint64 count = 0; /* Preflight the size */
+ cc_uint64 i;
+
+ if (!in_context) { err = cci_check_error (ccErrBadParam); }
+ if (!out_info ) { err = cci_check_error (ccErrBadParam); }
+
+ if (!err) {
+ ccache_cit *iterator = NULL;
+
+ err = cc_seq_fetch_NCs_begin (in_context, &iterator);
+
+ while (!err) {
+ ccache_p *ccache = NULL;
+
+ err = cc_seq_fetch_NCs_next (in_context, &ccache, iterator);
+
+ if (!err) { count++; }
+
+ if (ccache) { cc_close (in_context, &ccache); }
+ }
+ if (err == CC_END) { err = CC_NOERROR; }
+
+ if (!err) {
+ err = cc_seq_fetch_NCs_end (in_context, &iterator);
+ }
+ }
+
+ if (!err) {
+ info = malloc (sizeof (*info) * (count + 1));
+ if (info) {
+ for (i = 0; i < count + 1; i++) { info[i] = NULL; }
+ } else {
+ err = cci_check_error (CC_NOMEM);
+ }
+ }
+
+ if (!err) {
+ ccache_cit *iterator = NULL;
+
+ err = cc_seq_fetch_NCs_begin (in_context, &iterator);
+
+ for (i = 0; !err && i < count; i++) {
+ ccache_p *ccache = NULL;
+
+ err = cc_seq_fetch_NCs_next (in_context, &ccache, iterator);
+
+ if (!err) {
+ info[i] = malloc (sizeof (*info[i]));
+ if (info[i]) {
+ *info[i] = infoNC_initializer;
+ } else {
+ err = cci_check_error (CC_NOMEM);
+ }
+ }
+
+ if (!err) {
+ err = cc_get_name (in_context, ccache, &info[i]->name);
+ }
+
+ if (!err) {
+ err = cc_get_principal (in_context, ccache, &info[i]->principal);
+ }
+
+ if (!err) {
+ err = cc_get_cred_version (in_context, ccache, &info[i]->vers);
+ }
+
+ if (ccache) { cc_close (in_context, &ccache); }
+ }
+
+ if (!err) {
+ err = cc_seq_fetch_NCs_end (in_context, &iterator);
+ }
+ }
+
+ if (!err) {
+ *out_info = info;
+ info = NULL;
+ }
+
+ if (info) { cc_free_NC_info (in_context, &info); }
+
+ return cci_check_error (err);
+}
+
+#if TARGET_OS_MAC
+#pragma mark -
+#endif
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 cc_open (apiCB *in_context,
+ const char *in_name,
+ cc_int32 in_version,
+ cc_uint32 in_flags,
+ ccache_p **out_ccache)
+{
+ cc_result err = ccNoError;
+ cc_ccache_t ccache = NULL;
+ cc_uint32 compat_version;
+ cc_uint32 real_version;
+
+ if (!in_context) { err = cci_check_error (ccErrBadParam); }
+ if (!in_name ) { err = cci_check_error (ccErrBadParam); }
+ if (!out_ccache) { err = cci_check_error (ccErrBadParam); }
+
+ if (!err) {
+ err = cci_remap_version (in_version, &compat_version);
+ }
+
+ if (!err) {
+ err = ccapi_context_open_ccache (in_context, in_name, &ccache);
+ }
+
+ /* We must not allow a CCAPI v2 caller to open a v5-only ccache
+ as a v4 ccache and vice versa. Allowing that would break
+ (valid) assumptions made by CCAPI v2 callers. */
+
+ if (!err) {
+ err = ccapi_ccache_get_credentials_version (ccache, &real_version);
+ }
+
+ if (!err) {
+ /* check the version and set up the ccache to use it */
+ if (compat_version & real_version) {
+ err = cci_ccache_set_compat_version (ccache, compat_version);
+ } else {
+ err = ccErrBadCredentialsVersion;
+ }
+ }
+
+ if (!err) {
+ *out_ccache = ccache;
+ ccache = NULL;
+ }
+
+ if (ccache) { ccapi_ccache_release (ccache); }
+
+ return cci_remap_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_result cc_create (apiCB *in_context,
+ const char *in_name,
+ const char *in_principal,
+ cc_int32 in_version,
+ cc_uint32 in_flags,
+ ccache_p **out_ccache)
+{
+ cc_result err = ccNoError;
+ cc_ccache_t ccache = NULL;
+ cc_uint32 compat_version;
+
+ if (!in_context) { err = cci_check_error (ccErrBadParam); }
+ if (!in_name ) { err = cci_check_error (ccErrBadParam); }
+ if (!out_ccache) { err = cci_check_error (ccErrBadParam); }
+
+ if (!err) {
+ err = cci_remap_version (in_version, &compat_version);
+ }
+
+ if (!err) {
+ err = ccapi_context_create_ccache (in_context, in_name, compat_version,
+ in_principal, &ccache);
+ }
+
+ if (!err) {
+ err = cci_ccache_set_compat_version (ccache, compat_version);
+ }
+
+ if (!err) {
+ *out_ccache = ccache;
+ ccache = NULL;
+ }
+
+ if (ccache) { ccapi_ccache_release (ccache); }
+
+ return cci_remap_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_result cc_close (apiCB *in_context,
+ ccache_p **io_ccache)
+{
+ cc_result err = ccNoError;
+
+ if (!in_context) { err = cci_check_error (ccErrBadParam); }
+ if (!io_ccache ) { err = cci_check_error (ccErrBadParam); }
+
+ if (!err) {
+ err = ccapi_ccache_release (*io_ccache);
+ }
+
+ if (!err) {
+ *io_ccache = NULL;
+ }
+
+ return cci_remap_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_result cc_destroy (apiCB *in_context,
+ ccache_p **io_ccache)
+{
+ cc_result err = ccNoError;
+
+ if (!in_context) { err = cci_check_error (ccErrBadParam); }
+ if (!io_ccache ) { err = cci_check_error (ccErrBadParam); }
+
+ if (!err) {
+ err = ccapi_ccache_destroy (*io_ccache);
+ }
+
+ if (!err) {
+ *io_ccache = NULL;
+ }
+
+ return cci_remap_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_result cc_get_name (apiCB *in_context,
+ ccache_p *in_ccache,
+ char **out_name)
+{
+ cc_result err = ccNoError;
+ cc_string_t name = NULL;
+
+ if (!in_context) { err = cci_check_error (ccErrBadParam); }
+ if (!in_ccache ) { err = cci_check_error (ccErrBadParam); }
+ if (!out_name ) { err = cci_check_error (ccErrBadParam); }
+
+ if (!err) {
+ err = ccapi_ccache_get_name (in_ccache, &name);
+ }
+
+ if (!err) {
+ char *string = strdup (name->data);
+ if (string) {
+ *out_name = string;
+ } else {
+ err = cci_check_error (ccErrNoMem);
+ }
+ }
+
+ if (name) { ccapi_string_release (name); }
+
+ return cci_remap_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_result cc_get_cred_version (apiCB *in_context,
+ ccache_p *in_ccache,
+ cc_int32 *out_version)
+{
+ cc_result err = ccNoError;
+ cc_uint32 compat_version;
+
+ if (!in_context ) { err = cci_check_error (ccErrBadParam); }
+ if (!in_ccache ) { err = cci_check_error (ccErrBadParam); }
+ if (!out_version) { err = cci_check_error (ccErrBadParam); }
+
+ if (!err) {
+ err = cci_ccache_get_compat_version (in_ccache, &compat_version);
+ }
+
+ if (!err) {
+ if (compat_version == cc_credentials_v4) {
+ *out_version = CC_CRED_V4;
+
+ } else if (compat_version == cc_credentials_v5) {
+ *out_version = CC_CRED_V5;
+
+ } else {
+ err = ccErrBadCredentialsVersion;
+ }
+ }
+
+ return cci_remap_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_result cc_set_principal (apiCB *in_context,
+ ccache_p *io_ccache,
+ cc_int32 in_version,
+ char *in_principal)
+{
+ cc_result err = ccNoError;
+ cc_uint32 version;
+ cc_uint32 compat_version;
+
+ if (!in_context ) { err = cci_check_error (ccErrBadParam); }
+ if (!io_ccache ) { err = cci_check_error (ccErrBadParam); }
+ if (!in_principal) { err = cci_check_error (ccErrBadParam); }
+
+ if (!err) {
+ err = cci_remap_version (in_version, &version);
+ }
+
+ if (!err) {
+ err = cci_ccache_get_compat_version (io_ccache, &compat_version);
+ }
+
+ if (!err && version != compat_version) {
+ err = cci_check_error (ccErrBadCredentialsVersion);
+ }
+
+ if (!err) {
+ err = ccapi_ccache_set_principal (io_ccache, version, in_principal);
+ }
+
+ return cci_remap_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_result cc_get_principal (apiCB *in_context,
+ ccache_p *in_ccache,
+ char **out_principal)
+{
+ cc_result err = ccNoError;
+ cc_uint32 compat_version;
+ cc_string_t principal = NULL;
+
+ if (!in_context ) { err = cci_check_error (ccErrBadParam); }
+ if (!in_ccache ) { err = cci_check_error (ccErrBadParam); }
+ if (!out_principal) { err = cci_check_error (ccErrBadParam); }
+
+ if (!err) {
+ err = cci_ccache_get_compat_version (in_ccache, &compat_version);
+ }
+
+ if (!err) {
+ err = ccapi_ccache_get_principal (in_ccache, compat_version, &principal);
+ }
+
+ if (!err) {
+ char *string = strdup (principal->data);
+ if (string) {
+ *out_principal = string;
+ } else {
+ err = cci_check_error (ccErrNoMem);
+ }
+ }
+
+ if (principal) { ccapi_string_release (principal); }
+
+ return cci_remap_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_result cc_store (apiCB *in_context,
+ ccache_p *io_ccache,
+ cred_union in_credentials)
+{
+ cc_result err = ccNoError;
+ cc_credentials_union *creds_union = NULL;
+
+ if (!in_context) { err = cci_check_error (ccErrBadParam); }
+ if (!io_ccache ) { err = cci_check_error (ccErrBadParam); }
+
+ if (!err) {
+ err = cci_cred_union_to_credentials_union (&in_credentials,
+ &creds_union);
+ }
+
+ if (!err) {
+ err = ccapi_ccache_store_credentials (io_ccache, creds_union);
+ }
+
+ if (creds_union) { cci_credentials_union_release (creds_union); }
+ return cci_remap_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_result cc_remove_cred (apiCB *in_context,
+ ccache_p *in_ccache,
+ cred_union in_credentials)
+{
+ cc_result err = ccNoError;
+ cc_credentials_iterator_t iterator = NULL;
+ cc_uint32 found = 0;
+
+ if (!in_context) { err = cci_check_error (ccErrBadParam); }
+ if (!in_ccache ) { err = cci_check_error (ccErrBadParam); }
+
+ if (!err) {
+ err = ccapi_ccache_new_credentials_iterator (in_ccache, &iterator);
+ }
+
+ while (!err && !found) {
+ cc_credentials_t creds = NULL;
+
+ err = ccapi_credentials_iterator_next (iterator, &creds);
+
+ if (!err) {
+ err = cci_cred_union_compare_to_credentials_union (&in_credentials,
+ creds->data,
+ &found);
+ }
+
+ if (!err && found) {
+ err = ccapi_ccache_remove_credentials (in_ccache, creds);
+ }
+
+ ccapi_credentials_release (creds);
+ }
+ if (err == ccIteratorEnd) { err = cci_check_error (ccErrCredentialsNotFound); }
+
+ return cci_remap_error (err);
+}
+
+#if TARGET_OS_MAC
+#pragma mark -
+#endif
+
+/* ------------------------------------------------------------------------ */
+
+cc_result cc_seq_fetch_NCs_begin (apiCB *in_context,
+ ccache_cit **out_iterator)
+{
+ cc_result err = ccNoError;
+ cc_ccache_iterator_t iterator = NULL;
+
+ if (!in_context ) { err = cci_check_error (ccErrBadParam); }
+ if (!out_iterator) { err = cci_check_error (ccErrBadParam); }
+
+ if (!err) {
+ err = ccapi_context_new_ccache_iterator (in_context, &iterator);
+ }
+
+ if (!err) {
+ *out_iterator = (ccache_cit *) iterator;
+ iterator = NULL; /* take ownership */
+ }
+
+ if (iterator) { ccapi_ccache_iterator_release (iterator); }
+
+ return cci_remap_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_result cc_seq_fetch_NCs_next (apiCB *in_context,
+ ccache_p **out_ccache,
+ ccache_cit *in_iterator)
+{
+ cc_result err = ccNoError;
+ cc_ccache_iterator_t iterator = (cc_ccache_iterator_t) in_iterator;
+ cc_ccache_t ccache = NULL;
+ const char *saved_ccache_name;
+
+ if (!in_context ) { err = cci_check_error (ccErrBadParam); }
+ if (!out_ccache ) { err = cci_check_error (ccErrBadParam); }
+ if (!in_iterator) { err = cci_check_error (ccErrBadParam); }
+
+ /* CCache iterators need to return some ccaches twice (when v3 ccache has
+ * two kinds of credentials). To do that, we return such ccaches twice
+ * v4 first, then v5. */
+
+ if (!err) {
+ err = cci_ccache_iterator_get_saved_ccache_name (iterator,
+ &saved_ccache_name);
+ }
+
+ if (!err) {
+ if (saved_ccache_name) {
+ err = ccapi_context_open_ccache (in_context, saved_ccache_name,
+ &ccache);
+
+ if (!err) {
+ err = cci_ccache_set_compat_version (ccache, cc_credentials_v5);
+ }
+
+ if (!err) {
+ err = cci_ccache_iterator_set_saved_ccache_name (iterator, NULL);
+ }
+
+ } else {
+ cc_uint32 version = 0;
+
+ err = ccapi_ccache_iterator_next (iterator, &ccache);
+
+ if (!err) {
+ err = ccapi_ccache_get_credentials_version (ccache, &version);
+ }
+
+ if (!err) {
+ if (version == cc_credentials_v4_v5) {
+ cc_string_t name = NULL;
+
+ err = cci_ccache_set_compat_version (ccache, cc_credentials_v4);
+
+ if (!err) {
+ err = ccapi_ccache_get_name (ccache, &name);
+ }
+
+ if (!err) {
+ err = cci_ccache_iterator_set_saved_ccache_name (iterator,
+ name->data);
+ }
+
+ if (name) { ccapi_string_release (name); }
+
+ } else {
+ err = cci_ccache_set_compat_version (ccache, version);
+ }
+ }
+ }
+ }
+
+ if (!err) {
+ *out_ccache = ccache;
+ ccache = NULL; /* take ownership */
+ }
+
+ if (ccache) { ccapi_ccache_release (ccache); }
+
+ return cci_remap_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_result cc_seq_fetch_NCs_end (apiCB *in_context,
+ ccache_cit **io_iterator)
+{
+ cc_result err = ccNoError;
+ cc_ccache_iterator_t iterator = (cc_ccache_iterator_t) *io_iterator;
+
+ if (!in_context ) { err = cci_check_error (ccErrBadParam); }
+ if (!io_iterator) { err = cci_check_error (ccErrBadParam); }
+
+ if (!err) {
+ err = ccapi_ccache_iterator_release (iterator);
+ }
+
+ if (!err) {
+ *io_iterator = NULL;
+ }
+
+ return cci_remap_error (err);
+}
+
+#if TARGET_OS_MAC
+#pragma mark -
+#endif
+
+/* ------------------------------------------------------------------------ */
+
+cc_result cc_seq_fetch_creds_begin (apiCB *in_context,
+ const ccache_p *in_ccache,
+ ccache_cit **out_iterator)
+{
+ cc_result err = ccNoError;
+ cc_credentials_iterator_t iterator = NULL;
+ cc_uint32 compat_version;
+
+ if (!in_context ) { err = cci_check_error (ccErrBadParam); }
+ if (!in_ccache ) { err = cci_check_error (ccErrBadParam); }
+ if (!out_iterator) { err = cci_check_error (ccErrBadParam); }
+
+ if (!err) {
+ err = cci_ccache_get_compat_version ((cc_ccache_t) in_ccache,
+ &compat_version);
+ }
+
+ if (!err) {
+ err = ccapi_ccache_new_credentials_iterator ((cc_ccache_t) in_ccache,
+ &iterator);
+ }
+
+ if (!err) {
+ err = cci_credentials_iterator_set_compat_version (iterator,
+ compat_version);
+ }
+
+ if (!err) {
+ *out_iterator = (ccache_cit *) iterator;
+ iterator = NULL; /* take ownership */
+ }
+
+ if (iterator) { ccapi_credentials_iterator_release (iterator); }
+
+ return cci_remap_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_result cc_seq_fetch_creds_next (apiCB *in_context,
+ cred_union **out_creds,
+ ccache_cit *in_iterator)
+{
+ cc_result err = ccNoError;
+ cc_credentials_iterator_t iterator = (cc_credentials_iterator_t) in_iterator;
+ cc_uint32 compat_version;
+
+ if (!in_context ) { err = cci_check_error (ccErrBadParam); }
+ if (!out_creds ) { err = cci_check_error (ccErrBadParam); }
+ if (!in_iterator) { err = cci_check_error (ccErrBadParam); }
+
+ if (!err) {
+ err = cci_credentials_iterator_get_compat_version (iterator,
+ &compat_version);
+ }
+
+ while (!err) {
+ cc_credentials_t credentials = NULL;
+
+ err = ccapi_credentials_iterator_next (iterator, &credentials);
+
+ if (!err && (credentials->data->version & compat_version)) {
+ /* got the next credentials for the correct version */
+ err = cci_credentials_union_to_cred_union (credentials->data,
+ out_creds);
+ break;
+ }
+
+ if (credentials) { ccapi_credentials_release (credentials); }
+ }
+
+ return cci_remap_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_result cc_seq_fetch_creds_end (apiCB *in_context,
+ ccache_cit **io_iterator)
+{
+ cc_result err = ccNoError;
+ cc_credentials_iterator_t iterator = (cc_credentials_iterator_t) *io_iterator;
+
+ if (!in_context ) { err = cci_check_error (ccErrBadParam); }
+ if (!io_iterator) { err = cci_check_error (ccErrBadParam); }
+
+ if (!err) {
+ err = ccapi_credentials_iterator_release (iterator);
+ }
+
+ if (!err) {
+ *io_iterator = NULL;
+ }
+
+ return cci_remap_error (err);
+}
+
+#if TARGET_OS_MAC
+#pragma mark -
+#endif
+
+/* ------------------------------------------------------------------------ */
+
+cc_result cc_free_principal (apiCB *in_context,
+ char **io_principal)
+{
+ cc_result err = ccNoError;
+
+ if (!in_context ) { err = cci_check_error (ccErrBadParam); }
+ if (!io_principal) { err = cci_check_error (ccErrBadParam); }
+
+ if (!err) {
+ free (*io_principal);
+ *io_principal = NULL;
+ }
+
+ return cci_remap_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_result cc_free_name (apiCB *in_context,
+ char **io_name)
+{
+ cc_result err = ccNoError;
+
+ if (!in_context) { err = cci_check_error (ccErrBadParam); }
+ if (!io_name ) { err = cci_check_error (ccErrBadParam); }
+
+ if (!err) {
+ free (*io_name);
+ *io_name = NULL;
+ }
+
+ return cci_remap_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_result cc_free_creds (apiCB *in_context,
+ cred_union **io_credentials)
+{
+ cc_result err = ccNoError;
+
+ if (!in_context ) { err = cci_check_error (ccErrBadParam); }
+ if (!io_credentials) { err = cci_check_error (ccErrBadParam); }
+
+ if (!err) {
+ err = cci_cred_union_release (*io_credentials);
+ if (!err) { *io_credentials = NULL; }
+ }
+
+ return cci_remap_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_result cc_free_NC_info (apiCB *in_context,
+ infoNC ***io_info)
+{
+ cc_result err = ccNoError;
+
+ if (!in_context) { err = cci_check_error (ccErrBadParam); }
+ if (!io_info ) { err = cci_check_error (ccErrBadParam); }
+
+ if (!err && *io_info) {
+ infoNC **data = *io_info;
+ int i;
+
+ for (i = 0; data[i] != NULL; i++) {
+ cc_free_principal (in_context, &data[i]->principal);
+ cc_free_name (in_context, &data[i]->name);
+ free (data[i]);
+ }
+ free (data);
+
+ *io_info = NULL;
+ }
+
+ return cci_remap_error (err);
+}
diff --git a/src/ccapi/lib/ccapi_v2.exports b/src/ccapi/lib/ccapi_v2.exports
new file mode 100644
index 000000000000..efa9fcec7ba5
--- /dev/null
+++ b/src/ccapi/lib/ccapi_v2.exports
@@ -0,0 +1,23 @@
+cc_shutdown
+cc_create
+cc_close
+cc_destroy
+cc_get_change_time
+cc_open
+cc_store
+cc_remove_cred
+cc_set_principal
+cc_get_principal
+cc_get_cred_version
+cc_get_name
+cc_seq_fetch_NCs_begin
+cc_seq_fetch_NCs_next
+cc_seq_fetch_NCs_end
+cc_seq_fetch_creds_begin
+cc_seq_fetch_creds_next
+cc_seq_fetch_creds_end
+cc_get_NC_info
+cc_free_principal
+cc_free_name
+cc_free_creds
+cc_free_NC_info
diff --git a/src/ccapi/lib/deps b/src/ccapi/lib/deps
new file mode 100644
index 000000000000..ad996d9fab9e
--- /dev/null
+++ b/src/ccapi/lib/deps
@@ -0,0 +1,86 @@
+#
+# Generated makefile dependencies follow.
+#
+ccapi_ccache.so ccapi_ccache.po $(OUTPRE)ccapi_ccache.$(OBJEXT): \
+ $(BUILDTOP)/include/autoconf.h $(COM_ERR_DEPS) $(top_srcdir)/include/CredentialsCache.h \
+ $(top_srcdir)/include/CredentialsCache2.h $(top_srcdir)/include/k5-ipc_stream.h \
+ $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-thread.h \
+ $(srcdir)/../common/cci_common.h $(srcdir)/../common/cci_cred_union.h \
+ $(srcdir)/../common/cci_debugging.h $(srcdir)/../common/cci_identifier.h \
+ $(srcdir)/../common/cci_message.h $(srcdir)/../common/cci_types.h \
+ ccapi_ccache.c ccapi_ccache.h ccapi_credentials.h ccapi_credentials_iterator.h \
+ ccapi_ipc.h ccapi_string.h
+ccapi_ccache_iterator.so ccapi_ccache_iterator.po $(OUTPRE)ccapi_ccache_iterator.$(OBJEXT): \
+ $(BUILDTOP)/include/autoconf.h $(COM_ERR_DEPS) $(top_srcdir)/include/CredentialsCache.h \
+ $(top_srcdir)/include/CredentialsCache2.h $(top_srcdir)/include/k5-ipc_stream.h \
+ $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-thread.h \
+ $(srcdir)/../common/cci_common.h $(srcdir)/../common/cci_cred_union.h \
+ $(srcdir)/../common/cci_debugging.h $(srcdir)/../common/cci_identifier.h \
+ $(srcdir)/../common/cci_message.h $(srcdir)/../common/cci_types.h \
+ ccapi_ccache.h ccapi_ccache_iterator.c ccapi_ccache_iterator.h \
+ ccapi_ipc.h
+ccapi_context.so ccapi_context.po $(OUTPRE)ccapi_context.$(OBJEXT): \
+ $(BUILDTOP)/include/autoconf.h $(COM_ERR_DEPS) $(top_srcdir)/include/CredentialsCache.h \
+ $(top_srcdir)/include/CredentialsCache2.h $(top_srcdir)/include/k5-ipc_stream.h \
+ $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-thread.h \
+ $(srcdir)/../common/cci_common.h $(srcdir)/../common/cci_cred_union.h \
+ $(srcdir)/../common/cci_debugging.h $(srcdir)/../common/cci_identifier.h \
+ $(srcdir)/../common/cci_message.h $(srcdir)/../common/cci_types.h \
+ ccapi_ccache.h ccapi_ccache_iterator.h ccapi_context.c \
+ ccapi_context.h ccapi_context_change_time.h ccapi_err.h \
+ ccapi_ipc.h ccapi_string.h
+ccapi_context_change_time.so ccapi_context_change_time.po \
+ $(OUTPRE)ccapi_context_change_time.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+ $(COM_ERR_DEPS) $(top_srcdir)/include/CredentialsCache.h \
+ $(top_srcdir)/include/CredentialsCache2.h $(top_srcdir)/include/k5-ipc_stream.h \
+ $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-thread.h \
+ $(srcdir)/../common/cci_common.h $(srcdir)/../common/cci_cred_union.h \
+ $(srcdir)/../common/cci_debugging.h $(srcdir)/../common/cci_identifier.h \
+ $(srcdir)/../common/cci_message.h $(srcdir)/../common/cci_types.h \
+ ccapi_context_change_time.c ccapi_context_change_time.h
+ccapi_credentials.so ccapi_credentials.po $(OUTPRE)ccapi_credentials.$(OBJEXT): \
+ $(BUILDTOP)/include/autoconf.h $(COM_ERR_DEPS) $(top_srcdir)/include/CredentialsCache.h \
+ $(top_srcdir)/include/CredentialsCache2.h $(top_srcdir)/include/k5-ipc_stream.h \
+ $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-thread.h \
+ $(srcdir)/../common/cci_common.h $(srcdir)/../common/cci_cred_union.h \
+ $(srcdir)/../common/cci_debugging.h $(srcdir)/../common/cci_identifier.h \
+ $(srcdir)/../common/cci_message.h $(srcdir)/../common/cci_types.h \
+ ccapi_credentials.c ccapi_credentials.h ccapi_string.h
+ccapi_credentials_iterator.so ccapi_credentials_iterator.po \
+ $(OUTPRE)ccapi_credentials_iterator.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+ $(COM_ERR_DEPS) $(top_srcdir)/include/CredentialsCache.h \
+ $(top_srcdir)/include/CredentialsCache2.h $(top_srcdir)/include/k5-ipc_stream.h \
+ $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-thread.h \
+ $(srcdir)/../common/cci_common.h $(srcdir)/../common/cci_cred_union.h \
+ $(srcdir)/../common/cci_debugging.h $(srcdir)/../common/cci_identifier.h \
+ $(srcdir)/../common/cci_message.h $(srcdir)/../common/cci_types.h \
+ ccapi_credentials.h ccapi_credentials_iterator.c ccapi_credentials_iterator.h \
+ ccapi_ipc.h
+ccapi_err.so ccapi_err.po $(OUTPRE)ccapi_err.$(OBJEXT): \
+ $(COM_ERR_DEPS) ccapi_err.c
+ccapi_ipc.so ccapi_ipc.po $(OUTPRE)ccapi_ipc.$(OBJEXT): \
+ $(BUILDTOP)/include/autoconf.h $(COM_ERR_DEPS) $(top_srcdir)/include/CredentialsCache.h \
+ $(top_srcdir)/include/CredentialsCache2.h $(top_srcdir)/include/k5-ipc_stream.h \
+ $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-thread.h \
+ $(srcdir)/../common/cci_common.h $(srcdir)/../common/cci_cred_union.h \
+ $(srcdir)/../common/cci_debugging.h $(srcdir)/../common/cci_identifier.h \
+ $(srcdir)/../common/cci_message.h $(srcdir)/../common/cci_types.h \
+ ccapi_ipc.c ccapi_ipc.h ccapi_os_ipc.h
+ccapi_string.so ccapi_string.po $(OUTPRE)ccapi_string.$(OBJEXT): \
+ $(BUILDTOP)/include/autoconf.h $(COM_ERR_DEPS) $(top_srcdir)/include/CredentialsCache.h \
+ $(top_srcdir)/include/CredentialsCache2.h $(top_srcdir)/include/k5-ipc_stream.h \
+ $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-thread.h \
+ $(srcdir)/../common/cci_common.h $(srcdir)/../common/cci_cred_union.h \
+ $(srcdir)/../common/cci_debugging.h $(srcdir)/../common/cci_identifier.h \
+ $(srcdir)/../common/cci_message.h $(srcdir)/../common/cci_types.h \
+ ccapi_string.c ccapi_string.h
+ccapi_v2.so ccapi_v2.po $(OUTPRE)ccapi_v2.$(OBJEXT): \
+ $(BUILDTOP)/include/autoconf.h $(COM_ERR_DEPS) $(top_srcdir)/include/CredentialsCache.h \
+ $(top_srcdir)/include/CredentialsCache2.h $(top_srcdir)/include/k5-ipc_stream.h \
+ $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-thread.h \
+ $(srcdir)/../common/cci_common.h $(srcdir)/../common/cci_cred_union.h \
+ $(srcdir)/../common/cci_debugging.h $(srcdir)/../common/cci_identifier.h \
+ $(srcdir)/../common/cci_message.h $(srcdir)/../common/cci_types.h \
+ ccapi_ccache.h ccapi_ccache_iterator.h ccapi_context.h \
+ ccapi_credentials.h ccapi_credentials_iterator.h ccapi_string.h \
+ ccapi_v2.c
diff --git a/src/ccapi/lib/libkrb5-ccapi.exports b/src/ccapi/lib/libkrb5-ccapi.exports
new file mode 100644
index 000000000000..1a8560f0bc70
--- /dev/null
+++ b/src/ccapi/lib/libkrb5-ccapi.exports
@@ -0,0 +1 @@
+cc_close
diff --git a/src/ccapi/lib/mac/ccapi_os_ipc.c b/src/ccapi/lib/mac/ccapi_os_ipc.c
new file mode 100644
index 000000000000..d6b9a6caecc8
--- /dev/null
+++ b/src/ccapi/lib/mac/ccapi_os_ipc.c
@@ -0,0 +1,50 @@
+/* ccapi/lib/mac/ccapi_os_ipc.c */
+/*
+ * Copyright 2006 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 M.I.T. 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.
+ */
+
+#include "ccapi_os_ipc.h"
+
+#include "k5_mig_client.h"
+
+#define cci_server_bundle_id "edu.mit.Kerberos.CCacheServer"
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 cci_os_ipc_thread_init (void)
+{
+ /* k5_ipc_send_request handles all thread data for us */
+ return 0;
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 cci_os_ipc (cc_int32 in_launch_server,
+ k5_ipc_stream in_request_stream,
+ k5_ipc_stream *out_reply_stream)
+{
+ return cci_check_error (k5_ipc_send_request (cci_server_bundle_id,
+ in_launch_server,
+ in_request_stream,
+ out_reply_stream));
+}
diff --git a/src/ccapi/lib/mac/ccapi_vector.c b/src/ccapi/lib/mac/ccapi_vector.c
new file mode 100644
index 000000000000..155599d81a34
--- /dev/null
+++ b/src/ccapi/lib/mac/ccapi_vector.c
@@ -0,0 +1,838 @@
+/* ccapi/lib/mac/ccapi_vector.c */
+/*
+ * Copyright 2006 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 M.I.T. 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.
+ */
+
+#include "ccapi_vector.h"
+
+#include "ccapi_context.h"
+#include "ccapi_string.h"
+#include "ccapi_ccache.h"
+#include "ccapi_credentials.h"
+#include "ccapi_ccache_iterator.h"
+#include "ccapi_credentials_iterator.h"
+
+/* ------------------------------------------------------------------------ */
+
+static void cci_swap_string_functions (cc_string_t io_string)
+{
+ cc_string_f temp = *(io_string->functions);
+ *((cc_string_f *)io_string->functions) = *(io_string->vector_functions);
+ *((cc_string_f *)io_string->vector_functions) = temp;
+}
+
+/* ------------------------------------------------------------------------ */
+
+static void cci_swap_context_functions (cc_context_t io_context)
+{
+ cc_context_f temp = *(io_context->functions);
+ *((cc_context_f *)io_context->functions) = *(io_context->vector_functions);
+ *((cc_context_f *)io_context->vector_functions) = temp;
+}
+
+/* ------------------------------------------------------------------------ */
+
+static void cci_swap_ccache_functions (cc_ccache_t io_ccache)
+{
+ cc_ccache_f temp = *(io_ccache->functions);
+ *((cc_ccache_f *)io_ccache->functions) = *(io_ccache->vector_functions);
+ *((cc_ccache_f *)io_ccache->vector_functions) = temp;
+}
+
+/* ------------------------------------------------------------------------ */
+
+static void cci_swap_credentials_functions (cc_credentials_t io_credentials)
+{
+ cc_credentials_f temp = *(io_credentials->functions);
+ *((cc_credentials_f *)io_credentials->functions) = *(io_credentials->otherFunctions);
+ *((cc_credentials_f *)io_credentials->otherFunctions) = temp;
+}
+
+/* ------------------------------------------------------------------------ */
+
+static void cci_swap_ccache_iterator_functions (cc_ccache_iterator_t io_ccache_iterator)
+{
+ cc_ccache_iterator_f temp = *(io_ccache_iterator->functions);
+ *((cc_ccache_iterator_f *)io_ccache_iterator->functions) = *(io_ccache_iterator->vector_functions);
+ *((cc_ccache_iterator_f *)io_ccache_iterator->vector_functions) = temp;
+}
+
+/* ------------------------------------------------------------------------ */
+
+static void cci_swap_credentials_iterator_functions (cc_credentials_iterator_t io_credentials_iterator)
+{
+ cc_credentials_iterator_f temp = *(io_credentials_iterator->functions);
+ *((cc_credentials_iterator_f *)io_credentials_iterator->functions) = *(io_credentials_iterator->vector_functions);
+ *((cc_credentials_iterator_f *)io_credentials_iterator->vector_functions) = temp;
+}
+
+#pragma mark -
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 __cc_initialize_vector (cc_context_t *out_context,
+ cc_int32 in_version,
+ cc_int32 *out_supported_version,
+ char const **out_vendor)
+{
+ return cc_initialize (out_context, in_version, out_supported_version, out_vendor);
+}
+
+#pragma mark -
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 __cc_string_release_vector (cc_string_t in_string)
+{
+ cci_swap_string_functions (in_string);
+ return ccapi_string_release (in_string);
+}
+
+#pragma mark -
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 __cc_context_release_vector (cc_context_t io_context)
+{
+ cci_swap_context_functions (io_context);
+ return ccapi_context_release (io_context);
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 __cc_context_get_change_time_vector (cc_context_t in_context,
+ cc_time_t *out_change_time)
+{
+ cc_int32 err = ccNoError;
+ cci_swap_context_functions (in_context);
+ err = ccapi_context_get_change_time (in_context, out_change_time);
+ cci_swap_context_functions (in_context);
+ return err;
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 __cc_context_get_default_ccache_name_vector (cc_context_t in_context,
+ cc_string_t *out_name)
+{
+ cc_int32 err = ccNoError;
+ cci_swap_context_functions (in_context);
+ err = ccapi_context_get_default_ccache_name (in_context, out_name);
+ cci_swap_context_functions (in_context);
+ return err;
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 __cc_context_open_ccache_vector (cc_context_t in_context,
+ const char *in_name,
+ cc_ccache_t *out_ccache)
+{
+ cc_int32 err = ccNoError;
+ cci_swap_context_functions (in_context);
+ err = ccapi_context_open_ccache (in_context, in_name, out_ccache);
+ cci_swap_context_functions (in_context);
+ return err;
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 __cc_context_open_default_ccache_vector (cc_context_t in_context,
+ cc_ccache_t *out_ccache)
+{
+ cc_int32 err = ccNoError;
+ cci_swap_context_functions (in_context);
+ err = ccapi_context_open_default_ccache (in_context, out_ccache);
+ cci_swap_context_functions (in_context);
+ return err;
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 __cc_context_create_ccache_vector (cc_context_t in_context,
+ const char *in_name,
+ cc_uint32 in_cred_vers,
+ const char *in_principal,
+ cc_ccache_t *out_ccache)
+{
+ cc_int32 err = ccNoError;
+ cci_swap_context_functions (in_context);
+ err = ccapi_context_create_ccache (in_context, in_name, in_cred_vers, in_principal, out_ccache);
+ cci_swap_context_functions (in_context);
+ return err;
+}
+
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 __cc_context_create_default_ccache_vector (cc_context_t in_context,
+ cc_uint32 in_cred_vers,
+ const char *in_principal,
+ cc_ccache_t *out_ccache)
+{
+ cc_int32 err = ccNoError;
+ cci_swap_context_functions (in_context);
+ err = ccapi_context_create_default_ccache (in_context, in_cred_vers, in_principal, out_ccache);
+ cci_swap_context_functions (in_context);
+ return err;
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 __cc_context_create_new_ccache_vector (cc_context_t in_context,
+ cc_uint32 in_cred_vers,
+ const char *in_principal,
+ cc_ccache_t *out_ccache)
+{
+ cc_int32 err = ccNoError;
+ cci_swap_context_functions (in_context);
+ err = ccapi_context_create_new_ccache (in_context, in_cred_vers, in_principal, out_ccache);
+ cci_swap_context_functions (in_context);
+ return err;
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 __cc_context_new_ccache_iterator_vector (cc_context_t in_context,
+ cc_ccache_iterator_t *out_iterator)
+{
+ cc_int32 err = ccNoError;
+ cci_swap_context_functions (in_context);
+ err = ccapi_context_new_ccache_iterator (in_context, out_iterator);
+ cci_swap_context_functions (in_context);
+ return err;
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 __cc_context_lock_vector (cc_context_t in_context,
+ cc_uint32 in_lock_type,
+ cc_uint32 in_block)
+{
+ cc_int32 err = ccNoError;
+ cci_swap_context_functions (in_context);
+ err = ccapi_context_lock (in_context, in_lock_type, in_block);
+ cci_swap_context_functions (in_context);
+ return err;
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 __cc_context_unlock_vector (cc_context_t in_context)
+{
+ cc_int32 err = ccNoError;
+ cci_swap_context_functions (in_context);
+ err = ccapi_context_unlock (in_context);
+ cci_swap_context_functions (in_context);
+ return err;
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 __cc_context_compare_vector (cc_context_t in_context,
+ cc_context_t in_compare_to_context,
+ cc_uint32 *out_equal)
+{
+ cc_int32 err = ccNoError;
+ cci_swap_context_functions (in_context);
+ err = ccapi_context_compare (in_context, in_compare_to_context, out_equal);
+ cci_swap_context_functions (in_context);
+ return err;
+}
+
+#pragma mark -
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 __cc_ccache_release_vector (cc_ccache_t io_ccache)
+{
+ cci_swap_ccache_functions (io_ccache);
+ return ccapi_ccache_release (io_ccache);
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 __cc_ccache_destroy_vector (cc_ccache_t io_ccache)
+{
+ cci_swap_ccache_functions (io_ccache);
+ return ccapi_ccache_destroy (io_ccache);
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 __cc_ccache_set_default_vector (cc_ccache_t io_ccache)
+{
+ cc_int32 err = ccNoError;
+ cci_swap_ccache_functions (io_ccache);
+ err = ccapi_ccache_set_default (io_ccache);
+ cci_swap_ccache_functions (io_ccache);
+ return err;
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_uint32 __cc_ccache_get_credentials_version_vector (cc_ccache_t in_ccache,
+ cc_uint32 *out_credentials_version)
+{
+ cc_int32 err = ccNoError;
+ cci_swap_ccache_functions (in_ccache);
+ err = ccapi_ccache_get_credentials_version (in_ccache, out_credentials_version);
+ cci_swap_ccache_functions (in_ccache);
+ return err;
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 __cc_ccache_get_name_vector (cc_ccache_t in_ccache,
+ cc_string_t *out_name)
+{
+ cc_int32 err = ccNoError;
+ cci_swap_ccache_functions (in_ccache);
+ err = ccapi_ccache_get_name (in_ccache, out_name);
+ cci_swap_ccache_functions (in_ccache);
+ return err;
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 __cc_ccache_get_principal_vector (cc_ccache_t in_ccache,
+ cc_uint32 in_credentials_version,
+ cc_string_t *out_principal)
+{
+ cc_int32 err = ccNoError;
+ cci_swap_ccache_functions (in_ccache);
+ err = ccapi_ccache_get_principal (in_ccache, in_credentials_version, out_principal);
+ cci_swap_ccache_functions (in_ccache);
+ return err;
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 __cc_ccache_set_principal_vector (cc_ccache_t io_ccache,
+ cc_uint32 in_credentials_version,
+ const char *in_principal)
+{
+ cc_int32 err = ccNoError;
+ cci_swap_ccache_functions (io_ccache);
+ err = ccapi_ccache_set_principal (io_ccache, in_credentials_version, in_principal);
+ cci_swap_ccache_functions (io_ccache);
+ return err;
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 __cc_ccache_store_credentials_vector (cc_ccache_t io_ccache,
+ const cc_credentials_union *in_credentials_union)
+{
+ cc_int32 err = ccNoError;
+ cci_swap_ccache_functions (io_ccache);
+ err = ccapi_ccache_store_credentials (io_ccache, in_credentials_union);
+ cci_swap_ccache_functions (io_ccache);
+ return err;
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 __cc_ccache_remove_credentials_vector (cc_ccache_t io_ccache,
+ cc_credentials_t in_credentials)
+{
+ cc_int32 err = ccNoError;
+ cci_swap_ccache_functions (io_ccache);
+ cci_swap_credentials_functions (in_credentials);
+ err = ccapi_ccache_remove_credentials (io_ccache, in_credentials);
+ cci_swap_ccache_functions (io_ccache);
+ cci_swap_credentials_functions (in_credentials);
+ return err;
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 __cc_ccache_new_credentials_iterator_vector (cc_ccache_t in_ccache,
+ cc_credentials_iterator_t *out_credentials_iterator)
+{
+ cc_int32 err = ccNoError;
+ cci_swap_ccache_functions (in_ccache);
+ err = ccapi_ccache_new_credentials_iterator (in_ccache, out_credentials_iterator);
+ cci_swap_ccache_functions (in_ccache);
+ return err;
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 __cc_ccache_move_vector (cc_ccache_t io_source_ccache,
+ cc_ccache_t io_destination_ccache)
+{
+ cc_int32 err = ccNoError;
+ cci_swap_ccache_functions (io_source_ccache);
+ cci_swap_ccache_functions (io_destination_ccache);
+ err = ccapi_ccache_move (io_source_ccache, io_destination_ccache);
+ cci_swap_ccache_functions (io_source_ccache);
+ cci_swap_ccache_functions (io_destination_ccache);
+ return err;
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 __cc_ccache_lock_vector (cc_ccache_t io_ccache,
+ cc_uint32 in_lock_type,
+ cc_uint32 in_block)
+{
+ cc_int32 err = ccNoError;
+ cci_swap_ccache_functions (io_ccache);
+ err = ccapi_ccache_lock (io_ccache, in_lock_type, in_block);
+ cci_swap_ccache_functions (io_ccache);
+ return err;
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 __cc_ccache_unlock_vector (cc_ccache_t io_ccache)
+{
+ cc_int32 err = ccNoError;
+ cci_swap_ccache_functions (io_ccache);
+ err = ccapi_ccache_unlock (io_ccache);
+ cci_swap_ccache_functions (io_ccache);
+ return err;
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 __cc_ccache_get_last_default_time_vector (cc_ccache_t in_ccache,
+ cc_time_t *out_last_default_time)
+{
+ cc_int32 err = ccNoError;
+ cci_swap_ccache_functions (in_ccache);
+ err = ccapi_ccache_get_last_default_time (in_ccache, out_last_default_time);
+ cci_swap_ccache_functions (in_ccache);
+ return err;
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 __cc_ccache_get_change_time_vector (cc_ccache_t in_ccache,
+ cc_time_t *out_change_time)
+{
+ cc_int32 err = ccNoError;
+ cci_swap_ccache_functions (in_ccache);
+ err = ccapi_ccache_get_change_time (in_ccache, out_change_time);
+ cci_swap_ccache_functions (in_ccache);
+ return err;
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 __cc_ccache_compare_vector (cc_ccache_t in_ccache,
+ cc_ccache_t in_compare_to_ccache,
+ cc_uint32 *out_equal)
+{
+ cc_int32 err = ccNoError;
+ cci_swap_ccache_functions (in_ccache);
+ cci_swap_ccache_functions (in_compare_to_ccache);
+ err = ccapi_ccache_compare (in_ccache, in_compare_to_ccache, out_equal);
+ cci_swap_ccache_functions (in_ccache);
+ cci_swap_ccache_functions (in_compare_to_ccache);
+ return err;
+}
+
+#pragma mark -
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 __cc_credentials_release_vector (cc_credentials_t io_credentials)
+{
+ cci_swap_credentials_functions (io_credentials);
+ return ccapi_credentials_release (io_credentials);
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 __cc_credentials_compare_vector (cc_credentials_t in_credentials,
+ cc_credentials_t in_compare_to_credentials,
+ cc_uint32 *out_equal)
+{
+ cc_int32 err = ccNoError;
+ cci_swap_credentials_functions (in_credentials);
+ cci_swap_credentials_functions (in_compare_to_credentials);
+ err = ccapi_credentials_compare (in_credentials, in_compare_to_credentials, out_equal);
+ cci_swap_credentials_functions (in_credentials);
+ cci_swap_credentials_functions (in_compare_to_credentials);
+ return err;
+}
+
+#pragma mark -
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 __cc_ccache_iterator_release_vector (cc_ccache_iterator_t io_ccache_iterator)
+{
+ cci_swap_ccache_iterator_functions (io_ccache_iterator);
+ return ccapi_ccache_iterator_release (io_ccache_iterator);
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 __cc_ccache_iterator_next_vector (cc_ccache_iterator_t in_ccache_iterator,
+ cc_ccache_t *out_ccache)
+{
+ cc_int32 err = ccNoError;
+ cci_swap_ccache_iterator_functions (in_ccache_iterator);
+ err = ccapi_ccache_iterator_next (in_ccache_iterator, out_ccache);
+ cci_swap_ccache_iterator_functions (in_ccache_iterator);
+ return err;
+}
+
+#pragma mark -
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 __cc_credentials_iterator_release_vector (cc_credentials_iterator_t io_credentials_iterator)
+{
+ cci_swap_credentials_iterator_functions (io_credentials_iterator);
+ return ccapi_credentials_iterator_release (io_credentials_iterator);
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 __cc_credentials_iterator_next_vector (cc_credentials_iterator_t in_credentials_iterator,
+ cc_credentials_t *out_credentials)
+{
+ cc_int32 err = ccNoError;
+ cci_swap_credentials_iterator_functions (in_credentials_iterator);
+ err = ccapi_credentials_iterator_next (in_credentials_iterator, out_credentials);
+ cci_swap_credentials_iterator_functions (in_credentials_iterator);
+ return err;
+}
+
+#pragma mark -
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 __cc_shutdown_vector (apiCB **io_context)
+{
+ cci_swap_context_functions (*io_context);
+ return cc_shutdown (io_context);
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 __cc_get_NC_info_vector (apiCB *in_context,
+ infoNC ***out_info)
+{
+ cc_int32 err = ccNoError;
+ cci_swap_context_functions (in_context);
+ err = cc_get_NC_info (in_context, out_info);
+ cci_swap_context_functions (in_context);
+ return err;
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 __cc_get_change_time_vector (apiCB *in_context,
+ cc_time_t *out_change_time)
+{
+ cc_int32 err = ccNoError;
+ cci_swap_context_functions (in_context);
+ err = cc_get_change_time (in_context, out_change_time);
+ cci_swap_context_functions (in_context);
+ return err;
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 __cc_open_vector (apiCB *in_context,
+ const char *in_name,
+ cc_int32 in_version,
+ cc_uint32 in_flags,
+ ccache_p **out_ccache)
+{
+ cc_int32 err = ccNoError;
+ cci_swap_context_functions (in_context);
+ err = cc_open (in_context, in_name, in_version, in_flags, out_ccache);
+ cci_swap_context_functions (in_context);
+ return err;
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 __cc_create_vector (apiCB *in_context,
+ const char *in_name,
+ const char *in_principal,
+ cc_int32 in_version,
+ cc_uint32 in_flags,
+ ccache_p **out_ccache)
+{
+ cc_int32 err = ccNoError;
+ cci_swap_context_functions (in_context);
+ err = cc_create (in_context, in_name, in_principal, in_version, in_flags, out_ccache);
+ cci_swap_context_functions (in_context);
+ return err;
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 __cc_close_vector (apiCB *in_context,
+ ccache_p **io_ccache)
+{
+ cc_int32 err = ccNoError;
+ cci_swap_context_functions (in_context);
+ cci_swap_ccache_functions (*io_ccache);
+ err = cc_close (in_context, io_ccache);
+ cci_swap_context_functions (in_context);
+ return err;
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 __cc_destroy_vector (apiCB *in_context,
+ ccache_p **io_ccache)
+{
+ cc_int32 err = ccNoError;
+ cci_swap_context_functions (in_context);
+ cci_swap_ccache_functions (*io_ccache);
+ err = cc_destroy (in_context, io_ccache);
+ cci_swap_context_functions (in_context);
+ return err;
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 __cc_seq_fetch_NCs_begin_vector (apiCB *in_context,
+ ccache_cit **out_iterator)
+{
+ cc_int32 err = ccNoError;
+ cci_swap_context_functions (in_context);
+ err = cc_seq_fetch_NCs_begin (in_context, out_iterator);
+ cci_swap_context_functions (in_context);
+ return err;
+}
+
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 __cc_seq_fetch_NCs_next_vector (apiCB *in_context,
+ ccache_p **out_ccache,
+ ccache_cit *in_iterator)
+{
+ cc_int32 err = ccNoError;
+ cci_swap_context_functions (in_context);
+ cci_swap_ccache_iterator_functions ((ccache_cit_ccache *)in_iterator);
+ err = cc_seq_fetch_NCs_next (in_context, out_ccache, in_iterator);
+ cci_swap_context_functions (in_context);
+ cci_swap_ccache_iterator_functions ((ccache_cit_ccache *)in_iterator);
+ return err;
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 __cc_seq_fetch_NCs_end_vector (apiCB *in_context,
+ ccache_cit **io_iterator)
+{
+ cc_int32 err = ccNoError;
+ cci_swap_context_functions (in_context);
+ cci_swap_ccache_iterator_functions ((ccache_cit_ccache *) *io_iterator);
+ err = cc_seq_fetch_NCs_end (in_context, io_iterator);
+ cci_swap_context_functions (in_context);
+ return err;
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 __cc_get_name_vector (apiCB *in_context,
+ ccache_p *in_ccache,
+ char **out_name)
+{
+ cc_int32 err = ccNoError;
+ cci_swap_context_functions (in_context);
+ cci_swap_ccache_functions (in_ccache);
+ err = cc_get_name (in_context, in_ccache, out_name);
+ cci_swap_context_functions (in_context);
+ cci_swap_ccache_functions (in_ccache);
+ return err;
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 __cc_get_cred_version_vector (apiCB *in_context,
+ ccache_p *in_ccache,
+ cc_int32 *out_version)
+{
+ cc_int32 err = ccNoError;
+ cci_swap_context_functions (in_context);
+ cci_swap_ccache_functions (in_ccache);
+ err = cc_get_cred_version (in_context, in_ccache, out_version);
+ cci_swap_context_functions (in_context);
+ cci_swap_ccache_functions (in_ccache);
+ return err;
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 __cc_set_principal_vector (apiCB *in_context,
+ ccache_p *io_ccache,
+ cc_int32 in_version,
+ char *in_principal)
+{
+ cc_int32 err = ccNoError;
+ cci_swap_context_functions (in_context);
+ cci_swap_ccache_functions (io_ccache);
+ err = cc_set_principal (in_context, io_ccache, in_version, in_principal);
+ cci_swap_context_functions (in_context);
+ cci_swap_ccache_functions (io_ccache);
+ return err;
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 __cc_get_principal_vector (apiCB *in_context,
+ ccache_p *in_ccache,
+ char **out_principal)
+{
+ cc_int32 err = ccNoError;
+ cci_swap_context_functions (in_context);
+ cci_swap_ccache_functions (in_ccache);
+ err = cc_get_principal (in_context, in_ccache, out_principal);
+ cci_swap_context_functions (in_context);
+ cci_swap_ccache_functions (in_ccache);
+ return err;
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 __cc_store_vector (apiCB *in_context,
+ ccache_p *io_ccache,
+ cred_union in_credentials)
+{
+ cc_int32 err = ccNoError;
+ cci_swap_context_functions (in_context);
+ cci_swap_ccache_functions (io_ccache);
+ err = cc_store (in_context, io_ccache, in_credentials);
+ cci_swap_context_functions (in_context);
+ cci_swap_ccache_functions (io_ccache);
+ return err;
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 __cc_remove_cred_vector (apiCB *in_context,
+ ccache_p *in_ccache,
+ cred_union in_credentials)
+{
+ cc_int32 err = ccNoError;
+ cci_swap_context_functions (in_context);
+ cci_swap_ccache_functions (in_ccache);
+ err = cc_remove_cred (in_context, in_ccache, in_credentials);
+ cci_swap_context_functions (in_context);
+ cci_swap_ccache_functions (in_ccache);
+ return err;
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 __cc_seq_fetch_creds_begin_vector (apiCB *in_context,
+ const ccache_p *in_ccache,
+ ccache_cit **out_iterator)
+{
+ cc_int32 err = ccNoError;
+ cci_swap_context_functions (in_context);
+ cci_swap_ccache_functions ((ccache_p *)in_ccache);
+ err = cc_seq_fetch_creds_begin (in_context, in_ccache, out_iterator);
+ cci_swap_context_functions (in_context);
+ cci_swap_ccache_functions ((ccache_p *)in_ccache);
+ return err;
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 __cc_seq_fetch_creds_next_vector (apiCB *in_context,
+ cred_union **out_creds,
+ ccache_cit *in_iterator)
+{
+ cc_int32 err = ccNoError;
+ cci_swap_context_functions (in_context);
+ cci_swap_credentials_iterator_functions ((ccache_cit_creds *)in_iterator);
+ err = cc_seq_fetch_creds_next (in_context, out_creds, in_iterator);
+ cci_swap_context_functions (in_context);
+ cci_swap_credentials_iterator_functions ((ccache_cit_creds *)in_iterator);
+ return err;
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 __cc_seq_fetch_creds_end_vector (apiCB *in_context,
+ ccache_cit **io_iterator)
+{
+ cc_int32 err = ccNoError;
+ cci_swap_context_functions (in_context);
+ cci_swap_credentials_iterator_functions ((ccache_cit_creds *) *io_iterator);
+ err = cc_seq_fetch_creds_end (in_context, io_iterator);
+ cci_swap_context_functions (in_context);
+ return err;
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 __cc_free_principal_vector (apiCB *in_context,
+ char **io_principal)
+{
+ cc_int32 err = ccNoError;
+ cci_swap_context_functions (in_context);
+ err = cc_free_principal (in_context, io_principal);
+ cci_swap_context_functions (in_context);
+ return err;
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 __cc_free_name_vector (apiCB *in_context,
+ char **io_name)
+{
+ cc_int32 err = ccNoError;
+ cci_swap_context_functions (in_context);
+ err = cc_free_name (in_context, io_name);
+ cci_swap_context_functions (in_context);
+ return err;
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 __cc_free_creds_vector (apiCB *in_context,
+ cred_union **io_credentials)
+{
+ cc_int32 err = ccNoError;
+ cci_swap_context_functions (in_context);
+ err = cc_free_creds (in_context, io_credentials);
+ cci_swap_context_functions (in_context);
+ return err;
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 __cc_free_NC_info_vector (apiCB *in_context,
+ infoNC ***io_info)
+{
+ cc_int32 err = ccNoError;
+ cci_swap_context_functions (in_context);
+ err = cc_free_NC_info (in_context, io_info);
+ cci_swap_context_functions (in_context);
+ return err;
+}
diff --git a/src/ccapi/lib/mac/ccapi_vector.exports b/src/ccapi/lib/mac/ccapi_vector.exports
new file mode 100644
index 000000000000..0f02e4148f9a
--- /dev/null
+++ b/src/ccapi/lib/mac/ccapi_vector.exports
@@ -0,0 +1,59 @@
+__cc_context_release_vector
+__cc_context_get_change_time_vector
+__cc_context_get_default_ccache_name_vector
+__cc_context_open_ccache_vector
+__cc_context_open_default_ccache_vector
+__cc_context_create_ccache_vector
+__cc_context_create_default_ccache_vector
+__cc_context_create_new_ccache_vector
+__cc_context_new_ccache_iterator_vector
+__cc_context_lock_vector
+__cc_context_unlock_vector
+__cc_context_compare_vector
+__cc_ccache_release_vector
+__cc_ccache_destroy_vector
+__cc_ccache_set_default_vector
+__cc_ccache_get_credentials_version_vector
+__cc_ccache_get_name_vector
+__cc_ccache_get_principal_vector
+__cc_ccache_set_principal_vector
+__cc_ccache_store_credentials_vector
+__cc_ccache_remove_credentials_vector
+__cc_ccache_new_credentials_iterator_vector
+__cc_ccache_move_vector
+__cc_ccache_lock_vector
+__cc_ccache_unlock_vector
+__cc_ccache_get_last_default_time_vector
+__cc_ccache_get_change_time_vector
+__cc_ccache_compare_vector
+__cc_string_release_vector
+__cc_credentials_release_vector
+__cc_credentials_compare_vector
+__cc_ccache_iterator_release_vector
+__cc_ccache_iterator_next_vector
+__cc_credentials_iterator_release_vector
+__cc_credentials_iterator_next_vector
+__cc_initialize_vector
+__cc_shutdown_vector
+__cc_get_NC_info_vector
+__cc_get_change_time_vector
+__cc_open_vector
+__cc_create_vector
+__cc_close_vector
+__cc_destroy_vector
+__cc_seq_fetch_NCs_begin_vector
+__cc_seq_fetch_NCs_next_vector
+__cc_seq_fetch_NCs_end_vector
+__cc_get_name_vector
+__cc_get_cred_version_vector
+__cc_set_principal_vector
+__cc_get_principal_vector
+__cc_store_vector
+__cc_remove_cred_vector
+__cc_seq_fetch_creds_begin_vector
+__cc_seq_fetch_creds_next_vector
+__cc_seq_fetch_creds_end_vector
+__cc_free_principal_vector
+__cc_free_name_vector
+__cc_free_creds_vector
+__cc_free_NC_info_vector
diff --git a/src/ccapi/lib/mac/ccapi_vector.h b/src/ccapi/lib/mac/ccapi_vector.h
new file mode 100644
index 000000000000..803257cdcdf3
--- /dev/null
+++ b/src/ccapi/lib/mac/ccapi_vector.h
@@ -0,0 +1,227 @@
+/* ccapi/lib/mac/ccapi_vector.h */
+/*
+ * Copyright 2006 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 M.I.T. 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.
+ */
+
+#include <CredentialsCache2.h>
+
+
+cc_int32 __cc_initialize_vector (cc_context_t *out_context,
+ cc_int32 in_version,
+ cc_int32 *out_supported_version,
+ char const **out_vendor);
+
+cc_int32 __cc_string_release_vector (cc_string_t in_string);
+
+cc_int32 __cc_context_release_vector (cc_context_t io_context);
+
+cc_int32 __cc_context_get_change_time_vector (cc_context_t in_context,
+ cc_time_t *out_change_time);
+
+cc_int32 __cc_context_get_default_ccache_name_vector (cc_context_t in_context,
+ cc_string_t *out_name);
+
+cc_int32 __cc_context_open_ccache_vector (cc_context_t in_context,
+ const char *in_name,
+ cc_ccache_t *out_ccache);
+
+cc_int32 __cc_context_open_default_ccache_vector (cc_context_t in_context,
+ cc_ccache_t *out_ccache);
+
+cc_int32 __cc_context_create_ccache_vector (cc_context_t in_context,
+ const char *in_name,
+ cc_uint32 in_cred_vers,
+ const char *in_principal,
+ cc_ccache_t *out_ccache);
+
+cc_int32 __cc_context_create_default_ccache_vector (cc_context_t in_context,
+ cc_uint32 in_cred_vers,
+ const char *in_principal,
+ cc_ccache_t *out_ccache);
+
+cc_int32 __cc_context_create_new_ccache_vector (cc_context_t in_context,
+ cc_uint32 in_cred_vers,
+ const char *in_principal,
+ cc_ccache_t *out_ccache);
+
+cc_int32 __cc_context_new_ccache_iterator_vector (cc_context_t in_context,
+ cc_ccache_iterator_t *out_iterator);
+
+cc_int32 __cc_context_lock_vector (cc_context_t in_context,
+ cc_uint32 in_lock_type,
+ cc_uint32 in_block);
+
+cc_int32 __cc_context_unlock_vector (cc_context_t in_context);
+
+cc_int32 __cc_context_compare_vector (cc_context_t in_context,
+ cc_context_t in_compare_to_context,
+ cc_uint32 *out_equal);
+
+cc_int32 __cc_ccache_release_vector (cc_ccache_t io_ccache);
+
+cc_int32 __cc_ccache_destroy_vector (cc_ccache_t io_ccache);
+
+cc_int32 __cc_ccache_set_default_vector (cc_ccache_t io_ccache);
+
+cc_uint32 __cc_ccache_get_credentials_version_vector (cc_ccache_t in_ccache,
+ cc_uint32 *out_credentials_version);
+
+cc_int32 __cc_ccache_get_name_vector (cc_ccache_t in_ccache,
+ cc_string_t *out_name);
+
+cc_int32 __cc_ccache_get_principal_vector (cc_ccache_t in_ccache,
+ cc_uint32 in_credentials_version,
+ cc_string_t *out_principal);
+
+cc_int32 __cc_ccache_set_principal_vector (cc_ccache_t io_ccache,
+ cc_uint32 in_credentials_version,
+ const char *in_principal);
+
+cc_int32 __cc_ccache_store_credentials_vector (cc_ccache_t io_ccache,
+ const cc_credentials_union *in_credentials_union);
+
+cc_int32 __cc_ccache_remove_credentials_vector (cc_ccache_t io_ccache,
+ cc_credentials_t in_credentials);
+
+cc_int32 __cc_ccache_new_credentials_iterator_vector (cc_ccache_t in_ccache,
+ cc_credentials_iterator_t *out_credentials_iterator);
+
+cc_int32 __cc_ccache_move_vector (cc_ccache_t io_source_ccache,
+ cc_ccache_t io_destination_ccache);
+
+cc_int32 __cc_ccache_lock_vector (cc_ccache_t io_ccache,
+ cc_uint32 in_lock_type,
+ cc_uint32 in_block);
+
+cc_int32 __cc_ccache_unlock_vector (cc_ccache_t io_ccache);
+
+cc_int32 __cc_ccache_get_last_default_time_vector (cc_ccache_t in_ccache,
+ cc_time_t *out_last_default_time);
+
+cc_int32 __cc_ccache_get_change_time_vector (cc_ccache_t in_ccache,
+ cc_time_t *out_change_time);
+
+cc_int32 __cc_ccache_compare_vector (cc_ccache_t in_ccache,
+ cc_ccache_t in_compare_to_ccache,
+ cc_uint32 *out_equal);
+
+cc_int32 __cc_credentials_release_vector (cc_credentials_t io_credentials);
+
+cc_int32 __cc_credentials_compare_vector (cc_credentials_t in_credentials,
+ cc_credentials_t in_compare_to_credentials,
+ cc_uint32 *out_equal);
+
+cc_int32 __cc_ccache_iterator_release_vector (cc_ccache_iterator_t io_ccache_iterator);
+
+cc_int32 __cc_ccache_iterator_next_vector (cc_ccache_iterator_t in_ccache_iterator,
+ cc_ccache_t *out_ccache);
+
+cc_int32 __cc_credentials_iterator_release_vector (cc_credentials_iterator_t io_credentials_iterator);
+
+cc_int32 __cc_credentials_iterator_next_vector (cc_credentials_iterator_t in_credentials_iterator,
+ cc_credentials_t *out_credentials);
+
+cc_int32 __cc_shutdown_vector (apiCB **io_context);
+
+cc_int32 __cc_get_NC_info_vector (apiCB *in_context,
+ infoNC ***out_info);
+
+cc_int32 __cc_get_change_time_vector (apiCB *in_context,
+ cc_time_t *out_change_time);
+
+cc_int32 __cc_open_vector (apiCB *in_context,
+ const char *in_name,
+ cc_int32 in_version,
+ cc_uint32 in_flags,
+ ccache_p **out_ccache);
+
+cc_int32 __cc_create_vector (apiCB *in_context,
+ const char *in_name,
+ const char *in_principal,
+ cc_int32 in_version,
+ cc_uint32 in_flags,
+ ccache_p **out_ccache);
+
+cc_int32 __cc_close_vector (apiCB *in_context,
+ ccache_p **io_ccache);
+
+cc_int32 __cc_destroy_vector (apiCB *in_context,
+ ccache_p **io_ccache);
+
+cc_int32 __cc_seq_fetch_NCs_begin_vector (apiCB *in_context,
+ ccache_cit **out_iterator);
+
+cc_int32 __cc_seq_fetch_NCs_next_vector (apiCB *in_context,
+ ccache_p **out_ccache,
+ ccache_cit *in_iterator);
+
+cc_int32 __cc_seq_fetch_NCs_end_vector (apiCB *in_context,
+ ccache_cit **io_iterator);
+
+cc_int32 __cc_get_name_vector (apiCB *in_context,
+ ccache_p *in_ccache,
+ char **out_name);
+
+cc_int32 __cc_get_cred_version_vector (apiCB *in_context,
+ ccache_p *in_ccache,
+ cc_int32 *out_version);
+
+cc_int32 __cc_set_principal_vector (apiCB *in_context,
+ ccache_p *io_ccache,
+ cc_int32 in_version,
+ char *in_principal);
+
+cc_int32 __cc_get_principal_vector (apiCB *in_context,
+ ccache_p *in_ccache,
+ char **out_principal);
+
+cc_int32 __cc_store_vector (apiCB *in_context,
+ ccache_p *io_ccache,
+ cred_union in_credentials);
+
+cc_int32 __cc_remove_cred_vector (apiCB *in_context,
+ ccache_p *in_ccache,
+ cred_union in_credentials);
+
+cc_int32 __cc_seq_fetch_creds_begin_vector (apiCB *in_context,
+ const ccache_p *in_ccache,
+ ccache_cit **out_iterator);
+
+cc_int32 __cc_seq_fetch_creds_next_vector (apiCB *in_context,
+ cred_union **out_creds,
+ ccache_cit *in_iterator);
+
+cc_int32 __cc_seq_fetch_creds_end_vector (apiCB *in_context,
+ ccache_cit **io_iterator);
+
+cc_int32 __cc_free_principal_vector (apiCB *in_context,
+ char **io_principal);
+
+cc_int32 __cc_free_name_vector (apiCB *in_context,
+ char **io_name);
+
+cc_int32 __cc_free_creds_vector (apiCB *in_context,
+ cred_union **io_credentials);
+
+cc_int32 __cc_free_NC_info_vector (apiCB *in_context,
+ infoNC ***io_info);
diff --git a/src/ccapi/lib/unix/Makefile.in b/src/ccapi/lib/unix/Makefile.in
new file mode 100644
index 000000000000..ce47d65d9277
--- /dev/null
+++ b/src/ccapi/lib/unix/Makefile.in
@@ -0,0 +1,12 @@
+mydir=ccapi$(S)lib$(S)unix
+BUILDTOP=$(REL)..$(S)..$(S)..
+LOCALINCLUDES= -I$(srcdir)/.. -I$(srcdir)/../../common
+
+STLIBOBJS= stubs.o
+OBJS= $(OUTPRE)stubs.$(OBJEXT)
+
+all-unix: all-libobjs
+clean-unix:: clean-libobjs
+
+@libobj_frag@
+
diff --git a/src/ccapi/lib/unix/deps b/src/ccapi/lib/unix/deps
new file mode 100644
index 000000000000..2feac3c9d388
--- /dev/null
+++ b/src/ccapi/lib/unix/deps
@@ -0,0 +1 @@
+# No dependencies here.
diff --git a/src/ccapi/lib/unix/stubs.c b/src/ccapi/lib/unix/stubs.c
new file mode 100644
index 000000000000..3afd8f10eeb0
--- /dev/null
+++ b/src/ccapi/lib/unix/stubs.c
@@ -0,0 +1,10 @@
+#include <errno.h>
+#include "ccapi_os_ipc.h"
+
+cc_int32 cci_os_ipc_thread_init (void)
+{
+ return EINVAL;
+}
+void cci_os_ipc_thread_fini (void)
+{
+}
diff --git a/src/ccapi/lib/win/Makefile.in b/src/ccapi/lib/win/Makefile.in
new file mode 100644
index 000000000000..45676092ed33
--- /dev/null
+++ b/src/ccapi/lib/win/Makefile.in
@@ -0,0 +1,123 @@
+# makefile: Constructs the Kerberos for Windows CCAPI DLL.
+#
+OBJS = $(OUTPRE)ccapi_ccache.obj \
+ $(OUTPRE)ccapi_ccache_iterator.obj \
+ $(OUTPRE)ccapi_context.obj \
+ $(OUTPRE)ccapi_context_change_time.obj \
+ $(OUTPRE)ccapi_credentials.obj \
+ $(OUTPRE)ccapi_credentials_iterator.obj \
+ $(OUTPRE)ccapi_ipc.obj \
+ $(OUTPRE)ccapi_err.obj \
+ $(OUTPRE)ccapi_os_ipc.obj \
+ $(OUTPRE)ccapi_string.obj \
+ $(OUTPRE)ccapi_v2.obj \
+ $(OUTPRE)cci_array_internal.obj \
+ $(OUTPRE)cci_cred_union.obj \
+ $(OUTPRE)cci_debugging.obj \
+ $(OUTPRE)cci_identifier.obj \
+ $(OUTPRE)cci_message.obj \
+ $(OUTPRE)cci_os_debugging.obj \
+ $(OUTPRE)cci_os_identifier.obj \
+ $(OUTPRE)ccs_reply_proc.obj \
+ $(OUTPRE)ccs_reply_s.obj \
+ $(OUTPRE)ccs_request_c.obj \
+ $(OUTPRE)ccutils.obj \
+ $(OUTPRE)client.obj \
+ $(OUTPRE)dllmain.obj \
+ $(OUTPRE)init.obj \
+ $(OUTPRE)secure.obj \
+ $(OUTPRE)tls.obj \
+ $(OUTPRE)util.obj \
+ $(OUTPRE)win-utils.obj
+
+##### Options
+# Set NODEBUG if building release instead of debug
+
+#BUILDTOP is krb5/src and is relative to krb5/src/ccapi/lib/win, for making Makefile.
+BUILDTOP= ..\..\..
+CCAPI = $(BUILDTOP)\CCAPI
+CO = $(CCAPI)\common
+COWIN = $(CCAPI)\common\win
+CCUTIL = $(CCAPI)\common\win\OldCC
+LIBDIR = $(CCAPI)\lib
+LIBWIN = $(LIBDIR)\win
+POSIX = $(BUILDTOP)\lib\krb5\posix
+OLDCC = $(LIBWIN)\OldCC
+SRCTMP = $(LIBWIN)\srctmp
+
+!if defined(KRB5_KFW_COMPILE)
+KFWINC= /I$(BUILDTOP)\..\..\krbcc\include
+!endif
+
+# Because all the sources are pulled together into the temp directory SRCTMP,
+# the only includes we need are to directories outside of ccapi.
+LOCALINCLUDES = /I..\$(BUILDTOP) /I..\$(BUILDTOP)\include /I..\$(BUILDTOP)\include\krb5 $(KFWINC) \
+ -I..\$(BUILDTOP)\util\et
+MIDLINCLUDES = /I..\$(BUILDTOP)\include
+
+CPPFLAGS = $(CPPFLAGS) /EHsc -D_CRTAPI1=_cdecl -D_CRTAPI2=_cdecl -DWINVER=0x0501 \
+-D_WIN32_WINNT=0x0501 -D_CRT_SECURE_NO_WARNINGS $(cvarsdll)
+
+
+##### Linker
+LINK = link
+LIBS = ..\$(CLIB) ..\$(SLIB) kernel32.lib ws2_32.lib user32.lib advapi32.lib
+LFLAGS = /nologo $(LOPTS)
+
+all: Makefile copysrc midl $(OUTPRE)$(CCLIB).dll finish
+
+ccs_request.h ccs_request_c.c ccs_request_s.c : ccs_request.idl ccs_request.acf
+ midl $(MIDL_OPTIMIZATION) $(MIDLI) -oldnames -cpp_cmd $(CC) -cpp_opt "-E" \
+ ccs_request.idl
+
+ccs_reply.h ccs_reply_c.c ccs_reply_s.c : ccs_reply.idl ccs_reply.acf
+ midl $(MIDL_OPTIMIZATION) $(MIDLI) -oldnames -cpp_cmd $(CC) -cpp_opt "-E" \
+ ccs_reply.idl
+
+copysrc :
+ echo "Copying all sources needed to build $(CCLIB).dll to $(SRCTMP)"
+ if NOT exist $(SRCTMP)\nul mkdir $(SRCTMP)
+ xcopy /D/Y $(CO)\*.* $(SRCTMP)
+ xcopy /D/Y $(COWIN)\*.* $(SRCTMP)
+ xcopy /D/Y $(CCUTIL)\*.* $(SRCTMP)
+ xcopy /D/Y $(LIBDIR)\*.* $(SRCTMP)
+ xcopy /D/Y $(LIBWIN)\*.* $(SRCTMP)
+ xcopy /D/Y $(OLDCC)\*.* $(SRCTMP)
+ cd $(SRCTMP)
+ if NOT exist $(OUTPRE)\nul mkdir $(OUTPRE)
+
+midl : ccs_request.h ccs_reply.h
+
+VERSIONRC = $(BUILDTOP)\..\windows\version.rc
+CCLIBRES = $(OUTPRE)$(CCLIB).res
+# Main program:
+$(CCLIBRES): $(VERSIONRC)
+ $(RC) $(RCFLAGS) -DCCAPI_LIB -fo $@ -r $**
+
+$(OUTPRE)$(CCLIB).dll: $(OBJS) $(CCLIB).def $(CCLIBRES)
+ $(LINK) $(LFLAGS) -entry:$(ENTRYPOINT) -dll /map:$*.map /out:$@ /DEF:$(CCLIB).def $(OBJS) \
+ /implib:$(CCLIB).lib $(dllflags) $(LIBS) $(KFWLIB) $(SCLIB) $(CCLIBRES) rpcrt4.lib $(conlibsdll) $(conflags)
+
+$(CCLIB).def:
+ echo ;$(CCLIB).def is generated by a Makefile rule. > $(CCLIB).def
+ echo HEAPSIZE 8192 >> $(CCLIB).def
+ echo EXPORTS >> $(CCLIB).def
+ type ccapi.exports >> $(CCLIB).def
+ type ccapi_v2.exports >> $(CCLIB).def
+ type debug.exports >> $(CCLIB).def
+
+finish:
+ echo "Finished in ccapi/lib/win."
+ cd ..
+
+install:
+ echo "Doing nothing for make install"
+
+clean:
+ if exist $(OUTPRE)*.exe del $(OUTPRE)*.exe
+ if exist $(OUTPRE)*.obj del $(OUTPRE)*.obj
+ if exist $(OUTPRE)*.res del $(OUTPRE)*.res
+ if exist $(OUTPRE)*.map del $(OUTPRE)*.map
+ if exist $(OUTPRE)*.pdb del $(OUTPRE)*.pdb
+ if exist *.err del *.err
+ if exist $(SRCTMP) rmdir /s /q $(SRCTMP)
diff --git a/src/ccapi/lib/win/OldCC/ccapi.h b/src/ccapi/lib/win/OldCC/ccapi.h
new file mode 100644
index 000000000000..82512771a85e
--- /dev/null
+++ b/src/ccapi/lib/win/OldCC/ccapi.h
@@ -0,0 +1,280 @@
+/* this ALWAYS GENERATED file contains the definitions for the interfaces */
+
+
+ /* File created by MIDL compiler version 6.00.0366 */
+/* at Fri Nov 30 10:06:16 2007
+ */
+/* Compiler settings for ccapi.idl:
+ Oic, W1, Zp8, env=Win32 (32b run)
+ protocol : dce , ms_ext, c_ext, oldnames
+ error checks: allocation ref bounds_check enum stub_data
+ VC __declspec() decoration level:
+ __declspec(uuid()), __declspec(selectany), __declspec(novtable)
+ DECLSPEC_UUID(), MIDL_INTERFACE()
+*/
+//@@MIDL_FILE_HEADING( )
+
+#pragma warning( disable: 4049 ) /* more than 64k source lines */
+
+
+/* verify that the <rpcndr.h> version is high enough to compile this file*/
+#ifndef __REQUIRED_RPCNDR_H_VERSION__
+#define __REQUIRED_RPCNDR_H_VERSION__ 440
+#endif
+
+#include "rpc.h"
+#include "rpcndr.h"
+
+#ifndef __ccapi_h__
+#define __ccapi_h__
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+#pragma once
+#endif
+
+/* Forward Declarations */
+
+#ifdef __cplusplus
+extern "C"{
+#endif
+
+void * __RPC_USER MIDL_user_allocate(size_t);
+void __RPC_USER MIDL_user_free( void * );
+
+#ifndef __ccapi_INTERFACE_DEFINED__
+#define __ccapi_INTERFACE_DEFINED__
+
+/* interface ccapi */
+/* [implicit_handle][unique][version][uuid] */
+
+typedef /* [context_handle] */ struct opaque_handle_CTX *HCTX;
+
+typedef /* [context_handle] */ struct opaque_handle_CACHE *HCACHE;
+
+typedef /* [context_handle] */ struct opaque_handle_CACHE_ITER *HCACHE_ITER;
+
+typedef /* [context_handle] */ struct opaque_handle_CRED_ITER *HCRED_ITER;
+
+typedef unsigned char CC_CHAR;
+
+typedef unsigned char CC_UCHAR;
+
+typedef int CC_INT32;
+
+typedef unsigned int CC_UINT32;
+
+typedef CC_INT32 CC_TIME_T;
+
+
+enum __MIDL_ccapi_0001
+ { STK_AFS = 0,
+ STK_DES = 1
+ } ;
+
+enum __MIDL_ccapi_0002
+ { CC_API_VER_1 = 1,
+ CC_API_VER_2 = 2
+ } ;
+
+enum __MIDL_ccapi_0003
+ { KRB_NAME_SZ = 40,
+ KRB_INSTANCE_SZ = 40,
+ KRB_REALM_SZ = 40,
+ MAX_V4_CRED_LEN = 1250
+ } ;
+typedef struct _NC_INFO
+ {
+ /* [string] */ CC_CHAR *name;
+ /* [string] */ CC_CHAR *principal;
+ CC_INT32 vers;
+ } NC_INFO;
+
+typedef struct _NC_INFO_LIST
+ {
+ CC_UINT32 length;
+ /* [size_is] */ NC_INFO *info;
+ } NC_INFO_LIST;
+
+typedef struct _V4_CRED
+ {
+ CC_UCHAR kversion;
+ CC_CHAR principal[ 41 ];
+ CC_CHAR principal_instance[ 41 ];
+ CC_CHAR service[ 41 ];
+ CC_CHAR service_instance[ 41 ];
+ CC_CHAR realm[ 41 ];
+ CC_UCHAR session_key[ 8 ];
+ CC_INT32 kvno;
+ CC_INT32 str_to_key;
+ CC_INT32 issue_date;
+ CC_INT32 lifetime;
+ CC_UINT32 address;
+ CC_INT32 ticket_sz;
+ CC_UCHAR ticket[ 1250 ];
+ } V4_CRED;
+
+typedef struct _CC_DATA
+ {
+ CC_UINT32 type;
+ CC_UINT32 length;
+ /* [size_is] */ CC_UCHAR *data;
+ } CC_DATA;
+
+typedef struct _CC_DATA_LIST
+ {
+ CC_UINT32 count;
+ /* [size_is] */ CC_DATA *data;
+ } CC_DATA_LIST;
+
+typedef struct _V5_CRED
+ {
+ /* [string] */ CC_CHAR *client;
+ /* [string] */ CC_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_LIST addresses;
+ CC_DATA ticket;
+ CC_DATA second_ticket;
+ CC_DATA_LIST authdata;
+ } V5_CRED;
+
+typedef /* [switch_type] */ union _CRED_PTR_UNION
+ {
+ /* [case()] */ V4_CRED *pV4Cred;
+ /* [case()] */ V5_CRED *pV5Cred;
+ } CRED_PTR_UNION;
+
+typedef struct _CRED_UNION
+ {
+ CC_INT32 cred_type;
+ /* [switch_is] */ CRED_PTR_UNION cred;
+ } CRED_UNION;
+
+CC_INT32 rcc_initialize(
+ /* [out] */ HCTX *pctx);
+
+CC_INT32 rcc_shutdown(
+ /* [out][in] */ HCTX *pctx);
+
+CC_INT32 rcc_get_change_time(
+ /* [in] */ HCTX ctx,
+ /* [out] */ CC_TIME_T *time);
+
+CC_INT32 rcc_create(
+ /* [in] */ HCTX ctx,
+ /* [string][in] */ const CC_CHAR *name,
+ /* [string][in] */ const CC_CHAR *principal,
+ /* [in] */ CC_INT32 vers,
+ /* [in] */ CC_UINT32 flags,
+ /* [out] */ HCACHE *pcache);
+
+CC_INT32 rcc_open(
+ /* [in] */ HCTX ctx,
+ /* [string][in] */ const CC_CHAR *name,
+ /* [in] */ CC_INT32 vers,
+ /* [in] */ CC_UINT32 flags,
+ /* [out] */ HCACHE *pcache);
+
+CC_INT32 rcc_close(
+ /* [out][in] */ HCACHE *pcache);
+
+CC_INT32 rcc_destroy(
+ /* [out][in] */ HCACHE *pcache);
+
+CC_INT32 rcc_seq_fetch_NCs_begin(
+ /* [in] */ HCTX ctx,
+ /* [out] */ HCACHE_ITER *piter);
+
+CC_INT32 rcc_seq_fetch_NCs_end(
+ /* [out][in] */ HCACHE_ITER *piter);
+
+CC_INT32 rcc_seq_fetch_NCs_next(
+ /* [in] */ HCACHE_ITER iter,
+ /* [out] */ HCACHE *pcache);
+
+CC_INT32 rcc_seq_fetch_NCs(
+ /* [in] */ HCTX ctx,
+ /* [out][in] */ HCACHE_ITER *piter,
+ /* [out] */ HCACHE *pcache);
+
+CC_INT32 rcc_get_NC_info(
+ /* [in] */ HCTX ctx,
+ /* [out] */ NC_INFO_LIST **info_list);
+
+CC_INT32 rcc_get_name(
+ /* [in] */ HCACHE cache,
+ /* [string][out] */ CC_CHAR **name);
+
+CC_INT32 rcc_set_principal(
+ /* [in] */ HCACHE cache,
+ /* [in] */ CC_INT32 vers,
+ /* [string][in] */ const CC_CHAR *principal);
+
+CC_INT32 rcc_get_principal(
+ /* [in] */ HCACHE cache,
+ /* [string][out] */ CC_CHAR **principal);
+
+CC_INT32 rcc_get_cred_version(
+ /* [in] */ HCACHE cache,
+ /* [out] */ CC_INT32 *vers);
+
+CC_INT32 rcc_lock_request(
+ /* [in] */ HCACHE cache,
+ /* [in] */ CC_INT32 lock_type);
+
+CC_INT32 rcc_store(
+ /* [in] */ HCACHE cache,
+ /* [in] */ CRED_UNION cred);
+
+CC_INT32 rcc_remove_cred(
+ /* [in] */ HCACHE cache,
+ /* [in] */ CRED_UNION cred);
+
+CC_INT32 rcc_seq_fetch_creds(
+ /* [in] */ HCACHE cache,
+ /* [out][in] */ HCRED_ITER *piter,
+ /* [out] */ CRED_UNION **cred);
+
+CC_INT32 rcc_seq_fetch_creds_begin(
+ /* [in] */ HCACHE cache,
+ /* [out] */ HCRED_ITER *piter);
+
+CC_INT32 rcc_seq_fetch_creds_end(
+ /* [out][in] */ HCRED_ITER *piter);
+
+CC_INT32 rcc_seq_fetch_creds_next(
+ /* [in] */ HCRED_ITER iter,
+ /* [out] */ CRED_UNION **cred);
+
+CC_UINT32 Connect(
+ /* [string][in] */ CC_CHAR *name);
+
+void Shutdown( void);
+
+
+extern handle_t ccapi_IfHandle;
+
+
+extern RPC_IF_HANDLE ccapi_ClientIfHandle;
+extern RPC_IF_HANDLE ccapi_ServerIfHandle;
+#endif /* __ccapi_INTERFACE_DEFINED__ */
+
+/* Additional Prototypes for ALL interfaces */
+
+void __RPC_USER HCTX_rundown( HCTX );
+void __RPC_USER HCACHE_rundown( HCACHE );
+void __RPC_USER HCACHE_ITER_rundown( HCACHE_ITER );
+void __RPC_USER HCRED_ITER_rundown( HCRED_ITER );
+
+/* end of Additional Prototypes */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/src/ccapi/lib/win/OldCC/client.cxx b/src/ccapi/lib/win/OldCC/client.cxx
new file mode 100644
index 000000000000..4b2d718cc431
--- /dev/null
+++ b/src/ccapi/lib/win/OldCC/client.cxx
@@ -0,0 +1,427 @@
+/*
+ * $Header$
+ *
+ * Copyright 2008 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 M.I.T. 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.
+ */
+
+#include "stdio.h" // KPKDBG
+
+#include "ccs_request.h"
+
+#include "ccapi.h"
+#include "util.h"
+
+extern "C" {
+#include "cci_debugging.h"
+#include "tls.h" // KPKDBG
+ }
+
+#include "client.h"
+#include "init.hxx"
+#include "name.h"
+#include "secure.hxx"
+
+#define SECONDS_TO_WAIT 10
+
+#define STARTUP "CLIENT STARTUP: "
+#define DISCONNECT "CLIENT DISCONNECT: "
+
+bool Client::s_init = false;
+CcOsLock Client::sLock;
+
+static DWORD bind_client(char* ep OPTIONAL, Init::InitInfo& info, LPSTR* endpoint) {
+ DWORD status = 0;
+ unsigned char * pszStringBinding = NULL;
+
+ if (!ep) {
+ status = alloc_name(endpoint, "ep", isNT());
+ }
+ else {
+ *endpoint = ep;
+ }
+
+ if (!status) {
+ /* Use a convenience function to concatenate the elements of */
+ /* the string binding into the proper sequence. */
+ status = RpcStringBindingCompose(0, // uuid
+ (unsigned char*)"ncalrpc", // protseq
+ 0, // address
+ (unsigned char*)(*endpoint), // endpoint
+ 0, // options
+ &pszStringBinding);
+ cci_check_error(status);
+ }
+
+ if (!status) {
+ /* Set the binding handle that will be used to bind to the server. */
+ status = RpcBindingFromStringBinding(pszStringBinding, &ccs_request_IfHandle);
+ cci_check_error(status);
+ }
+
+ if (!status) {
+ // Win9x might call RpcBindingSetAuthInfo (not Ex), but it does not
+ // quite work on Win9x...
+ if (isNT()) {
+ RPC_SECURITY_QOS qos;
+ qos.Version = RPC_C_SECURITY_QOS_VERSION;
+ qos.Capabilities = RPC_C_QOS_CAPABILITIES_DEFAULT;
+ qos.IdentityTracking = RPC_C_QOS_IDENTITY_STATIC;
+ qos.ImpersonationType = RPC_C_IMP_LEVEL_IDENTIFY;
+
+ status = info.fRpcBindingSetAuthInfoEx(ccs_request_IfHandle,
+ 0, // principal
+ RPC_C_AUTHN_LEVEL_CONNECT,
+ RPC_C_AUTHN_WINNT,
+ 0, // current address space
+ RPC_C_AUTHZ_NAME,
+ &qos);
+ cci_check_error(status);
+ }
+ }
+
+ if (pszStringBinding) {
+ DWORD status = RpcStringFree(&pszStringBinding);
+ cci_check_error(status);
+ }
+ return cci_check_error(status);
+ }
+
+DWORD find_server(Init::InitInfo& info, LPSTR endpoint) {
+ DWORD status = 0;
+ LPSTR event_name = 0;
+ HANDLE hEvent = 0;
+ SECURITY_ATTRIBUTES sa = { 0 };
+ PSECURITY_ATTRIBUTES psa = 0;
+ STARTUPINFO si = { 0 };
+ PROCESS_INFORMATION pi = { 0 };
+ char* szExe = 0;
+ char* szDir = 0;
+ BOOL bRes = FALSE;
+ char* cmdline = NULL;
+#if 0
+ HANDLE hToken = 0;
+#endif
+
+ psa = isNT() ? &sa : 0;
+
+ cci_debug_printf("%s Looking for server; ccs_request_IfHandle:0x%X", __FUNCTION__, ccs_request_IfHandle);
+ status = cci_check_error(RpcMgmtIsServerListening(ccs_request_IfHandle));
+ if (status == RPC_S_NOT_LISTENING) {
+ cci_debug_printf(" Server *NOT* found!");
+ si.cb = sizeof(si);
+
+ status = alloc_module_dir_name(CCAPI_DLL, &szDir);
+
+ if (!status) {
+ status = alloc_module_dir_name_with_file(CCAPI_DLL, CCAPI_EXE, &szExe);
+ }
+
+ if (!status) {
+ status = alloc_name(&event_name, "startup", isNT());
+ cci_check_error(status);
+ }
+
+ if (!status) {
+ if (isNT()) {
+ sa.nLength = sizeof(sa);
+ status = alloc_own_security_descriptor_NT(&sa.lpSecurityDescriptor);
+ cci_check_error(status);
+ }
+ }
+
+ if (!status) {
+ hEvent = CreateEvent(psa, FALSE, FALSE, event_name);
+ cci_debug_printf(" CreateEvent(... %s) returned hEvent 0x%X", event_name, hEvent);
+ if (!hEvent) status = GetLastError();
+ }
+
+ if (!status) {
+
+#if 0
+ if (SecureClient::IsImp()) {
+ cci_debug_printf(STARTUP "Token is impersonation token"));
+ SecureClient::DuplicateImpAsPrimary(hToken);
+ }
+ else {
+ cci_debug_printf(STARTUP "Token is NOT impersonation token"));
+ }
+#endif
+
+#if 0
+ if (hToken)
+ bRes = CreateProcessAsUser(hToken,
+ szExe, // app name
+ NULL, // cmd line
+ psa, // SA
+ psa, // SA
+ FALSE,
+ CREATE_NEW_PROCESS_GROUP |
+ //CREATE_NEW_CONSOLE |
+ NORMAL_PRIORITY_CLASS |
+ // CREATE_NO_WINDOW |
+ DETACHED_PROCESS |
+ 0
+ ,
+ NULL, // environment
+ szDir, // current dir
+ &si,
+ &pi);
+ else
+#endif
+ alloc_cmdline_2_args(szExe, endpoint, "-D", &cmdline);
+ bRes = CreateProcess( szExe, // app name
+ NULL, //cmdline, // cmd line is <server endpoint -[DC]>
+ psa, // SA
+ psa, // SA
+ FALSE,
+ CREATE_NEW_PROCESS_GROUP |
+ NORMAL_PRIORITY_CLASS |
+#ifdef CCAPI_LAUNCH_SERVER_WITH_CONSOLE
+ CREATE_NEW_CONSOLE |
+#else
+ DETACHED_PROCESS |
+#endif
+ 0,
+ NULL, // environment
+ szDir, // current dir
+ &si,
+ &pi);
+ if (!bRes) {
+ status = GetLastError();
+ cci_debug_printf(" CreateProcess returned %d; LastError: %d", bRes, status);
+ }
+ cci_debug_printf(" Waiting...");
+ }
+ cci_check_error(status);
+
+ if (!status) {
+ status = WaitForSingleObject(hEvent, (SECONDS_TO_WAIT)*1000);
+ status = RpcMgmtIsServerListening(ccs_request_IfHandle);
+ }
+ }
+ else if (status) {
+ cci_debug_printf(" unexpected error while looking for server: 0D%d / 0U%u / 0X%X", status, status, status);
+ }
+
+#if 0
+ if (hToken)
+ CloseHandle(hToken);
+#endif
+ if (szDir) free_alloc_p(&szDir);
+ if (szExe) free_alloc_p(&szExe);
+ if (hEvent) CloseHandle(hEvent);
+ if (pi.hThread) CloseHandle(pi.hThread);
+ if (pi.hProcess) CloseHandle(pi.hProcess);
+ if (sa.lpSecurityDescriptor) free_alloc_p(&sa.lpSecurityDescriptor);
+ return cci_check_error(status);
+
+}
+
+static
+DWORD
+make_random_challenge(DWORD *challenge_out) {
+ HCRYPTPROV provider;
+ DWORD status = 0;
+ *challenge_out = 0;
+ if (!CryptAcquireContext(&provider, NULL, NULL, PROV_RSA_FULL,
+ CRYPT_VERIFYCONTEXT)) {
+ status = GetLastError();
+ cci_check_error(status);
+ return status;
+ }
+ if (!CryptGenRandom(provider, sizeof(*challenge_out),
+ (BYTE *)challenge_out)) {
+ status = GetLastError();
+ cci_check_error(status);
+ return status;
+ }
+ if (!CryptReleaseContext(provider, 0)) {
+ /*
+ * Note: even though CryptReleaseContext() failed, we don't really
+ * care since a) we've already successfully obtained our challenge
+ * anyway and b) at least one of the potential errors, "ERROR_BUSY"
+ * does not really seem to be an error at all. So GetLastError() is
+ * logged for informational purposes only and should not be returned.
+ */
+ cci_check_error(GetLastError());
+ }
+ return status;
+}
+
+static
+DWORD
+authenticate_server(Init::InitInfo& info) {
+ DWORD challenge, desired_response;
+ HANDLE hMap = 0;
+ LPSTR mem_name = 0;
+ PDWORD pvalue = 0;
+ CC_UINT32 response = 0;
+ SECURITY_ATTRIBUTES sa = { 0 };
+ DWORD status = 0;
+
+ cci_debug_printf("%s entry", __FUNCTION__);
+
+ status = alloc_name(&mem_name, "auth", isNT());
+ cci_check_error(status);
+
+ if (!status) {
+ status = make_random_challenge(&challenge);
+ desired_response = challenge + 1;
+ cci_check_error(status);
+ }
+
+ if (!status) {
+ if (isNT()) {
+ sa.nLength = sizeof(sa);
+ status = alloc_own_security_descriptor_NT(&sa.lpSecurityDescriptor);
+ }
+ }
+ cci_check_error(status);
+
+ if (!status) {
+ hMap = CreateFileMapping(INVALID_HANDLE_VALUE, isNT() ? &sa : 0,
+ PAGE_READWRITE, 0, sizeof(DWORD), mem_name);
+ if (!hMap)
+ status = GetLastError();
+ }
+ cci_check_error(status);
+
+ if (!status) {
+ pvalue = (PDWORD)MapViewOfFile(hMap, FILE_MAP_ALL_ACCESS, 0, 0, 0);
+ if (!pvalue) status = GetLastError();
+ }
+ cci_check_error(status);
+
+ if (!status) {
+ *pvalue = challenge;
+
+ RpcTryExcept {
+ response = ccs_authenticate( (CC_CHAR*)mem_name );
+ }
+ RpcExcept(1) {
+ status = RpcExceptionCode();
+ cci_check_error(status);
+ }
+ RpcEndExcept;
+ }
+ cci_check_error(status);
+
+ if (!status) {
+ // Check response
+ if ((response != desired_response) && (*pvalue != desired_response)) {
+ cci_debug_printf(" Could not authenticate server.");
+ status = ERROR_ACCESS_DENIED; // XXX - CO_E_NOMATCHINGSIDFOUND?
+ }
+ else {
+ cci_debug_printf(" Server authenticated!");
+ }
+ cci_check_error(status);
+ }
+
+ free_alloc_p(&mem_name);
+ free_alloc_p(&sa.lpSecurityDescriptor);
+ if (pvalue) {
+ BOOL ok = UnmapViewOfFile(pvalue);
+// DEBUG_ASSERT(ok);
+ }
+ if (hMap) CloseHandle(hMap);
+ return status;
+}
+
+DWORD
+Client::Disconnect() {
+ DWORD status = 0;
+ if (ccs_request_IfHandle) {
+ /* The calls to the remote procedures are complete. */
+ /* Free the binding handle */
+ status = RpcBindingFree(&ccs_request_IfHandle);
+ }
+ s_init = false;
+ return status;
+ }
+
+DWORD
+Client::Connect(char* ep OPTIONAL) {
+ LPSTR endpoint = 0;
+ DWORD status = 0;
+
+ if (!ccs_request_IfHandle) {
+ Init::InitInfo info;
+
+ status = Init::Info(info);
+ cci_check_error(status);
+
+ if (!status) {
+ status = bind_client(ep, info, &endpoint);
+ cci_check_error(status);
+ }
+
+ if (!status) {
+ status = find_server(info, endpoint);
+ cci_check_error(status);
+ }
+
+ if (!status) {
+ status = authenticate_server(info);
+ cci_check_error(status);
+ }
+ }
+
+
+ if (endpoint && (endpoint != ep)) free_alloc_p(&endpoint);
+
+ if (status) Client::Disconnect();
+ return status;
+ }
+
+DWORD Client::Initialize(char* ep OPTIONAL) {
+ CcAutoTryLock AL(Client::sLock);
+ if (!AL.IsLocked() || s_init)
+ return 0;
+ SecureClient s;
+ ccs_request_IfHandle = NULL;
+ DWORD status = Client::Connect(ep);
+ if (!status) s_init = true;
+ return status;
+ }
+
+DWORD Client::Cleanup() {
+ CcAutoLock AL(Client::sLock);
+ SecureClient s;
+ return Client::Disconnect();
+ }
+
+DWORD Client::Reconnect(char* ep OPTIONAL) {
+ CcAutoLock AL(Client::sLock);
+ SecureClient s;
+ DWORD status = 0;
+
+ if (Initialized()) {
+ DWORD status = Client::Cleanup();
+ }
+ if ( (!status) ) {
+ status = Client::Initialize(ep);
+ }
+
+ return status;
+ }
diff --git a/src/ccapi/lib/win/OldCC/client.h b/src/ccapi/lib/win/OldCC/client.h
new file mode 100644
index 000000000000..1c67acd147b1
--- /dev/null
+++ b/src/ccapi/lib/win/OldCC/client.h
@@ -0,0 +1,60 @@
+/* ccapi/lib/win/OldCC/client.h */
+/*
+ * Copyright 2008 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 M.I.T. 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.
+ */
+
+#ifndef __DLL_CLIENT_H__
+#define __DLL_CLIENT_H__
+
+#include "autolock.hxx"
+#include "init.hxx"
+
+class Client {
+public:
+ static DWORD Initialize(char* ep OPTIONAL);
+ static DWORD Cleanup();
+ static DWORD Reconnect(char* ep OPTIONAL);
+
+ static bool Initialized() { return s_init; }
+
+ static CcOsLock sLock;
+
+private:
+ static bool s_init;
+
+ static DWORD Disconnect();
+ static DWORD Connect(char* ep OPTIONAL);
+ };
+
+#define CLIENT_INIT_EX(trap, error) \
+do \
+{ \
+ INIT_INIT_EX(trap, error); \
+ if (!Client::Initialized()) \
+ { \
+ DWORD status = Client::Initialize(0); \
+ if (status) return (trap) ? (error) : status; \
+ } \
+} while(0)
+
+#endif
diff --git a/src/ccapi/lib/win/WINCCAPI.sln b/src/ccapi/lib/win/WINCCAPI.sln
new file mode 100644
index 000000000000..cee989151932
--- /dev/null
+++ b/src/ccapi/lib/win/WINCCAPI.sln
@@ -0,0 +1,20 @@
+
+Microsoft Visual Studio Solution File, Format Version 9.00
+# Visual Studio 2005
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "WINCCAPI", "WINCCAPI.vcproj", "{1137FC16-E53E-48C1-8293-085B4BE68C32}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Win32 = Debug|Win32
+ Release|Win32 = Release|Win32
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {1137FC16-E53E-48C1-8293-085B4BE68C32}.Debug|Win32.ActiveCfg = Debug|Win32
+ {1137FC16-E53E-48C1-8293-085B4BE68C32}.Debug|Win32.Build.0 = Debug|Win32
+ {1137FC16-E53E-48C1-8293-085B4BE68C32}.Release|Win32.ActiveCfg = Release|Win32
+ {1137FC16-E53E-48C1-8293-085B4BE68C32}.Release|Win32.Build.0 = Release|Win32
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+EndGlobal
diff --git a/src/ccapi/lib/win/WINCCAPI.vcproj b/src/ccapi/lib/win/WINCCAPI.vcproj
new file mode 100644
index 000000000000..9af0e21a0b91
--- /dev/null
+++ b/src/ccapi/lib/win/WINCCAPI.vcproj
@@ -0,0 +1,111 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="8.00"
+ Name="WINCCAPI"
+ ProjectGUID="{1137FC16-E53E-48C1-8293-085B4BE68C32}"
+ RootNamespace="WINCCAPI"
+ Keyword="MakeFileProj"
+ >
+ <Platforms>
+ <Platform
+ Name="Win32"
+ />
+ </Platforms>
+ <ToolFiles>
+ </ToolFiles>
+ <Configurations>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory="Debug"
+ IntermediateDirectory="Debug"
+ ConfigurationType="0"
+ >
+ <Tool
+ Name="VCNMakeTool"
+ BuildCommandLine="nmake"
+ ReBuildCommandLine="nmake"
+ CleanCommandLine="nmake clean"
+ Output="output.log"
+ PreprocessorDefinitions="WIN32;_DEBUG;"
+ IncludeSearchPath=""
+ ForcedIncludes=""
+ AssemblySearchPath=""
+ ForcedUsingAssemblies=""
+ CompileAsManaged=""
+ />
+ </Configuration>
+ <Configuration
+ Name="Release|Win32"
+ OutputDirectory="Release"
+ IntermediateDirectory="Release"
+ ConfigurationType="0"
+ >
+ <Tool
+ Name="VCNMakeTool"
+ BuildCommandLine="nmake"
+ ReBuildCommandLine="nmake"
+ CleanCommandLine="nmake clean"
+ Output="output.log"
+ PreprocessorDefinitions="WIN32;NDEBUG;"
+ IncludeSearchPath=""
+ ForcedIncludes=""
+ AssemblySearchPath=""
+ ForcedUsingAssemblies=""
+ CompileAsManaged=""
+ />
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <Filter
+ Name="Header Files"
+ Filter="h;hpp;hxx;hm;inl;inc;xsd"
+ UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
+ >
+ <File
+ RelativePath="..\..\common\win\win-utils.h"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="Resource Files"
+ Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx"
+ UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"
+ >
+ </Filter>
+ <Filter
+ Name="Source Files"
+ Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
+ UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
+ >
+ <File
+ RelativePath="..\..\common\win\ccs_reply.Idl"
+ >
+ </File>
+ <File
+ RelativePath="..\..\common\win\ccs_request.idl"
+ >
+ </File>
+ <File
+ RelativePath="..\..\common\win\win-utils.c"
+ >
+ </File>
+ </Filter>
+ <File
+ RelativePath="..\..\common\win\ccs_reply.Acf"
+ >
+ </File>
+ <File
+ RelativePath="..\..\common\win\ccs_request.Acf"
+ >
+ </File>
+ <File
+ RelativePath=".\Makefile"
+ >
+ </File>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/src/ccapi/lib/win/ccapi_os_ipc.cxx b/src/ccapi/lib/win/ccapi_os_ipc.cxx
new file mode 100644
index 000000000000..35589a54f881
--- /dev/null
+++ b/src/ccapi/lib/win/ccapi_os_ipc.cxx
@@ -0,0 +1,380 @@
+/*
+ * $Header$
+ *
+ * Copyright 2008 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 M.I.T. 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.
+ */
+
+extern "C" {
+#include "k5-thread.h"
+#include "ccapi_os_ipc.h"
+#include "cci_debugging.h"
+#include "ccs_reply.h"
+#include "ccs_request.h"
+#include "ccutils.h"
+#include "tls.h"
+#include "util.h"
+#include "win-utils.h"
+ }
+
+#include "autolock.hxx"
+#include "CredentialsCache.h"
+#include "secure.hxx"
+#include "opts.hxx"
+#include "client.h"
+
+extern "C" DWORD GetTlsIndex();
+
+#define SECONDS_TO_WAIT 10
+#define CLIENT_REQUEST_RPC_HANDLE ccs_request_IfHandle
+
+extern HANDLE hCCAPIv2Mutex;
+ParseOpts::Opts opts = { 0 };
+PSECURITY_ATTRIBUTES psa = 0;
+SECURITY_ATTRIBUTES sa = { 0 };
+
+/* The layout of the rest of this module:
+
+ The entrypoints defined in ccs_os_ipc.h:
+ cci_os_ipc_thread_init
+ cci_os_ipc
+
+ Other routines needed by those four.
+ cci_os_connect
+ handle_exception
+ */
+
+cc_int32 ccapi_connect(const struct tspdata* tsp);
+static DWORD handle_exception(DWORD code, struct tspdata* ptspdata);
+
+extern "C" {
+cc_int32 cci_os_ipc_msg( cc_int32 in_launch_server,
+ k5_ipc_stream in_request_stream,
+ cc_int32 in_msg,
+ k5_ipc_stream* out_reply_stream);
+ }
+
+/* ------------------------------------------------------------------------ */
+
+extern "C" cc_int32 cci_os_ipc_process_init (void) {
+ RPC_STATUS status;
+
+ if (!isNT()) {
+ status = RpcServerRegisterIf(ccs_reply_ServerIfHandle, // interface
+ NULL, // MgrTypeUuid
+ NULL); // MgrEpv; null means use default
+ }
+ else {
+ status = RpcServerRegisterIfEx(ccs_reply_ServerIfHandle, // interface
+ NULL, // MgrTypeUuid
+ NULL, // MgrEpv; 0 means default
+ RPC_IF_ALLOW_SECURE_ONLY,
+ RPC_C_LISTEN_MAX_CALLS_DEFAULT,
+ NULL); // No security callback.
+ }
+ cci_check_error(status);
+
+ if (!status) {
+ status = RpcServerRegisterAuthInfo(0, // server principal
+ RPC_C_AUTHN_WINNT,
+ 0,
+ 0 );
+ cci_check_error(status);
+ }
+
+ return status; // ugh. needs translation
+}
+
+/* ------------------------------------------------------------------------ */
+
+extern "C" cc_int32 cci_os_ipc_thread_init (void) {
+ cc_int32 err = ccNoError;
+ struct tspdata* ptspdata;
+ HANDLE replyEvent = NULL;
+ UUID __RPC_FAR uuid;
+ RPC_CSTR __RPC_FAR uuidString = NULL;
+ char* endpoint = NULL;
+
+ if (!GetTspData(GetTlsIndex(), &ptspdata)) return ccErrNoMem;
+
+ err = cci_check_error(UuidCreate(&uuid)); // Get a UUID
+ if (err == RPC_S_OK) { // Convert to string
+ err = UuidToString(&uuid, &uuidString);
+ cci_check_error(err);
+ }
+ if (!err) { // Save in thread local storage
+ tspdata_setUUID(ptspdata, uuidString);
+ endpoint = clientEndpoint((const char *)uuidString);
+ err = RpcServerUseProtseqEp((RPC_CSTR)"ncalrpc",
+ RPC_C_PROTSEQ_MAX_REQS_DEFAULT,
+ (RPC_CSTR)endpoint,
+ sa.lpSecurityDescriptor); // SD
+ free(endpoint);
+ cci_check_error(err);
+ }
+
+#if 0
+ cci_debug_printf("%s UUID:<%s>", __FUNCTION__, tspdata_getUUID(ptspdata));
+#endif
+ // Initialize old CCAPI if necessary:
+ if (!err) if (!Init:: Initialized()) err = Init:: Initialize( );
+ if (!err) if (!Client::Initialized()) err = Client::Initialize(0);
+
+ if (!err) {
+ /* Whenever a reply to an RPC request is received, the RPC caller needs to
+ know when the reply has been received. It does that by waiting for a
+ client-specific event to be set. Define the event name to be <UUID>_reply: */
+ replyEvent = createThreadEvent((char*)uuidString, REPLY_SUFFIX);
+ }
+
+ if (!err) {
+ static bool bListening = false;
+ if (!bListening) {
+ err = RpcServerListen(1, RPC_C_LISTEN_MAX_CALLS_DEFAULT, TRUE);
+ cci_check_error(err);
+ }
+ bListening = err == 0;
+ }
+
+ if (replyEvent) tspdata_setReplyEvent(ptspdata, replyEvent);
+ else err = cci_check_error(GetLastError());
+
+ if (uuidString) RpcStringFree(&uuidString);
+
+ return cci_check_error(err);
+ }
+
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 cci_os_ipc (cc_int32 in_launch_server,
+ k5_ipc_stream in_request_stream,
+ k5_ipc_stream* out_reply_stream) {
+ return cci_os_ipc_msg( in_launch_server,
+ in_request_stream,
+ CCMSG_REQUEST,
+ out_reply_stream);
+ }
+
+extern "C" cc_int32 cci_os_ipc_msg( cc_int32 in_launch_server,
+ k5_ipc_stream in_request_stream,
+ cc_int32 in_msg,
+ k5_ipc_stream* out_reply_stream) {
+
+ cc_int32 err = ccNoError;
+ cc_int32 done = FALSE;
+ cc_int32 try_count = 0;
+ cc_int32 server_died = FALSE;
+ TCHAR* pszStringBinding= NULL;
+ struct tspdata* ptspdata = NULL;
+ char* uuid = NULL;
+ int lenUUID = 0;
+ unsigned int trycount = 0;
+ time_t sst = 0;
+ STARTUPINFO si = { 0 };
+ PROCESS_INFORMATION pi = { 0 };
+ HANDLE replyEvent = 0;
+ BOOL bCCAPI_Connected= FALSE;
+ BOOL bListening = FALSE;
+ unsigned char tspdata_handle[8] = { 0 };
+
+ if (!in_request_stream) { err = cci_check_error (ccErrBadParam); }
+ if (!out_reply_stream ) { err = cci_check_error (ccErrBadParam); }
+
+ if (!GetTspData(GetTlsIndex(), &ptspdata)) {return ccErrBadParam;}
+ bListening = tspdata_getListening(ptspdata);
+ if (!bListening) {
+ err = cci_check_error(cci_os_ipc_thread_init());
+ bListening = !err;
+ tspdata_setListening(ptspdata, bListening);
+ }
+
+ bCCAPI_Connected = tspdata_getConnected (ptspdata);
+ replyEvent = tspdata_getReplyEvent (ptspdata);
+ sst = tspdata_getSST (ptspdata);
+ uuid = tspdata_getUUID(ptspdata);
+
+ // The lazy connection to the server has been put off as long as possible!
+ // ccapi_connect starts listening for replies as an RPC server and then
+ // calls ccs_rpc_connect.
+ if (!err && !bCCAPI_Connected) {
+ err = cci_check_error(ccapi_connect(ptspdata));
+ bCCAPI_Connected = !err;
+ tspdata_setConnected(ptspdata, bCCAPI_Connected);
+ }
+
+ // Clear replyEvent so we can detect when a reply to our request has been received:
+ ResetEvent(replyEvent);
+
+ //++ Use the old CCAPI implementation to try to talk to the server:
+ // It has all the code to use the RPC in a thread-safe way, make the endpoint,
+ // (re)connect and (re)start the server.
+ // Note: the old implementation wrapped the thread-safety stuff in a macro.
+ // Here it is expanded and thus duplicated for each RPC call. The new code has
+ // a very limited number of RPC calls, unlike the older code.
+ WaitForSingleObject( hCCAPIv2Mutex, INFINITE );
+ SecureClient* s = 0;
+ SecureClient::Start(s);
+ CcAutoLock* a = 0;
+ CcAutoLock::Start(a, Client::sLock);
+
+ // New code using new RPC procedures for sending the data and receiving a reply:
+ if (!err) {
+ RpcTryExcept {
+ if (!GetTspData(GetTlsIndex(), &ptspdata)) {return ccErrBadParam;}
+ uuid = tspdata_getUUID(ptspdata);
+ lenUUID = 1 + strlen(uuid); /* 1+ includes terminating \0. */
+#if 0
+ cci_debug_printf("%s calling remote ccs_rpc_request tsp*:0x%X", __FUNCTION__, ptspdata);
+ cci_debug_printf(" rpcmsg:%d; UUID[%d]:<%s> SST:%ld", in_msg, lenUUID, uuid, sst);
+#endif
+ /* copy ptr into handle; ptr may be 4 or 8 bytes, depending on platform; handle is always 8 */
+ memcpy(tspdata_handle, &ptspdata, sizeof(ptspdata));
+ ccs_rpc_request( /* make call with user message: */
+ in_msg, /* Message type */
+ tspdata_handle, /* Our tspdata* will be sent back to the reply proc. */
+ (unsigned char*)uuid,
+ krb5int_ipc_stream_size(in_request_stream),
+ (unsigned char*)krb5int_ipc_stream_data(in_request_stream), /* Data buffer */
+ sst, /* session start time */
+ (long*)(&err) ); /* Return code */
+ }
+ RpcExcept(1) {
+ err = handle_exception(RpcExceptionCode(), ptspdata);
+ }
+ RpcEndExcept;
+ }
+
+ cci_check_error(err);
+ CcAutoLock::Stop(a);
+ SecureClient::Stop(s);
+ ReleaseMutex(hCCAPIv2Mutex);
+ //-- Use the old CCAPI implementation to try to talk to the server.
+
+ // Wait for reply handler to set event:
+ if (!err) {
+ err = cci_check_error(WaitForSingleObject(replyEvent, INFINITE));//(SECONDS_TO_WAIT)*1000));
+ }
+
+ if (!err) {
+ err = cci_check_error(RpcMgmtIsServerListening(CLIENT_REQUEST_RPC_HANDLE));
+ }
+
+ if (!err && server_died) {
+ err = cci_check_error (ccErrServerUnavailable);
+ }
+#if 0
+ if (err == BOOTSTRAP_UNKNOWN_SERVICE && !in_launch_server) {
+ err = ccNoError; /* If the server is not running just return an empty stream. */
+ }
+#endif
+
+ if (!err) {
+ *out_reply_stream = tspdata_getStream(ptspdata);
+ }
+
+ return cci_check_error (err);
+ }
+
+
+
+static DWORD handle_exception(DWORD code, struct tspdata* ptspdata) {
+ cci_debug_printf("%s code %u; ccs_request_IfHandle:0x%X", __FUNCTION__, code, ccs_request_IfHandle);
+ if ( (code == RPC_S_SERVER_UNAVAILABLE) || (code == RPC_S_INVALID_BINDING) ) {
+ Client::Cleanup();
+ tspdata_setConnected(ptspdata, FALSE);
+ }
+ return code;
+ }
+
+
+/* Establish a CCAPI connection with the server.
+ * The connect logic here is identical to the logic in the send request code.
+ * TODO: merge this connect code with that request code.
+ */
+cc_int32 ccapi_connect(const struct tspdata* tsp) {
+ BOOL bListen = TRUE;
+ HANDLE replyEvent = 0;
+ RPC_STATUS status = FALSE;
+ char* uuid = NULL;
+ unsigned char tspdata_handle[8] = {0};
+
+ /* Start listening to our uuid before establishing the connection,
+ * so that when the server tries to call ccapi_listen, we will be ready.
+ */
+
+ /* Build complete RPC uuid using previous CCAPI implementation: */
+ replyEvent = tspdata_getReplyEvent(tsp);
+ uuid = tspdata_getUUID(tsp);
+
+ cci_debug_printf("%s is listening ...", __FUNCTION__);
+
+ // Clear replyEvent so we can detect when a reply to our connect request has been received:
+ ResetEvent(replyEvent);
+
+ // We use the old CCAPI implementation to try to talk to the server.
+ // It has all the code to make the uuid, (re)connect and (re)start the server.
+ WaitForSingleObject( hCCAPIv2Mutex, INFINITE );
+ SecureClient* s = 0;
+ SecureClient::Start(s);
+ CcAutoLock* a = 0;
+ CcAutoLock::Start(a, Client::sLock);
+
+ // Initialize old CCAPI if necessary:
+ if (!status) if (!Init:: Initialized()) status = Init:: Initialize( );
+ if (!status) if (!Client::Initialized()) status = Client::Initialize(0);
+
+ // New code using new RPC procedures for sending the data and receiving a reply:
+ if (!status) {
+ memcpy(tspdata_handle, &tsp, sizeof(tsp));
+ RpcTryExcept {
+ ccs_rpc_connect( /* make call with user message: */
+ CCMSG_CONNECT, /* Message type */
+ tspdata_handle, /* Our tspdata* will be sent back to the reply proc. */
+ (unsigned char*)uuid,
+ (long*)(&status) ); /* Return code */
+ }
+ RpcExcept(1) {
+ cci_check_error(RpcExceptionCode());
+ status = ccErrBadInternalMessage;
+ }
+ RpcEndExcept;
+ }
+
+ CcAutoLock::Stop(a);
+ SecureClient::Stop(s);
+ ReleaseMutex(hCCAPIv2Mutex);
+
+ if (!status) {
+#if 0
+ cci_debug_printf("%s Waiting for replyEvent.", __FUNCTION__);
+#endif
+ status = WaitForSingleObject(replyEvent, INFINITE);//(SECONDS_TO_WAIT)*1000);
+ status = cci_check_error(RpcMgmtIsServerListening(CLIENT_REQUEST_RPC_HANDLE));
+ cci_debug_printf(" Server %sFOUND!", (status) ? "NOT " : "");
+ }
+ if (status) {
+ cci_debug_printf(" unexpected error while looking for server... (%u)", status);
+ }
+
+ return status;
+ }
diff --git a/src/ccapi/lib/win/ccs_reply_proc.c b/src/ccapi/lib/win/ccs_reply_proc.c
new file mode 100644
index 000000000000..bf8c7f4f4158
--- /dev/null
+++ b/src/ccapi/lib/win/ccs_reply_proc.c
@@ -0,0 +1,95 @@
+/* ccapi/lib/win/ccs_reply_proc.c */
+/*
+ * Copyright 2008 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 M.I.T. 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.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <windows.h>
+
+#include "cci_debugging.h"
+#include "ccs_reply.h" /* generated by MIDL compiler */
+#include "ccutils.h"
+#include "tls.h"
+#include "win-utils.h"
+
+
+void ccs_rpc_request_reply(
+ const long rpcmsg, /* Message type */
+ const char tspHandle[], /* Client's tspdata* */
+ const char* uuid, /* uuid for making thread-specific event name */
+ const long srvStartTime, /* Server Start Time */
+ const long cbIn, /* Length of buffer */
+ const char* chIn, /* Data buffer */
+ long* ret_status ) { /* Return code */
+
+ HANDLE hEvent = openThreadEvent(uuid, REPLY_SUFFIX);
+ struct tspdata* tsp;
+ k5_ipc_stream stream;
+ long status = 0;
+#if 0
+ cci_debug_printf("%s! msg#:%d SST:%ld uuid:%s", __FUNCTION__, rpcmsg, srvStartTime, uuid);
+#endif
+ memcpy(&tsp, tspHandle, sizeof(tsp));
+ if (!status) {
+ status = krb5int_ipc_stream_new (&stream); /* Create a stream for the request data */
+ }
+
+ if (!status) { /* Put the data into the stream */
+ status = krb5int_ipc_stream_write (stream, chIn, cbIn);
+ }
+
+ if (!status) { /* Put the data into the stream */
+ tspdata_setStream(tsp, stream);
+ }
+
+ SetEvent(hEvent);
+ CloseHandle(hEvent);
+ *ret_status = status;
+ }
+
+void ccs_rpc_connect_reply(
+ const long rpcmsg, /* Message type */
+ const char tspHandle[], /* Client's tspdata* */
+ const char* uuid, /* uuid for making thread-specific event name */
+ const long srvStartTime, /* Server Start Time */
+ long* status ) { /* Return code */
+
+ HANDLE hEvent = openThreadEvent(uuid, REPLY_SUFFIX);
+ DWORD* p = (DWORD*)(tspHandle);
+#if 0
+ cci_debug_printf("%s! msg#:%d SST:%ld uuid:%s", __FUNCTION__, rpcmsg, srvStartTime, uuid);
+#endif
+ SetEvent(hEvent);
+ CloseHandle(hEvent);
+ }
+
+void ccapi_listen(
+ RPC_ASYNC_STATE* rpcState,
+ handle_t hBinding,
+ const long rpcmsg, /* Message type */
+ long* status ) { /* Return code */
+
+ cci_debug_printf("%s %s!", __FUNCTION__, rpcState->UserInfo);
+ *status = 0;
+ }
diff --git a/src/ccapi/lib/win/debug.exports b/src/ccapi/lib/win/debug.exports
new file mode 100644
index 000000000000..6dc1fc083a2a
--- /dev/null
+++ b/src/ccapi/lib/win/debug.exports
@@ -0,0 +1,11 @@
+ cci_debug_printf
+ _cci_check_error
+ cci_os_ipc
+ cci_os_ipc_msg
+ cci_os_ipc_thread_init
+ krb5int_ipc_stream_data
+ krb5int_ipc_stream_write
+ krb5int_ipc_stream_new
+
+ ccs_authenticate
+ cci_os_ipc_process_init
diff --git a/src/ccapi/lib/win/dllmain.cxx b/src/ccapi/lib/win/dllmain.cxx
new file mode 100644
index 000000000000..82cacad9c87c
--- /dev/null
+++ b/src/ccapi/lib/win/dllmain.cxx
@@ -0,0 +1,222 @@
+/*
+ * $Header$
+ *
+ * Copyright 2008 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 M.I.T. 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.
+ */
+
+extern "C" {
+#include <windows.h>
+#include <LMCons.h>
+
+#include "dllmain.h"
+#include "tls.h"
+#include "cci_debugging.h"
+#include "ccapi_context.h"
+#include "ccapi_ipc.h"
+#include "client.h"
+
+void cci_process_init__auxinit();
+ }
+
+
+#define CCAPI_V2_MUTEX_NAME TEXT("MIT_CCAPI_V4_MUTEX")
+
+// Process-specific data:
+static DWORD dwTlsIndex;
+static char _user[UNLEN+1]; // Username is used as part of the server and client endpoints.
+static HANDLE sessionToken;
+static char* ep_prefices[] = {"CCS", "CCAPI"};
+HANDLE hCCAPIv2Mutex = NULL;
+DWORD firstThreadID = 0;
+
+// These data structures are used by the old CCAPI implementation
+// to keep track of the state of the RPC connection. All data is static.
+static Init init;
+static Client client;
+
+DWORD GetTlsIndex() {return dwTlsIndex;}
+
+// DllMain() is the entry-point function for this DLL.
+BOOL WINAPI DllMain(HINSTANCE hinstDLL, // DLL module handle
+ DWORD fdwReason, // reason called
+ LPVOID lpvReserved) { // reserved
+
+ struct tspdata* ptspdata;
+ BOOL fIgnore;
+ BOOL bStatus;
+ DWORD status = 0; // 0 is success.
+ DWORD maxUN = sizeof(_user);
+ unsigned int i = 0;
+ unsigned int j = 0;
+
+ switch (fdwReason) {
+ // The DLL is loading due to process initialization or a call to LoadLibrary:
+ case DLL_PROCESS_ATTACH:
+ cci_debug_printf("%s DLL_PROCESS_ATTACH", __FUNCTION__);
+ // Process-wide mutex used to allow only one thread at a time into the RPC code:
+ hCCAPIv2Mutex = CreateMutex(NULL, FALSE, CCAPI_V2_MUTEX_NAME);
+
+ // Figure out our username; it's process-wide:
+ bStatus = GetUserName(_user, &maxUN);
+ if (!bStatus) return bStatus;
+
+ // Remove any characters that aren't valid endpoint characters:
+ while (_user[j] != 0) {
+ if (isalnum(_user[j])) _user[i++] = _user[j];
+ j++;
+ }
+ _user[i] = '\0';
+
+ // Our logon session is determined in client.cxx, old CCAPI code carried
+ // over to this implementation.
+
+ // Allocate a TLS index:
+ if ((dwTlsIndex = TlsAlloc()) == TLS_OUT_OF_INDEXES) return FALSE;
+
+ cci_process_init__auxinit();
+ // Don't break; fallthrough: Initialize the TLS index for first thread.
+
+ // The attached process creates a new thread:
+ case DLL_THREAD_ATTACH:
+ cci_debug_printf("%s DLL_THREAD_ATTACH", __FUNCTION__);
+ // Don't actually rely on this case for allocation of resources.
+ // Applications (like SecureCRT) may have threads already
+ // created (say 'A' and 'B') before the dll is loaded. If the dll
+ // is loaded in thread 'A' but then used in thread 'B', thread 'B'
+ // will never execute this code.
+ fIgnore = TlsSetValue(dwTlsIndex, NULL);
+
+ // Do not call cci_ipc_thread_init() yet; defer until we actually
+ // need it. On XP, cci_ipc_thread_init() will cause additional
+ // threads to be immediately spawned, which will bring us right
+ // back here again ad infinitum, until windows
+ // resources are exhausted.
+ break;
+
+ // The thread of the attached process terminates:
+ case DLL_THREAD_DETACH:
+ cci_debug_printf("%s DLL_THREAD_DETACH", __FUNCTION__);
+ // Release the allocated memory for this thread
+ ptspdata = (struct tspdata*)TlsGetValue(dwTlsIndex);
+ if (ptspdata != NULL) {
+ free(ptspdata);
+ TlsSetValue(dwTlsIndex, NULL);
+ }
+ break;
+
+ // DLL unload due to process termination or FreeLibrary:
+ case DLL_PROCESS_DETACH:
+ cci_debug_printf("%s DLL_PROCESS_DETACH", __FUNCTION__);
+ //++ Copied from previous implementation:
+ // Process Teardown "Problem"
+ //
+ // There are two problems that occur during process teardown:
+ //
+ // 1) Windows (NT/9x/2000) does not keep track of load/unload
+ // ordering dependencies for use in process teardown.
+ //
+ // 2) The RPC exception handling in the RPC calls do not work
+ // during process shutdown in Win9x.
+ //
+ // When a process is being torn down in Windows, the krbcc DLL
+ // may get a DLL_PROCESS_DETACH before other DLLs are done
+ // with it. Thus, it may disconnect from the RPC server
+ // before the last shutdown RPC call.
+ //
+ // On NT/2000, this is ok because the RPC call will fail and just
+ // return an error.
+ //
+ // On Win9x/Me, the RPC exception will not be caught.
+ // However, Win9x ignores exceptions during process shutdown,
+ // so the exception will never be seen unless a debugger is
+ // attached to the proccess.
+ //
+ // A good potential woraround would be to have a global
+ // variable that denotes whether the DLL is attached to the
+ // process. If it is not, all entrypoints into the DLL should
+ // return failure.
+ //
+ // A not as good workaround is below but ifdefed out.
+ //
+ // However, we can safely ignore this problem since it can
+ // only affects people running debuggers under 9x/Me who are
+ // using multiple DLLs that use this DLL.
+ //
+ WaitForSingleObject( hCCAPIv2Mutex, INFINITE );
+#if 0
+ bool process_teardown_workaround = false;
+ if (lpvReserved) {
+ Init::InitInfo info;
+ status = Init::Info(info);
+ if (status) break;
+ if (!info.isNT) process_teardown_workaround = true;
+ }
+ if (process_teardown_workaround)
+ break;
+#endif
+ // return value is ignored, so we set status for debugging purposes
+ status = Client::Cleanup();
+ status = Init::Cleanup();
+ ReleaseMutex( hCCAPIv2Mutex );
+ CloseHandle( hCCAPIv2Mutex );
+ //-- Copied from previous implementation.
+
+ // Release the allocated memory for this thread:
+ ptspdata = (struct tspdata*)TlsGetValue(dwTlsIndex);
+ if (ptspdata != NULL)
+ free(ptspdata);
+ TlsFree(dwTlsIndex); // Release the TLS index.
+ // Ideally, we would enumerate all other threads here and
+ // release their thread local storage as well.
+ break;
+
+ default:
+ cci_debug_printf("%s unexpected reason %d", __FUNCTION__, fdwReason);
+ break;
+ }
+
+ UNREFERENCED_PARAMETER(hinstDLL); // no whining!
+ UNREFERENCED_PARAMETER(lpvReserved);
+ return status ? FALSE : TRUE;
+}
+
+
+#ifdef __cplusplus // If used by C++ code,
+extern "C" { // we need to export the C interface
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+/*********************************************************************/
+/* MIDL allocate and free */
+/*********************************************************************/
+
+extern "C" void __RPC_FAR * __RPC_USER MIDL_user_allocate(size_t len) {
+ return(malloc(len));
+ }
+
+extern "C" void __RPC_USER MIDL_user_free(void __RPC_FAR * ptr) {
+ free(ptr);
+ }
diff --git a/src/ccapi/lib/win/dllmain.h b/src/ccapi/lib/win/dllmain.h
new file mode 100644
index 000000000000..8238566e4c8f
--- /dev/null
+++ b/src/ccapi/lib/win/dllmain.h
@@ -0,0 +1,41 @@
+/* ccapi/lib/win/dllmain.h */
+/*
+ * Copyright 2008 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 M.I.T. 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.
+ */
+
+#ifndef _dll_h
+#define _dll_h
+
+#include "windows.h"
+
+#ifdef __cplusplus // If used by C++ code,
+extern "C" { // we need to export the C interface
+#endif
+
+DWORD GetTlsIndex();
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif _dll_h
diff --git a/src/ccapi/server/Makefile.in b/src/ccapi/server/Makefile.in
new file mode 100644
index 000000000000..2c01307f523c
--- /dev/null
+++ b/src/ccapi/server/Makefile.in
@@ -0,0 +1,59 @@
+mydir=ccapi$(S)server
+BUILDTOP=$(REL)..$(S)..
+SUBDIRS=unix
+
+LOCALINCLUDES= -I$(srcdir)/../common
+
+STLIBOBJS= \
+ ccs_array.o \
+ ccs_cache_collection.o \
+ ccs_callback.o \
+ ccs_ccache.o \
+ ccs_ccache_iterator.o \
+ ccs_client.o \
+ ccs_credentials.o \
+ ccs_credentials_iterator.o \
+ ccs_list.o \
+ ccs_list_internal.o \
+ ccs_lock.o \
+ ccs_lock_state.o \
+ ccs_pipe.o \
+ ccs_server.o
+
+OBJS= \
+ $(OUTPRE)ccs_array.$(OBJEXT) \
+ $(OUTPRE)ccs_cache_collection.$(OBJEXT) \
+ $(OUTPRE)ccs_callback.$(OBJEXT) \
+ $(OUTPRE)ccs_ccache.$(OBJEXT) \
+ $(OUTPRE)ccs_ccache_iterator.$(OBJEXT) \
+ $(OUTPRE)ccs_client.$(OBJEXT) \
+ $(OUTPRE)ccs_credentials.$(OBJEXT) \
+ $(OUTPRE)ccs_credentials_iterator.$(OBJEXT) \
+ $(OUTPRE)ccs_list.$(OBJEXT) \
+ $(OUTPRE)ccs_list_internal.$(OBJEXT) \
+ $(OUTPRE)ccs_lock.$(OBJEXT) \
+ $(OUTPRE)ccs_lock_state.$(OBJEXT) \
+ $(OUTPRE)ccs_pipe.$(OBJEXT) \
+ $(OUTPRE)ccs_server.$(OBJEXT)
+
+SRCS= \
+ ccs_array.c \
+ ccs_cache_collection.c \
+ ccs_callback.c \
+ ccs_ccache.c \
+ ccs_ccache_iterator.c \
+ ccs_client.c \
+ ccs_credentials.c \
+ ccs_credentials_iterator.c \
+ ccs_list.c \
+ ccs_list_internal.c \
+ ccs_lock.c \
+ ccs_lock_state.c \
+ ccs_pipe.c \
+ ccs_server.c
+
+all-unix: all-libobjs
+clean-unix:: clean-libobjs
+
+@libobj_frag@
+
diff --git a/src/ccapi/server/ccs_array.c b/src/ccapi/server/ccs_array.c
new file mode 100644
index 000000000000..7e0874a85aa4
--- /dev/null
+++ b/src/ccapi/server/ccs_array.c
@@ -0,0 +1,309 @@
+/* ccapi/server/ccs_array.c */
+/*
+ * Copyright 2006, 2007 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 M.I.T. 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.
+ */
+
+#include "ccs_common.h"
+#include "cci_array_internal.h"
+
+/* ------------------------------------------------------------------------ */
+
+static cc_int32 ccs_client_object_release (cci_array_object_t io_client)
+{
+ return cci_check_error (ccs_client_release ((ccs_client_t) io_client));
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 ccs_client_array_new (ccs_client_array_t *out_array)
+{
+ return cci_array_new (out_array, ccs_client_object_release);
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 ccs_client_array_release (ccs_client_array_t io_array)
+{
+ return cci_array_release (io_array);
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_uint64 ccs_client_array_count (ccs_client_array_t in_array)
+{
+ return cci_array_count (in_array);
+}
+
+/* ------------------------------------------------------------------------ */
+
+ccs_client_t ccs_client_array_object_at_index (ccs_client_array_t io_array,
+ cc_uint64 in_position)
+{
+ return (ccs_client_t) cci_array_object_at_index (io_array, in_position);
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 ccs_client_array_insert (ccs_client_array_t io_array,
+ ccs_client_t in_client,
+ cc_uint64 in_position)
+{
+ return cci_array_insert (io_array, (cci_array_object_t) in_client, in_position);
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 ccs_client_array_remove (ccs_client_array_t io_array,
+ cc_uint64 in_position)
+{
+ return cci_array_remove (io_array, in_position);
+}
+
+#ifdef TARGET_OS_MAC
+#pragma mark -
+#endif
+
+/* ------------------------------------------------------------------------ */
+
+static cc_int32 ccs_lock_object_release (cci_array_object_t io_lock)
+{
+ return cci_check_error (ccs_lock_release ((ccs_lock_t) io_lock));
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 ccs_lock_array_new (ccs_lock_array_t *out_array)
+{
+ return cci_array_new (out_array, ccs_lock_object_release);
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 ccs_lock_array_release (ccs_lock_array_t io_array)
+{
+ return cci_array_release (io_array);
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_uint64 ccs_lock_array_count (ccs_lock_array_t in_array)
+{
+ return cci_array_count (in_array);
+}
+
+/* ------------------------------------------------------------------------ */
+
+ccs_lock_t ccs_lock_array_object_at_index (ccs_lock_array_t io_array,
+ cc_uint64 in_position)
+{
+ return (ccs_lock_t) cci_array_object_at_index (io_array, in_position);
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 ccs_lock_array_insert (ccs_lock_array_t io_array,
+ ccs_lock_t in_lock,
+ cc_uint64 in_position)
+{
+ return cci_array_insert (io_array, (cci_array_object_t) in_lock, in_position);
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 ccs_lock_array_remove (ccs_lock_array_t io_array,
+ cc_uint64 in_position)
+{
+ return cci_array_remove (io_array, in_position);
+}
+
+/* ------------------------------------------------------------------------ */
+cc_int32 ccs_lock_array_move (ccs_lock_array_t io_array,
+ cc_uint64 in_position,
+ cc_uint64 in_new_position,
+ cc_uint64 *out_real_new_position)
+{
+ return cci_array_move (io_array, in_position, in_new_position, out_real_new_position);
+}
+
+#ifdef TARGET_OS_MAC
+#pragma mark -
+#endif
+
+/* ------------------------------------------------------------------------ */
+
+static cc_int32 ccs_callback_object_release (cci_array_object_t io_callback)
+{
+ return cci_check_error (ccs_callback_release ((ccs_callback_t) io_callback));
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 ccs_callback_array_new (ccs_callback_array_t *out_array)
+{
+ return cci_array_new (out_array, ccs_callback_object_release);
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 ccs_callback_array_release (ccs_callback_array_t io_array)
+{
+ return cci_array_release (io_array);
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_uint64 ccs_callback_array_count (ccs_callback_array_t in_array)
+{
+ return cci_array_count (in_array);
+}
+
+/* ------------------------------------------------------------------------ */
+
+ccs_callback_t ccs_callback_array_object_at_index (ccs_callback_array_t io_array,
+ cc_uint64 in_position)
+{
+ return (ccs_callback_t) cci_array_object_at_index (io_array, in_position);
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 ccs_callback_array_insert (ccs_callback_array_t io_array,
+ ccs_callback_t in_callback,
+ cc_uint64 in_position)
+{
+ return cci_array_insert (io_array, (cci_array_object_t) in_callback, in_position);
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 ccs_callback_array_remove (ccs_callback_array_t io_array,
+ cc_uint64 in_position)
+{
+ return cci_array_remove (io_array, in_position);
+}
+
+#ifdef TARGET_OS_MAC
+#pragma mark -
+#endif
+
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 ccs_callbackref_array_new (ccs_callbackref_array_t *out_array)
+{
+ /* Ref arrays do not own their contents; pass NULL for release function */
+ return cci_array_new (out_array, NULL);
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 ccs_callbackref_array_release (ccs_callbackref_array_t io_array)
+{
+ return cci_array_release (io_array);
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_uint64 ccs_callbackref_array_count (ccs_callbackref_array_t in_array)
+{
+ return cci_array_count (in_array);
+}
+
+/* ------------------------------------------------------------------------ */
+
+ccs_callback_t ccs_callbackref_array_object_at_index (ccs_callbackref_array_t io_array,
+ cc_uint64 in_position)
+{
+ return (ccs_callback_t) cci_array_object_at_index (io_array, in_position);
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 ccs_callbackref_array_insert (ccs_callbackref_array_t io_array,
+ ccs_callback_t in_callback,
+ cc_uint64 in_position)
+{
+ return cci_array_insert (io_array, (cci_array_object_t) in_callback, in_position);
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 ccs_callbackref_array_remove (ccs_callbackref_array_t io_array,
+ cc_uint64 in_position)
+{
+ return cci_array_remove (io_array, in_position);
+}
+
+#ifdef TARGET_OS_MAC
+#pragma mark -
+#endif
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 ccs_iteratorref_array_new (ccs_iteratorref_array_t *out_array)
+{
+ /* Ref arrays do not own their contents; pass NULL for release function */
+ return cci_array_new (out_array, NULL);
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 ccs_iteratorref_array_release (ccs_iteratorref_array_t io_array)
+{
+ return cci_array_release (io_array);
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_uint64 ccs_iteratorref_array_count (ccs_iteratorref_array_t in_array)
+{
+ return cci_array_count (in_array);
+}
+
+/* ------------------------------------------------------------------------ */
+
+ccs_generic_list_iterator_t ccs_iteratorref_array_object_at_index (ccs_iteratorref_array_t io_array,
+ cc_uint64 in_position)
+{
+ return (ccs_generic_list_iterator_t) cci_array_object_at_index (io_array,
+ in_position);
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 ccs_iteratorref_array_insert (ccs_iteratorref_array_t io_array,
+ ccs_generic_list_iterator_t in_iterator,
+ cc_uint64 in_position)
+{
+ return cci_array_insert (io_array,
+ (cci_array_object_t) in_iterator,
+ in_position);
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 ccs_iteratorref_array_remove (ccs_iteratorref_array_t io_array,
+ cc_uint64 in_position)
+{
+ return cci_array_remove (io_array, in_position);
+}
diff --git a/src/ccapi/server/ccs_array.h b/src/ccapi/server/ccs_array.h
new file mode 100644
index 000000000000..470812b3dcfe
--- /dev/null
+++ b/src/ccapi/server/ccs_array.h
@@ -0,0 +1,132 @@
+/* ccapi/server/ccs_array.h */
+/*
+ * Copyright 2006, 2007 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 M.I.T. 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.
+ */
+
+#ifndef CCS_ARRAY_H
+#define CCS_ARRAY_H
+
+#include "ccs_types.h"
+
+cc_int32 ccs_client_array_new (ccs_client_array_t *out_array);
+
+cc_int32 ccs_client_array_release (ccs_client_array_t io_array);
+
+cc_uint64 ccs_client_array_count (ccs_client_array_t in_array);
+
+ccs_client_t ccs_client_array_object_at_index (ccs_client_array_t io_array,
+ cc_uint64 in_position);
+
+cc_int32 ccs_client_array_insert (ccs_client_array_t io_array,
+ ccs_client_t in_client,
+ cc_uint64 in_position);
+
+cc_int32 ccs_client_array_remove (ccs_client_array_t io_array,
+ cc_uint64 in_position);
+
+#ifdef TARGET_OS_MAC
+#pragma mark -
+#endif
+
+cc_int32 ccs_lock_array_new (ccs_lock_array_t *out_array);
+
+cc_int32 ccs_lock_array_release (ccs_lock_array_t io_array);
+
+cc_uint64 ccs_lock_array_count (ccs_lock_array_t in_array);
+
+ccs_lock_t ccs_lock_array_object_at_index (ccs_lock_array_t io_array,
+ cc_uint64 in_position);
+
+cc_int32 ccs_lock_array_insert (ccs_lock_array_t io_array,
+ ccs_lock_t in_lock,
+ cc_uint64 in_position);
+
+cc_int32 ccs_lock_array_remove (ccs_lock_array_t io_array,
+ cc_uint64 in_position);
+
+cc_int32 ccs_lock_array_move (ccs_lock_array_t io_array,
+ cc_uint64 in_position,
+ cc_uint64 in_new_position,
+ cc_uint64 *out_real_new_position);
+
+#ifdef TARGET_OS_MAC
+#pragma mark -
+#endif
+
+cc_int32 ccs_callback_array_new (ccs_callback_array_t *out_array);
+
+cc_int32 ccs_callback_array_release (ccs_callback_array_t io_array);
+
+cc_uint64 ccs_callback_array_count (ccs_callback_array_t in_array);
+
+ccs_callback_t ccs_callback_array_object_at_index (ccs_callback_array_t io_array,
+ cc_uint64 in_position);
+
+cc_int32 ccs_callback_array_insert (ccs_callback_array_t io_array,
+ ccs_callback_t in_callback,
+ cc_uint64 in_position);
+
+cc_int32 ccs_callback_array_remove (ccs_callback_array_t io_array,
+ cc_uint64 in_position);
+
+#ifdef TARGET_OS_MAC
+#pragma mark -
+#endif
+
+cc_int32 ccs_callbackref_array_new (ccs_callbackref_array_t *out_array);
+
+cc_int32 ccs_callbackref_array_release (ccs_callbackref_array_t io_array);
+
+cc_uint64 ccs_callbackref_array_count (ccs_callbackref_array_t in_array);
+
+ccs_callback_t ccs_callbackref_array_object_at_index (ccs_callbackref_array_t io_array,
+ cc_uint64 in_position);
+
+cc_int32 ccs_callbackref_array_insert (ccs_callbackref_array_t io_array,
+ ccs_callback_t in_callback,
+ cc_uint64 in_position);
+
+cc_int32 ccs_callbackref_array_remove (ccs_callbackref_array_t io_array,
+ cc_uint64 in_position);
+
+#ifdef TARGET_OS_MAC
+#pragma mark -
+#endif
+
+cc_int32 ccs_iteratorref_array_new (ccs_iteratorref_array_t *out_array);
+
+cc_int32 ccs_iteratorref_array_release (ccs_iteratorref_array_t io_array);
+
+cc_uint64 ccs_iteratorref_array_count (ccs_iteratorref_array_t in_array);
+
+ccs_generic_list_iterator_t ccs_iteratorref_array_object_at_index (ccs_iteratorref_array_t io_array,
+ cc_uint64 in_position);
+
+cc_int32 ccs_iteratorref_array_insert (ccs_iteratorref_array_t io_array,
+ ccs_generic_list_iterator_t in_iterator,
+ cc_uint64 in_position);
+
+cc_int32 ccs_iteratorref_array_remove (ccs_iteratorref_array_t io_array,
+ cc_uint64 in_position);
+
+#endif /* CCS_ARRAY_H */
diff --git a/src/ccapi/server/ccs_cache_collection.c b/src/ccapi/server/ccs_cache_collection.c
new file mode 100644
index 000000000000..333007352c5f
--- /dev/null
+++ b/src/ccapi/server/ccs_cache_collection.c
@@ -0,0 +1,1109 @@
+/* ccapi/server/ccs_cache_collection.c */
+/*
+ * Copyright 2006, 2007 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 M.I.T. 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.
+ */
+
+#include "k5-platform.h" /* pull in asprintf decl/defn */
+#include "ccs_common.h"
+#include "ccs_os_notify.h"
+
+struct ccs_cache_collection_d {
+ cc_time_t last_changed_time;
+ cc_uint64 next_unique_name;
+ cci_identifier_t identifier;
+ ccs_lock_state_t lock_state;
+ ccs_ccache_list_t ccaches;
+ ccs_callback_array_t change_callbacks;
+};
+
+struct ccs_cache_collection_d ccs_cache_collection_initializer = { 0, 0, NULL, NULL, NULL, NULL };
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 ccs_cache_collection_new (ccs_cache_collection_t *out_cache_collection)
+{
+ cc_int32 err = ccNoError;
+ ccs_cache_collection_t cache_collection = NULL;
+
+ if (!out_cache_collection) { err = cci_check_error (ccErrBadParam); }
+
+ if (!err) {
+ cache_collection = malloc (sizeof (*cache_collection));
+ if (cache_collection) {
+ *cache_collection = ccs_cache_collection_initializer;
+ } else {
+ err = cci_check_error (ccErrNoMem);
+ }
+ }
+
+ if (!err) {
+ err = ccs_server_new_identifier (&cache_collection->identifier);
+ }
+
+ if (!err) {
+ err = ccs_lock_state_new (&cache_collection->lock_state,
+ ccErrInvalidContext,
+ ccErrContextLocked,
+ ccErrContextUnlocked);
+ }
+
+ if (!err) {
+ err = ccs_ccache_list_new (&cache_collection->ccaches);
+ }
+
+ if (!err) {
+ err = ccs_callback_array_new (&cache_collection->change_callbacks);
+ }
+
+ if (!err) {
+ err = ccs_cache_collection_changed (cache_collection);
+ }
+
+ if (!err) {
+ *out_cache_collection = cache_collection;
+ cache_collection = NULL;
+ }
+
+ ccs_cache_collection_release (cache_collection);
+
+ return cci_check_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 ccs_cache_collection_release (ccs_cache_collection_t io_cache_collection)
+{
+ cc_int32 err = ccNoError;
+
+ if (!err && io_cache_collection) {
+ cci_identifier_release (io_cache_collection->identifier);
+ ccs_lock_state_release (io_cache_collection->lock_state);
+ ccs_ccache_list_release (io_cache_collection->ccaches);
+ ccs_callback_array_release (io_cache_collection->change_callbacks);
+ free (io_cache_collection);
+ }
+
+ return cci_check_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 ccs_cache_collection_compare_identifier (ccs_cache_collection_t in_cache_collection,
+ cci_identifier_t in_identifier,
+ cc_uint32 *out_equal)
+{
+ cc_int32 err = ccNoError;
+
+ if (!in_cache_collection) { err = cci_check_error (ccErrBadParam); }
+ if (!in_identifier ) { err = cci_check_error (ccErrBadParam); }
+ if (!out_equal ) { err = cci_check_error (ccErrBadParam); }
+
+ if (!err) {
+ err = cci_identifier_compare (in_cache_collection->identifier,
+ in_identifier,
+ out_equal);
+ }
+
+ return cci_check_error (err);
+}
+
+#ifdef TARGET_OS_MAC
+#pragma mark -
+#endif
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 ccs_cache_collection_changed (ccs_cache_collection_t io_cache_collection)
+{
+ cc_int32 err = ccNoError;
+ k5_ipc_stream reply_data = NULL;
+
+ if (!io_cache_collection) { err = cci_check_error (ccErrBadParam); }
+
+ if (!err) {
+ cc_time_t now = time (NULL);
+
+ if (io_cache_collection->last_changed_time < now) {
+ io_cache_collection->last_changed_time = now;
+ } else {
+ io_cache_collection->last_changed_time++;
+ }
+ }
+
+ if (!err) {
+ err = krb5int_ipc_stream_new (&reply_data);
+ }
+
+ if (!err) {
+ err = krb5int_ipc_stream_write_time (reply_data, io_cache_collection->last_changed_time);
+ }
+
+ if (!err) {
+ /* Loop over callbacks sending messages to them */
+ cc_uint64 i;
+ cc_uint64 count = ccs_callback_array_count (io_cache_collection->change_callbacks);
+
+ for (i = 0; !err && i < count; i++) {
+ ccs_callback_t callback = ccs_callback_array_object_at_index (io_cache_collection->change_callbacks, i);
+
+ err = ccs_callback_reply_to_client (callback, reply_data);
+
+ if (!err) {
+ cci_debug_printf ("%s: Removing callback reference %p.", __FUNCTION__, callback);
+ err = ccs_callback_array_remove (io_cache_collection->change_callbacks, i);
+ break;
+ }
+ }
+ }
+
+ if (!err) {
+ err = ccs_os_notify_cache_collection_changed (io_cache_collection);
+ }
+
+ krb5int_ipc_stream_release (reply_data);
+
+ return cci_check_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+static cc_int32 ccs_cache_collection_invalidate_change_callback (ccs_callback_owner_t io_cache_collection,
+ ccs_callback_t in_callback)
+{
+ cc_int32 err = ccNoError;
+
+ if (!io_cache_collection) { err = cci_check_error (ccErrBadParam); }
+ if (!in_callback ) { err = cci_check_error (ccErrBadParam); }
+
+ if (!err) {
+ /* Remove callback */
+ ccs_cache_collection_t cache_collection = (ccs_cache_collection_t) io_cache_collection;
+ cc_uint64 i;
+ cc_uint64 count = ccs_callback_array_count (cache_collection->change_callbacks);
+
+ for (i = 0; !err && i < count; i++) {
+ ccs_callback_t callback = ccs_callback_array_object_at_index (cache_collection->change_callbacks, i);
+
+ if (callback == in_callback) {
+ cci_debug_printf ("%s: Removing callback reference %p.", __FUNCTION__, callback);
+ err = ccs_callback_array_remove (cache_collection->change_callbacks, i);
+ break;
+ }
+ }
+ }
+
+ return cci_check_error (err);
+}
+
+#ifdef TARGET_OS_MAC
+#pragma mark -
+#endif
+
+/* ------------------------------------------------------------------------ */
+
+static cc_int32 ccs_cache_collection_find_ccache_by_name (ccs_cache_collection_t in_cache_collection,
+ const char *in_name,
+ ccs_ccache_t *out_ccache)
+{
+ cc_int32 err = ccNoError;
+ ccs_ccache_list_iterator_t iterator = NULL;
+
+ if (!in_cache_collection) { err = cci_check_error (ccErrBadParam); }
+ if (!in_name ) { err = cci_check_error (ccErrBadParam); }
+ if (!out_ccache ) { err = cci_check_error (ccErrBadParam); }
+
+ if (!err) {
+ err = ccs_ccache_list_new_iterator (in_cache_collection->ccaches,
+ CCS_PIPE_NULL,
+ &iterator);
+ }
+
+ while (!err) {
+ ccs_ccache_t ccache = NULL;
+
+ err = ccs_ccache_list_iterator_next (iterator, &ccache);
+
+ if (!err) {
+ cc_uint32 equal = 0;
+
+ err = ccs_ccache_compare_name (ccache, in_name, &equal);
+
+ if (!err && equal) {
+ *out_ccache = ccache;
+ break;
+ }
+ }
+ }
+ if (err == ccIteratorEnd) { err = ccErrCCacheNotFound; }
+
+ if (iterator) { ccs_ccache_list_iterator_release (iterator); }
+
+ return cci_check_error (err);
+}
+
+#ifdef TARGET_OS_MAC
+#pragma mark -
+#endif
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 ccs_cache_collection_find_ccache (ccs_cache_collection_t in_cache_collection,
+ cci_identifier_t in_identifier,
+ ccs_ccache_t *out_ccache)
+{
+ cc_int32 err = ccNoError;
+
+ if (!in_cache_collection) { err = cci_check_error (ccErrBadParam); }
+ if (!in_identifier ) { err = cci_check_error (ccErrBadParam); }
+ if (!out_ccache ) { err = cci_check_error (ccErrBadParam); }
+
+ if (!err) {
+ err = ccs_ccache_list_find (in_cache_collection->ccaches,
+ in_identifier, out_ccache);
+ }
+
+ return cci_check_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 ccs_ccache_collection_move_ccache (ccs_cache_collection_t io_cache_collection,
+ cci_identifier_t in_source_identifier,
+ ccs_ccache_t io_destination_ccache)
+{
+ cc_int32 err = ccNoError;
+ ccs_ccache_t source_ccache = NULL;
+
+ if (!io_cache_collection ) { err = cci_check_error (ccErrBadParam); }
+ if (!in_source_identifier ) { err = cci_check_error (ccErrBadParam); }
+ if (!io_destination_ccache) { err = cci_check_error (ccErrBadParam); }
+
+ if (!err) {
+ err = ccs_cache_collection_find_ccache (io_cache_collection,
+ in_source_identifier,
+ &source_ccache);
+ }
+
+ if (!err) {
+ err = ccs_ccache_swap_contents (source_ccache,
+ io_destination_ccache,
+ io_cache_collection);
+ }
+
+ if (!err) {
+ err = ccs_cache_collection_destroy_ccache (io_cache_collection,
+ in_source_identifier);
+ }
+
+ return cci_check_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 ccs_cache_collection_destroy_ccache (ccs_cache_collection_t io_cache_collection,
+ cci_identifier_t in_identifier)
+{
+ cc_int32 err = ccNoError;
+ ccs_ccache_t ccache = NULL;
+
+ if (!io_cache_collection) { err = cci_check_error (ccErrBadParam); }
+ if (!in_identifier ) { err = cci_check_error (ccErrBadParam); }
+
+ if (!err) {
+ err = ccs_cache_collection_find_ccache (io_cache_collection,
+ in_identifier,
+ &ccache);
+ }
+
+ if (!err) {
+ /* Notify before deletion because after deletion the ccache
+ * will no longer exist (and won't know about its clients) */
+ err = ccs_ccache_changed (ccache, io_cache_collection);
+ }
+
+ if (!err) {
+ err = ccs_ccache_list_remove (io_cache_collection->ccaches,
+ in_identifier);
+ }
+
+ return cci_check_error (err);
+}
+
+#ifdef TARGET_OS_MAC
+#pragma mark -
+#endif
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 ccs_cache_collection_find_ccache_iterator (ccs_cache_collection_t in_cache_collection,
+ cci_identifier_t in_identifier,
+ ccs_ccache_iterator_t *out_ccache_iterator)
+{
+ cc_int32 err = ccNoError;
+
+ if (!in_cache_collection) { err = cci_check_error (ccErrBadParam); }
+ if (!in_identifier ) { err = cci_check_error (ccErrBadParam); }
+ if (!out_ccache_iterator) { err = cci_check_error (ccErrBadParam); }
+
+ if (!err) {
+ err = ccs_ccache_list_find_iterator (in_cache_collection->ccaches,
+ in_identifier,
+ out_ccache_iterator);
+ }
+
+ return cci_check_error (err);
+}
+
+#ifdef TARGET_OS_MAC
+#pragma mark -
+#endif
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 ccs_cache_collection_find_credentials_iterator (ccs_cache_collection_t in_cache_collection,
+ cci_identifier_t in_identifier,
+ ccs_ccache_t *out_ccache,
+ ccs_credentials_iterator_t *out_credentials_iterator)
+{
+ cc_int32 err = ccNoError;
+ ccs_ccache_list_iterator_t iterator = NULL;
+
+ if (!in_cache_collection ) { err = cci_check_error (ccErrBadParam); }
+ if (!in_identifier ) { err = cci_check_error (ccErrBadParam); }
+ if (!out_credentials_iterator) { err = cci_check_error (ccErrBadParam); }
+
+ if (!err) {
+ err = ccs_ccache_list_new_iterator (in_cache_collection->ccaches,
+ CCS_PIPE_NULL,
+ &iterator);
+ }
+
+ while (!err) {
+ ccs_ccache_t ccache = NULL;
+
+ err = ccs_ccache_list_iterator_next (iterator, &ccache);
+
+ if (!err) {
+ cc_int32 terr = ccs_ccache_find_credentials_iterator (ccache,
+ in_identifier,
+ out_credentials_iterator);
+ if (!terr) {
+ *out_ccache = ccache;
+ break;
+ }
+ }
+ }
+ if (err == ccIteratorEnd) { err = cci_check_error (ccErrInvalidCredentialsIterator); }
+
+ if (iterator) { ccs_ccache_list_iterator_release (iterator); }
+
+ return cci_check_error (err);
+}
+
+#ifdef TARGET_OS_MAC
+#pragma mark -
+#endif
+
+/* ------------------------------------------------------------------------ */
+
+static cc_int32 ccs_cache_collection_get_next_unique_ccache_name (ccs_cache_collection_t io_cache_collection,
+ char **out_name)
+{
+ cc_int32 err = ccNoError;
+ cc_uint64 count = 0;
+ char *name = NULL;
+
+ if (!io_cache_collection) { err = cci_check_error (ccErrBadParam); }
+ if (!out_name ) { err = cci_check_error (ccErrBadParam); }
+
+ if (!err) {
+ err = ccs_cache_collection_list_count (io_cache_collection->ccaches, &count);
+ }
+
+ if (!err) {
+ if (count > 0) {
+ while (!err) {
+ int ret = asprintf (&name, "%lld", io_cache_collection->next_unique_name++);
+ if (ret < 0 || !name) { err = cci_check_error (ccErrNoMem); }
+
+ if (!err) {
+ ccs_ccache_t ccache = NULL; /* temporary to hold ccache pointer */
+ err = ccs_cache_collection_find_ccache_by_name (io_cache_collection,
+ name, &ccache);
+ }
+
+ if (err == ccErrCCacheNotFound) {
+ err = ccNoError;
+ break; /* found a unique one */
+ }
+ }
+ } else {
+ name = strdup (k_cci_context_initial_ccache_name);
+ if (!name) { err = cci_check_error (ccErrNoMem); }
+ }
+ }
+
+ if (!err) {
+ *out_name = name;
+ name = NULL;
+ }
+
+ free (name);
+
+ return cci_check_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+static cc_int32 ccs_cache_collection_get_default_ccache (ccs_cache_collection_t in_cache_collection,
+ ccs_ccache_t *out_ccache)
+{
+ cc_int32 err = ccNoError;
+ cc_uint64 count = 0;
+
+ if (!in_cache_collection) { err = cci_check_error (ccErrBadParam); }
+ if (!out_ccache ) { err = cci_check_error (ccErrBadParam); }
+
+ if (!err) {
+ err = ccs_ccache_list_count (in_cache_collection->ccaches, &count);
+ }
+
+ if (!err) {
+ if (count > 0) {
+ /* First ccache is the default */
+ ccs_ccache_list_iterator_t iterator = NULL;
+
+ err = ccs_ccache_list_new_iterator (in_cache_collection->ccaches,
+ CCS_PIPE_NULL,
+ &iterator);
+
+ if (!err) {
+ err = ccs_ccache_list_iterator_next (iterator, out_ccache);
+ }
+
+ ccs_ccache_list_iterator_release (iterator);
+
+ } else {
+ err = cci_check_error (ccErrCCacheNotFound);
+ }
+ }
+
+ return cci_check_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 ccs_cache_collection_set_default_ccache (ccs_cache_collection_t io_cache_collection,
+ cci_identifier_t in_identifier)
+{
+ cc_int32 err = ccNoError;
+ ccs_ccache_t old_default = NULL;
+ ccs_ccache_t new_default = NULL;
+ cc_uint32 equal = 0;
+
+ if (!io_cache_collection) { err = cci_check_error (ccErrBadParam); }
+ if (!in_identifier ) { err = cci_check_error (ccErrBadParam); }
+
+ if (!err) {
+ err = ccs_cache_collection_get_default_ccache (io_cache_collection,
+ &old_default);
+ }
+
+ if (!err) {
+ err = ccs_ccache_compare_identifier (old_default, in_identifier, &equal);
+ }
+
+
+ if (!err && !equal) {
+ err = ccs_ccache_list_push_front (io_cache_collection->ccaches,
+ in_identifier);
+
+ if (!err) {
+ err = ccs_ccache_notify_default_state_changed (old_default,
+ io_cache_collection,
+ 0 /* no longer default */);
+ }
+
+ if (!err) {
+ err = ccs_cache_collection_get_default_ccache (io_cache_collection,
+ &new_default);
+ }
+
+ if (!err) {
+ err = ccs_ccache_notify_default_state_changed (new_default,
+ io_cache_collection,
+ 1 /* now default */);
+ }
+
+ if (!err) {
+ err = ccs_cache_collection_changed (io_cache_collection);
+ }
+ }
+
+ return cci_check_error (err);
+}
+
+#ifdef TARGET_OS_MAC
+#pragma mark -
+#pragma mark -- IPC Messages --
+#endif
+
+/* ------------------------------------------------------------------------ */
+
+static cc_int32 ccs_cache_collection_sync (ccs_cache_collection_t io_cache_collection,
+ k5_ipc_stream in_request_data,
+ k5_ipc_stream io_reply_data)
+{
+ cc_int32 err = ccNoError;
+
+ if (!io_cache_collection) { err = cci_check_error (ccErrBadParam); }
+ if (!in_request_data ) { err = cci_check_error (ccErrBadParam); }
+ if (!io_reply_data ) { err = cci_check_error (ccErrBadParam); }
+
+ if (!err) {
+ err = cci_identifier_write (io_cache_collection->identifier, io_reply_data);
+ }
+
+ return cci_check_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+static cc_int32 ccs_cache_collection_get_change_time (ccs_cache_collection_t io_cache_collection,
+ k5_ipc_stream in_request_data,
+ k5_ipc_stream io_reply_data)
+{
+ cc_int32 err = ccNoError;
+
+ if (!io_cache_collection) { err = cci_check_error (ccErrBadParam); }
+ if (!in_request_data ) { err = cci_check_error (ccErrBadParam); }
+ if (!io_reply_data ) { err = cci_check_error (ccErrBadParam); }
+
+ if (!err) {
+ err = krb5int_ipc_stream_write_time (io_reply_data, io_cache_collection->last_changed_time);
+ }
+
+ return cci_check_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+static cc_int32 ccs_cache_collection_wait_for_change (ccs_pipe_t in_client_pipe,
+ ccs_pipe_t in_reply_pipe,
+ ccs_cache_collection_t io_cache_collection,
+ k5_ipc_stream in_request_data,
+ k5_ipc_stream io_reply_data,
+ cc_uint32 *out_will_block)
+{
+ cc_int32 err = ccNoError;
+ cc_time_t last_wait_for_change_time = 0;
+ cc_uint32 will_block = 0;
+
+ if (!ccs_pipe_valid (in_client_pipe)) { err = cci_check_error (ccErrBadParam); }
+ if (!ccs_pipe_valid (in_reply_pipe )) { err = cci_check_error (ccErrBadParam); }
+ if (!io_cache_collection ) { err = cci_check_error (ccErrBadParam); }
+ if (!in_request_data ) { err = cci_check_error (ccErrBadParam); }
+ if (!out_will_block ) { err = cci_check_error (ccErrBadParam); }
+
+ if (!err) {
+ err = krb5int_ipc_stream_read_time (in_request_data, &last_wait_for_change_time);
+ }
+
+ if (!err) {
+ if (last_wait_for_change_time < io_cache_collection->last_changed_time) {
+ err = krb5int_ipc_stream_write_time (io_reply_data, io_cache_collection->last_changed_time);
+
+ } else {
+ ccs_callback_t callback = NULL;
+
+ err = ccs_callback_new (&callback,
+ ccErrInvalidContext,
+ in_client_pipe,
+ in_reply_pipe,
+ (ccs_callback_owner_t) io_cache_collection,
+ ccs_cache_collection_invalidate_change_callback);
+
+ if (!err) {
+ err = ccs_callback_array_insert (io_cache_collection->change_callbacks, callback,
+ ccs_callback_array_count (io_cache_collection->change_callbacks));
+ if (!err) { callback = NULL; /* take ownership */ }
+
+ will_block = 1;
+ }
+
+ ccs_callback_release (callback);
+ }
+ }
+
+ if (!err) {
+ *out_will_block = will_block;
+ }
+
+ return cci_check_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+static cc_int32 ccs_cache_collection_get_default_ccache_name (ccs_cache_collection_t io_cache_collection,
+ k5_ipc_stream in_request_data,
+ k5_ipc_stream io_reply_data)
+{
+ cc_int32 err = ccNoError;
+ cc_uint64 count = 0;
+
+ if (!io_cache_collection) { err = cci_check_error (ccErrBadParam); }
+ if (!in_request_data ) { err = cci_check_error (ccErrBadParam); }
+ if (!io_reply_data ) { err = cci_check_error (ccErrBadParam); }
+
+ if (!err) {
+ err = ccs_cache_collection_list_count (io_cache_collection->ccaches, &count);
+ }
+
+ if (!err) {
+ if (count > 0) {
+ ccs_ccache_t ccache = NULL;
+
+ err = ccs_cache_collection_get_default_ccache (io_cache_collection, &ccache);
+
+ if (!err) {
+ err = ccs_ccache_write_name (ccache, io_reply_data);
+ }
+ } else {
+ err = krb5int_ipc_stream_write_string (io_reply_data,
+ k_cci_context_initial_ccache_name);
+ }
+ }
+
+ return cci_check_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+static cc_int32 ccs_cache_collection_open_ccache (ccs_cache_collection_t io_cache_collection,
+ k5_ipc_stream in_request_data,
+ k5_ipc_stream io_reply_data)
+{
+ cc_int32 err = ccNoError;
+ char *name = NULL;
+ ccs_ccache_t ccache = NULL;
+
+ if (!io_cache_collection) { err = cci_check_error (ccErrBadParam); }
+ if (!in_request_data ) { err = cci_check_error (ccErrBadParam); }
+ if (!io_reply_data ) { err = cci_check_error (ccErrBadParam); }
+
+ if (!err) {
+ err = krb5int_ipc_stream_read_string (in_request_data, &name);
+ }
+
+ if (!err) {
+ err = ccs_cache_collection_find_ccache_by_name (io_cache_collection,
+ name, &ccache);
+ }
+
+ if (!err) {
+ err = ccs_ccache_write (ccache, io_reply_data);
+ }
+
+ krb5int_ipc_stream_free_string (name);
+
+ return cci_check_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+static cc_int32 ccs_cache_collection_open_default_ccache (ccs_cache_collection_t io_cache_collection,
+ k5_ipc_stream in_request_data,
+ k5_ipc_stream io_reply_data)
+{
+ cc_int32 err = ccNoError;
+ ccs_ccache_t ccache = NULL;
+
+ if (!io_cache_collection) { err = cci_check_error (ccErrBadParam); }
+ if (!in_request_data ) { err = cci_check_error (ccErrBadParam); }
+ if (!io_reply_data ) { err = cci_check_error (ccErrBadParam); }
+
+ if (!err) {
+ err = ccs_cache_collection_get_default_ccache (io_cache_collection,
+ &ccache);
+ }
+
+ if (!err) {
+ err = ccs_ccache_write (ccache, io_reply_data);
+ }
+
+ return cci_check_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+static cc_int32 ccs_cache_collection_create_ccache (ccs_cache_collection_t io_cache_collection,
+ k5_ipc_stream in_request_data,
+ k5_ipc_stream io_reply_data)
+{
+ cc_int32 err = ccNoError;
+ char *name = NULL;
+ cc_uint32 cred_vers;
+ char *principal = NULL;
+ ccs_ccache_t ccache = NULL;
+
+ if (!io_cache_collection) { err = cci_check_error (ccErrBadParam); }
+ if (!in_request_data ) { err = cci_check_error (ccErrBadParam); }
+ if (!io_reply_data ) { err = cci_check_error (ccErrBadParam); }
+
+ if (!err) {
+ err = krb5int_ipc_stream_read_string (in_request_data, &name);
+ }
+
+ if (!err) {
+ err = krb5int_ipc_stream_read_uint32 (in_request_data, &cred_vers);
+ }
+
+ if (!err) {
+ err = krb5int_ipc_stream_read_string (in_request_data, &principal);
+ }
+
+ if (!err) {
+ cc_int32 terr = ccs_cache_collection_find_ccache_by_name (io_cache_collection,
+ name,
+ &ccache);
+
+ if (!terr) {
+ err = ccs_ccache_reset (ccache, io_cache_collection, cred_vers, principal);
+
+ } else {
+ err = ccs_ccache_new (&ccache, cred_vers, name, principal,
+ io_cache_collection->ccaches);
+ }
+ }
+
+ if (!err) {
+ err = ccs_ccache_write (ccache, io_reply_data);
+ }
+
+ if (!err) {
+ err = ccs_cache_collection_changed (io_cache_collection);
+ }
+
+ krb5int_ipc_stream_free_string (name);
+ krb5int_ipc_stream_free_string (principal);
+
+ return cci_check_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+static cc_int32 ccs_cache_collection_create_default_ccache (ccs_cache_collection_t io_cache_collection,
+ k5_ipc_stream in_request_data,
+ k5_ipc_stream io_reply_data)
+{
+ cc_int32 err = ccNoError;
+ cc_uint32 cred_vers;
+ char *principal = NULL;
+ ccs_ccache_t ccache = NULL;
+
+ if (!io_cache_collection) { err = cci_check_error (ccErrBadParam); }
+ if (!in_request_data ) { err = cci_check_error (ccErrBadParam); }
+ if (!io_reply_data ) { err = cci_check_error (ccErrBadParam); }
+
+ if (!err) {
+ err = krb5int_ipc_stream_read_uint32 (in_request_data, &cred_vers);
+ }
+
+ if (!err) {
+ err = krb5int_ipc_stream_read_string (in_request_data, &principal);
+ }
+
+ if (!err) {
+ err = ccs_cache_collection_get_default_ccache (io_cache_collection,
+ &ccache);
+
+ if (!err) {
+ err = ccs_ccache_reset (ccache, io_cache_collection, cred_vers, principal);
+
+ } else if (err == ccErrCCacheNotFound) {
+ char *name = NULL;
+
+ err = ccs_cache_collection_get_next_unique_ccache_name (io_cache_collection,
+ &name);
+
+ if (!err) {
+ err = ccs_ccache_new (&ccache, cred_vers, name, principal,
+ io_cache_collection->ccaches);
+ }
+
+ free (name);
+ }
+ }
+
+ if (!err) {
+ err = ccs_ccache_write (ccache, io_reply_data);
+ }
+
+ if (!err) {
+ err = ccs_cache_collection_changed (io_cache_collection);
+ }
+
+ krb5int_ipc_stream_free_string (principal);
+
+ return cci_check_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+static cc_int32 ccs_cache_collection_create_new_ccache (ccs_cache_collection_t io_cache_collection,
+ k5_ipc_stream in_request_data,
+ k5_ipc_stream io_reply_data)
+{
+ cc_int32 err = ccNoError;
+ cc_uint32 cred_vers;
+ char *principal = NULL;
+ char *name = NULL;
+ ccs_ccache_t ccache = NULL;
+
+ if (!io_cache_collection) { err = cci_check_error (ccErrBadParam); }
+ if (!in_request_data ) { err = cci_check_error (ccErrBadParam); }
+ if (!io_reply_data ) { err = cci_check_error (ccErrBadParam); }
+
+ if (!err) {
+ err = krb5int_ipc_stream_read_uint32 (in_request_data, &cred_vers);
+ }
+
+ if (!err) {
+ err = krb5int_ipc_stream_read_string (in_request_data, &principal);
+ }
+
+ if (!err) {
+ err = ccs_cache_collection_get_next_unique_ccache_name (io_cache_collection,
+ &name);
+ }
+
+ if (!err) {
+ err = ccs_ccache_new (&ccache, cred_vers, name, principal,
+ io_cache_collection->ccaches);
+ }
+
+ if (!err) {
+ err = ccs_ccache_write (ccache, io_reply_data);
+ }
+
+ if (!err) {
+ err = ccs_cache_collection_changed (io_cache_collection);
+ }
+
+ free (name);
+ krb5int_ipc_stream_free_string (principal);
+
+ return cci_check_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+static cc_int32 ccs_cache_collection_new_ccache_iterator (ccs_cache_collection_t io_cache_collection,
+ ccs_pipe_t in_client_pipe,
+ k5_ipc_stream in_request_data,
+ k5_ipc_stream io_reply_data)
+{
+ cc_int32 err = ccNoError;
+ ccs_ccache_iterator_t ccache_iterator = NULL;
+
+ if (!io_cache_collection) { err = cci_check_error (ccErrBadParam); }
+ if (!in_request_data ) { err = cci_check_error (ccErrBadParam); }
+ if (!io_reply_data ) { err = cci_check_error (ccErrBadParam); }
+
+ if (!err) {
+ err = ccs_ccache_list_new_iterator (io_cache_collection->ccaches,
+ in_client_pipe,
+ &ccache_iterator);
+ }
+
+ if (!err) {
+ err = ccs_ccache_list_iterator_write (ccache_iterator, io_reply_data);
+ }
+
+ return cci_check_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+static cc_int32 ccs_cache_collection_lock (ccs_pipe_t in_client_pipe,
+ ccs_pipe_t in_reply_pipe,
+ ccs_cache_collection_t io_cache_collection,
+ k5_ipc_stream in_request_data,
+ cc_uint32 *out_will_block,
+ k5_ipc_stream io_reply_data)
+{
+ cc_int32 err = ccNoError;
+ cc_uint32 lock_type;
+ cc_uint32 block;
+
+ if (!ccs_pipe_valid (in_client_pipe)) { err = cci_check_error (ccErrBadParam); }
+ if (!io_cache_collection ) { err = cci_check_error (ccErrBadParam); }
+ if (!in_request_data ) { err = cci_check_error (ccErrBadParam); }
+ if (!out_will_block ) { err = cci_check_error (ccErrBadParam); }
+ if (!io_reply_data ) { err = cci_check_error (ccErrBadParam); }
+
+ if (!err) {
+ err = krb5int_ipc_stream_read_uint32 (in_request_data, &lock_type);
+ }
+
+ if (!err) {
+ err = krb5int_ipc_stream_read_uint32 (in_request_data, &block);
+ }
+
+ if (!err) {
+ err = ccs_lock_state_add (io_cache_collection->lock_state,
+ in_client_pipe, in_reply_pipe,
+ lock_type, block, out_will_block);
+ }
+
+ return cci_check_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+static cc_int32 ccs_cache_collection_unlock (ccs_pipe_t in_client_pipe,
+ ccs_cache_collection_t io_cache_collection,
+ k5_ipc_stream in_request_data,
+ k5_ipc_stream io_reply_data)
+{
+ cc_int32 err = ccNoError;
+
+ if (!ccs_pipe_valid (in_client_pipe)) { err = cci_check_error (ccErrBadParam); }
+ if (!io_cache_collection ) { err = cci_check_error (ccErrBadParam); }
+ if (!in_request_data ) { err = cci_check_error (ccErrBadParam); }
+ if (!io_reply_data ) { err = cci_check_error (ccErrBadParam); }
+
+ if (!err) {
+ err = ccs_lock_state_remove (io_cache_collection->lock_state,
+ in_client_pipe);
+ }
+
+ return cci_check_error (err);
+}
+
+#ifdef TARGET_OS_MAC
+#pragma mark -
+#endif
+
+/* ------------------------------------------------------------------------ */
+
+ cc_int32 ccs_cache_collection_handle_message (ccs_pipe_t in_client_pipe,
+ ccs_pipe_t in_reply_pipe,
+ ccs_cache_collection_t io_cache_collection,
+ enum cci_msg_id_t in_request_name,
+ k5_ipc_stream in_request_data,
+ cc_uint32 *out_will_block,
+ k5_ipc_stream *out_reply_data)
+{
+ cc_int32 err = ccNoError;
+ cc_uint32 will_block = 0;
+ k5_ipc_stream reply_data = NULL;
+
+ if (!ccs_pipe_valid (in_client_pipe)) { err = cci_check_error (ccErrBadParam); }
+ if (!ccs_pipe_valid (in_reply_pipe) ) { err = cci_check_error (ccErrBadParam); }
+ if (!io_cache_collection ) { err = cci_check_error (ccErrBadParam); }
+ if (!in_request_data ) { err = cci_check_error (ccErrBadParam); }
+ if (!out_will_block ) { err = cci_check_error (ccErrBadParam); }
+ if (!out_reply_data ) { err = cci_check_error (ccErrBadParam); }
+
+ if (!err) {
+ err = krb5int_ipc_stream_new (&reply_data);
+ }
+
+ if (!err) {
+ if (in_request_name == cci_context_unused_release_msg_id) {
+ /* Old release message. Do nothing. */
+
+ } else if (in_request_name == cci_context_sync_msg_id) {
+ err = ccs_cache_collection_sync (io_cache_collection,
+ in_request_data, reply_data);
+
+ } else if (in_request_name == cci_context_get_change_time_msg_id) {
+ err = ccs_cache_collection_get_change_time (io_cache_collection,
+ in_request_data, reply_data);
+
+ } else if (in_request_name == cci_context_wait_for_change_msg_id) {
+ err = ccs_cache_collection_wait_for_change (in_client_pipe, in_reply_pipe,
+ io_cache_collection,
+ in_request_data, reply_data,
+ &will_block);
+
+ } else if (in_request_name == cci_context_get_default_ccache_name_msg_id) {
+ err = ccs_cache_collection_get_default_ccache_name (io_cache_collection,
+ in_request_data, reply_data);
+
+ } else if (in_request_name == cci_context_open_ccache_msg_id) {
+ err = ccs_cache_collection_open_ccache (io_cache_collection,
+ in_request_data, reply_data);
+
+ } else if (in_request_name == cci_context_open_default_ccache_msg_id) {
+ err = ccs_cache_collection_open_default_ccache (io_cache_collection,
+ in_request_data, reply_data);
+
+ } else if (in_request_name == cci_context_create_ccache_msg_id) {
+ err = ccs_cache_collection_create_ccache (io_cache_collection,
+ in_request_data, reply_data);
+
+ } else if (in_request_name == cci_context_create_default_ccache_msg_id) {
+ err = ccs_cache_collection_create_default_ccache (io_cache_collection,
+ in_request_data, reply_data);
+
+ } else if (in_request_name == cci_context_create_new_ccache_msg_id) {
+ err = ccs_cache_collection_create_new_ccache (io_cache_collection,
+ in_request_data, reply_data);
+
+ } else if (in_request_name == cci_context_new_ccache_iterator_msg_id) {
+ err = ccs_cache_collection_new_ccache_iterator (io_cache_collection,
+ in_client_pipe,
+ in_request_data,
+ reply_data);
+
+ } else if (in_request_name == cci_context_lock_msg_id) {
+ err = ccs_cache_collection_lock (in_client_pipe, in_reply_pipe,
+ io_cache_collection,
+ in_request_data,
+ &will_block, reply_data);
+
+ } else if (in_request_name == cci_context_unlock_msg_id) {
+ err = ccs_cache_collection_unlock (in_client_pipe, io_cache_collection,
+ in_request_data, reply_data);
+
+ } else {
+ err = ccErrBadInternalMessage;
+ }
+ }
+
+ if (!err) {
+ *out_will_block = will_block;
+ if (!will_block) {
+ *out_reply_data = reply_data;
+ reply_data = NULL; /* take ownership */
+ } else {
+ *out_reply_data = NULL;
+ }
+ }
+
+ krb5int_ipc_stream_release (reply_data);
+
+ return cci_check_error (err);
+}
diff --git a/src/ccapi/server/ccs_cache_collection.h b/src/ccapi/server/ccs_cache_collection.h
new file mode 100644
index 000000000000..37f7633a38be
--- /dev/null
+++ b/src/ccapi/server/ccs_cache_collection.h
@@ -0,0 +1,72 @@
+/* ccapi/server/ccs_cache_collection.h */
+/*
+ * Copyright 2006 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 M.I.T. 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.
+ */
+
+#ifndef CCS_CACHE_COLLECTION_H
+#define CCS_CACHE_COLLECTION_H
+
+#include "ccs_types.h"
+
+cc_int32 ccs_cache_collection_new (ccs_cache_collection_t *out_cache_collection);
+
+cc_int32 ccs_cache_collection_release (ccs_cache_collection_t io_cache_collection);
+
+cc_int32 ccs_cache_collection_compare_identifier (ccs_cache_collection_t in_cache_collection,
+ cci_identifier_t in_identifier,
+ cc_uint32 *out_equal);
+
+cc_int32 ccs_cache_collection_changed (ccs_cache_collection_t io_cache_collection);
+
+cc_int32 ccs_cache_collection_set_default_ccache (ccs_cache_collection_t in_cache_collection,
+ cci_identifier_t in_identifier);
+
+cc_int32 ccs_cache_collection_find_ccache (ccs_cache_collection_t in_cache_collection,
+ cci_identifier_t in_identifier,
+ ccs_ccache_t *out_ccache);
+
+cc_int32 ccs_ccache_collection_move_ccache (ccs_cache_collection_t io_cache_collection,
+ cci_identifier_t in_source_identifier,
+ ccs_ccache_t io_destination_ccache);
+
+cc_int32 ccs_cache_collection_destroy_ccache (ccs_cache_collection_t in_cache_collection,
+ cci_identifier_t in_identifier);
+
+cc_int32 ccs_cache_collection_find_ccache_iterator (ccs_cache_collection_t in_cache_collection,
+ cci_identifier_t in_identifier,
+ ccs_ccache_iterator_t *out_ccache_iterator);
+
+cc_int32 ccs_cache_collection_find_credentials_iterator (ccs_cache_collection_t in_cache_collection,
+ cci_identifier_t in_identifier,
+ ccs_ccache_t *out_ccache,
+ ccs_credentials_iterator_t *out_credentials_iterator);
+
+cc_int32 ccs_cache_collection_handle_message (ccs_pipe_t in_client_pipe,
+ ccs_pipe_t in_reply_pipe,
+ ccs_cache_collection_t io_cache_collection,
+ enum cci_msg_id_t in_request_name,
+ k5_ipc_stream in_request_data,
+ cc_uint32 *out_will_block,
+ k5_ipc_stream *out_reply_data);
+
+#endif /* CCS_CACHE_COLLECTION_H */
diff --git a/src/ccapi/server/ccs_callback.c b/src/ccapi/server/ccs_callback.c
new file mode 100644
index 000000000000..d758acb1528f
--- /dev/null
+++ b/src/ccapi/server/ccs_callback.c
@@ -0,0 +1,238 @@
+/* ccapi/server/ccs_callback.c */
+/*
+ * Copyright 2006 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 M.I.T. 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.
+ */
+
+#include "ccs_common.h"
+
+struct ccs_callback_d {
+ cc_int32 pending;
+ cc_int32 invalid_object_err;
+ ccs_pipe_t client_pipe;
+ ccs_pipe_t reply_pipe;
+ ccs_callback_owner_t owner; /* pointer to owner */
+ ccs_callback_owner_invalidate_t owner_invalidate;
+};
+
+struct ccs_callback_d ccs_callback_initializer = { 1, 1, CCS_PIPE_NULL, CCS_PIPE_NULL, NULL, NULL };
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 ccs_callback_new (ccs_callback_t *out_callback,
+ cc_int32 in_invalid_object_err,
+ ccs_pipe_t in_client_pipe,
+ ccs_pipe_t in_reply_pipe,
+ ccs_callback_owner_t in_owner,
+ ccs_callback_owner_invalidate_t in_owner_invalidate_function)
+{
+ cc_int32 err = ccNoError;
+ ccs_callback_t callback = NULL;
+ ccs_client_t client = NULL;
+
+ if (!out_callback ) { err = cci_check_error (ccErrBadParam); }
+ if (!ccs_pipe_valid (in_client_pipe)) { err = cci_check_error (ccErrBadParam); }
+ if (!ccs_pipe_valid (in_reply_pipe) ) { err = cci_check_error (ccErrBadParam); }
+ if (!in_owner ) { err = cci_check_error (ccErrBadParam); }
+ if (!in_owner_invalidate_function ) { err = cci_check_error (ccErrBadParam); }
+
+ if (!err) {
+ callback = malloc (sizeof (*callback));
+ if (callback) {
+ *callback = ccs_callback_initializer;
+ } else {
+ err = cci_check_error (ccErrNoMem);
+ }
+ }
+
+ if (!err) {
+ err = ccs_server_client_for_pipe (in_client_pipe, &client);
+ }
+
+ if (!err) {
+ err = ccs_pipe_copy (&callback->client_pipe, in_client_pipe);
+ }
+
+ if (!err) {
+ err = ccs_pipe_copy (&callback->reply_pipe, in_reply_pipe);
+ }
+
+ if (!err) {
+ callback->client_pipe = in_client_pipe;
+ callback->reply_pipe = in_reply_pipe;
+ callback->invalid_object_err = in_invalid_object_err;
+ callback->owner = in_owner;
+ callback->owner_invalidate = in_owner_invalidate_function;
+
+ err = ccs_client_add_callback (client, callback);
+ }
+
+ if (!err) {
+ *out_callback = callback;
+ callback = NULL;
+ }
+
+ ccs_callback_release (callback);
+
+ return cci_check_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 ccs_callback_release (ccs_callback_t io_callback)
+{
+ cc_int32 err = ccNoError;
+
+ if (!err && io_callback) {
+ ccs_client_t client = NULL;
+
+ if (io_callback->pending) {
+ err = ccs_server_send_reply (io_callback->reply_pipe,
+ io_callback->invalid_object_err, NULL);
+
+ io_callback->pending = 0;
+ }
+
+ if (!err) {
+ err = ccs_server_client_for_pipe (io_callback->client_pipe, &client);
+ }
+
+ if (!err && client) {
+ /* if client object still has a reference to us, remove it */
+ err = ccs_client_remove_callback (client, io_callback);
+ }
+
+ if (!err) {
+ ccs_pipe_release (io_callback->client_pipe);
+ ccs_pipe_release (io_callback->reply_pipe);
+ free (io_callback);
+ }
+ }
+
+ return cci_check_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 ccs_callback_invalidate (ccs_callback_t io_callback)
+{
+ cc_int32 err = ccNoError;
+
+ if (!io_callback) { err = cci_check_error (ccErrBadParam); }
+
+ if (!err) {
+ io_callback->pending = 0; /* client is dead, don't try to talk to it */
+ if (io_callback->owner_invalidate) {
+ err = io_callback->owner_invalidate (io_callback->owner, io_callback);
+ } else {
+ cci_debug_printf ("WARNING %s() unable to notify callback owner!",
+ __FUNCTION__);
+ }
+ }
+
+ return cci_check_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 ccs_callback_reply_to_client (ccs_callback_t io_callback,
+ k5_ipc_stream in_stream)
+{
+ cc_int32 err = ccNoError;
+
+ if (!io_callback) { err = cci_check_error (ccErrBadParam); }
+
+ if (!err) {
+ if (io_callback->pending) {
+ cci_debug_printf ("%s: callback %p replying to client.", __FUNCTION__, io_callback);
+
+ err = ccs_server_send_reply (io_callback->reply_pipe, err, in_stream);
+
+ if (err) {
+ cci_debug_printf ("WARNING %s() called on a lock belonging to a dead client!",
+ __FUNCTION__);
+ }
+
+ io_callback->pending = 0;
+ } else {
+ cci_debug_printf ("WARNING %s() called on non-pending callback!",
+ __FUNCTION__);
+ }
+ }
+
+ return cci_check_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_uint32 ccs_callback_is_pending (ccs_callback_t in_callback,
+ cc_uint32 *out_pending)
+{
+ cc_int32 err = ccNoError;
+
+ if (!in_callback) { err = cci_check_error (ccErrBadParam); }
+ if (!out_pending) { err = cci_check_error (ccErrBadParam); }
+
+ if (!err) {
+ *out_pending = in_callback->pending;
+ }
+
+ return cci_check_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 ccs_callback_is_for_client_pipe (ccs_callback_t in_callback,
+ ccs_pipe_t in_client_pipe,
+ cc_uint32 *out_is_for_client_pipe)
+{
+ cc_int32 err = ccNoError;
+
+ if (!in_callback ) { err = cci_check_error (ccErrBadParam); }
+ if (!ccs_pipe_valid (in_client_pipe)) { err = cci_check_error (ccErrBadParam); }
+ if (!out_is_for_client_pipe ) { err = cci_check_error (ccErrBadParam); }
+
+ if (!err) {
+ err = ccs_pipe_compare (in_callback->client_pipe, in_client_pipe,
+ out_is_for_client_pipe);
+ }
+
+ return cci_check_error (err);
+}
+
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 ccs_callback_client_pipe (ccs_callback_t in_callback,
+ ccs_pipe_t *out_client_pipe)
+{
+ cc_int32 err = ccNoError;
+
+ if (!in_callback ) { err = cci_check_error (ccErrBadParam); }
+ if (!out_client_pipe) { err = cci_check_error (ccErrBadParam); }
+
+ if (!err) {
+ *out_client_pipe = in_callback->client_pipe;
+ }
+
+ return cci_check_error (err);
+}
diff --git a/src/ccapi/server/ccs_callback.h b/src/ccapi/server/ccs_callback.h
new file mode 100644
index 000000000000..30c2228010a7
--- /dev/null
+++ b/src/ccapi/server/ccs_callback.h
@@ -0,0 +1,61 @@
+/* ccapi/server/ccs_callback.h */
+/*
+ * Copyright 2006 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 M.I.T. 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.
+ */
+
+#ifndef CCS_CALLBACK_H
+#define CCS_CALLBACK_H
+
+#include "ccs_types.h"
+
+struct ccs_callback_owner_d;
+typedef struct ccs_callback_owner_d *ccs_callback_owner_t;
+
+typedef cc_int32 (*ccs_callback_owner_invalidate_t) (ccs_callback_owner_t, ccs_callback_t);
+
+
+cc_int32 ccs_callback_new (ccs_callback_t *out_callback,
+ cc_int32 in_invalid_object_err,
+ ccs_pipe_t in_client_pipe,
+ ccs_pipe_t in_reply_pipe,
+ ccs_callback_owner_t in_owner,
+ ccs_callback_owner_invalidate_t in_owner_invalidate_function);
+
+cc_int32 ccs_callback_release (ccs_callback_t io_callback);
+
+cc_int32 ccs_callback_invalidate (ccs_callback_t io_callback);
+
+cc_int32 ccs_callback_reply_to_client (ccs_callback_t io_callback,
+ k5_ipc_stream in_stream);
+
+cc_uint32 ccs_callback_is_pending (ccs_callback_t in_callback,
+ cc_uint32 *out_pending);
+
+cc_int32 ccs_callback_is_for_client_pipe (ccs_callback_t in_callback,
+ ccs_pipe_t in_client_pipe,
+ cc_uint32 *out_is_for_client_pipe);
+
+cc_int32 ccs_callback_client_pipe (ccs_callback_t in_callback,
+ ccs_pipe_t *out_client_pipe);
+
+#endif /* CCS_CALLBACK_H */
diff --git a/src/ccapi/server/ccs_ccache.c b/src/ccapi/server/ccs_ccache.c
new file mode 100644
index 000000000000..65c59e4be8e6
--- /dev/null
+++ b/src/ccapi/server/ccs_ccache.c
@@ -0,0 +1,1236 @@
+/* ccapi/server/ccs_ccache.c */
+/*
+ * Copyright 2006, 2007 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 M.I.T. 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.
+ */
+
+#include "ccs_common.h"
+#include "ccs_os_notify.h"
+
+struct ccs_ccache_d {
+ cci_identifier_t identifier;
+ ccs_lock_state_t lock_state;
+ cc_uint32 creds_version;
+ char *name;
+ char *v4_principal;
+ char *v5_principal;
+ cc_time_t last_default_time;
+ cc_time_t last_changed_time;
+ cc_uint32 kdc_time_offset_v4_valid;
+ cc_time_t kdc_time_offset_v4;
+ cc_uint32 kdc_time_offset_v5_valid;
+ cc_time_t kdc_time_offset_v5;
+ ccs_credentials_list_t credentials;
+ ccs_callback_array_t change_callbacks;
+};
+
+struct ccs_ccache_d ccs_ccache_initializer = { NULL, NULL, 0, NULL, NULL, NULL, 0, 0, 0, 0, 0, 0, NULL, NULL };
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 ccs_ccache_new (ccs_ccache_t *out_ccache,
+ cc_uint32 in_creds_version,
+ const char *in_name,
+ const char *in_principal,
+ ccs_ccache_list_t io_ccache_list)
+{
+ cc_int32 err = ccNoError;
+ ccs_ccache_t ccache = NULL;
+
+ if (!out_ccache ) { err = cci_check_error (ccErrBadParam); }
+ if (!in_name ) { err = cci_check_error (ccErrBadParam); }
+ if (!in_principal) { err = cci_check_error (ccErrBadParam); }
+
+ if (!err) {
+ ccache = malloc (sizeof (*ccache));
+ if (ccache) {
+ *ccache = ccs_ccache_initializer;
+ } else {
+ err = cci_check_error (ccErrNoMem);
+ }
+ }
+
+ if (!err) {
+ err = ccs_server_new_identifier (&ccache->identifier);
+ }
+
+ if (!err) {
+ err = ccs_lock_state_new (&ccache->lock_state,
+ ccErrInvalidCCache,
+ ccErrCCacheLocked,
+ ccErrCCacheUnlocked);
+ }
+
+ if (!err) {
+ ccache->name = strdup (in_name);
+ if (!ccache->name) { err = cci_check_error (ccErrNoMem); }
+ }
+
+ if (!err) {
+ ccache->creds_version = in_creds_version;
+
+ if (ccache->creds_version == cc_credentials_v4) {
+ ccache->v4_principal = strdup (in_principal);
+ if (!ccache->v4_principal) { err = cci_check_error (ccErrNoMem); }
+
+ } else if (ccache->creds_version == cc_credentials_v5) {
+ ccache->v5_principal = strdup (in_principal);
+ if (!ccache->v5_principal) { err = cci_check_error (ccErrNoMem); }
+
+ } else {
+ err = cci_check_error (ccErrBadCredentialsVersion);
+ }
+ }
+
+ if (!err) {
+ err = ccs_credentials_list_new (&ccache->credentials);
+ }
+
+ if (!err) {
+ err = ccs_callback_array_new (&ccache->change_callbacks);
+ }
+
+ if (!err) {
+ cc_uint64 now = time (NULL);
+ cc_uint64 count = 0;
+
+ err = ccs_ccache_list_count (io_ccache_list, &count);
+
+ if (!err) {
+ /* first cache is default */
+ ccache->last_default_time = (count == 0) ? now : 0;
+ cci_debug_printf ("%s ccache->last_default_time is %d.",
+ __FUNCTION__, ccache->last_default_time);
+ ccache->last_changed_time = now;
+ }
+ }
+
+ if (!err) {
+ /* Add self to the list of ccaches */
+ err = ccs_ccache_list_add (io_ccache_list, ccache);
+ }
+
+ if (!err) {
+ *out_ccache = ccache;
+ ccache = NULL;
+ }
+
+ ccs_ccache_release (ccache);
+
+ return cci_check_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 ccs_ccache_reset (ccs_ccache_t io_ccache,
+ ccs_cache_collection_t io_cache_collection,
+ cc_uint32 in_creds_version,
+ const char *in_principal)
+{
+ cc_int32 err = ccNoError;
+ char *v4_principal = NULL;
+ char *v5_principal = NULL;
+ ccs_credentials_list_t credentials = NULL;
+
+ if (!io_ccache ) { err = cci_check_error (ccErrBadParam); }
+ if (!io_cache_collection) { err = cci_check_error (ccErrBadParam); }
+ if (!in_principal ) { err = cci_check_error (ccErrBadParam); }
+
+ if (!err) {
+ io_ccache->creds_version = in_creds_version;
+
+ if (io_ccache->creds_version == cc_credentials_v4) {
+ v4_principal = strdup (in_principal);
+ if (!v4_principal) { err = cci_check_error (ccErrNoMem); }
+
+ } else if (io_ccache->creds_version == cc_credentials_v5) {
+ v5_principal = strdup (in_principal);
+ if (!v5_principal) { err = cci_check_error (ccErrNoMem); }
+
+ } else {
+ err = cci_check_error (ccErrBadCredentialsVersion);
+ }
+ }
+
+ if (!err) {
+ err = ccs_credentials_list_new (&credentials);
+ }
+
+ if (!err) {
+ io_ccache->kdc_time_offset_v4 = 0;
+ io_ccache->kdc_time_offset_v4_valid = 0;
+ io_ccache->kdc_time_offset_v5 = 0;
+ io_ccache->kdc_time_offset_v5_valid = 0;
+
+ if (io_ccache->v4_principal) { free (io_ccache->v4_principal); }
+ io_ccache->v4_principal = v4_principal;
+ v4_principal = NULL; /* take ownership */
+
+ if (io_ccache->v5_principal) { free (io_ccache->v5_principal); }
+ io_ccache->v5_principal = v5_principal;
+ v5_principal = NULL; /* take ownership */
+
+ ccs_credentials_list_release (io_ccache->credentials);
+ io_ccache->credentials = credentials;
+ credentials = NULL; /* take ownership */
+
+ err = ccs_ccache_changed (io_ccache, io_cache_collection);
+ }
+
+ free (v4_principal);
+ free (v5_principal);
+ ccs_credentials_list_release (credentials);
+
+ return cci_check_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 ccs_ccache_swap_contents (ccs_ccache_t io_source_ccache,
+ ccs_ccache_t io_destination_ccache,
+ ccs_cache_collection_t io_cache_collection)
+{
+ cc_int32 err = ccNoError;
+
+ if (!io_source_ccache ) { err = cci_check_error (ccErrBadParam); }
+ if (!io_destination_ccache) { err = cci_check_error (ccErrBadParam); }
+
+ if (!err) {
+ struct ccs_ccache_d temp_ccache = *io_destination_ccache;
+
+ /* swap everything */
+ *io_destination_ccache = *io_source_ccache;
+ *io_source_ccache = temp_ccache;
+
+ /* swap back the name and identifier */
+ io_source_ccache->identifier = io_destination_ccache->identifier;
+ io_destination_ccache->identifier = temp_ccache.identifier;
+
+ io_source_ccache->name = io_destination_ccache->name;
+ io_destination_ccache->name = temp_ccache.name;
+ }
+
+ if (!err) {
+ err = ccs_ccache_changed (io_source_ccache, io_cache_collection);
+ }
+
+ if (!err) {
+ err = ccs_ccache_changed (io_destination_ccache, io_cache_collection);
+ }
+
+ return cci_check_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 ccs_ccache_release (ccs_ccache_t io_ccache)
+{
+ cc_int32 err = ccNoError;
+
+ if (!err && io_ccache) {
+ cci_identifier_release (io_ccache->identifier);
+ ccs_lock_state_release (io_ccache->lock_state);
+ free (io_ccache->name);
+ free (io_ccache->v4_principal);
+ free (io_ccache->v5_principal);
+ ccs_credentials_list_release (io_ccache->credentials);
+ ccs_callback_array_release (io_ccache->change_callbacks);
+ free (io_ccache);
+ }
+
+ return cci_check_error (err);
+}
+
+#ifdef TARGET_OS_MAC
+#pragma mark -
+#endif
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 ccs_ccache_compare_identifier (ccs_ccache_t in_ccache,
+ cci_identifier_t in_identifier,
+ cc_uint32 *out_equal)
+{
+ cc_int32 err = ccNoError;
+
+ if (!in_ccache ) { err = cci_check_error (ccErrBadParam); }
+ if (!in_identifier) { err = cci_check_error (ccErrBadParam); }
+ if (!out_equal ) { err = cci_check_error (ccErrBadParam); }
+
+ if (!err) {
+ err = cci_identifier_compare (in_ccache->identifier,
+ in_identifier,
+ out_equal);
+ }
+
+ return cci_check_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 ccs_ccache_compare_name (ccs_ccache_t in_ccache,
+ const char *in_name,
+ cc_uint32 *out_equal)
+{
+ cc_int32 err = ccNoError;
+
+ if (!in_ccache) { err = cci_check_error (ccErrBadParam); }
+ if (!in_name ) { err = cci_check_error (ccErrBadParam); }
+ if (!out_equal) { err = cci_check_error (ccErrBadParam); }
+
+ if (!err) {
+ *out_equal = (strcmp (in_ccache->name, in_name) == 0);
+ }
+
+ return cci_check_error (err);
+}
+
+#ifdef TARGET_OS_MAC
+#pragma mark -
+#endif
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 ccs_ccache_changed (ccs_ccache_t io_ccache,
+ ccs_cache_collection_t io_cache_collection)
+{
+ cc_int32 err = ccNoError;
+ k5_ipc_stream reply_data = NULL;
+
+ if (!io_ccache ) { err = cci_check_error (ccErrBadParam); }
+ if (!io_cache_collection) { err = cci_check_error (ccErrBadParam); }
+
+ if (!err) {
+ cc_time_t now = time (NULL);
+
+ if (io_ccache->last_changed_time < now) {
+ io_ccache->last_changed_time = now;
+ } else {
+ io_ccache->last_changed_time++;
+ }
+ }
+
+ if (!err) {
+ err = ccs_cache_collection_changed (io_cache_collection);
+ }
+
+ if (!err) {
+ err = krb5int_ipc_stream_new (&reply_data);
+ }
+
+ if (!err) {
+ err = krb5int_ipc_stream_write_time (reply_data, io_ccache->last_changed_time);
+ }
+
+ if (!err) {
+ /* Loop over callbacks sending messages to them */
+ cc_uint64 i;
+ cc_uint64 count = ccs_callback_array_count (io_ccache->change_callbacks);
+
+ for (i = 0; !err && i < count; i++) {
+ ccs_callback_t callback = ccs_callback_array_object_at_index (io_ccache->change_callbacks, i);
+
+ err = ccs_callback_reply_to_client (callback, reply_data);
+
+ if (!err) {
+ cci_debug_printf ("%s: Removing callback reference %p.", __FUNCTION__, callback);
+ err = ccs_callback_array_remove (io_ccache->change_callbacks, i);
+ break;
+ }
+ }
+ }
+
+ if (!err) {
+ err = ccs_os_notify_ccache_changed (io_cache_collection,
+ io_ccache->name);
+ }
+
+ krb5int_ipc_stream_release (reply_data);
+
+ return cci_check_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+static cc_int32 ccs_ccache_invalidate_change_callback (ccs_callback_owner_t io_ccache,
+ ccs_callback_t in_callback)
+{
+ cc_int32 err = ccNoError;
+
+ if (!io_ccache ) { err = cci_check_error (ccErrBadParam); }
+ if (!in_callback) { err = cci_check_error (ccErrBadParam); }
+
+ if (!err) {
+ /* Remove callback */
+ ccs_ccache_t ccache = (ccs_ccache_t) io_ccache;
+ cc_uint64 i;
+ cc_uint64 count = ccs_callback_array_count (ccache->change_callbacks);
+
+ for (i = 0; !err && i < count; i++) {
+ ccs_callback_t callback = ccs_callback_array_object_at_index (ccache->change_callbacks, i);
+
+ if (callback == in_callback) {
+ cci_debug_printf ("%s: Removing callback reference %p.", __FUNCTION__, callback);
+ err = ccs_callback_array_remove (ccache->change_callbacks, i);
+ break;
+ }
+ }
+ }
+
+ return cci_check_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 ccs_ccache_notify_default_state_changed (ccs_ccache_t io_ccache,
+ ccs_cache_collection_t io_cache_collection,
+ cc_uint32 in_new_default_state)
+{
+ cc_int32 err = ccNoError;
+
+ if (!io_ccache ) { err = cci_check_error (ccErrBadParam); }
+ if (!io_cache_collection) { err = cci_check_error (ccErrBadParam); }
+
+ if (!err && in_new_default_state) {
+ cc_time_t now = time (NULL);
+
+ if (io_ccache->last_default_time < now) {
+ io_ccache->last_default_time = now;
+ } else {
+ io_ccache->last_default_time++;
+ }
+ }
+
+ if (!err) {
+ err = ccs_ccache_changed (io_ccache, io_cache_collection);
+ }
+
+ return cci_check_error (err);
+}
+
+#ifdef TARGET_OS_MAC
+#pragma mark -
+#endif
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 ccs_ccache_find_credentials_iterator (ccs_ccache_t in_ccache,
+ cci_identifier_t in_identifier,
+ ccs_credentials_iterator_t *out_credentials_iterator)
+{
+ cc_int32 err = ccNoError;
+
+ if (!in_ccache ) { err = cci_check_error (ccErrBadParam); }
+ if (!in_identifier ) { err = cci_check_error (ccErrBadParam); }
+ if (!out_credentials_iterator) { err = cci_check_error (ccErrBadParam); }
+
+ if (!err) {
+ err = ccs_credentials_list_find_iterator (in_ccache->credentials,
+ in_identifier,
+ out_credentials_iterator);
+ }
+
+ // Don't report ccErrInvalidCredentials to the log file. Non-fatal.
+ return (err == ccErrInvalidCredentials) ? err : cci_check_error (err);
+}
+
+#ifdef TARGET_OS_MAC
+#pragma mark -
+#endif
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 ccs_ccache_write (ccs_ccache_t in_ccache,
+ k5_ipc_stream io_stream)
+{
+ cc_int32 err = ccNoError;
+
+ if (!in_ccache) { err = cci_check_error (ccErrBadParam); }
+ if (!io_stream) { err = cci_check_error (ccErrBadParam); }
+
+ if (!err) {
+ err = cci_identifier_write (in_ccache->identifier, io_stream);
+ }
+
+ return cci_check_error (err);
+}
+
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 ccs_ccache_write_name (ccs_ccache_t in_ccache,
+ k5_ipc_stream io_stream)
+{
+ cc_int32 err = ccNoError;
+
+ if (!in_ccache) { err = cci_check_error (ccErrBadParam); }
+ if (!io_stream) { err = cci_check_error (ccErrBadParam); }
+
+ if (!err) {
+ err = krb5int_ipc_stream_write_string (io_stream, in_ccache->name);
+ }
+
+ return cci_check_error (err);
+}
+
+#ifdef TARGET_OS_MAC
+#pragma mark -
+#pragma mark -- IPC Messages --
+#endif
+
+/* ------------------------------------------------------------------------ */
+
+static cc_int32 ccs_ccache_destroy (ccs_ccache_t io_ccache,
+ ccs_cache_collection_t io_cache_collection,
+ k5_ipc_stream in_request_data,
+ k5_ipc_stream io_reply_data)
+{
+ cc_int32 err = ccNoError;
+
+ if (!io_ccache ) { err = cci_check_error (ccErrBadParam); }
+ if (!io_cache_collection) { err = cci_check_error (ccErrBadParam); }
+ if (!in_request_data ) { err = cci_check_error (ccErrBadParam); }
+ if (!io_reply_data ) { err = cci_check_error (ccErrBadParam); }
+
+ if (!err) {
+ err = ccs_cache_collection_destroy_ccache (io_cache_collection,
+ io_ccache->identifier);
+ }
+
+ if (!err) {
+ /* ccache has been destroyed so just mark the cache collection */
+ err = ccs_cache_collection_changed (io_cache_collection);
+ }
+
+ return cci_check_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+static cc_int32 ccs_ccache_set_default (ccs_ccache_t io_ccache,
+ ccs_cache_collection_t io_cache_collection,
+ k5_ipc_stream in_request_data,
+ k5_ipc_stream io_reply_data)
+{
+ cc_int32 err = ccNoError;
+
+ if (!io_ccache ) { err = cci_check_error (ccErrBadParam); }
+ if (!io_cache_collection) { err = cci_check_error (ccErrBadParam); }
+ if (!in_request_data ) { err = cci_check_error (ccErrBadParam); }
+ if (!io_reply_data ) { err = cci_check_error (ccErrBadParam); }
+
+ if (!err) {
+ err = ccs_cache_collection_set_default_ccache (io_cache_collection,
+ io_ccache->identifier);
+ }
+
+ return cci_check_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+static cc_int32 ccs_ccache_get_credentials_version (ccs_ccache_t io_ccache,
+ ccs_cache_collection_t io_cache_collection,
+ k5_ipc_stream in_request_data,
+ k5_ipc_stream io_reply_data)
+{
+ cc_int32 err = ccNoError;
+
+ if (!io_ccache ) { err = cci_check_error (ccErrBadParam); }
+ if (!io_cache_collection) { err = cci_check_error (ccErrBadParam); }
+ if (!in_request_data ) { err = cci_check_error (ccErrBadParam); }
+ if (!io_reply_data ) { err = cci_check_error (ccErrBadParam); }
+
+ if (!err) {
+ err = krb5int_ipc_stream_write_uint32 (io_reply_data, io_ccache->creds_version);
+ }
+
+ return cci_check_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+static cc_int32 ccs_ccache_get_name (ccs_ccache_t io_ccache,
+ ccs_cache_collection_t io_cache_collection,
+ k5_ipc_stream in_request_data,
+ k5_ipc_stream io_reply_data)
+{
+ cc_int32 err = ccNoError;
+
+ if (!io_ccache ) { err = cci_check_error (ccErrBadParam); }
+ if (!io_cache_collection) { err = cci_check_error (ccErrBadParam); }
+ if (!in_request_data ) { err = cci_check_error (ccErrBadParam); }
+ if (!io_reply_data ) { err = cci_check_error (ccErrBadParam); }
+
+ if (!err) {
+ err = krb5int_ipc_stream_write_string (io_reply_data, io_ccache->name);
+ }
+
+ return cci_check_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+static cc_int32 ccs_ccache_get_principal (ccs_ccache_t io_ccache,
+ ccs_cache_collection_t io_cache_collection,
+ k5_ipc_stream in_request_data,
+ k5_ipc_stream io_reply_data)
+{
+ cc_int32 err = ccNoError;
+ cc_uint32 version = 0;
+
+ if (!io_ccache ) { err = cci_check_error (ccErrBadParam); }
+ if (!io_cache_collection) { err = cci_check_error (ccErrBadParam); }
+ if (!in_request_data ) { err = cci_check_error (ccErrBadParam); }
+ if (!io_reply_data ) { err = cci_check_error (ccErrBadParam); }
+
+ if (!err) {
+ err = krb5int_ipc_stream_read_uint32 (in_request_data, &version);
+ }
+
+ if (!err && version == cc_credentials_v4_v5) {
+ err = cci_check_error (ccErrBadCredentialsVersion);
+ }
+
+ if (!err) {
+ if (version == cc_credentials_v4) {
+ err = krb5int_ipc_stream_write_string (io_reply_data, io_ccache->v4_principal);
+
+ } else if (version == cc_credentials_v5) {
+ err = krb5int_ipc_stream_write_string (io_reply_data, io_ccache->v5_principal);
+
+ } else {
+ err = cci_check_error (ccErrBadCredentialsVersion);
+ }
+ }
+
+ return cci_check_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+static cc_int32 ccs_ccache_set_principal (ccs_ccache_t io_ccache,
+ ccs_cache_collection_t io_cache_collection,
+ k5_ipc_stream in_request_data,
+ k5_ipc_stream io_reply_data)
+{
+ cc_int32 err = ccNoError;
+ cc_uint32 version = 0;
+ char *principal = NULL;
+
+ if (!io_ccache ) { err = cci_check_error (ccErrBadParam); }
+ if (!io_cache_collection) { err = cci_check_error (ccErrBadParam); }
+ if (!in_request_data ) { err = cci_check_error (ccErrBadParam); }
+ if (!io_reply_data ) { err = cci_check_error (ccErrBadParam); }
+
+ if (!err) {
+ err = krb5int_ipc_stream_read_uint32 (in_request_data, &version);
+ }
+
+ if (!err) {
+ err = krb5int_ipc_stream_read_string (in_request_data, &principal);
+ }
+
+ if (!err) {
+ /* reset KDC time offsets because they are per-KDC */
+ if (version == cc_credentials_v4) {
+ io_ccache->kdc_time_offset_v4 = 0;
+ io_ccache->kdc_time_offset_v4_valid = 0;
+
+ if (io_ccache->v4_principal) { free (io_ccache->v4_principal); }
+ io_ccache->v4_principal = principal;
+ principal = NULL; /* take ownership */
+
+
+ } else if (version == cc_credentials_v5) {
+ io_ccache->kdc_time_offset_v5 = 0;
+ io_ccache->kdc_time_offset_v5_valid = 0;
+
+ if (io_ccache->v5_principal) { free (io_ccache->v5_principal); }
+ io_ccache->v5_principal = principal;
+ principal = NULL; /* take ownership */
+
+ } else {
+ err = cci_check_error (ccErrBadCredentialsVersion);
+ }
+ }
+
+ if (!err) {
+ io_ccache->creds_version |= version;
+
+ err = ccs_ccache_changed (io_ccache, io_cache_collection);
+ }
+
+ krb5int_ipc_stream_free_string (principal);
+
+ return cci_check_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+static cc_int32 ccs_ccache_store_credentials (ccs_ccache_t io_ccache,
+ ccs_cache_collection_t io_cache_collection,
+ k5_ipc_stream in_request_data,
+ k5_ipc_stream io_reply_data)
+{
+ cc_int32 err = ccNoError;
+ ccs_credentials_t credentials = NULL;
+
+ if (!io_ccache ) { err = cci_check_error (ccErrBadParam); }
+ if (!io_cache_collection) { err = cci_check_error (ccErrBadParam); }
+ if (!in_request_data ) { err = cci_check_error (ccErrBadParam); }
+ if (!io_reply_data ) { err = cci_check_error (ccErrBadParam); }
+
+ if (!err) {
+ err = ccs_credentials_new (&credentials, in_request_data,
+ io_ccache->creds_version,
+ io_ccache->credentials);
+ }
+
+ if (!err) {
+ err = ccs_ccache_changed (io_ccache, io_cache_collection);
+ }
+
+
+ return cci_check_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+static cc_int32 ccs_ccache_remove_credentials (ccs_ccache_t io_ccache,
+ ccs_cache_collection_t io_cache_collection,
+ k5_ipc_stream in_request_data,
+ k5_ipc_stream io_reply_data)
+{
+ cc_int32 err = ccNoError;
+ cci_identifier_t credentials_identifier = NULL;
+
+ if (!io_ccache ) { err = cci_check_error (ccErrBadParam); }
+ if (!io_cache_collection) { err = cci_check_error (ccErrBadParam); }
+ if (!in_request_data ) { err = cci_check_error (ccErrBadParam); }
+ if (!io_reply_data ) { err = cci_check_error (ccErrBadParam); }
+
+ if (!err) {
+ err = cci_identifier_read (&credentials_identifier, in_request_data);
+ }
+
+ if (!err) {
+ err = ccs_credentials_list_remove (io_ccache->credentials, credentials_identifier);
+ }
+
+ if (!err) {
+ err = ccs_ccache_changed (io_ccache, io_cache_collection);
+ }
+
+ cci_identifier_release (credentials_identifier);
+
+ return cci_check_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+static cc_int32 ccs_ccache_new_credentials_iterator (ccs_ccache_t io_ccache,
+ ccs_cache_collection_t io_cache_collection,
+ ccs_pipe_t in_client_pipe,
+ k5_ipc_stream in_request_data,
+ k5_ipc_stream io_reply_data)
+{
+ cc_int32 err = ccNoError;
+ ccs_credentials_iterator_t credentials_iterator = NULL;
+
+ if (!io_ccache ) { err = cci_check_error (ccErrBadParam); }
+ if (!io_cache_collection) { err = cci_check_error (ccErrBadParam); }
+ if (!in_request_data ) { err = cci_check_error (ccErrBadParam); }
+ if (!io_reply_data ) { err = cci_check_error (ccErrBadParam); }
+
+ if (!err) {
+ err = ccs_credentials_list_new_iterator (io_ccache->credentials,
+ in_client_pipe,
+ &credentials_iterator);
+ }
+
+ if (!err) {
+ err = ccs_credentials_list_iterator_write (credentials_iterator, io_reply_data);
+ }
+
+ return cci_check_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+static cc_int32 ccs_ccache_move (ccs_ccache_t io_ccache,
+ ccs_cache_collection_t io_cache_collection,
+ k5_ipc_stream in_request_data,
+ k5_ipc_stream io_reply_data)
+{
+ cc_int32 err = ccNoError;
+ cci_identifier_t source_identifier = NULL;
+
+ if (!io_ccache ) { err = cci_check_error (ccErrBadParam); }
+ if (!io_cache_collection) { err = cci_check_error (ccErrBadParam); }
+ if (!in_request_data ) { err = cci_check_error (ccErrBadParam); }
+ if (!io_reply_data ) { err = cci_check_error (ccErrBadParam); }
+
+ if (!err) {
+ /* Note: message is sent as the destination ccache to avoid */
+ /* extra work on the server when deleting it the source ccache. */
+ err = cci_identifier_read (&source_identifier, in_request_data);
+ }
+
+ if (!err) {
+ err = ccs_ccache_collection_move_ccache (io_cache_collection,
+ source_identifier,
+ io_ccache);
+ }
+
+ if (!err) {
+ err = ccs_ccache_changed (io_ccache, io_cache_collection);
+ }
+
+ cci_identifier_release (source_identifier);
+
+ return cci_check_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+static cc_int32 ccs_ccache_lock (ccs_pipe_t in_client_pipe,
+ ccs_pipe_t in_reply_pipe,
+ ccs_ccache_t io_ccache,
+ ccs_cache_collection_t io_cache_collection,
+ k5_ipc_stream in_request_data,
+ cc_uint32 *out_will_block,
+ k5_ipc_stream io_reply_data)
+{
+ cc_int32 err = ccNoError;
+ cc_uint32 lock_type;
+ cc_uint32 block;
+
+ if (!ccs_pipe_valid (in_client_pipe)) { err = cci_check_error (ccErrBadParam); }
+ if (!io_ccache ) { err = cci_check_error (ccErrBadParam); }
+ if (!io_cache_collection ) { err = cci_check_error (ccErrBadParam); }
+ if (!in_request_data ) { err = cci_check_error (ccErrBadParam); }
+ if (!out_will_block ) { err = cci_check_error (ccErrBadParam); }
+ if (!io_reply_data ) { err = cci_check_error (ccErrBadParam); }
+
+ if (!err) {
+ err = krb5int_ipc_stream_read_uint32 (in_request_data, &lock_type);
+ }
+
+ if (!err) {
+ err = krb5int_ipc_stream_read_uint32 (in_request_data, &block);
+ }
+
+ if (!err) {
+ err = ccs_lock_state_add (io_ccache->lock_state,
+ in_client_pipe, in_reply_pipe,
+ lock_type, block, out_will_block);
+ }
+
+ return cci_check_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+static cc_int32 ccs_ccache_unlock (ccs_pipe_t in_client_pipe,
+ ccs_ccache_t io_ccache,
+ ccs_cache_collection_t io_cache_collection,
+ k5_ipc_stream in_request_data,
+ k5_ipc_stream io_reply_data)
+{
+ cc_int32 err = ccNoError;
+
+ if (!ccs_pipe_valid (in_client_pipe)) { err = cci_check_error (ccErrBadParam); }
+ if (!io_ccache ) { err = cci_check_error (ccErrBadParam); }
+ if (!io_cache_collection ) { err = cci_check_error (ccErrBadParam); }
+ if (!in_request_data ) { err = cci_check_error (ccErrBadParam); }
+ if (!io_reply_data ) { err = cci_check_error (ccErrBadParam); }
+
+ if (!err) {
+ err = ccs_lock_state_remove (io_ccache->lock_state, in_client_pipe);
+ }
+
+ return cci_check_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+static cc_int32 ccs_ccache_get_last_default_time (ccs_ccache_t io_ccache,
+ ccs_cache_collection_t io_cache_collection,
+ k5_ipc_stream in_request_data,
+ k5_ipc_stream io_reply_data)
+{
+ cc_int32 err = ccNoError;
+
+ if (!io_ccache ) { err = cci_check_error (ccErrBadParam); }
+ if (!io_cache_collection) { err = cci_check_error (ccErrBadParam); }
+ if (!in_request_data ) { err = cci_check_error (ccErrBadParam); }
+ if (!io_reply_data ) { err = cci_check_error (ccErrBadParam); }
+
+ if (!err && io_ccache->last_default_time == 0) {
+ err = cci_check_error (ccErrNeverDefault);
+ }
+
+ if (!err) {
+ err = krb5int_ipc_stream_write_time (io_reply_data, io_ccache->last_default_time);
+ }
+
+ return cci_check_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+static cc_int32 ccs_ccache_get_change_time (ccs_ccache_t io_ccache,
+ ccs_cache_collection_t io_cache_collection,
+ k5_ipc_stream in_request_data,
+ k5_ipc_stream io_reply_data)
+{
+ cc_int32 err = ccNoError;
+
+ if (!io_ccache ) { err = cci_check_error (ccErrBadParam); }
+ if (!io_cache_collection) { err = cci_check_error (ccErrBadParam); }
+ if (!in_request_data ) { err = cci_check_error (ccErrBadParam); }
+ if (!io_reply_data ) { err = cci_check_error (ccErrBadParam); }
+
+ if (!err) {
+ err = krb5int_ipc_stream