From: Alexandra Ellwood Date: Sun, 28 Sep 2008 19:43:47 +0000 (+0000) Subject: Create common stream and ipc layer for CCAPI and KIM. X-Git-Tag: krb5-1.7-alpha1~402 X-Git-Url: http://git.tremily.us/?a=commitdiff_plain;h=b5dce4285a9330d25542528030ce93da78e36375;p=krb5.git Create common stream and ipc layer for CCAPI and KIM. Will switch CCAPI to this new code later though, so as not to destabilize KfM and the Windows builds. ticket: 6055 git-svn-id: svn://anonsvn.mit.edu/krb5/trunk@20769 dc483132-0cff-0310-8789-dd5450dbe970 --- diff --git a/src/include/k5-ipc_stream.h b/src/include/k5-ipc_stream.h new file mode 100644 index 000000000..55397ef90 --- /dev/null +++ b/src/include/k5-ipc_stream.h @@ -0,0 +1,82 @@ +/* + * $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 K5_IPC_STREAM_H +#define K5_IPC_STREAM_H + +#include "k5-platform.h" + +struct k5_ipc_stream; +typedef struct k5_ipc_stream *k5_ipc_stream; + + +int32_t k5_ipc_stream_new (k5_ipc_stream *out_stream); + +uint32_t k5_ipc_stream_release (k5_ipc_stream io_stream); + +uint64_t k5_ipc_stream_size (k5_ipc_stream in_stream); + +const char *k5_ipc_stream_data (k5_ipc_stream in_stream); + +uint32_t k5_ipc_stream_read (k5_ipc_stream in_stream, + void *io_data, + uint64_t in_size); +uint32_t k5_ipc_stream_write (k5_ipc_stream in_stream, + const void *in_data, + uint64_t in_size); + +uint32_t k5_ipc_stream_read_string (k5_ipc_stream io_stream, + char **out_string); +uint32_t k5_ipc_stream_write_string (k5_ipc_stream io_stream, + const char *in_string); +void k5_ipc_stream_free_string (char *in_string); + +uint32_t k5_ipc_stream_read_int32 (k5_ipc_stream io_stream, + int32_t *out_int32); +uint32_t k5_ipc_stream_write_int32 (k5_ipc_stream io_stream, + int32_t in_int32); + +uint32_t k5_ipc_stream_read_uint32 (k5_ipc_stream io_stream, + uint32_t *out_uint32); +uint32_t k5_ipc_stream_write_uint32 (k5_ipc_stream io_stream, + uint32_t in_uint32); + +uint32_t k5_ipc_stream_read_int64 (k5_ipc_stream io_stream, + int64_t *out_int64); +uint32_t k5_ipc_stream_write_int64 (k5_ipc_stream io_stream, + int64_t in_int64); + +uint32_t k5_ipc_stream_read_uint64 (k5_ipc_stream io_stream, + uint64_t *out_uint64); +uint32_t k5_ipc_stream_write_uint64 (k5_ipc_stream io_stream, + uint64_t in_uint64); + +uint32_t k5_ipc_stream_read_time (k5_ipc_stream io_stream, + time_t *out_time); +uint32_t k5_ipc_stream_write_time (k5_ipc_stream io_stream, + time_t in_time); + +#endif /* K5_IPC_STREAM_H */ diff --git a/src/include/k5-thread.h b/src/include/k5-thread.h index c2d4f4bf2..57aa78f4b 100644 --- a/src/include/k5-thread.h +++ b/src/include/k5-thread.h @@ -414,6 +414,9 @@ typedef enum { K5_KEY_CCAPI_REQUEST_PORT, K5_KEY_CCAPI_REPLY_STREAM, K5_KEY_CCAPI_SERVER_DIED, + K5_KEY_IPC_REQUEST_PORT, + K5_KEY_IPC_REPLY_STREAM, + K5_KEY_IPC_SERVER_DIED, K5_KEY_COM_ERR_REENTER, #endif K5_KEY_MAX diff --git a/src/include/kim/kim_ui_plugin.h b/src/include/kim/kim_ui_plugin.h index b7d48ad89..0f6895ffc 100644 --- a/src/include/kim/kim_ui_plugin.h +++ b/src/include/kim/kim_ui_plugin.h @@ -40,7 +40,7 @@ enum kim_prompt_type_enum { kim_prompt_type_password = 0, kim_prompt_type_preauth = 1 }; - + /* * Plugins for Controlling Identity Selection and Credential Acquisition * diff --git a/src/kim/agent/mac/ServerDemux.h b/src/kim/agent/mac/ServerDemux.h new file mode 100644 index 000000000..12afa36c2 --- /dev/null +++ b/src/kim/agent/mac/ServerDemux.h @@ -0,0 +1,58 @@ +/* + * 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. + */ + +#import "k5_mig_requestServer.h" +#import "k5_mig_reply.h" +#import "k5-ipc_stream.h" +#import "k5_mig_server.h" + + +int32_t kim_agent_listen_loop (void); + +int32_t kim_handle_reply_init (mach_port_t in_reply_port, + int32_t in_error); + +int32_t kim_handle_reply_enter_identity (mach_port_t in_reply_port, + kim_identity in_identity, + int32_t in_error); + +int32_t kim_handle_reply_select_identity (mach_port_t in_reply_port, + kim_identity in_identity, + int32_t in_error); + +int32_t kim_handle_reply_auth_prompt (mach_port_t in_reply_port, + kim_string in_prompt_response, + int32_t in_error); + +int32_t kim_handle_reply_change_password (mach_port_t in_reply_port, + kim_string in_old_password, + kim_string in_new_password, + kim_string in_vfy_password, + int32_t in_error); + +int32_t kim_handle_reply_handle_error (mach_port_t in_reply_port, + int32_t in_error); + +int32_t kim_handle_reply_fini (mach_port_t in_reply_port, + int32_t in_error); diff --git a/src/kim/agent/mac/ServerDemux.m b/src/kim/agent/mac/ServerDemux.m index b7f208417..7c2e4f084 100644 --- a/src/kim/agent/mac/ServerDemux.m +++ b/src/kim/agent/mac/ServerDemux.m @@ -22,18 +22,16 @@ * or implied warranty. */ -#import "kim_migServer.h" -#import "ServerThread.h" +#import "ServerDemux.h" // --------------------------------------------------------------------------- -static kim_boolean caller_is_front_process (task_t in_task, +static kim_boolean caller_is_front_process (pid_t in_pid, NSString *in_path) { kim_error err = KIM_NO_ERROR; - Boolean is_front_process; - pid_t task_pid; - ProcessSerialNumber task_psn, front_psn; + kim_boolean is_front_process = FALSE; + NSNumber *active_pid = NULL; NSBundle *bundle = [NSBundle bundleWithPath: in_path]; if (bundle) { @@ -46,573 +44,553 @@ static kim_boolean caller_is_front_process (task_t in_task, } if (!err) { - err = pid_for_task (in_task, &task_pid); + NSDictionary *activeApplication = [[NSWorkspace sharedWorkspace] activeApplication]; + if (activeApplication) { + active_pid = [activeApplication objectForKey: @"NSApplicationProcessIdentifier"]; + } + } + + if (!err && active_pid) { + is_front_process = ([active_pid intValue] == in_pid); } + return is_front_process; +} + +#pragma mark - + +/* ------------------------------------------------------------------------ */ + +static int32_t kim_handle_request_init (mach_port_t in_client_port, + mach_port_t in_reply_port, + k5_ipc_stream in_request_stream) +{ + int32_t err = 0; + int32_t pid = 0; + char *name = NULL; + char *path = NULL; + bool isFrontProcess = 0; + if (!err) { - err = GetProcessForPID (task_pid, &task_psn); + err = k5_ipc_stream_read_int32 (in_request_stream, &pid); } if (!err) { - err = GetFrontProcess (&front_psn); + err = k5_ipc_stream_read_string (in_request_stream, &name); + } + + if (!err) { + err = k5_ipc_stream_read_string (in_request_stream, &path); + } + + + if (!err) { + isFrontProcess = caller_is_front_process (pid, + [NSString stringWithUTF8String: path]); } if (!err) { - err = SameProcess (&task_psn, &front_psn, &is_front_process); +#warning Send init message to main thread with 2 ports, name and path } - return !err ? is_front_process : FALSE; -} + k5_ipc_stream_free_string (name); + k5_ipc_stream_free_string (path); -#pragma mark - + return err; +} /* ------------------------------------------------------------------------ */ -kern_return_t kim_mipc_srv_init (mach_port_t in_server_port, - task_t in_application_task, - kim_mipc_in_string in_application_name, - mach_msg_type_number_t in_application_nameCnt, - kim_mipc_in_string in_application_path, - mach_msg_type_number_t in_application_pathCnt, - kim_mipc_error *out_error) +int32_t kim_handle_reply_init (mach_port_t in_reply_port, + int32_t in_error) { - kern_return_t err = 0; - ServerThread *sthread = NULL; + int32_t err = 0; + k5_ipc_stream reply = NULL; if (!err) { - sthread = [ServerThread sharedServerThread]; - if (!sthread) { err = KIM_OUT_OF_MEMORY_ERR; } + err = k5_ipc_stream_new (&reply); } if (!err) { - kim_mipc_error result = KIM_NO_ERROR; - NSString *name = NULL; - NSString *path = NULL; + err = k5_ipc_stream_write_int32 (reply, in_error); + } + + if (!err) { + err = k5_ipc_server_send_reply (in_reply_port, reply); + } + + k5_ipc_stream_release (reply); + + return err; +} - if (in_application_name) { - name = [NSString stringWithUTF8String: in_application_name]; - } +#pragma mark - - if (in_application_path) { - path = [NSString stringWithUTF8String: in_application_path]; - } - - [sthread addConnectionWithPort: in_server_port - name: name - path: path - frontProcess: caller_is_front_process (in_application_task, - path)]; - *out_error = result; +/* ------------------------------------------------------------------------ */ + +static int32_t kim_handle_request_enter_identity (mach_port_t in_client_port, + mach_port_t in_reply_port, + k5_ipc_stream in_request_stream) +{ + int32_t err = 0; + + if (!err) { +#warning Send enter identity message to main thread with 2 ports } - return err; + return err; } /* ------------------------------------------------------------------------ */ -kern_return_t kim_mipc_srv_enter_identity (mach_port_t in_server_port, - kim_mipc_out_string *out_identity, - mach_msg_type_number_t *out_identityCnt, - kim_mipc_error *out_error) +int32_t kim_handle_reply_enter_identity (mach_port_t in_reply_port, + kim_identity in_identity, + int32_t in_error) { - kern_return_t err = 0; - kim_error result = KIM_NO_ERROR; - ClientConnection *client = NULL; - kim_identity identity = NULL; + int32_t err = 0; + k5_ipc_stream reply = NULL; kim_string identity_string = NULL; - mach_msg_type_number_t identity_len = 0; - kim_mipc_out_string identity_buf = NULL; if (!err) { - ServerThread *sthread = [ServerThread sharedServerThread]; - if (!sthread) { err = KIM_OUT_OF_MEMORY_ERR; } - - if (!err) { - client = [sthread connectionForPort: in_server_port]; - if (!client) { err = KIM_OUT_OF_MEMORY_ERR; } - } + err = kim_identity_get_string (in_identity, &identity_string); } if (!err) { - identity = [client enterIdentityWithError: &result]; + err = k5_ipc_stream_new (&reply); } - if (!err && !result) { - err = kim_identity_get_string (identity, &identity_string); - } - - if (!err && !result && identity_string) { - identity_len = strlen (identity_string) + 1; - err = vm_allocate (mach_task_self (), - (vm_address_t *) &identity_buf, identity_len, TRUE); - + if (!err) { + err = k5_ipc_stream_write_int32 (reply, in_error); } - if (!err && !result) { - memmove (identity_buf, identity_string, identity_len); - *out_identity = identity_buf; - *out_identityCnt = identity_len; - identity_buf = NULL; + if (!err && !in_error) { + err = k5_ipc_stream_write_string (reply, identity_string); } if (!err) { - *out_error = result; + err = k5_ipc_server_send_reply (in_reply_port, reply); } - if (identity_buf) { vm_deallocate (mach_task_self (), (vm_address_t) identity_buf, identity_len); } kim_string_free (&identity_string); - kim_identity_free (&identity); + k5_ipc_stream_release (reply); - return err; + return err; } +#pragma mark - + /* ------------------------------------------------------------------------ */ -kern_return_t kim_mipc_srv_select_identity (mach_port_t in_server_port, - kim_mipc_in_string in_application_id, - mach_msg_type_number_t in_application_idCnt, - kim_mipc_in_string in_explanation, - mach_msg_type_number_t in_explanationCnt, - kim_mipc_time in_start_time, - kim_mipc_lifetime in_lifetime, - kim_mipc_boolean in_renewable, - kim_mipc_lifetime in_renewal_lifetime, - kim_mipc_boolean in_forwardable, - kim_mipc_boolean in_proxiable, - kim_mipc_boolean in_addressless, - kim_mipc_in_string in_service_name, - mach_msg_type_number_t in_service_nameCnt, - kim_mipc_in_string in_service_identity_hint, - mach_msg_type_number_t in_service_identity_hintCnt, - kim_mipc_in_string in_client_realm_hint, - mach_msg_type_number_t in_client_realm_hintCnt, - kim_mipc_in_string in_user_hint, - mach_msg_type_number_t in_user_hintCnt, - kim_mipc_in_string in_service_realm_hint, - mach_msg_type_number_t in_service_realm_hintCnt, - kim_mipc_in_string in_service_hint, - mach_msg_type_number_t in_service_hintCnt, - kim_mipc_in_string in_server_hint, - mach_msg_type_number_t in_server_hintCnt, - kim_mipc_out_string *out_identity, - mach_msg_type_number_t *out_identityCnt, - kim_mipc_error *out_error) +static int32_t kim_handle_request_select_identity (mach_port_t in_client_port, + mach_port_t in_reply_port, + k5_ipc_stream in_request_stream) { - kern_return_t err = 0; - kim_error result = KIM_NO_ERROR; - ClientConnection *client = NULL; + int32_t err = 0; kim_selection_hints hints = NULL; - kim_identity identity = NULL; - kim_string identity_string = NULL; - mach_msg_type_number_t identity_len = 0; - kim_mipc_out_string identity_buf = NULL; if (!err) { - err = kim_selection_hints_create (&hints, in_application_id); - } + //err = kim_os_selection_hints_read (out_hints, in_request_stream); + } if (!err) { - kim_options options = NULL; - - err = kim_options_create (&options); - - if (!err) { - err = kim_options_set_start_time (options, in_start_time); - } - - if (!err) { - err = kim_options_set_lifetime (options, in_lifetime); - } - - if (!err) { - err = kim_options_set_renewable (options, in_renewable); - } - - if (!err) { - err = kim_options_set_renewal_lifetime (options, in_renewal_lifetime); - } - - if (!err) { - err = kim_options_set_forwardable (options, in_forwardable); - } - - if (!err) { - err = kim_options_set_proxiable (options, in_proxiable); - } - - if (!err) { - err = kim_options_set_addressless (options, in_addressless); - } - - if (!err) { - err = kim_options_set_service_name (options, in_service_name); - } - - if (!err) { - err = kim_selection_hints_set_options (hints, options); - } - - kim_options_free (&options); +#warning Send select identity message to main thread with 2 ports } + kim_selection_hints_free (&hints); + + return err; +} + +/* ------------------------------------------------------------------------ */ + +int32_t kim_handle_reply_select_identity (mach_port_t in_reply_port, + kim_identity in_identity, + int32_t in_error) +{ + int32_t err = 0; + k5_ipc_stream reply = NULL; + kim_string identity_string = NULL; + if (!err) { - err = kim_selection_hints_set_explanation (hints, in_explanation); + err = kim_identity_get_string (in_identity, &identity_string); } - if (!err && in_service_identity_hint) { - err = kim_selection_hints_set_hint (hints, - kim_hint_key_service_identity, - in_service_identity_hint); + if (!err) { + err = k5_ipc_stream_new (&reply); } - if (!err && in_client_realm_hint) { - err = kim_selection_hints_set_hint (hints, - kim_hint_key_client_realm, - in_client_realm_hint); + if (!err) { + err = k5_ipc_stream_write_int32 (reply, in_error); } - if (!err && in_user_hint) { - err = kim_selection_hints_set_hint (hints, - kim_hint_key_user, - in_user_hint); + if (!err && !in_error) { + err = k5_ipc_stream_write_string (reply, identity_string); } - if (!err && in_service_realm_hint) { - err = kim_selection_hints_set_hint (hints, - kim_hint_key_service_realm, - in_service_realm_hint); + if (!err) { + err = k5_ipc_server_send_reply (in_reply_port, reply); } - if (!err && in_service_hint) { - err = kim_selection_hints_set_hint (hints, - kim_hint_key_service, - in_service_hint); - } + kim_string_free (&identity_string); + k5_ipc_stream_release (reply); - if (!err && in_server_hint) { - err = kim_selection_hints_set_hint (hints, - kim_hint_key_server, - in_server_hint); - } + return err; +} + +#pragma mark - + +/* ------------------------------------------------------------------------ */ + +static int32_t kim_handle_request_auth_prompt (mach_port_t in_client_port, + mach_port_t in_reply_port, + k5_ipc_stream in_request_stream) +{ + int32_t err = 0; + char *identity_string = NULL; + int32_t type = 0; + int32_t hide_reply = 0; + char *title = NULL; + char *message = NULL; + char *description = NULL; if (!err) { - ServerThread *sthread = [ServerThread sharedServerThread]; - if (!sthread) { err = KIM_OUT_OF_MEMORY_ERR; } - - if (!err) { - client = [sthread connectionForPort: in_server_port]; - if (!client) { err = KIM_OUT_OF_MEMORY_ERR; } - } - } + err = k5_ipc_stream_read_string (in_request_stream, &identity_string); + } if (!err) { - identity = [client selectIdentityWithHints: hints - error: &result]; - } + err = k5_ipc_stream_read_int32 (in_request_stream, &type); + } + + if (!err) { + err = k5_ipc_stream_read_int32 (in_request_stream, &hide_reply); + } + + if (!err) { + err = k5_ipc_stream_read_string (in_request_stream, &title); + } + + if (!err) { + err = k5_ipc_stream_read_string (in_request_stream, &message); + } - if (!err && !result) { - err = kim_identity_get_string (identity, &identity_string); + if (!err) { + err = k5_ipc_stream_read_string (in_request_stream, &description); + } + + if (!err) { +#warning Send auth prompt message to main thread with 2 ports and arguments } + + k5_ipc_stream_free_string (identity_string); + k5_ipc_stream_free_string (title); + k5_ipc_stream_free_string (message); + k5_ipc_stream_free_string (description); + + return err; +} - if (!err && !result && identity_string) { - identity_len = strlen (identity_string) + 1; - err = vm_allocate (mach_task_self (), - (vm_address_t *) &identity_buf, identity_len, TRUE); +/* ------------------------------------------------------------------------ */ + +int32_t kim_handle_reply_auth_prompt (mach_port_t in_reply_port, + kim_string in_prompt_response, + int32_t in_error) +{ + int32_t err = 0; + k5_ipc_stream reply = NULL; + + if (!err) { + err = k5_ipc_stream_new (&reply); + } + + if (!err) { + err = k5_ipc_stream_write_int32 (reply, in_error); } - if (!err && !result) { - memmove (identity_buf, identity_string, identity_len); - *out_identity = identity_buf; - *out_identityCnt = identity_len; - identity_buf = NULL; + if (!err && !in_error) { + err = k5_ipc_stream_write_string (reply, in_prompt_response); } - + if (!err) { - *out_error = result; + err = k5_ipc_server_send_reply (in_reply_port, reply); } - if (identity_buf) { vm_deallocate (mach_task_self (), - (vm_address_t) identity_buf, - identity_len); } - kim_string_free (&identity_string); - kim_identity_free (&identity); - kim_selection_hints_free (&hints); - - return err; + k5_ipc_stream_release (reply); + + return err; } +#pragma mark - + /* ------------------------------------------------------------------------ */ -kern_return_t kim_mipc_srv_auth_prompt (mach_port_t in_server_port, - kim_mipc_in_string in_identity, - mach_msg_type_number_t in_identityCnt, - kim_mipc_prompt_type in_prompt_type, - kim_mipc_boolean in_hide_reply, - kim_mipc_in_string in_title, - mach_msg_type_number_t in_titleCnt, - kim_mipc_in_string in_message, - mach_msg_type_number_t in_messageCnt, - kim_mipc_in_string in_description, - mach_msg_type_number_t in_descriptionCnt, - kim_mipc_out_string *out_response, - mach_msg_type_number_t *out_responseCnt, - kim_mipc_error *out_error) +static int32_t kim_handle_request_change_password (mach_port_t in_client_port, + mach_port_t in_reply_port, + k5_ipc_stream in_request_stream) { - kern_return_t err = 0; - kim_error result = KIM_NO_ERROR; - ClientConnection *client = NULL; - kim_identity identity = NULL; - const char *response_string = NULL; - mach_msg_type_number_t response_len = 0; - kim_mipc_out_string response_buf = NULL; - - if (!err) { - ServerThread *sthread = [ServerThread sharedServerThread]; - if (!sthread) { err = KIM_OUT_OF_MEMORY_ERR; } - - if (!err) { - client = [sthread connectionForPort: in_server_port]; - if (!client) { err = KIM_OUT_OF_MEMORY_ERR; } - } + int32_t err = 0; + char *identity_string = NULL; + int32_t old_password_expired = 0; + + if (!err) { + err = k5_ipc_stream_read_string (in_request_stream, &identity_string); + } + + if (!err) { + err = k5_ipc_stream_read_int32 (in_request_stream, + &old_password_expired); + } + + if (!err) { +#warning Send change password message to main thread with 2 ports and arguments } + k5_ipc_stream_free_string (identity_string); + + return err; +} + +/* ------------------------------------------------------------------------ */ + +int32_t kim_handle_reply_change_password (mach_port_t in_reply_port, + kim_string in_old_password, + kim_string in_new_password, + kim_string in_vfy_password, + int32_t in_error) +{ + int32_t err = 0; + k5_ipc_stream reply = NULL; + if (!err) { - err = kim_identity_create_from_string (&identity, in_identity); + err = k5_ipc_stream_new (&reply); } if (!err) { - NSString *title = NULL; - NSString *message = NULL; - NSString *description = NULL; - - if (in_title) { - title = [NSString stringWithUTF8String: in_title]; - } - - if (in_message) { - message = [NSString stringWithUTF8String: in_message]; - } - - if (in_description) { - description = [NSString stringWithUTF8String: in_description]; - } - - response_string = [[client authPromptWithIdentity: identity - type: in_prompt_type - hideReply: in_hide_reply - title: title - message: message - description: description - error: &result] UTF8String]; + err = k5_ipc_stream_write_int32 (reply, in_error); + } + + if (!err && !in_error) { + err = k5_ipc_stream_write_string (reply, in_old_password); } - if (!err && !result && response_string) { - response_len = strlen (response_string) + 1; - err = vm_allocate (mach_task_self (), - (vm_address_t *) &response_buf, response_len, TRUE); - + if (!err && !in_error) { + err = k5_ipc_stream_write_string (reply, in_new_password); } - if (!err && !result) { - memmove (response_buf, response_string, response_len); - *out_response = response_buf; - *out_responseCnt = response_len; - response_buf = NULL; + if (!err && !in_error) { + err = k5_ipc_stream_write_string (reply, in_vfy_password); } if (!err) { - *out_error = result; + err = k5_ipc_server_send_reply (in_reply_port, reply); } - if (response_buf) { vm_deallocate (mach_task_self (), - (vm_address_t) response_buf, - response_len); } - kim_identity_free (&identity); + k5_ipc_stream_release (reply); - return err; + return err; } +#pragma mark - + /* ------------------------------------------------------------------------ */ -kern_return_t kim_mipc_srv_change_password (mach_port_t in_server_port, - kim_mipc_in_string in_identity, - mach_msg_type_number_t in_identityCnt, - kim_mipc_boolean in_old_password_expired, - kim_mipc_out_string *out_old_password, - mach_msg_type_number_t *out_old_passwordCnt, - kim_mipc_out_string *out_new_password, - mach_msg_type_number_t *out_new_passwordCnt, - kim_mipc_out_string *out_vfy_password, - mach_msg_type_number_t *out_vfy_passwordCnt, - kim_mipc_error *out_error) +static int32_t kim_handle_request_handle_error (mach_port_t in_client_port, + mach_port_t in_reply_port, + k5_ipc_stream in_request_stream) { - kern_return_t err = 0; - kim_error result = KIM_NO_ERROR; - ClientConnection *client = NULL; - kim_identity identity = NULL; - NSArray *passwords = NULL; - const char *old_password_string = NULL; - const char *new_password_string = NULL; - const char *vfy_password_string = NULL; - mach_msg_type_number_t old_password_len = 0; - mach_msg_type_number_t new_password_len = 0; - mach_msg_type_number_t vfy_password_len = 0; - kim_mipc_out_string old_password_buf = NULL; - kim_mipc_out_string new_password_buf = NULL; - kim_mipc_out_string vfy_password_buf = NULL; - - if (!err) { - ServerThread *sthread = [ServerThread sharedServerThread]; - if (!sthread) { err = KIM_OUT_OF_MEMORY_ERR; } - - if (!err) { - client = [sthread connectionForPort: in_server_port]; - if (!client) { err = KIM_OUT_OF_MEMORY_ERR; } - } - } + int32_t err = 0; + char *identity_string = NULL; + int32_t error = 0; + char *message = NULL; + char *description = NULL; if (!err) { - err = kim_identity_create_from_string (&identity, in_identity); - } + err = k5_ipc_stream_read_string (in_request_stream, &identity_string); + } if (!err) { - passwords = [client changePasswordWithIdentity: identity - oldPasswordIsExpired: in_old_password_expired - error: &result]; - } + err = k5_ipc_stream_read_int32 (in_request_stream, &error); + } - if (!err && !result) { - if (passwords && [passwords count] == 3) { - old_password_string = [[passwords objectAtIndex: 1] UTF8String]; - new_password_string = [[passwords objectAtIndex: 2] UTF8String]; - vfy_password_string = [[passwords objectAtIndex: 3] UTF8String]; - } else { - err = KIM_OUT_OF_MEMORY_ERR; - } - } - - if (!err && !result && old_password_string) { - old_password_len = strlen (old_password_string) + 1; - err = vm_allocate (mach_task_self (), (vm_address_t *) &old_password_buf, old_password_len, TRUE); - + if (!err) { + err = k5_ipc_stream_read_string (in_request_stream, &message); + } + + if (!err) { + err = k5_ipc_stream_read_string (in_request_stream, &description); + } + + if (!err) { +#warning Send handle error message to main thread with 2 ports and arguments } + + k5_ipc_stream_free_string (identity_string); + k5_ipc_stream_free_string (message); + k5_ipc_stream_free_string (description); + + return err; +} - if (!err && !result && new_password_string) { - new_password_len = strlen (new_password_string) + 1; - err = vm_allocate (mach_task_self (), (vm_address_t *) &new_password_buf, new_password_len, TRUE); - - } +/* ------------------------------------------------------------------------ */ + +int32_t kim_handle_reply_handle_error (mach_port_t in_reply_port, + int32_t in_error) +{ + int32_t err = 0; + k5_ipc_stream reply = NULL; - if (!err && !result && vfy_password_string) { - vfy_password_len = strlen (vfy_password_string) + 1; - err = vm_allocate (mach_task_self (), (vm_address_t *) &vfy_password_buf, vfy_password_len, TRUE); + if (!err) { + err = k5_ipc_stream_new (&reply); } - if (!err && !result) { - memmove (old_password_buf, old_password_string, old_password_len); - memmove (new_password_buf, new_password_string, new_password_len); - memmove (vfy_password_buf, vfy_password_string, vfy_password_len); - *out_old_password = old_password_buf; - *out_new_password = new_password_buf; - *out_vfy_password = vfy_password_buf; - *out_old_passwordCnt = old_password_len; - *out_new_passwordCnt = new_password_len; - *out_vfy_passwordCnt = vfy_password_len; - old_password_buf = NULL; - new_password_buf = NULL; - vfy_password_buf = NULL; + if (!err) { + err = k5_ipc_stream_write_int32 (reply, in_error); } - + if (!err) { - *out_error = result; + err = k5_ipc_server_send_reply (in_reply_port, reply); } - if (old_password_buf) { vm_deallocate (mach_task_self (), (vm_address_t) old_password_buf, old_password_len); } - if (new_password_buf) { vm_deallocate (mach_task_self (), (vm_address_t) new_password_buf, new_password_len); } - if (vfy_password_buf) { vm_deallocate (mach_task_self (), (vm_address_t) vfy_password_buf, vfy_password_len); } - kim_identity_free (&identity); + k5_ipc_stream_release (reply); - return err; + return err; } +#pragma mark - + /* ------------------------------------------------------------------------ */ -kern_return_t kim_mipc_srv_handle_error (mach_port_t in_server_port, - kim_mipc_in_string in_identity, - mach_msg_type_number_t in_identityCnt, - kim_mipc_error in_error, - kim_mipc_in_string in_message, - mach_msg_type_number_t in_messageCnt, - kim_mipc_in_string in_description, - mach_msg_type_number_t in_descriptionCnt, - kim_mipc_error *out_error) +static int32_t kim_handle_request_fini (mach_port_t in_client_port, + mach_port_t in_reply_port, + k5_ipc_stream in_request_stream) { - kern_return_t err = 0; - kim_error result = KIM_NO_ERROR; - ClientConnection *client = NULL; - kim_identity identity = NULL; - - if (!err) { - ServerThread *sthread = [ServerThread sharedServerThread]; - if (!sthread) { err = KIM_OUT_OF_MEMORY_ERR; } - - if (!err) { - client = [sthread connectionForPort: in_server_port]; - if (!client) { err = KIM_OUT_OF_MEMORY_ERR; } - } + int32_t err = 0; + + if (!err) { +#warning Send fini message to main thread with 2 ports } + return err; +} + +/* ------------------------------------------------------------------------ */ + +int32_t kim_handle_reply_fini (mach_port_t in_reply_port, + int32_t in_error) +{ + int32_t err = 0; + k5_ipc_stream reply = NULL; + if (!err) { - err = kim_identity_create_from_string (&identity, in_identity); + err = k5_ipc_stream_new (&reply); } if (!err) { - NSString *message = NULL; - NSString *description = NULL; - - if (in_message) { - message = [NSString stringWithUTF8String: in_message]; - } - - if (in_description) { - description = [NSString stringWithUTF8String: in_description]; - } - - result = [client handleError: in_error - identity: identity - message: message - description: description]; + err = k5_ipc_stream_write_int32 (reply, in_error); } if (!err) { - *out_error = result; + err = k5_ipc_server_send_reply (in_reply_port, reply); } - kim_identity_free (&identity); + k5_ipc_stream_release (reply); + + return err; +} + +#pragma mark - + +/* ------------------------------------------------------------------------ */ + +int32_t k5_ipc_server_add_client (mach_port_t in_client_port) +{ + int32_t err = 0; + + if (!err) { + /* Don't need to do anything here since we have an init message */ + } return err; } /* ------------------------------------------------------------------------ */ -kern_return_t kim_mipc_srv_fini (mach_port_t in_server_port, - kim_mipc_error *out_error) +int32_t k5_ipc_server_remove_client (mach_port_t in_client_port) { - kern_return_t err = 0; - ServerThread *sthread = NULL; + int32_t err = 0; if (!err) { - sthread = [ServerThread sharedServerThread]; - if (!sthread) { err = KIM_OUT_OF_MEMORY_ERR; } + /* Client exited. Main thread should check for windows belonging to + * in_client_port and close any it finds. */ +#warning Insert code to handle client death here } + + return err; +} + +/* ------------------------------------------------------------------------ */ +int32_t k5_ipc_server_handle_request (mach_port_t in_client_port, + mach_port_t in_reply_port, + k5_ipc_stream in_request_stream) +{ + int32_t err = 0; + char *message_type = NULL; + if (!err) { - [sthread removeConnectionWithPort: in_server_port]; + err = k5_ipc_stream_read_string (in_request_stream, &message_type); } if (!err) { - *out_error = KIM_NO_ERROR; + if (!strcmp (message_type, "init")) { + err = kim_handle_request_init (in_client_port, + in_reply_port, + in_request_stream); + + } else if (!strcmp (message_type, "enter_identity")) { + err = kim_handle_request_enter_identity (in_client_port, + in_reply_port, + in_request_stream); + + } else if (!strcmp (message_type, "select_identity")) { + err = kim_handle_request_select_identity (in_client_port, + in_reply_port, + in_request_stream); + + } else if (!strcmp (message_type, "auth_prompt")) { + err = kim_handle_request_auth_prompt (in_client_port, + in_reply_port, + in_request_stream); + + } else if (!strcmp (message_type, "change_password")) { + err = kim_handle_request_change_password (in_client_port, + in_reply_port, + in_request_stream); + + } else if (!strcmp (message_type, "handle_error")) { + err = kim_handle_request_handle_error (in_client_port, + in_reply_port, + in_request_stream); + + } else if (!strcmp (message_type, "fini")) { + err = kim_handle_request_fini (in_client_port, + in_reply_port, + in_request_stream); + + } else { + err = EINVAL; + } } + k5_ipc_stream_free_string (message_type); + return err; } + +#pragma mark - + +/* ------------------------------------------------------------------------ */ + +int32_t kim_agent_listen_loop (void) +{ + return k5_ipc_server_listen_loop (); +} diff --git a/src/kim/agent/mac/ServerThread.h b/src/kim/agent/mac/ServerThread.h deleted file mode 100644 index 4457f2a62..000000000 --- a/src/kim/agent/mac/ServerThread.h +++ /dev/null @@ -1,92 +0,0 @@ -/* - * 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 -#include - -@interface ClientConnection : NSObject { - mach_port_t port; - bool callerIsFrontProcess; - NSString *applicationName; - NSString *applicationPath; -} - -@property(readonly) mach_port_t port; - -- (id) initWithPort: (mach_port_t) port - name: (NSString *) name - path: (NSString *) path - front_process: (bool) frontProcess; - -- (kim_identity) enterIdentityWithError: (kim_error *) outError; - -- (kim_identity) selectIdentityWithHints: (kim_selection_hints) hints - error: (kim_error *) outError; - -- (NSString *) authPromptWithIdentity: (kim_identity) identity - type: (kim_prompt_type) type - hideReply: (bool) hideReply - title: (NSString *) title - message: (NSString *) message - description: (NSString *) description - error: (kim_error *) outError; - -- (NSArray *) changePasswordWithIdentity: (kim_identity) identity - oldPasswordIsExpired: (bool) oldPasswordIsExpired - error: (kim_error *) outError; - -- (kim_error) handleError: (kim_error) error - identity: (kim_identity) identity - message: (NSString *) message - description: (NSString *) description; - -- (void) dealloc; - -@end - -/* ------------------------------------------------------------------------ */ - -@interface ServerThread : NSObject { - NSMutableArray *connections; -} - -+ (ServerThread *) sharedServerThread; - -- (id) init; - -- (void) dealloc; - -- (kern_return_t) listen; - -- (void) addConnectionWithPort: (mach_port_t) port - name: (NSString *) name - path: (NSString *) path - frontProcess: (bool) frontProcess; - -- (void) removeConnectionWithPort: (mach_port_t) port; - - -- (ClientConnection *) connectionForPort: (mach_port_t) port; - -@end diff --git a/src/kim/agent/mac/ServerThread.m b/src/kim/agent/mac/ServerThread.m deleted file mode 100644 index 6d5ba5ed5..000000000 --- a/src/kim/agent/mac/ServerThread.m +++ /dev/null @@ -1,221 +0,0 @@ -/* - * 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. - */ -#import "ServerThread.h" -#import -#import -#import "kim_migServer.h" - - -@implementation ClientConnection - -@synthesize port; - -/* ------------------------------------------------------------------------ */ - -- (id) initWithPort: (mach_port_t) connectionPort - name: (NSString *) name - path: (NSString *) path - front_process: (bool) frontProcess -{ - if ((self = [super init])) { - port = connectionPort; - callerIsFrontProcess = frontProcess; - applicationName = [name retain]; - applicationPath = [path retain]; - } - - return self; -} - -/* ------------------------------------------------------------------------ */ - -- (kim_identity) enterIdentityWithError: (kim_error *) outError -{ - kim_error err = KIM_NO_ERROR; - kim_identity identity = NULL; - - *outError = err; - return identity; -} - -/* ------------------------------------------------------------------------ */ - -- (kim_identity) selectIdentityWithHints: (kim_selection_hints) hints - error: (kim_error *) outError -{ - kim_error err = KIM_NO_ERROR; - kim_identity identity = NULL; - - *outError = err; - return identity; -} - -/* ------------------------------------------------------------------------ */ - -- (NSString *) authPromptWithIdentity: (kim_identity) identity - type: (kim_prompt_type) type - hideReply: (bool) hideReply - title: (NSString *) title - message: (NSString *) message - description: (NSString *) description - error: (kim_error *) outError -{ - kim_error err = KIM_NO_ERROR; - NSString *reply = @"A reply"; - - *outError = err; - return reply; -} - -/* ------------------------------------------------------------------------ */ - -- (NSArray *) changePasswordWithIdentity: (kim_identity) identity - oldPasswordIsExpired: (bool) oldPasswordIsExpired - error: (kim_error *) outError -{ - kim_error err = KIM_NO_ERROR; - NSString *oldPassword = @"an old password"; - NSString *newPassword = @"a new password"; - NSString *verifyPassword = @"a verify password"; - - *outError = err; - return !err ? [NSArray arrayWithObjects: oldPassword, newPassword, verifyPassword, NULL] : NULL; -} - -/* ------------------------------------------------------------------------ */ - -- (kim_error) handleError: (kim_error) error - identity: (kim_identity) identity - message: (NSString *) message - description: (NSString *) description -{ - kim_error err = KIM_NO_ERROR; - - return err; -} - -/* ------------------------------------------------------------------------ */ - -- (void) dealloc -{ - [applicationName release]; - [applicationPath release]; - [super dealloc]; -} - -@end - -@implementation ServerThread - -/* ------------------------------------------------------------------------ */ - -+ (ServerThread *) sharedServerThread -{ - static ServerThread *gServerThread = NULL; - - if (!gServerThread) { - gServerThread = [[ServerThread alloc] init]; - } - - return gServerThread; -} - -/* ------------------------------------------------------------------------ */ - -- (id) init -{ - if ((self = [super init])) { - connections = [[NSMutableArray alloc] init]; - if (!connections) { - [self release]; - self = nil; - } - } - - return self; -} - -/* ------------------------------------------------------------------------ */ - -- (void) dealloc -{ - [connections release]; - [super dealloc]; -} - -/* ------------------------------------------------------------------------ */ - -- (kern_return_t) listen -{ - return kipc_server_run_server (kim_server); -} - -/* ------------------------------------------------------------------------ */ - -- (void) addConnectionWithPort: (mach_port_t) port - name: (NSString *) name - path: (NSString *) path - frontProcess: (bool) frontProcess -{ - ClientConnection *client = [[ClientConnection alloc] initWithPort: port - name: name - path: path - front_process: frontProcess]; - if (client) { - [connections addObject: client]; - } - - [client release]; -} - -/* ------------------------------------------------------------------------ */ - -- (void) removeConnectionWithPort: (mach_port_t) port -{ - for (ClientConnection *client in connections) { - if (client.port == port) { - [connections removeObject: client]; - } - } - - if (![connections count]) { - kipc_server_quit (); - } -} - - -/* ------------------------------------------------------------------------ */ - -- (ClientConnection *) connectionForPort: (mach_port_t) port -{ - for (ClientConnection *client in connections) { - if (client.port == port) { - return client; - } - } - return NULL; -} - -@end - diff --git a/src/kim/agent/mac/main.m b/src/kim/agent/mac/main.m index fb0b9dfd3..a6ffad1d0 100644 --- a/src/kim/agent/mac/main.m +++ b/src/kim/agent/mac/main.m @@ -1,6 +1,19 @@ #import +#import "k5_mig_server.h" -int main(int argc, char *argv[]) +int main(int argc, const char *argv[]) { - return NSApplicationMain(argc, (const char **) argv); + int err = 0; + + err = k5_ipc_server_initialize (argc, argv); + + if (!err) { + err = NSApplicationMain(argc, argv); + } + + if (!err) { + err = k5_ipc_server_cleanup (argc, argv); + } + + return err; } diff --git a/src/kim/lib/mac/kim_os_ui_gui.c b/src/kim/lib/mac/kim_os_ui_gui.c index 4f629105d..7559dbed9 100644 --- a/src/kim/lib/mac/kim_os_ui_gui.c +++ b/src/kim/lib/mac/kim_os_ui_gui.c @@ -27,107 +27,74 @@ #ifndef LEAN_CLIENT #include "kim_os_private.h" -#include "kim_mig_types.h" -#include "kim_mig.h" -#define kKerberosAgentBundleID "edu.mit.Kerberos.KerberosAgent" -#define kKerberosAgentPath "/System/Library/CoreServices/KerberosAgent.app/Contents/MacOS/KerberosAgent" +#include "k5_mig_client.h" #include #include #include +#include -struct kim_ui_gui_context { - mach_port_t port; -}; /* ------------------------------------------------------------------------ */ -static void kim_os_ui_gui_context_free (kim_ui_gui_context *io_context) -{ - if (io_context && *io_context) { - free (*io_context); - *io_context = NULL; - } -} - -/* ------------------------------------------------------------------------ */ - -static kim_error kim_os_ui_gui_context_allocate (kim_ui_gui_context *out_context) +kim_error kim_os_ui_gui_init (kim_ui_context *io_context) { kim_error err = KIM_NO_ERROR; - kim_ui_gui_context context = NULL; - - if (!err && !out_context) { err = check_error (KIM_NULL_PARAMETER_ERR); } + kim_string name = NULL; + kim_string path = NULL; + k5_ipc_stream request = NULL; + k5_ipc_stream reply = NULL; if (!err) { - context = malloc (sizeof (*context)); - if (!context) { err = KIM_OUT_OF_MEMORY_ERR; } + err = kim_library_get_application_name (&name); } if (!err) { - context->port = MACH_PORT_NULL; - - *out_context = context; - context = NULL; + err = kim_os_library_get_application_path (&path); } - kim_os_ui_gui_context_free (&context); - - return check_error (err); -} - -#pragma mark - - -/* ------------------------------------------------------------------------ */ - -kim_error kim_os_ui_gui_init (kim_ui_context *io_context) -{ - kim_error err = KIM_NO_ERROR; - kim_ui_gui_context context = NULL; - kim_string name = NULL; - kim_string path = NULL; + if (!err) { + err = k5_ipc_stream_new (&request); + } - if (!err && !io_context) { err = check_error (KIM_NULL_PARAMETER_ERR); } + if (!err) { + err = k5_ipc_stream_write_string (request, "init"); + } if (!err) { - err = kim_os_ui_gui_context_allocate (&context); + err = k5_ipc_stream_write_int32 (request, getpid()); } if (!err) { - err = kim_library_get_application_name (&name); + err = k5_ipc_stream_write_string (request, name); } if (!err) { - err = kim_os_library_get_application_path (&path); + err = k5_ipc_stream_write_string (request, path); } - + if (!err) { - err = kipc_client_lookup_server (kim_os_agent_bundle_id, - 1 /* launch */, - 0 /* don't use cached port */, - &context->port); + err = k5_ipc_send_request (1 /* launch server */, + request, + &reply); } if (!err) { - kim_mipc_error result = 0; - - err = kim_mipc_cli_init (context->port, - mach_task_self (), - name, kim_string_buflen (name), - path, kim_string_buflen (path), - &result); + int32_t result = 0; + + err = k5_ipc_stream_read_int32 (reply, &result); if (!err) { err = check_error (result); } } if (!err) { - io_context->tcontext = context; - context = NULL; + io_context->tcontext = NULL; } + k5_ipc_stream_release (request); + k5_ipc_stream_release (reply); kim_string_free (&name); kim_string_free (&path); - kim_os_ui_gui_context_free (&context); return check_error (err); } @@ -138,29 +105,46 @@ kim_error kim_os_ui_gui_enter_identity (kim_ui_context *in_context, kim_identity *out_identity) { kim_error err = KIM_NO_ERROR; - kim_mipc_out_string identity = NULL; - mach_msg_type_number_t identity_len = 0; + k5_ipc_stream request = NULL; + k5_ipc_stream reply = NULL; + char *identity_string = NULL; - if (!err && !in_context ) { err = check_error (KIM_NULL_PARAMETER_ERR); } if (!err && !out_identity) { err = check_error (KIM_NULL_PARAMETER_ERR); } if (!err) { - kim_ui_gui_context context = (kim_ui_gui_context) in_context->tcontext; - kim_mipc_error result = 0; + err = k5_ipc_stream_new (&request); + } + + if (!err) { + err = k5_ipc_stream_write_string (request, "enter_identity"); + } - err = kim_mipc_cli_enter_identity (context->port, - &identity, - &identity_len, - &result); + + if (!err) { + err = k5_ipc_send_request (0 /* don't launch server */, + request, + &reply); + if (!reply) { err = check_error (KIM_NO_SERVER_ERR); } + } + + if (!err) { + int32_t result = 0; + + err = k5_ipc_stream_read_int32 (reply, &result); if (!err) { err = check_error (result); } } if (!err) { - err = kim_identity_create_from_string (out_identity, identity); + err = k5_ipc_stream_read_string (reply, &identity_string); + } + + if (!err) { + err = kim_identity_create_from_string (out_identity, identity_string); } - if (identity) { vm_deallocate (mach_task_self (), - (vm_address_t) identity, identity_len); } + k5_ipc_stream_free_string (identity_string); + k5_ipc_stream_release (request); + k5_ipc_stream_release (reply); return check_error (err); } @@ -172,232 +156,136 @@ kim_error kim_os_ui_gui_select_identity (kim_ui_context *in_context, kim_identity *out_identity) { kim_error err = KIM_NO_ERROR; - kim_options options = NULL; - kim_time start_time = 0; - kim_lifetime lifetime; - kim_boolean renewable; - kim_lifetime renewal_lifetime; - kim_boolean forwardable; - kim_boolean proxiable; - kim_boolean addressless; - kim_string service_name = NULL; - kim_string application_id = NULL; - kim_string explanation = NULL; - kim_string service_identity_hint = NULL; - kim_string client_realm_hint = NULL; - kim_string user_hint = NULL; - kim_string service_realm_hint = NULL; - kim_string service_hint = NULL; - kim_string server_hint = NULL; - kim_mipc_out_string identity = NULL; - mach_msg_type_number_t identity_len = 0; - - if (!err && !in_context ) { err = check_error (KIM_NULL_PARAMETER_ERR); } + k5_ipc_stream request = NULL; + k5_ipc_stream reply = NULL; + char *identity_string = NULL; + if (!err && !in_hints ) { err = check_error (KIM_NULL_PARAMETER_ERR); } if (!err && !out_identity) { err = check_error (KIM_NULL_PARAMETER_ERR); } if (!err) { - err = kim_selection_hints_get_options (in_hints, &options); - - if (!err && !options) { - err = kim_options_create (&options); - } + err = k5_ipc_stream_new (&request); } if (!err) { - err = kim_options_get_start_time (options, &start_time); + err = k5_ipc_stream_write_string (request, "select_identity"); } if (!err) { - err = kim_options_get_lifetime (options, &lifetime); + //err = kim_os_selection_hints_write (in_hints, request); } if (!err) { - err = kim_options_get_renewable (options, &renewable); + err = k5_ipc_send_request (0 /* don't launch server */, + request, + &reply); + if (!reply) { err = check_error (KIM_NO_SERVER_ERR); } } if (!err) { - err = kim_options_get_renewal_lifetime (options, &renewal_lifetime); - } - - if (!err) { - err = kim_options_get_forwardable (options, &forwardable); + int32_t result = 0; + + err = k5_ipc_stream_read_int32 (reply, &result); + if (!err) { err = check_error (result); } } if (!err) { - err = kim_options_get_proxiable (options, &proxiable); + err = k5_ipc_stream_read_string (reply, &identity_string); } if (!err) { - err = kim_options_get_addressless (options, &addressless); + err = kim_identity_create_from_string (out_identity, identity_string); } - if (!err) { - err = kim_options_get_service_name (options, &service_name); - } + k5_ipc_stream_free_string (identity_string); + k5_ipc_stream_release (request); + k5_ipc_stream_release (reply); - if (!err) { - err = kim_selection_hints_get_explanation (in_hints, &explanation); - } + return check_error (err); +} +/* ------------------------------------------------------------------------ */ + +kim_error kim_os_ui_gui_auth_prompt (kim_ui_context *in_context, + kim_identity in_identity, + kim_prompt_type in_type, + kim_boolean in_hide_reply, + kim_string in_title, + kim_string in_message, + kim_string in_description, + char **out_reply) +{ + kim_error err = KIM_NO_ERROR; + k5_ipc_stream request = NULL; + k5_ipc_stream reply = NULL; + kim_string identity_string = NULL; + + if (!err && !in_identity) { err = check_error (KIM_NULL_PARAMETER_ERR); } + if (!err && !out_reply ) { err = check_error (KIM_NULL_PARAMETER_ERR); } + /* in_title, in_message or in_description may be NULL */ + if (!err) { - err = kim_selection_hints_get_application_id (in_hints, &application_id); + err = kim_identity_get_string (in_identity, &identity_string); } if (!err) { - err = kim_selection_hints_get_hint (in_hints, - kim_hint_key_service_identity, - &service_identity_hint); + err = k5_ipc_stream_new (&request); } if (!err) { - err = kim_selection_hints_get_hint (in_hints, - kim_hint_key_client_realm, - &client_realm_hint); + err = k5_ipc_stream_write_string (request, "auth_prompt"); } if (!err) { - err = kim_selection_hints_get_hint (in_hints, - kim_hint_key_user, - &user_hint); + err = k5_ipc_stream_write_string (request, identity_string); } if (!err) { - err = kim_selection_hints_get_hint (in_hints, - kim_hint_key_service_realm, - &service_realm_hint); + err = k5_ipc_stream_write_int32 (request, in_type); } if (!err) { - err = kim_selection_hints_get_hint (in_hints, - kim_hint_key_service, - &service_hint); + err = k5_ipc_stream_write_int32 (request, in_hide_reply); } if (!err) { - err = kim_selection_hints_get_hint (in_hints, - kim_hint_key_server, - &server_hint); + err = k5_ipc_stream_write_string (request, + in_title ? in_title : ""); } if (!err) { - kim_ui_gui_context context = (kim_ui_gui_context) in_context->tcontext; - kim_mipc_error result = 0; - - err = kim_mipc_cli_select_identity (context->port, - application_id, - kim_string_buflen (application_id), - explanation, - kim_string_buflen (explanation), - - start_time, - lifetime, - renewable, - renewal_lifetime, - forwardable, - proxiable, - addressless, - service_name, - kim_string_buflen (service_name), - - service_identity_hint, - kim_string_buflen (service_identity_hint), - - client_realm_hint, - kim_string_buflen (client_realm_hint), - - user_hint, - kim_string_buflen (user_hint), - - service_realm_hint, - kim_string_buflen (service_realm_hint), - - service_hint, - kim_string_buflen (service_hint), - - server_hint, - kim_string_buflen (server_hint), - - &identity, - &identity_len, - &result); - if (!err) { err = check_error (result); } + err = k5_ipc_stream_write_string (request, + in_message ? in_message : ""); } if (!err) { - err = kim_identity_create_from_string (out_identity, identity); + err = k5_ipc_stream_write_string (request, + in_description ? in_description : ""); } - if (identity) { vm_deallocate (mach_task_self (), - (vm_address_t) identity, identity_len); } - - kim_string_free (&application_id); - kim_string_free (&explanation); - kim_string_free (&service_name); - kim_string_free (&service_identity_hint); - kim_string_free (&client_realm_hint); - kim_string_free (&user_hint); - kim_string_free (&service_realm_hint); - kim_string_free (&service_hint); - kim_string_free (&server_hint); - kim_options_free (&options); - - return check_error (err); -} - -/* ------------------------------------------------------------------------ */ - -kim_error kim_os_ui_gui_auth_prompt (kim_ui_context *in_context, - kim_identity in_identity, - kim_prompt_type in_type, - kim_boolean in_hide_reply, - kim_string in_title, - kim_string in_message, - kim_string in_description, - char **out_reply) -{ - kim_error err = KIM_NO_ERROR; - kim_string identity_string = NULL; - kim_mipc_out_string reply = NULL; - mach_msg_type_number_t reply_len = 0; - - if (!err && !in_context ) { err = check_error (KIM_NULL_PARAMETER_ERR); } - if (!err && !in_identity) { err = check_error (KIM_NULL_PARAMETER_ERR); } - if (!err && !out_reply ) { err = check_error (KIM_NULL_PARAMETER_ERR); } - /* in_title, in_message or in_description may be NULL */ - if (!err) { - err = kim_identity_get_string (in_identity, &identity_string); + err = k5_ipc_send_request (0 /* don't launch server */, + request, + &reply); + if (!reply) { err = check_error (KIM_NO_SERVER_ERR); } } if (!err) { - kim_ui_gui_context context = (kim_ui_gui_context) in_context->tcontext; - kim_mipc_error result = 0; - - err = kim_mipc_cli_auth_prompt (context->port, - identity_string, - kim_string_buflen (identity_string), - in_type, - in_hide_reply, - in_title, - kim_string_buflen (in_title), - in_message, - kim_string_buflen (in_message), - in_description, - kim_string_buflen (in_description), - &reply, - &reply_len, - &result); + int32_t result = 0; + + err = k5_ipc_stream_read_int32 (reply, &result); if (!err) { err = check_error (result); } } if (!err) { - err = kim_string_copy ((kim_string *) out_reply, reply); - } + err = k5_ipc_stream_read_string (reply, out_reply); + } - if (reply) { vm_deallocate (mach_task_self (), (vm_address_t) reply, reply_len); } kim_string_free (&identity_string); - + + k5_ipc_stream_release (request); + k5_ipc_stream_release (reply); + return check_error (err); } @@ -408,85 +296,85 @@ kim_error kim_os_ui_gui_change_password (kim_ui_context *in_context, kim_boolean in_old_password_expired, char **out_old_password, char **out_new_password, - char **out_verify_password) + char **out_vfy_password) { kim_error err = KIM_NO_ERROR; + k5_ipc_stream request = NULL; + k5_ipc_stream reply = NULL; kim_string identity_string = NULL; - kim_mipc_out_string old_password_buf = NULL; - mach_msg_type_number_t old_password_len = 0; - kim_mipc_out_string new_password_buf = NULL; - mach_msg_type_number_t new_password_len = 0; - kim_mipc_out_string verify_password_buf = NULL; - mach_msg_type_number_t verify_password_len = 0; - - kim_string old_password = NULL; - kim_string new_password = NULL; - kim_string verify_password = NULL; + char *old_password = NULL; + char *new_password = NULL; + char *vfy_password = NULL; - if (!err && !in_context ) { err = check_error (KIM_NULL_PARAMETER_ERR); } - if (!err && !in_identity ) { err = check_error (KIM_NULL_PARAMETER_ERR); } - if (!err && !out_old_password ) { err = check_error (KIM_NULL_PARAMETER_ERR); } - if (!err && !out_new_password ) { err = check_error (KIM_NULL_PARAMETER_ERR); } - if (!err && !out_verify_password) { err = check_error (KIM_NULL_PARAMETER_ERR); } + if (!err && !in_identity ) { err = check_error (KIM_NULL_PARAMETER_ERR); } + if (!err && !out_old_password) { err = check_error (KIM_NULL_PARAMETER_ERR); } + if (!err && !out_new_password) { err = check_error (KIM_NULL_PARAMETER_ERR); } + if (!err && !out_vfy_password) { err = check_error (KIM_NULL_PARAMETER_ERR); } if (!err) { err = kim_identity_get_string (in_identity, &identity_string); } if (!err) { - kim_ui_gui_context context = (kim_ui_gui_context) in_context->tcontext; - kim_mipc_error result = 0; - - err = kim_mipc_cli_change_password (context->port, - identity_string, - kim_string_buflen (identity_string), - in_old_password_expired, - &old_password_buf, - &old_password_len, - &new_password_buf, - &new_password_len, - &verify_password_buf, - &verify_password_len, - &result); - if (!err) { err = check_error (result); } + err = k5_ipc_stream_new (&request); } if (!err) { - err = kim_string_copy (&old_password, old_password_buf); + err = k5_ipc_stream_write_string (request, "change_password"); } if (!err) { - err = kim_string_copy (&new_password, new_password_buf); + err = k5_ipc_stream_write_string (request, identity_string); } if (!err) { - err = kim_string_copy (&verify_password, verify_password_buf); + err = k5_ipc_stream_write_int32 (request, in_old_password_expired); } + if (!err) { + err = k5_ipc_send_request (0 /* don't launch server */, + request, + &reply); + if (!reply) { err = check_error (KIM_NO_SERVER_ERR); } + } + + if (!err) { + int32_t result = 0; + + err = k5_ipc_stream_read_int32 (reply, &result); + if (!err) { err = check_error (result); } + } + + if (!err) { + err = k5_ipc_stream_read_string (reply, &old_password); + } + + if (!err) { + err = k5_ipc_stream_read_string (reply, &new_password); + } + + if (!err) { + err = k5_ipc_stream_read_string (reply, &vfy_password); + } + if (!err) { *out_old_password = (char *) old_password; old_password = NULL; *out_new_password = (char *) new_password; new_password = NULL; - *out_verify_password = (char *) verify_password; - verify_password = NULL; - } - - if (old_password_buf) { vm_deallocate (mach_task_self (), - (vm_address_t) old_password_buf, - old_password_len); } - if (new_password_buf) { vm_deallocate (mach_task_self (), - (vm_address_t) new_password_buf, - new_password_len); } - if (verify_password_buf) { vm_deallocate (mach_task_self (), - (vm_address_t) verify_password_buf, - verify_password_len); } + *out_vfy_password = (char *) vfy_password; + vfy_password = NULL; + } + kim_string_free (&identity_string); - kim_string_free (&old_password); - kim_string_free (&new_password); - kim_string_free (&verify_password); + k5_ipc_stream_free_string (old_password); + k5_ipc_stream_free_string (new_password); + k5_ipc_stream_free_string (vfy_password); + k5_ipc_stream_release (request); + k5_ipc_stream_release (reply); + return check_error (err); } @@ -499,9 +387,10 @@ kim_error kim_os_ui_gui_handle_error (kim_ui_context *in_context, kim_string in_error_description) { kim_error err = KIM_NO_ERROR; + k5_ipc_stream request = NULL; + k5_ipc_stream reply = NULL; kim_string identity_string = NULL; - if (!err && !in_context ) { err = check_error (KIM_NULL_PARAMETER_ERR); } if (!err && !in_error_message ) { err = check_error (KIM_NULL_PARAMETER_ERR); } if (!err && !in_error_description) { err = check_error (KIM_NULL_PARAMETER_ERR); } @@ -510,23 +399,48 @@ kim_error kim_os_ui_gui_handle_error (kim_ui_context *in_context, } if (!err) { - kim_ui_gui_context context = (kim_ui_gui_context) in_context->tcontext; - kim_mipc_error result = 0; + err = k5_ipc_stream_new (&request); + } + + if (!err) { + err = k5_ipc_stream_write_string (request, "handle_error"); + } + + if (!err) { + err = k5_ipc_stream_write_string (request, identity_string); + } + + if (!err) { + err = k5_ipc_stream_write_int32 (request, in_error); + } + + if (!err) { + err = k5_ipc_stream_write_string (request, in_error_message); + } + + if (!err) { + err = k5_ipc_stream_write_string (request, in_error_description); + } + + if (!err) { + err = k5_ipc_send_request (0 /* don't launch server */, + request, + &reply); + if (!reply) { err = check_error (KIM_NO_SERVER_ERR); } + } + + if (!err) { + int32_t result = 0; - err = kim_mipc_cli_handle_error (context->port, - identity_string, - kim_string_buflen (identity_string), - in_error, - in_error_message, - kim_string_buflen (in_error_message), - in_error_description, - kim_string_buflen (in_error_description), - &result); - if (!err) { err = check_error (result); } + err = k5_ipc_stream_read_int32 (reply, &result); + if (!err) { err = check_error (result); } } kim_string_free (&identity_string); + k5_ipc_stream_release (request); + k5_ipc_stream_release (reply); + return check_error (err); } @@ -543,23 +457,34 @@ void kim_os_ui_gui_free_string (kim_ui_context *in_context, kim_error kim_os_ui_gui_fini (kim_ui_context *io_context) { kim_error err = KIM_NO_ERROR; + k5_ipc_stream request = NULL; + k5_ipc_stream reply = NULL; + + if (!err) { + err = k5_ipc_stream_new (&request); + } + + if (!err) { + err = k5_ipc_stream_write_string (request, "fini"); + } - if (!err && !io_context) { err = check_error (KIM_NULL_PARAMETER_ERR); } + if (!err) { + err = k5_ipc_send_request (0 /* don't launch server */, + request, + &reply); + if (!reply) { err = check_error (KIM_NO_SERVER_ERR); } + } if (!err) { - kim_ui_gui_context context = (kim_ui_gui_context) io_context->tcontext; - kim_mipc_error result = 0; + int32_t result = 0; - err = kim_mipc_cli_fini (context->port, &result); + err = k5_ipc_stream_read_int32 (reply, &result); if (!err) { err = check_error (result); } - - - if (!err) { - kim_os_ui_gui_context_free (&context); - io_context->tcontext = NULL; - } } + k5_ipc_stream_release (request); + k5_ipc_stream_release (reply); + return check_error (err); } diff --git a/src/kim/mac/kim_mig.defs b/src/kim/mac/kim_mig.defs deleted file mode 100644 index 8d041cf40..000000000 --- a/src/kim/mac/kim_mig.defs +++ /dev/null @@ -1,107 +0,0 @@ -/* - * $Header$ - * - * Copyright 2006-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 -#include - -import "kim_mig_types.h"; - -subsystem kim 100; - -serverprefix kim_mipc_srv_; -userprefix kim_mipc_cli_; - -type kim_mipc_in_string = array [] of char; -type kim_mipc_out_string = array [] of char; -type kim_mipc_error = int32_t; -type kim_mipc_boolean = boolean_t; -type kim_mipc_time = uint32_t; -type kim_mipc_lifetime = uint32_t; -type kim_mipc_prompt_type = uint32_t; - -routine init (in_server_port : mach_port_t; - in_application_task : task_t; - in_application_name : kim_mipc_in_string; - in_application_path : kim_mipc_in_string; - out out_error : kim_mipc_error); - -routine fini (in_server_port : mach_port_t; - out out_error : kim_mipc_error); - - -routine enter_identity (in_server_port : mach_port_t; - out out_identity : kim_mipc_out_string; - out out_error : kim_mipc_error); - -routine select_identity (in_server_port : mach_port_t; - in_application_id : kim_mipc_in_string; - in_explanation : kim_mipc_in_string; - - in_start_time : kim_mipc_time; - in_lifetime : kim_mipc_lifetime; - in_renewable : kim_mipc_boolean; - in_renewal_lifetime : kim_mipc_lifetime; - in_forwardable : kim_mipc_boolean; - in_proxiable : kim_mipc_boolean; - in_addressless : kim_mipc_boolean; - in_service_name : kim_mipc_in_string; - - in_service_identity_hint : kim_mipc_in_string; - in_client_realm_hint : kim_mipc_in_string; - in_user_hint : kim_mipc_in_string; - in_service_realm_hint : kim_mipc_in_string; - in_service_hint : kim_mipc_in_string; - in_server_hint : kim_mipc_in_string; - - out out_identity : kim_mipc_out_string; - out out_error : kim_mipc_error); - -routine auth_prompt (in_server_port : mach_port_t; - in_identity : kim_mipc_in_string; - in_prompt_type : kim_mipc_prompt_type; - in_hide_reply : kim_mipc_boolean; - in_title : kim_mipc_in_string; - in_message : kim_mipc_in_string; - in_description : kim_mipc_in_string; - out out_response : kim_mipc_out_string; - out out_error : kim_mipc_error); - -routine change_password (in_server_port : mach_port_t; - in_identity : kim_mipc_in_string; - in_old_password_expired : kim_mipc_boolean; - out out_old_password : kim_mipc_out_string; - out out_new_password : kim_mipc_out_string; - out out_verify_password : kim_mipc_out_string; - out out_error : kim_mipc_error); - - routine handle_error (in_server_port : mach_port_t; - in_identity : kim_mipc_in_string; - in_error : kim_mipc_error; - in_message : kim_mipc_in_string; - in_description : kim_mipc_in_string; - out out_error : kim_mipc_error); - - diff --git a/src/util/mac/k5_mig.defs b/src/util/mac/k5_mig.defs new file mode 100644 index 000000000..6349eb877 --- /dev/null +++ b/src/util/mac/k5_mig.defs @@ -0,0 +1,54 @@ +/* $Copyright: + * + * Copyright 2004-2006 by the Massachusetts Institute of Technology. + * + * All rights reserved. + * + * Export of this software from the United States of America may require a + * specific license from the United States Government. It is the + * responsibility of any person or organization contemplating export to + * obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and distribute + * this software and its documentation for any purpose and without fee is + * hereby granted, provided that the above copyright notice appear in all + * copies and that both that copyright notice and this permission notice + * appear in supporting documentation, and that the name of M.I.T. not be + * used in advertising or publicity pertaining to distribution of the + * software without specific, written prior permission. Furthermore if you + * modify this software you must label your software as modified software + * and not distribute it in such a fashion that it might be confused with + * the original MIT software. M.I.T. makes no representations about the + * suitability of this software for any purpose. It is provided "as is" + * without express or implied warranty. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF + * MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + * + * Individual source code files are copyright MIT, Cygnus Support, + * OpenVision, Oracle, Sun Soft, FundsXpress, and others. + * + * Project Athena, Athena, Athena MUSE, Discuss, Hesiod, Kerberos, Moira, + * and Zephyr are trademarks of the Massachusetts Institute of Technology + * (MIT). No commercial use of these trademarks may be made without prior + * written permission of MIT. + * + * "Commercial use" means use of a name in a product or other for-profit + * manner. It does NOT prevent a commercial firm from referring to the MIT + * trademarks in order to convey information (although in doing so, + * recognition of their trademark status should be given). + * $ + */ + +#include +#include + +import "k5_mig_types.h"; + +/* Note the 1024 must be the same as K5_IPC_MAX_MSG_SIZE */ +type k5_ipc_inl_request_t = array [ * : 1024 ] of char; +type k5_ipc_ool_request_t = array [] of char; + +type k5_ipc_inl_reply_t = array [ * : 1024 ] of char; +type k5_ipc_ool_reply_t = array [] of char; diff --git a/src/util/mac/k5_mig_client.c b/src/util/mac/k5_mig_client.c new file mode 100644 index 000000000..5ffe7deb8 --- /dev/null +++ b/src/util/mac/k5_mig_client.c @@ -0,0 +1,292 @@ +/* + * $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 "k5_mig_client.h" + +#include +#include "k5_mig_request.h" +#include "k5_mig_replyServer.h" +#include "k5-thread.h" + +MAKE_INIT_FUNCTION(k5_cli_ipc_thread_init); +MAKE_FINI_FUNCTION(k5_cli_ipc_thread_fini); + +/* ------------------------------------------------------------------------ */ + +static int k5_cli_ipc_thread_init (void) +{ + int err = 0; + + err = k5_key_register (K5_KEY_IPC_REQUEST_PORT, free); + + if (!err) { + err = k5_key_register (K5_KEY_IPC_REPLY_STREAM, NULL); + } + + if (!err) { + err = k5_key_register (K5_KEY_IPC_SERVER_DIED, NULL); + } + + return err; +} + +/* ------------------------------------------------------------------------ */ + +static void k5_cli_ipc_thread_fini (void) +{ + k5_key_delete (K5_KEY_IPC_REQUEST_PORT); + k5_key_delete (K5_KEY_IPC_REPLY_STREAM); + k5_key_delete (K5_KEY_IPC_SERVER_DIED); +} + +#pragma mark - + +/* ------------------------------------------------------------------------ */ + +static boolean_t k5_ipc_reply_demux (mach_msg_header_t *request, + mach_msg_header_t *reply) +{ + boolean_t handled = 0; + + if (CALL_INIT_FUNCTION (k5_cli_ipc_thread_init) != 0) { + return 0; + } + + if (!handled && request->msgh_id == MACH_NOTIFY_NO_SENDERS) { + int32_t *server_died = k5_getspecific (K5_KEY_IPC_SERVER_DIED); + if (!server_died) { + *server_died = 1; + } + + handled = 1; /* server died */ + } + + if (!handled) { + handled = k5_ipc_reply_server (request, reply); + } + + return handled; +} + +/* ------------------------------------------------------------------------ */ + +kern_return_t k5_ipc_client_reply (mach_port_t in_reply_port, + k5_ipc_inl_reply_t in_inl_reply, + mach_msg_type_number_t in_inl_replyCnt, + k5_ipc_ool_reply_t in_ool_reply, + mach_msg_type_number_t in_ool_replyCnt) +{ + kern_return_t err = KERN_SUCCESS; + k5_ipc_stream reply_stream = NULL; + + if (!err) { + err = CALL_INIT_FUNCTION (k5_cli_ipc_thread_init); + } + + if (!err) { + reply_stream = k5_getspecific (K5_KEY_IPC_REPLY_STREAM); + if (!reply_stream) { err = EINVAL; } + } + + if (!err) { + if (in_inl_replyCnt) { + err = k5_ipc_stream_write (reply_stream, in_inl_reply, in_inl_replyCnt); + + } else if (in_ool_replyCnt) { + err = k5_ipc_stream_write (reply_stream, in_ool_reply, in_ool_replyCnt); + + } else { + err = EINVAL; + } + } + + if (in_ool_replyCnt) { vm_deallocate (mach_task_self (), (vm_address_t) in_ool_reply, in_ool_replyCnt); } + + return err; +} + +#pragma mark - + +/* ------------------------------------------------------------------------ */ + +int32_t k5_ipc_send_request (int32_t in_launch_server, + k5_ipc_stream in_request_stream, + k5_ipc_stream *out_reply_stream) +{ + int err = 0; + int32_t done = 0; + int32_t try_count = 0; + int32_t server_died = 0; + mach_port_t server_port = MACH_PORT_NULL; + mach_port_t *request_port = NULL; + mach_port_t reply_port = MACH_PORT_NULL; + const char *inl_request = NULL; /* char * so we can pass the buffer in directly */ + mach_msg_type_number_t inl_request_length = 0; + k5_ipc_ool_request_t ool_request = NULL; + mach_msg_type_number_t ool_request_length = 0; + k5_ipc_stream reply_stream = NULL; + + if (!in_request_stream) { err = EINVAL; } + if (!out_reply_stream ) { err = EINVAL; } + + if (!err) { + err = CALL_INIT_FUNCTION (k5_cli_ipc_thread_init); + } + + if (!err) { + /* depending on how big the message is, use the fast inline buffer or + * the slow dynamically allocated buffer */ + mach_msg_type_number_t request_length = k5_ipc_stream_size (in_request_stream); + + if (request_length > K5_IPC_MAX_MSG_SIZE) { + //dprintf ("%s choosing out of line buffer (size is %d)", + // __FUNCTION__, request_length); + + err = vm_read (mach_task_self (), + (vm_address_t) k5_ipc_stream_data (in_request_stream), request_length, + (vm_address_t *) &ool_request, &ool_request_length); + } else { + //dprintf ("%s choosing in line buffer (size is %d)", + // __FUNCTION__, request_length); + + inl_request_length = request_length; + inl_request = k5_ipc_stream_data (in_request_stream); + } + } + + if (!err) { + request_port = k5_getspecific (K5_KEY_IPC_REQUEST_PORT); + + if (!request_port) { + request_port = malloc (sizeof (mach_port_t)); + if (!request_port) { err = ENOMEM; } + + if (!err) { + *request_port = MACH_PORT_NULL; + err = k5_setspecific (K5_KEY_IPC_REQUEST_PORT, request_port); + } + } + } + + if (!err) { + err = mach_port_allocate (mach_task_self (), MACH_PORT_RIGHT_RECEIVE, &reply_port); + } + + if (!err) { + err = kipc_client_lookup_server (K5_IPC_SERVER_ID, + in_launch_server, TRUE, &server_port); + } + + while (!err && !done) { + if (!err && !MACH_PORT_VALID (*request_port)) { + err = k5_ipc_client_create_client_connection (server_port, request_port); + } + + if (!err) { + err = k5_ipc_client_request (*request_port, reply_port, + inl_request, inl_request_length, + ool_request, ool_request_length); + + } + + if (err == MACH_SEND_INVALID_DEST) { + if (try_count < 2) { + try_count++; + err = 0; + } + + if (request_port && MACH_PORT_VALID (*request_port)) { + mach_port_mod_refs (mach_task_self(), *request_port, MACH_PORT_RIGHT_SEND, -1 ); + *request_port = MACH_PORT_NULL; + } + + /* Look up server name again without using the cached copy */ + err = kipc_client_lookup_server (K5_IPC_SERVER_ID, + in_launch_server, FALSE, &server_port); + + } else { + /* Talked to server, though we may have gotten an error */ + done = 1; + + /* Because we use ",dealloc" ool_request will be freed by mach. + * Don't double free it. */ + ool_request = NULL; + ool_request_length = 0; + } + } + + if (!err) { + err = k5_ipc_stream_new (&reply_stream); + } + + if (!err) { + err = k5_setspecific (K5_KEY_IPC_REPLY_STREAM, reply_stream); + } + + if (!err) { + err = k5_setspecific (K5_KEY_IPC_SERVER_DIED, &server_died); + } + + if (!err) { + mach_port_t old_notification_target = MACH_PORT_NULL; + + /* request no-senders notification so we can get a message when server dies */ + err = mach_port_request_notification (mach_task_self (), reply_port, + MACH_NOTIFY_NO_SENDERS, 1, reply_port, + MACH_MSG_TYPE_MAKE_SEND_ONCE, + &old_notification_target); + + if (!err && old_notification_target != MACH_PORT_NULL) { + mach_port_deallocate (mach_task_self (), old_notification_target); + } + } + + if (!err) { + err = mach_msg_server_once (k5_ipc_reply_demux, kkipc_max_message_size, + reply_port, MACH_MSG_TIMEOUT_NONE); + } + + if (!err && server_died) { + err = ENOTCONN; + } + + if (err == BOOTSTRAP_UNKNOWN_SERVICE && !in_launch_server) { + err = 0; /* If the server is not running just return an empty stream. */ + } + + if (!err) { + *out_reply_stream = reply_stream; + reply_stream = NULL; + } + + k5_setspecific (K5_KEY_IPC_REPLY_STREAM, NULL); + k5_setspecific (K5_KEY_IPC_SERVER_DIED, NULL); + if (reply_port != MACH_PORT_NULL) { mach_port_destroy (mach_task_self (), reply_port); } + if (ool_request_length ) { vm_deallocate (mach_task_self (), (vm_address_t) ool_request, ool_request_length); } + if (reply_stream ) { k5_ipc_stream_release (reply_stream); } + + return err; +} diff --git a/src/kim/mac/kim_mig_types.h b/src/util/mac/k5_mig_client.h similarity index 73% rename from src/kim/mac/kim_mig_types.h rename to src/util/mac/k5_mig_client.h index 189fe06eb..b5eefdc3a 100644 --- a/src/kim/mac/kim_mig_types.h +++ b/src/util/mac/k5_mig_client.h @@ -1,14 +1,14 @@ /* * $Header$ * - * Copyright 2006-2008 Massachusetts Institute of Technology. + * 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 @@ -24,17 +24,13 @@ * or implied warranty. */ -#ifndef KIM_MIG_H -#define KIM_MIG_H +#ifndef K5_MIG_CLIENT_H +#define K5_MIG_CLIENT_H -#include +#include "k5-ipc_stream.h" -typedef const char *kim_mipc_in_string; -typedef char *kim_mipc_out_string; -typedef int32_t kim_mipc_error; -typedef boolean_t kim_mipc_boolean; -typedef uint32_t kim_mipc_lifetime; -typedef uint32_t kim_mipc_time; -typedef uint32_t kim_mipc_prompt_type; +int32_t k5_ipc_send_request (int32_t in_launch_server, + k5_ipc_stream in_request_stream, + k5_ipc_stream *out_reply_stream); -#endif /* KIM_MIG_H */ +#endif /* K5_MIG_CLIENT_H */ diff --git a/src/util/mac/k5_mig_reply.defs b/src/util/mac/k5_mig_reply.defs new file mode 100644 index 000000000..301778e15 --- /dev/null +++ b/src/util/mac/k5_mig_reply.defs @@ -0,0 +1,58 @@ +/* $Copyright: + * + * Copyright 2004-2006 by the Massachusetts Institute of Technology. + * + * All rights reserved. + * + * Export of this software from the United States of America may require a + * specific license from the United States Government. It is the + * responsibility of any person or organization contemplating export to + * obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and distribute + * this software and its documentation for any purpose and without fee is + * hereby granted, provided that the above copyright notice appear in all + * copies and that both that copyright notice and this permission notice + * appear in supporting documentation, and that the name of M.I.T. not be + * used in advertising or publicity pertaining to distribution of the + * software without specific, written prior permission. Furthermore if you + * modify this software you must label your software as modified software + * and not distribute it in such a fashion that it might be confused with + * the original MIT software. M.I.T. makes no representations about the + * suitability of this software for any purpose. It is provided "as is" + * without express or implied warranty. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF + * MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + * + * Individual source code files are copyright MIT, Cygnus Support, + * OpenVision, Oracle, Sun Soft, FundsXpress, and others. + * + * Project Athena, Athena, Athena MUSE, Discuss, Hesiod, Kerberos, Moira, + * and Zephyr are trademarks of the Massachusetts Institute of Technology + * (MIT). No commercial use of these trademarks may be made without prior + * written permission of MIT. + * + * "Commercial use" means use of a name in a product or other for-profit + * manner. It does NOT prevent a commercial firm from referring to the MIT + * trademarks in order to convey information (although in doing so, + * recognition of their trademark status should be given). + * $ + */ + +#include "k5_mig.defs" + +subsystem k5_ipc_reply 200; + +serverprefix k5_ipc_client_; +userprefix k5_ipc_server_; + +/* ",dealloc" means that the vm_read() memory will be moved to + * the other process rather than copied. This is necessary on the + * client side because we can't know when server has copied our + * buffers so we can't vm_deallocate() them ourselves. */ + +simpleroutine reply (in_reply_port : mach_port_move_send_once_t; + in_inl_reply : k5_ipc_inl_reply_t; + in_ool_reply : k5_ipc_ool_reply_t, dealloc); diff --git a/src/util/mac/k5_mig_request.defs b/src/util/mac/k5_mig_request.defs new file mode 100644 index 000000000..bbb23f0e3 --- /dev/null +++ b/src/util/mac/k5_mig_request.defs @@ -0,0 +1,62 @@ +/* $Copyright: + * + * Copyright 2004-2006 by the Massachusetts Institute of Technology. + * + * All rights reserved. + * + * Export of this software from the United States of America may require a + * specific license from the United States Government. It is the + * responsibility of any person or organization contemplating export to + * obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and distribute + * this software and its documentation for any purpose and without fee is + * hereby granted, provided that the above copyright notice appear in all + * copies and that both that copyright notice and this permission notice + * appear in supporting documentation, and that the name of M.I.T. not be + * used in advertising or publicity pertaining to distribution of the + * software without specific, written prior permission. Furthermore if you + * modify this software you must label your software as modified software + * and not distribute it in such a fashion that it might be confused with + * the original MIT software. M.I.T. makes no representations about the + * suitability of this software for any purpose. It is provided "as is" + * without express or implied warranty. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF + * MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + * + * Individual source code files are copyright MIT, Cygnus Support, + * OpenVision, Oracle, Sun Soft, FundsXpress, and others. + * + * Project Athena, Athena, Athena MUSE, Discuss, Hesiod, Kerberos, Moira, + * and Zephyr are trademarks of the Massachusetts Institute of Technology + * (MIT). No commercial use of these trademarks may be made without prior + * written permission of MIT. + * + * "Commercial use" means use of a name in a product or other for-profit + * manner. It does NOT prevent a commercial firm from referring to the MIT + * trademarks in order to convey information (although in doing so, + * recognition of their trademark status should be given). + * $ + */ + +#include "k5_mig.defs" + +subsystem k5_ipc_request 100; + +serverprefix k5_ipc_server_; +userprefix k5_ipc_client_; + +routine create_client_connection (in_server_port : mach_port_t; + out out_connection_port : mach_port_t = MACH_MSG_TYPE_MAKE_SEND); + +/* ",dealloc" means that the vm_read() memory will be moved to + * the other process rather than copied. This is necessary on the + * server side because we can't know when client has copied our + * buffers so we can't vm_deallocate() them ourselves. */ + +simpleroutine request (in_connection_port : mach_port_t; + in_reply_port : mach_port_make_send_once_t; + in_inl_request : k5_ipc_inl_request_t; + in_ool_request : k5_ipc_ool_request_t, dealloc); diff --git a/src/util/mac/k5_mig_server.c b/src/util/mac/k5_mig_server.c new file mode 100644 index 000000000..ddf81ce0b --- /dev/null +++ b/src/util/mac/k5_mig_server.c @@ -0,0 +1,233 @@ +/* + * $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 "k5_mig_server.h" + +#include +#include +#include "k5_mig_requestServer.h" +#include "k5_mig_reply.h" + + +/* ------------------------------------------------------------------------ */ + +static boolean_t k5_ipc_request_demux (mach_msg_header_t *request, + mach_msg_header_t *reply) +{ + boolean_t handled = false; + + if (!handled) { + handled = k5_ipc_request_server (request, reply); + } + + if (!handled && request->msgh_id == MACH_NOTIFY_NO_SENDERS) { + kern_return_t err = KERN_SUCCESS; + + err = k5_ipc_server_remove_client (request->msgh_local_port); + + if (!err) { + /* Check here for a client in our table and free rights associated with it */ + err = mach_port_mod_refs (mach_task_self (), request->msgh_local_port, + MACH_PORT_RIGHT_RECEIVE, -1); + } + + if (!err) { + handled = 1; /* was a port we are tracking */ + } + } + + return handled; +} + +/* ------------------------------------------------------------------------ */ + +kern_return_t k5_ipc_server_create_client_connection (mach_port_t in_server_port, + mach_port_t *out_connection_port) +{ + kern_return_t err = KERN_SUCCESS; + mach_port_t connection_port = MACH_PORT_NULL; + mach_port_t old_notification_target = MACH_PORT_NULL; + + if (!err) { + err = mach_port_allocate (mach_task_self (), MACH_PORT_RIGHT_RECEIVE, &connection_port); + } + + if (!err) { + err = mach_port_move_member (mach_task_self (), connection_port, kipc_server_get_listen_portset ()); + } + + if (!err) { + /* request no-senders notification so we can tell when client quits/crashes */ + err = mach_port_request_notification (mach_task_self (), connection_port, + MACH_NOTIFY_NO_SENDERS, 1, connection_port, + MACH_MSG_TYPE_MAKE_SEND_ONCE, &old_notification_target ); + } + + if (!err) { + err = k5_ipc_server_add_client (connection_port); + } + + if (!err) { + *out_connection_port = connection_port; + connection_port = MACH_PORT_NULL; + } + + if (MACH_PORT_VALID (connection_port)) { mach_port_deallocate (mach_task_self (), connection_port); } + + return err; +} + +/* ------------------------------------------------------------------------ */ + +kern_return_t k5_ipc_server_request (mach_port_t in_connection_port, + mach_port_t in_reply_port, + k5_ipc_inl_request_t in_inl_request, + mach_msg_type_number_t in_inl_requestCnt, + k5_ipc_ool_request_t in_ool_request, + mach_msg_type_number_t in_ool_requestCnt) +{ + kern_return_t err = KERN_SUCCESS; + k5_ipc_stream request_stream = NULL; + + if (!err) { + err = k5_ipc_stream_new (&request_stream); + } + + if (!err) { + if (in_inl_requestCnt) { + err = k5_ipc_stream_write (request_stream, in_inl_request, in_inl_requestCnt); + + } else if (in_ool_requestCnt) { + err = k5_ipc_stream_write (request_stream, in_ool_request, in_ool_requestCnt); + + } else { + err = EINVAL; + } + } + + if (!err) { + err = k5_ipc_server_handle_request (in_connection_port, in_reply_port, request_stream); + } + + k5_ipc_stream_release (request_stream); + if (in_ool_requestCnt) { vm_deallocate (mach_task_self (), (vm_address_t) in_ool_request, in_ool_requestCnt); } + + return err; +} + +#pragma mark - + +/* ------------------------------------------------------------------------ */ + +int32_t k5_ipc_server_initialize (int argc, const char *argv[]) +{ + int32_t err = 0; + + openlog (argv[0], LOG_CONS | LOG_PID, LOG_AUTH); + syslog (LOG_INFO, "Starting up."); + + syslog (LOG_NOTICE, "Exiting: %s (%d)", kipc_error_string (err), err); + + return err; +} + +/* ------------------------------------------------------------------------ */ + +int32_t k5_ipc_server_cleanup (int argc, const char *argv[]) +{ + int32_t err = 0; + + openlog (argv[0], LOG_CONS | LOG_PID, LOG_AUTH); + syslog (LOG_INFO, "Starting up."); + + syslog (LOG_NOTICE, "Exiting: %s (%d)", kipc_error_string (err), err); + + return err; +} + +/* ------------------------------------------------------------------------ */ + +int32_t k5_ipc_server_listen_loop (void) +{ + /* Run the Mach IPC listen loop. + * This will call k5_ipc_server_create_client_connection for new clients + * and k5_ipc_server_request for existing clients */ + + return kipc_server_run_server (k5_ipc_request_demux); +} + +/* ------------------------------------------------------------------------ */ + +int32_t k5_ipc_server_send_reply (mach_port_t in_reply_port, + k5_ipc_stream in_reply_stream) +{ + kern_return_t err = KERN_SUCCESS; + k5_ipc_inl_reply_t inl_reply; + mach_msg_type_number_t inl_reply_length = 0; + k5_ipc_ool_reply_t ool_reply = NULL; + mach_msg_type_number_t ool_reply_length = 0; + + if (!MACH_PORT_VALID (in_reply_port)) { err = EINVAL; } + if (!in_reply_stream ) { err = EINVAL; } + + if (!err) { + /* depending on how big the message is, use the fast inline buffer or + * the slow dynamically allocated buffer */ + mach_msg_type_number_t reply_length = k5_ipc_stream_size (in_reply_stream); + + if (reply_length > K5_IPC_MAX_MSG_SIZE) { + //dprintf ("%s choosing out of line buffer (size is %d)", + // __FUNCTION__, reply_length); + + err = vm_read (mach_task_self (), + (vm_address_t) k5_ipc_stream_data (in_reply_stream), reply_length, + (vm_address_t *) &ool_reply, &ool_reply_length); + + } else { + //cci_debug_printf ("%s choosing in line buffer (size is %d)", + // __FUNCTION__, reply_length); + + inl_reply_length = reply_length; + memcpy (inl_reply, k5_ipc_stream_data (in_reply_stream), reply_length); + } + } + + if (!err) { + err = k5_ipc_server_reply (in_reply_port, + inl_reply, inl_reply_length, + ool_reply, ool_reply_length); + } + + if (!err) { + /* Because we use ",dealloc" ool_reply will be freed by mach. Don't double free it. */ + ool_reply = NULL; + ool_reply_length = 0; + } + + if (ool_reply_length) { vm_deallocate (mach_task_self (), (vm_address_t) ool_reply, ool_reply_length); } + + return err; +} diff --git a/src/util/mac/k5_mig_server.h b/src/util/mac/k5_mig_server.h new file mode 100644 index 000000000..c98d1dc4b --- /dev/null +++ b/src/util/mac/k5_mig_server.h @@ -0,0 +1,53 @@ +/* + * $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 K5_MIG_SERVER +#define K5_MIG_SERVER + +#include "k5-ipc_stream.h" + +/* Defined by caller */ + +int32_t k5_ipc_server_add_client (mach_port_t in_client_port); + +int32_t k5_ipc_server_remove_client (mach_port_t in_client_port); + +int32_t k5_ipc_server_handle_request (mach_port_t in_connection_port, + mach_port_t in_reply_port, + k5_ipc_stream in_request_stream); + +/* Server control functions */ + +int32_t k5_ipc_server_initialize (int argc, const char *argv[]); + +int32_t k5_ipc_server_cleanup (int argc, const char *argv[]); + +int32_t k5_ipc_server_listen_loop (void); + +int32_t k5_ipc_server_send_reply (mach_port_t in_reply_pipe, + k5_ipc_stream in_reply_stream); + +#endif /* K5_MIG_SERVER */ diff --git a/src/util/mac/k5_mig_types.h b/src/util/mac/k5_mig_types.h new file mode 100644 index 000000000..4c8ddb73b --- /dev/null +++ b/src/util/mac/k5_mig_types.h @@ -0,0 +1,55 @@ +/* $Copyright: +* +* Copyright 2004-2006 by the Massachusetts Institute of Technology. +* +* All rights reserved. +* +* Export of this software from the United States of America may require a +* specific license from the United States Government. It is the +* responsibility of any person or organization contemplating export to +* obtain such a license before exporting. +* +* WITHIN THAT CONSTRAINT, permission to use, copy, modify, and distribute +* this software and its documentation for any purpose and without fee is +* hereby granted, provided that the above copyright notice appear in all +* copies and that both that copyright notice and this permission notice +* appear in supporting documentation, and that the name of M.I.T. not be +* used in advertising or publicity pertaining to distribution of the +* software without specific, written prior permission. Furthermore if you +* modify this software you must label your software as modified software +* and not distribute it in such a fashion that it might be confused with +* the original MIT software. M.I.T. makes no representations about the +* suitability of this software for any purpose. It is provided "as is" +* without express or implied warranty. +* +* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED +* WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF +* MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. +* +* Individual source code files are copyright MIT, Cygnus Support, +* OpenVision, Oracle, Sun Soft, FundsXpress, and others. +* +* Project Athena, Athena, Athena MUSE, Discuss, Hesiod, Kerberos, Moira, +* and Zephyr are trademarks of the Massachusetts Institute of Technology +* (MIT). No commercial use of these trademarks may be made without prior +* written permission of MIT. +* +* "Commercial use" means use of a name in a product or other for-profit +* manner. It does NOT prevent a commercial firm from referring to the MIT +* trademarks in order to convey information (although in doing so, +* recognition of their trademark status should be given). +* $ +*/ + +#ifndef K5_MIG_TYPES_H +#define K5_MIG_TYPES_H + + +#define K5_IPC_MAX_MSG_SIZE 1024 + +typedef const char k5_ipc_inl_request_t[K5_IPC_MAX_MSG_SIZE]; +typedef const char *k5_ipc_ool_request_t; +typedef char k5_ipc_inl_reply_t[K5_IPC_MAX_MSG_SIZE]; +typedef char *k5_ipc_ool_reply_t; + +#endif /* K5_MIG_TYPES_H */ diff --git a/src/util/support/ipc_stream.c b/src/util/support/ipc_stream.c new file mode 100644 index 000000000..608e0fb37 --- /dev/null +++ b/src/util/support/ipc_stream.c @@ -0,0 +1,507 @@ +/* + * $Header$ + * + * 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-ipc_stream.h" + +#if !defined(htonll) +#define htonll(x) k5_htonll(x) +#endif + +#if !defined(ntohll) +#define ntohll(x) k5_ntohll(x) +#endif + +/* Add debugging later */ +#define k5_check_error(x) (x) + +struct k5_ipc_stream { + char *data; + uint64_t size; + uint64_t max_size; +}; + +const struct k5_ipc_stream k5_ipc_stream_initializer = { NULL, 0, 0 }; + +#define K5_IPC_STREAM_SIZE_INCREMENT 128 + +/* ------------------------------------------------------------------------ */ + +static uint32_t k5_ipc_stream_reallocate (k5_ipc_stream io_stream, + uint64_t in_new_size) +{ + int32_t err = 0; + uint64_t new_max_size = 0; + + if (!io_stream) { err = k5_check_error (EINVAL); } + + if (!err) { + uint64_t old_max_size = io_stream->max_size; + new_max_size = io_stream->max_size; + + if (in_new_size > old_max_size) { + /* Expand the stream */ + while (in_new_size > new_max_size) { + new_max_size += K5_IPC_STREAM_SIZE_INCREMENT; + } + + + } else if ((in_new_size + K5_IPC_STREAM_SIZE_INCREMENT) < old_max_size) { + /* Shrink the array, but never drop below K5_IPC_STREAM_SIZE_INCREMENT */ + while ((in_new_size + K5_IPC_STREAM_SIZE_INCREMENT) < new_max_size && + (new_max_size > K5_IPC_STREAM_SIZE_INCREMENT)) { + new_max_size -= K5_IPC_STREAM_SIZE_INCREMENT; + } + } + } + + if (!err && new_max_size != io_stream->max_size) { + char *data = io_stream->data; + + if (!data) { + data = malloc (new_max_size * sizeof (*data)); + } else { + data = realloc (data, new_max_size * sizeof (*data)); + } + + if (data) { + io_stream->data = data; + io_stream->max_size = new_max_size; + } else { + err = k5_check_error (ENOMEM); + } + } + + return k5_check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +int32_t k5_ipc_stream_new (k5_ipc_stream *out_stream) +{ + int32_t err = 0; + k5_ipc_stream stream = NULL; + + if (!out_stream) { err = k5_check_error (EINVAL); } + + if (!err) { + stream = malloc (sizeof (*stream)); + if (stream) { + *stream = k5_ipc_stream_initializer; + } else { + err = k5_check_error (ENOMEM); + } + } + + if (!err) { + *out_stream = stream; + stream = NULL; + } + + k5_ipc_stream_release (stream); + + return k5_check_error (err); +} + + +/* ------------------------------------------------------------------------ */ + +uint32_t k5_ipc_stream_release (k5_ipc_stream io_stream) +{ + int32_t err = 0; + + if (!err && io_stream) { + free (io_stream->data); + free (io_stream); + } + + return err; +} + +/* ------------------------------------------------------------------------ */ + +uint64_t k5_ipc_stream_size (k5_ipc_stream in_stream) +{ + return in_stream ? in_stream->size : 0; +} + + +/* ------------------------------------------------------------------------ */ + +const char *k5_ipc_stream_data (k5_ipc_stream in_stream) +{ + return in_stream ? in_stream->data : NULL; +} + +#ifdef TARGET_OS_MAC +#pragma mark - +#endif + +/* ------------------------------------------------------------------------ */ + +uint32_t k5_ipc_stream_read (k5_ipc_stream io_stream, + void *io_data, + uint64_t in_size) +{ + int32_t err = 0; + + if (!io_stream) { err = k5_check_error (EINVAL); } + if (!io_data ) { err = k5_check_error (EINVAL); } + + if (!err) { + if (in_size > io_stream->size) { + err = k5_check_error (EINVAL); + } + } + + if (!err) { + memcpy (io_data, io_stream->data, in_size); + memmove (io_stream->data, &io_stream->data[in_size], + io_stream->size - in_size); + + err = k5_ipc_stream_reallocate (io_stream, io_stream->size - in_size); + + if (!err) { + io_stream->size -= in_size; + } + } + + return k5_check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +uint32_t k5_ipc_stream_write (k5_ipc_stream io_stream, + const void *in_data, + uint64_t in_size) +{ + int32_t err = 0; + + if (!io_stream) { err = k5_check_error (EINVAL); } + if (!in_data ) { err = k5_check_error (EINVAL); } + + if (!err) { + /* Security check: Do not let the caller overflow the length */ + if (in_size > (UINT64_MAX - io_stream->size)) { + err = k5_check_error (EINVAL); + } + } + + if (!err) { + err = k5_ipc_stream_reallocate (io_stream, io_stream->size + in_size); + } + + if (!err) { + memcpy (&io_stream->data[io_stream->size], in_data, in_size); + io_stream->size += in_size; + } + + return k5_check_error (err); +} + +#ifdef TARGET_OS_MAC +#pragma mark - +#endif + +/* ------------------------------------------------------------------------ */ + +void k5_ipc_stream_free_string (char *in_string) +{ + free (in_string); +} + +/* ------------------------------------------------------------------------ */ + +uint32_t k5_ipc_stream_read_string (k5_ipc_stream io_stream, + char **out_string) +{ + int32_t err = 0; + uint32_t length = 0; + char *string = NULL; + + if (!io_stream ) { err = k5_check_error (EINVAL); } + if (!out_string) { err = k5_check_error (EINVAL); } + + if (!err) { + err = k5_ipc_stream_read_uint32 (io_stream, &length); + } + + if (!err) { + string = malloc (length); + if (!string) { err = k5_check_error (ENOMEM); } + } + + if (!err) { + err = k5_ipc_stream_read (io_stream, string, length); + } + + if (!err) { + *out_string = string; + string = NULL; + } + + free (string); + + return k5_check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +uint32_t k5_ipc_stream_write_string (k5_ipc_stream io_stream, + const char *in_string) +{ + int32_t err = 0; + uint32_t length = 0; + + if (!io_stream) { err = k5_check_error (EINVAL); } + if (!in_string) { err = k5_check_error (EINVAL); } + + if (!err) { + length = strlen (in_string) + 1; + + err = k5_ipc_stream_write_uint32 (io_stream, length); + } + + if (!err) { + err = k5_ipc_stream_write (io_stream, in_string, length); + } + + return k5_check_error (err); +} + +#ifdef TARGET_OS_MAC +#pragma mark - +#endif + +/* ------------------------------------------------------------------------ */ + +uint32_t k5_ipc_stream_read_int32 (k5_ipc_stream io_stream, + int32_t *out_int32) +{ + int32_t err = 0; + int32_t int32 = 0; + + if (!io_stream) { err = k5_check_error (EINVAL); } + if (!out_int32) { err = k5_check_error (EINVAL); } + + if (!err) { + err = k5_ipc_stream_read (io_stream, &int32, sizeof (int32)); + } + + if (!err) { + *out_int32 = ntohl (int32); + } + + return k5_check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +uint32_t k5_ipc_stream_write_int32 (k5_ipc_stream io_stream, + int32_t in_int32) +{ + int32_t err = 0; + int32_t int32 = htonl (in_int32); + + if (!io_stream) { err = k5_check_error (EINVAL); } + + if (!err) { + err = k5_ipc_stream_write (io_stream, &int32, sizeof (int32)); + } + + return k5_check_error (err); +} + +#ifdef TARGET_OS_MAC +#pragma mark - +#endif + +/* ------------------------------------------------------------------------ */ + +uint32_t k5_ipc_stream_read_uint32 (k5_ipc_stream io_stream, + uint32_t *out_uint32) +{ + int32_t err = 0; + uint32_t uint32 = 0; + + if (!io_stream) { err = k5_check_error (EINVAL); } + if (!out_uint32) { err = k5_check_error (EINVAL); } + + if (!err) { + err = k5_ipc_stream_read (io_stream, &uint32, sizeof (uint32)); + } + + if (!err) { + *out_uint32 = ntohl (uint32); + } + + return k5_check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +uint32_t k5_ipc_stream_write_uint32 (k5_ipc_stream io_stream, + uint32_t in_uint32) +{ + int32_t err = 0; + int32_t uint32 = htonl (in_uint32); + + if (!io_stream) { err = k5_check_error (EINVAL); } + + if (!err) { + err = k5_ipc_stream_write (io_stream, &uint32, sizeof (uint32)); + } + + return k5_check_error (err); +} + +#ifdef TARGET_OS_MAC +#pragma mark - +#endif + +/* ------------------------------------------------------------------------ */ + +uint32_t k5_ipc_stream_read_int64 (k5_ipc_stream io_stream, + int64_t *out_int64) +{ + int32_t err = 0; + uint64_t int64 = 0; + + if (!io_stream) { err = k5_check_error (EINVAL); } + if (!out_int64) { err = k5_check_error (EINVAL); } + + if (!err) { + err = k5_ipc_stream_read (io_stream, &int64, sizeof (int64)); + } + + if (!err) { + *out_int64 = ntohll (int64); + } + + return k5_check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +uint32_t k5_ipc_stream_write_int64 (k5_ipc_stream io_stream, + int64_t in_int64) +{ + int32_t err = 0; + int64_t int64 = htonll (in_int64); + + if (!io_stream) { err = k5_check_error (EINVAL); } + + if (!err) { + err = k5_ipc_stream_write (io_stream, &int64, sizeof (int64)); + } + + return k5_check_error (err); +} + + +#ifdef TARGET_OS_MAC +#pragma mark - +#endif + +/* ------------------------------------------------------------------------ */ + +uint32_t k5_ipc_stream_read_uint64 (k5_ipc_stream io_stream, + uint64_t *out_uint64) +{ + int32_t err = 0; + uint64_t uint64 = 0; + + if (!io_stream) { err = k5_check_error (EINVAL); } + if (!out_uint64) { err = k5_check_error (EINVAL); } + + if (!err) { + err = k5_ipc_stream_read (io_stream, &uint64, sizeof (uint64)); + } + + if (!err) { + *out_uint64 = ntohll (uint64); + } + + return k5_check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +uint32_t k5_ipc_stream_write_uint64 (k5_ipc_stream io_stream, + uint64_t in_uint64) +{ + int32_t err = 0; + int64_t uint64 = htonll (in_uint64); + + if (!io_stream) { err = k5_check_error (EINVAL); } + + if (!err) { + err = k5_ipc_stream_write (io_stream, &uint64, sizeof (uint64)); + } + + return k5_check_error (err); +} + +#ifdef TARGET_OS_MAC +#pragma mark - +#endif + +/* ------------------------------------------------------------------------ */ + +uint32_t k5_ipc_stream_read_time (k5_ipc_stream io_stream, + time_t *out_time) +{ + int32_t err = 0; + int64_t t = 0; + + if (!io_stream) { err = k5_check_error (EINVAL); } + if (!out_time ) { err = k5_check_error (EINVAL); } + + if (!err) { + err = k5_ipc_stream_read_int64 (io_stream, &t); + } + + if (!err) { + *out_time = t; + } + + return k5_check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +uint32_t k5_ipc_stream_write_time (k5_ipc_stream io_stream, + time_t in_time) +{ + int32_t err = 0; + + if (!io_stream) { err = k5_check_error (EINVAL); } + + if (!err) { + err = k5_ipc_stream_write_int64 (io_stream, in_time); + } + + return k5_check_error (err); +}