Temporarily copied KerberosIPC libary from the KfM repository for
authorAlexandra Ellwood <lxs@mit.edu>
Fri, 9 Jun 2006 22:01:11 +0000 (22:01 +0000)
committerAlexandra Ellwood <lxs@mit.edu>
Fri, 9 Jun 2006 22:01:11 +0000 (22:01 +0000)
testing purposes.  Note that this will be removed when the CCAPI
branch is merged onto the trunk.

git-svn-id: svn://anonsvn.mit.edu/krb5/branches/ccapi@18100 dc483132-0cff-0310-8789-dd5450dbe970

src/lib/ccapi/common/mac/KerberosIPC/Kerberos/kipc_client.h [new file with mode: 0644]
src/lib/ccapi/common/mac/KerberosIPC/Kerberos/kipc_common.h [new file with mode: 0644]
src/lib/ccapi/common/mac/KerberosIPC/Kerberos/kipc_server.h [new file with mode: 0644]
src/lib/ccapi/common/mac/KerberosIPC/Kerberos/kipc_session.h [new file with mode: 0644]
src/lib/ccapi/common/mac/KerberosIPC/README [new file with mode: 0644]
src/lib/ccapi/common/mac/KerberosIPC/kipc_client.c [new file with mode: 0644]
src/lib/ccapi/common/mac/KerberosIPC/kipc_common.c [new file with mode: 0644]
src/lib/ccapi/common/mac/KerberosIPC/kipc_server.c [new file with mode: 0644]
src/lib/ccapi/common/mac/KerberosIPC/kipc_session.c [new file with mode: 0644]
src/lib/ccapi/common/mac/KerberosIPC/notify.defs [new file with mode: 0644]

