summaryrefslogtreecommitdiffstats
path: root/src/ccapi/lib/ccapi_context.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/ccapi/lib/ccapi_context.c')
-rw-r--r--src/ccapi/lib/ccapi_context.c789
1 files changed, 789 insertions, 0 deletions
diff --git a/src/ccapi/lib/ccapi_context.c b/src/ccapi/lib/ccapi_context.c
new file mode 100644
index 000000000..7a24f2248
--- /dev/null
+++ b/src/ccapi/lib/ccapi_context.c
@@ -0,0 +1,789 @@
+/*
+ * $Header$
+ *
+ * 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_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 <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;
+} *cci_context_t;
+
+/* ------------------------------------------------------------------------ */
+
+struct cci_context_d cci_context_initializer = {
+ NULL
+ VECTOR_FUNCTIONS_INITIALIZER,
+ NULL,
+ 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);
+
+#pragma mark -
+
+MAKE_INIT_FUNCTION(cci_thread_init);
+
+/* ------------------------------------------------------------------------ */
+
+static int cci_thread_init (void)
+{
+ cc_int32 err = ccNoError;
+
+ if (!err) {
+ err = cci_context_change_time_thread_init ();
+ }
+
+ if (!err) {
+ err = cci_ipc_thread_init ();
+ }
+
+ return err;
+}
+
+#pragma mark -
+
+/* ------------------------------------------------------------------------ */
+
+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_thread_init);
+ }
+
+ if (!err) {
+ switch (in_version) {
+ case ccapi_version_2:
+ err = CC_NOT_SUPP;
+ break;
+
+ case ccapi_version_3:
+ case ccapi_version_4:
+ case ccapi_version_5:
+ case ccapi_version_6:
+ 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);
+}
+
+#pragma mark -
+
+/* ------------------------------------------------------------------------ */
+
+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) {
+ err = cci_context_sync (context, 0);
+ }
+
+ if (!err) {
+ err = cci_ipc_send_no_launch (cci_context_release_msg_id,
+ context->identifier,
+ NULL,
+ NULL);
+ }
+
+ 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;
+ cci_stream_t 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 && cci_stream_size (reply) > 0) {
+ cc_time_t change_time = 0;
+
+ /* got a response from the server */
+ err = cci_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);
+ }
+
+ cci_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;
+
+ if (!in_context) { err = cci_check_error (ccErrBadParam); }
+
+ if (!err) {
+ err = cci_context_sync (context, 0);
+ }
+
+ if (!err) {
+ err = cci_ipc_send_no_launch (cci_context_wait_for_change_msg_id,
+ context->identifier,
+ NULL, NULL);
+ }
+
+ 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;
+ cci_stream_t 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 (cci_stream_size (reply) > 0) {
+ /* got a response from the server */
+ err = cci_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);
+ }
+
+ cci_stream_release (reply);
+ free (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;
+ cci_stream_t request = NULL;
+ cci_stream_t 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 = cci_stream_new (&request);
+ }
+
+ if (!err) {
+ err = cci_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 && !(cci_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);
+ cci_stream_release (reply);
+ cci_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;
+ cci_stream_t 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 && !(cci_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);
+ cci_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;
+ cci_stream_t request = NULL;
+ cci_stream_t 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 = cci_stream_new (&request);
+ }
+
+ if (!err) {
+ err = cci_stream_write_string (request, in_name);
+ }
+
+ if (!err) {
+ err = cci_stream_write_uint32 (request, in_cred_vers);
+ }
+
+ if (!err) {
+ err = cci_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);
+ cci_stream_release (reply);
+ cci_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;
+ cci_stream_t request = NULL;
+ cci_stream_t 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 = cci_stream_new (&request);
+ }
+
+ if (!err) {
+ err = cci_stream_write_uint32 (request, in_cred_vers);
+ }
+
+ if (!err) {
+ err = cci_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);
+ cci_stream_release (reply);
+ cci_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;
+ cci_stream_t request = NULL;
+ cci_stream_t 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 = cci_stream_new (&request);
+ }
+
+ if (!err) {
+ err = cci_stream_write_uint32 (request, in_cred_vers);
+ }
+
+ if (!err) {
+ err = cci_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);
+ cci_stream_release (reply);
+ cci_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;
+ cci_stream_t 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 (cci_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);
+ }
+
+ cci_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;
+ cci_stream_t request = NULL;
+
+ if (!in_context) { err = cci_check_error (ccErrBadParam); }
+
+ if (!err) {
+ err = cci_stream_new (&request);
+ }
+
+ if (!err) {
+ err = cci_stream_write_uint32 (request, in_lock_type);
+ }
+
+ if (!err) {
+ err = cci_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);
+ }
+
+ cci_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);
+}
+
+#pragma mark -
+
+/* ------------------------------------------------------------------------ */
+
+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;
+ cci_stream_t 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 (cci_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);
+ cci_stream_release (reply);
+
+ return cci_check_error (err);
+}
+