diff --git a/src/lib/ccapi/common/mac/KerberosIPC/Kerberos/kipc_client.h b/src/lib/ccapi/common/mac/KerberosIPC/Kerberos/kipc_client.h
new file mode 100644 (file)
index 0000000..89923eb
--- /dev/null
@@ -0,0 +1,47 @@
+/*
+ * kipc_client.h
+ *
+ * $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.
+ */
+
+#ifndef KIPC_CLIENT_H
+#define KIPC_CLIENT_H
+
+#include <Kerberos/kipc_common.h>
+
+#if __cplusplus
+extern "C" {
+#endif
+    
+kipc_err_t
+kipc_client_lookup_server (const char  *in_service_id,
+                          boolean_t    in_launch_if_necessary,
+                          mach_port_t *out_service_port);
+    
+#if __cplusplus
+}
+#endif
+
+#endif /* KIPC_CLIENT_H */
diff --git a/src/lib/ccapi/common/mac/KerberosIPC/Kerberos/kipc_common.h b/src/lib/ccapi/common/mac/KerberosIPC/Kerberos/kipc_common.h
new file mode 100644 (file)
index 0000000..361f7f5
--- /dev/null
@@ -0,0 +1,76 @@
+/*
+ * KerberosIPCCommon.h
+ *
+ * $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.
+ */
+
+#ifndef KIPC_COMMON_H
+#define KIPC_COMMON_H
+
+//#include <Kerberos/KerberosDebug.h>
+#include <CoreFoundation/CoreFoundation.h>
+#include <mach/mach.h>
+#include <mach/boolean.h>
+#include <mach/mach_error.h>
+#include <mach/notify.h>
+#include <servers/bootstrap.h>
+#include <sys/types.h>
+#include <sys/time.h>
+#include <sys/resource.h>
+#include <sys/wait.h>
+#include <sys/param.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+
+
+#if __cplusplus
+extern "C" {
+#endif
+    
+typedef kern_return_t  kipc_err_t;
+typedef boolean_t      kipc_boolean_t;
+typedef char          *kipc_string;
+
+#define kkipc_max_message_size  2048 + MAX_TRAILER_SIZE
+#define kkipc_timeout           200
+
+// Debugging API used by library
+kipc_err_t __kipc_err (kipc_err_t inError, const char *function, const char *file, int line);
+#define kipc_err(err) __kipc_err(err, __FUNCTION__, __FILE__, __LINE__)
+    
+const char *kipc_error_string (kipc_err_t in_error);
+
+kipc_err_t kipc_get_lookup_name (char **out_lookup_name, const char *in_service_id);
+kipc_err_t kipc_get_service_name (char **out_service_name, const char *in_service_id);
+
+void kipc_free_string (char *io_string);
+
+#if __cplusplus
+}
+#endif
+
+#endif /* KIPC_COMMON_H */
diff --git a/src/lib/ccapi/common/mac/KerberosIPC/Kerberos/kipc_server.h b/src/lib/ccapi/common/mac/KerberosIPC/Kerberos/kipc_server.h
new file mode 100644 (file)
index 0000000..5d97547
--- /dev/null
@@ -0,0 +1,54 @@
+/*
+ * kipc_server.h
+ *
+ * $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.
+ */
+
+#ifndef KIPC_SERVER_H
+#define KIPC_SERVER_H
+
+#include <Kerberos/kipc_common.h>
+
+#define kKerberosIPCMaxMsgSize               2048 + MAX_TRAILER_SIZE
+#define kKerberosIPCTimeout                  200
+
+#if __cplusplus
+extern "C" {
+#endif
+    
+typedef kipc_boolean_t (*kipc_demux_proc) (mach_msg_header_t *, mach_msg_header_t *);
+    
+    
+kipc_err_t kipc_server_run_server (kipc_demux_proc in_demux_proc);
+    
+mach_port_t kipc_server_get_service_port ();
+    
+kipc_boolean_t kipc_server_quit (void);
+    
+#if __cplusplus
+}
+#endif
+
+#endif /* KIPC_SERVER_H */
diff --git a/src/lib/ccapi/common/mac/KerberosIPC/Kerberos/kipc_session.h b/src/lib/ccapi/common/mac/KerberosIPC/Kerberos/kipc_session.h
new file mode 100644 (file)
index 0000000..3f25956
--- /dev/null
@@ -0,0 +1,59 @@
+/*
+ * kipc_session.h
+ *
+ * $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.
+ */
+
+#ifndef KIPC_SESSION_H
+#define KIPC_SESSION_H
+
+#include <Kerberos/kipc_common.h>
+
+#if __cplusplus
+extern "C" {
+#endif
+    
+#define kkipc_session_has_gui_access  0x00000001
+#define kkipc_session_caller_uses_gui 0x00000002
+#define kkipc_session_has_cli_access  0x00000004
+
+typedef u_int32_t kipc_session_attributes_t;
+    
+    
+kipc_boolean_t kipc_session_is_root_session (void);
+    
+kipc_session_attributes_t kipc_session_get_attributes (void);
+
+kipc_string kipc_get_session_id_string (void);
+
+uid_t kipc_session_get_session_uid (void);
+    
+uid_t kipc_session_get_server_uid (void);
+    
+#if __cplusplus
+}
+#endif
+
+#endif /* KIPC_SESSION_H */
diff --git a/src/lib/ccapi/common/mac/KerberosIPC/README b/src/lib/ccapi/common/mac/KerberosIPC/README
new file mode 100644 (file)
index 0000000..2e2d70d
--- /dev/null
@@ -0,0 +1,3 @@
+This is a temporary copy of the KfM KerberosIPC library sources.
+Once this gets merged onto the trunk the KfM build will use the 
+KerberosIPC library instead.
diff --git a/src/lib/ccapi/common/mac/KerberosIPC/kipc_client.c b/src/lib/ccapi/common/mac/KerberosIPC/kipc_client.c
new file mode 100644 (file)
index 0000000..2e48c42
--- /dev/null
@@ -0,0 +1,86 @@
+/*
+ * kipc_client.c
+ *
+ * $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 <Kerberos/kipc_client.h>
+
+// ---------------------------------------------------------------------------
+
+kipc_err_t
+kipc_client_lookup_server (const char  *in_service_id,
+                           boolean_t    in_launch_if_necessary,
+                           mach_port_t *out_service_port) 
+{
+    kipc_err_t  err = 0;
+    mach_port_t boot_port = MACH_PORT_NULL;
+    char *service_name = NULL;
+    
+    if (in_service_id    == NULL) { err = kipc_err (EINVAL); }
+    if (out_service_port == NULL) { err = kipc_err (EINVAL); }
+    
+    if (!err) {
+        // Get our bootstrap port
+        err = task_get_bootstrap_port (mach_task_self (), &boot_port);
+    }
+    
+    if (!err && !in_launch_if_necessary) {
+        char *lookup_name = NULL;
+        mach_port_t lookup_port = MACH_PORT_NULL;
+        
+        err = kipc_get_lookup_name (&lookup_name, in_service_id);
+        
+        if (!err) {
+            // Use the lookup name because the service name will return 
+            // a valid port even if the server isn't running
+            err = bootstrap_look_up (boot_port, lookup_name, &lookup_port);
+            //dprintf ("%s(): bootstrap_look_up('%s'): port is %x (err = %d '%s')", 
+            //         __FUNCTION__, lookup_name, lookup_port, err, mach_error_string (err));
+        }
+        
+        if (lookup_name != NULL          ) { kipc_free_string (lookup_name); }
+        if (lookup_port != MACH_PORT_NULL) { mach_port_deallocate (mach_task_self (), lookup_port); }
+    }
+    
+    if (!err) {
+        err = kipc_get_service_name (&service_name, in_service_id);
+    }
+    
+    if (!err) {
+        err = bootstrap_look_up (boot_port, service_name, out_service_port);
+        //dprintf ("%s(): bootstrap_look_up('%s'): port is %x (err = %d '%s')", 
+        //         __FUNCTION__, service_name, *out_service_port, err, mach_error_string (err));
+    }
+    
+    if (service_name != NULL       ) { kipc_free_string (service_name); }
+    if (boot_port != MACH_PORT_NULL) { mach_port_deallocate (mach_task_self (), boot_port); }
+    
+    if (err == BOOTSTRAP_UNKNOWN_SERVICE) {
+        return err;  // Avoid spewing to the log file
+    } else {
+        return kipc_err (err);
+    }
+}
diff --git a/src/lib/ccapi/common/mac/KerberosIPC/kipc_common.c b/src/lib/ccapi/common/mac/KerberosIPC/kipc_common.c
new file mode 100644 (file)
index 0000000..438650f
--- /dev/null
@@ -0,0 +1,93 @@
+/*
+ * kipc_common.c
+ *
+ * $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 <Kerberos/kipc_common.h>
+#include <Kerberos/kipc_session.h>
+
+
+// ---------------------------------------------------------------------------
+
+kipc_err_t __kipc_err (kipc_err_t in_error, const char *in_function, const char *in_file, int in_line)
+{
+    if (in_error && (ddebuglevel () > 0)) {
+        dprintf ("%s() got %d ('%s') at %s: %d", 
+                 in_function, in_error, mach_error_string (in_error), in_file, in_line);
+        dprintsession ();
+        //dprintbootstrap (mach_task_self ());
+    }    
+    return in_error;
+}
+// ---------------------------------------------------------------------------
+
+
+const char *kipc_error_string (kipc_err_t in_error)
+{
+    return mach_error_string (in_error);
+}
+
+// ---------------------------------------------------------------------------
+
+kipc_err_t kipc_get_service_name (char **out_service_name, const char *in_service_id)
+{
+    kipc_err_t err = 0;
+    
+    if (out_service_name == NULL) { err = EINVAL; }
+    if (in_service_id    == NULL) { err = EINVAL; }
+    
+    if (!err) {
+        int wrote = asprintf (out_service_name, "%s%s", in_service_id, ".ipcService");
+        if (wrote < 0) { err = ENOMEM; }
+    }
+    
+    return kipc_err (err);
+}
+
+// ---------------------------------------------------------------------------
+
+kipc_err_t kipc_get_lookup_name (char **out_lookup_name, const char *in_service_id)
+{
+    kipc_err_t err = 0;
+    
+    if (out_lookup_name == NULL) { err = EINVAL; }
+    if (in_service_id   == NULL) { err = EINVAL; }
+    
+    if (!err) {
+        int wrote = asprintf (out_lookup_name, "%s%s", in_service_id, ".ipcLookup");
+        if (wrote < 0) { err = ENOMEM; }
+    }
+    
+    return kipc_err (err);    
+}
+
+// ---------------------------------------------------------------------------
+
+void kipc_free_string (char *io_string)
+{
+    free (io_string);
+}
+
diff --git a/src/lib/ccapi/common/mac/KerberosIPC/kipc_server.c b/src/lib/ccapi/common/mac/KerberosIPC/kipc_server.c
new file mode 100644 (file)
index 0000000..c7c973b
--- /dev/null
@@ -0,0 +1,313 @@
+/*
+ * kipc_server.c
+ *
+ * $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 <Kerberos/kipc_server.h>
+#include <Kerberos/kipc_session.h>
+#include "notifyServer.h"
+
+// Global variables for servers (used by demux)
+static mach_port_t       g_service_port = MACH_PORT_NULL;
+static kipc_boolean_t    g_ready_to_quit = FALSE;
+static kipc_demux_proc   g_demux_proc = NULL;
+
+#pragma mark -
+
+// ---------------------------------------------------------------------------
+
+mach_port_t
+kipc_server_get_service_port ()
+{
+    return g_service_port;
+}
+
+#pragma mark -
+
+// ---------------------------------------------------------------------------
+
+kipc_boolean_t
+kipc_server_quit (void)
+{
+    // Do not unregister our port because then we won't get automatically launched again.
+    dprintf ("mach_server_quit_self(): quitting...");
+    g_ready_to_quit = true;
+    return g_ready_to_quit;
+}
+
+#pragma mark -
+
+// ---------------------------------------------------------------------------
+
+static kipc_boolean_t 
+kipc_server_demux (mach_msg_header_t *request, mach_msg_header_t *reply) 
+{
+    if (mach_notify_server (request, reply) != false) {
+        return true;
+    } else {
+        return g_demux_proc (request, reply);
+    }
+    return false;
+}
+
+#pragma mark -
+
+// ---------------------------------------------------------------------------
+
+static kipc_err_t
+kipc_get_server_id (char **out_server_id)
+{
+    kern_return_t err = KERN_SUCCESS;
+    CFBundleRef   bundle = NULL;
+    CFStringRef   id_string = NULL;
+    CFIndex       id_length = 0;
+    char         *server_id = NULL;
+    
+    if (out_server_id == NULL) { err = kipc_err (EINVAL); }
+    
+    if (!err) {
+        bundle = CFBundleGetMainBundle ();
+        if (bundle == NULL) { err = ENOENT; }
+    }
+    
+    if (!err) {
+        id_string = CFBundleGetIdentifier (bundle);
+        if (id_string == NULL) { err = ENOMEM; }
+    }
+    
+    if (!err) {
+        id_length = CFStringGetMaximumSizeForEncoding (CFStringGetLength (id_string), 
+                                                       CFStringGetSystemEncoding ()) + 1;
+        server_id = calloc (id_length, sizeof (char));
+        if (server_id == NULL) { err = errno; }
+    }
+    
+    if (!err) {
+        if (!CFStringGetCString (id_string, server_id, id_length, CFStringGetSystemEncoding ())) { 
+            err = ENOMEM; 
+        }
+    }
+    
+    if (!err) {
+        *out_server_id = server_id;
+        server_id = NULL;
+    }
+    
+    if (server_id != NULL) { kipc_free_string (server_id); }
+    
+    return kipc_err (err);
+}
+
+// ---------------------------------------------------------------------------
+
+kipc_err_t
+kipc_server_run_server (kipc_demux_proc in_demux_proc)
+{
+    kern_return_t  err = KERN_SUCCESS;
+    char          *server_id = NULL;
+    char          *service_name = NULL;
+    char          *lookup_name = NULL;
+    mach_port_t    boot_port = MACH_PORT_NULL;
+    mach_port_t    lookup_port = MACH_PORT_NULL;
+    mach_port_t    notify_port = MACH_PORT_NULL;
+    mach_port_t    previous_notify_port = MACH_PORT_NULL;
+    mach_port_t    listen_port_set = MACH_PORT_NULL;
+    
+    if (in_demux_proc == NULL) { err = kipc_err (EINVAL); }
+    
+    // Shed root privileges if any
+    if (!err && (geteuid () == 0)) {
+        uid_t new_uid = kipc_session_get_server_uid ();
+        if (setuid (new_uid) < 0) {
+            dprintf ("%s(): setuid(%d) failed (euid is %d)", __FUNCTION__, new_uid, geteuid ());
+        }
+    }
+    
+    if (!err) {
+        // Set up the globals so the demux can find them
+        g_demux_proc = in_demux_proc;
+    }
+    
+    if (!err) {
+        err = kipc_get_server_id (&server_id);
+    }
+    
+    if (!err) {
+        err = kipc_get_service_name (&service_name, server_id);
+    }
+    
+    if (!err) {
+        err = kipc_get_lookup_name (&lookup_name, server_id);
+    }
+    
+    if (!err) {
+        // Get the bootstrap port
+        err = task_get_bootstrap_port (mach_task_self (), &boot_port);
+        dprintf ("%s(): task_get_bootstrap_port(): port is %x (err = %d '%s')", 
+                 __FUNCTION__, boot_port, err, mach_error_string (err));
+    }
+    
+    if (!err) {
+        // Create the lookup port:
+        err = mach_port_allocate (mach_task_self (), MACH_PORT_RIGHT_RECEIVE, &lookup_port);
+    }
+    
+    if (!err) {
+        err = mach_port_insert_right (mach_task_self (), lookup_port, lookup_port, MACH_MSG_TYPE_MAKE_SEND);
+    }
+    
+    if (!err) {
+        // Register the lookup port so others can tell whether or not we are running
+        err = bootstrap_register (boot_port, lookup_name, lookup_port);
+        dprintf ("%s(): bootstrap_register('%s', %x): (err = %d '%s')", 
+                 __FUNCTION__, lookup_name, lookup_port, err, mach_error_string (err));
+    }
+    
+    if (!err) {
+        // We are an on-demand server so our port already exists.  Just ask for it.
+        err = bootstrap_check_in (boot_port, (char *) service_name, &g_service_port);
+        dprintf ("%s(): bootstrap_check_in('%s'): port is %d (err = %d '%s')", 
+                 __FUNCTION__, service_name, g_service_port, err, mach_error_string (err));
+    }      
+    
+    if (!err) {
+        // Create the notification port:
+        err = mach_port_allocate (mach_task_self (), MACH_PORT_RIGHT_RECEIVE, &notify_port);
+    }    
+    
+    if (!err) {
+        // Ask for notification when the server port has no more senders
+        // A send-once right != a send right so our send-once right will not interfere with the notification
+        err = mach_port_request_notification (mach_task_self (), g_service_port, MACH_NOTIFY_NO_SENDERS, true, 
+                                              notify_port, MACH_MSG_TYPE_MAKE_SEND_ONCE, &previous_notify_port);
+        dprintf ("%s(): requesting notification for no senders of %x returned '%s', err = %d\n",
+                 __FUNCTION__, g_service_port, mach_error_string (err), err);
+    }
+    
+    if (!err) {
+        // Create the port set that the server will listen on
+        err = mach_port_allocate (mach_task_self (), MACH_PORT_RIGHT_PORT_SET, &listen_port_set);
+    }    
+    
+    if (!err) {
+        // Add the service port to the port set
+        err = mach_port_move_member (mach_task_self (), g_service_port, listen_port_set);
+    }    
+    
+    if (!err) {
+        // Add the notify port to the port set
+        err = mach_port_move_member (mach_task_self (), notify_port, listen_port_set);
+    }
+    
+    if (!err) {
+        dprintf ("%s(): \"%s\": starting up. service port = %x, bootstrap port = %x\n", 
+                 __FUNCTION__, service_name, g_service_port, boot_port);
+    }
+    
+    while (!err && !g_ready_to_quit) {
+        // Handle one message at a time so we can check to see if the server wants to quit
+        err = mach_msg_server_once (kipc_server_demux, kkipc_max_message_size, listen_port_set, MACH_MSG_OPTION_NONE);
+    }
+    
+    // Regardless of whether there was an error, unregister ourselves from no senders notifications 
+    // so we don't get launched again by the notification message when we quit
+    // A send-once right != a send right so our send-once right will not interfere with the notification
+    if (g_service_port != MACH_PORT_NULL) {
+        err = mach_port_request_notification (mach_task_self (), g_service_port, MACH_NOTIFY_NO_SENDERS, 
+                                              true, MACH_PORT_NULL, MACH_MSG_TYPE_MAKE_SEND_ONCE, 
+                                              &previous_notify_port);
+        dprintf ("%s(): removing notification for no senders of %x returned '%s', err = %d\n", 
+                 __FUNCTION__, previous_notify_port, mach_error_string (err), err);
+    }
+    
+    // Clean up the ports and strings
+    if (lookup_port != MACH_PORT_NULL) { 
+        kipc_err_t terr = bootstrap_register (boot_port, lookup_name, MACH_PORT_NULL);
+        dprintf ("%s(): bootstrap_register('%s', MACH_PORT_NULL): (err = %d '%s')", 
+                 __FUNCTION__, lookup_name, terr, mach_error_string (terr));
+        mach_port_deallocate (mach_task_self (), lookup_port); 
+    }
+    if (notify_port     != MACH_PORT_NULL) { mach_port_deallocate (mach_task_self (), notify_port); }
+    if (listen_port_set != MACH_PORT_NULL) { mach_port_deallocate (mach_task_self (), listen_port_set); }
+    if (boot_port       != MACH_PORT_NULL) { mach_port_deallocate (mach_task_self (), boot_port); }
+    if (lookup_name     != NULL          ) { kipc_free_string (lookup_name); }
+    if (service_name    != NULL          ) { kipc_free_string (service_name); }
+    if (server_id       != NULL          ) { kipc_free_string (server_id); }
+    
+    return kipc_err (err);    
+}
+
+#pragma mark -
+
+// ---------------------------------------------------------------------------
+
+kern_return_t 
+do_mach_notify_port_deleted (mach_port_t notify, mach_port_name_t name)
+{
+    dprintf ("Received MACH_NOTIFY_PORT_DELETED... quitting self");
+    kipc_server_quit ();
+    return KERN_SUCCESS;
+}
+
+// ---------------------------------------------------------------------------
+
+kern_return_t 
+do_mach_notify_port_destroyed (mach_port_t notify, mach_port_t rights)
+{
+    dprintf ("Received MACH_NOTIFY_PORT_DESTROYED... quitting self");
+    kipc_server_quit ();
+    return KERN_SUCCESS;
+}
+
+// ---------------------------------------------------------------------------
+
+kern_return_t 
+do_mach_notify_no_senders (mach_port_t notify, mach_port_mscount_t mscount)
+{
+    dprintf ("Received MACH_NOTIFY_NO_SENDERS... quitting self");
+    kipc_server_quit ();
+    return KERN_SUCCESS;
+}
+
+// ---------------------------------------------------------------------------
+
+kern_return_t 
+do_mach_notify_send_once (mach_port_t notify)
+{
+    dprintf ("Received MACH_NOTIFY_SEND_ONCE");
+    return KERN_SUCCESS;
+}
+
+// ---------------------------------------------------------------------------
+
+kern_return_t 
+do_mach_notify_dead_name (mach_port_t notify, mach_port_name_t name)
+{
+    dprintf ("Received MACH_NOTIFY_DEAD_NAME... quitting self");
+    kipc_server_quit ();
+    return KERN_SUCCESS;
+}
+
diff --git a/src/lib/ccapi/common/mac/KerberosIPC/kipc_session.c b/src/lib/ccapi/common/mac/KerberosIPC/kipc_session.c
new file mode 100644 (file)
index 0000000..c08e1bc
--- /dev/null
@@ -0,0 +1,141 @@
+/*
+ * kipc_session.c
+ *
+ * $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 <Security/AuthSession.h>
+#include <pwd.h>
+#include <Kerberos/kipc_session.h>
+
+// ---------------------------------------------------------------------------
+
+kipc_boolean_t kipc_session_is_root_session (void)
+{
+    kipc_err_t           err = 0;
+    kipc_boolean_t       is_root_session = TRUE;  // safer to assume root session
+    SessionAttributeBits sattrs = 0L;    
+    
+    err = SessionGetInfo (callerSecuritySession, NULL, &sattrs);
+    
+    if (!err) {
+        is_root_session = (sattrs & sessionIsRoot);
+        dprintf ("%s(): running in %s session", 
+                 __FUNCTION__, is_root_session ? "the root" : "a user");
+    } else {
+        dprintf ("%s(): SessionGetInfo() failed with %d", __FUNCTION__, err);
+    }
+    
+    return is_root_session;
+}
+
+// ---------------------------------------------------------------------------
+
+kipc_session_attributes_t kipc_session_get_attributes (void)
+{
+    kipc_session_attributes_t attributes = 0L;
+    SessionAttributeBits      sattrs = 0L;    
+    int                       fd_stdin = fileno (stdin);
+    int                       fd_stdout = fileno (stdout);
+    char                     *fd_stdin_name = ttyname (fd_stdin);
+    
+    if ((SessionGetInfo (callerSecuritySession, NULL, &sattrs) == noErr) && (sattrs & sessionHasGraphicAccess)) {
+        dprintf ("%s(): Session has graphic access.", __FUNCTION__);
+        attributes |= kkipc_session_has_gui_access;
+        
+        // Check for the HIToolbox (Carbon) or AppKit (Cocoa).  If either is loaded, we are a GUI app!
+        CFBundleRef hiToolBoxBundle = CFBundleGetBundleWithIdentifier (CFSTR ("com.apple.HIToolbox"));
+        if (hiToolBoxBundle != NULL && CFBundleIsExecutableLoaded (hiToolBoxBundle)) {
+            dprintf ("%s(): Carbon Toolbox is loaded.", __FUNCTION__);
+            attributes |= kkipc_session_caller_uses_gui;
+        }
+        
+        CFBundleRef appKitBundle = CFBundleGetBundleWithIdentifier (CFSTR ("com.apple.AppKit"));
+        if (appKitBundle != NULL && CFBundleIsExecutableLoaded (appKitBundle)) {
+            dprintf ("%s(): AppKit is loaded.", __FUNCTION__);
+            attributes |= kkipc_session_caller_uses_gui;
+        }
+    }
+    
+    // Session info isn't reliable for remote sessions.
+    // Check manually for terminal access with file descriptors
+    if (isatty (fd_stdin) && isatty (fd_stdout) && (fd_stdin_name != NULL)) {
+        dprintf ("%s(): Terminal '%s' of type '%s' exists.", 
+                 __FUNCTION__, fd_stdin_name, getenv ("TERM"));
+        attributes |= kkipc_session_has_cli_access;
+    }
+    
+    dprintf ("%s(): Attributes are %x", __FUNCTION__, attributes);
+    return attributes;
+}
+
+// ---------------------------------------------------------------------------
+
+kipc_string kipc_get_session_id_string (void)
+{
+    // Session ID is a 32 bit quanitity, so the longest string is 0xFFFFFFFF
+    static char          s_session_name[16];
+    SecuritySessionId    id;
+    
+    s_session_name[0] = '\0';
+    
+    if (SessionGetInfo (callerSecuritySession, &id, NULL) == noErr) {
+        snprintf (s_session_name, sizeof (s_session_name), "0x%lx", id);
+    }
+    
+    return s_session_name;
+}
+
+// ---------------------------------------------------------------------------
+
+uid_t kipc_session_get_session_uid (void)
+{
+    // Get the uid of the user that the server will be run and named for.
+    uid_t uid = geteuid ();
+    
+    // Avoid root because the client can later go back to the real uid    
+    if (uid == 0 /* root */) {
+        dprintf ("%s(): geteuid returned UID %d, trying getuid...\n", __FUNCTION__, uid);
+        uid = getuid ();
+    }
+    
+    return uid;
+}
+
+// ---------------------------------------------------------------------------
+
+uid_t kipc_session_get_server_uid (void)
+{
+    uid_t server_uid = 92;
+    
+    struct passwd *pw = getpwnam ("securityagent");
+    if (pw != NULL) {
+        server_uid = pw->pw_uid;
+    } else {
+        dprintf ("%s: getpwnam(securityagent) failed, using hardcoded value.", __FUNCTION__);
+    }
+    
+    return server_uid;
+}
diff --git a/src/lib/ccapi/common/mac/KerberosIPC/notify.defs b/src/lib/ccapi/common/mac/KerberosIPC/notify.defs
new file mode 100644 (file)
index 0000000..fea03c9
--- /dev/null
@@ -0,0 +1,36 @@
+/*
+ * mach_notify.defs
+ *
+ * $Header$
+ *
+ * Copyright 2003 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.
+ */
+
+/* 
+ * This is totally disgusting. 
+ * Rename the demux function so we don't collide with other libraries using this.
+ */
+#define notify_server mach_notify_server
+
+#include <mach/notify.defs>