From: Alexandra Ellwood Date: Sat, 27 Sep 2008 00:46:39 +0000 (+0000) Subject: KerberosAgent MachIPC support X-Git-Tag: krb5-1.7-alpha1~408 X-Git-Url: http://git.tremily.us/?a=commitdiff_plain;h=06847c646f5630878d6f28025993cee57f2839a8;p=krb5.git KerberosAgent MachIPC support ticket: 6055 git-svn-id: svn://anonsvn.mit.edu/krb5/trunk@20763 dc483132-0cff-0310-8789-dd5450dbe970 --- diff --git a/src/include/kim/kim_identity.h b/src/include/kim/kim_identity.h index f09c24aa7..c627758d1 100644 --- a/src/include/kim/kim_identity.h +++ b/src/include/kim/kim_identity.h @@ -241,6 +241,16 @@ kim_error kim_identity_get_component_at_index (kim_identity in_identity, kim_count in_index, kim_string *out_component_string); +/*! + * \param in_identity an identity object. + * \param out_components on exit, a string of the non-realm components of \a in_identity + * separated by '/' characters. Must be freed with kim_string_free(). + * \return On success, #KIM_NO_ERROR. On failure, an error code representing the failure. + * \brief Get a display string of the non-realm components of an identity. + */ +kim_error kim_identity_get_components (kim_identity in_identity, + kim_string *out_components); + /*! * \param in_identity an identity object. * \param in_krb5_context a krb5 context object. diff --git a/src/kim/agent/mac/ServerDemux.m b/src/kim/agent/mac/ServerDemux.m new file mode 100644 index 000000000..b7f208417 --- /dev/null +++ b/src/kim/agent/mac/ServerDemux.m @@ -0,0 +1,618 @@ +/* + * 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 "kim_migServer.h" +#import "ServerThread.h" + +// --------------------------------------------------------------------------- + +static kim_boolean caller_is_front_process (task_t in_task, + NSString *in_path) +{ + kim_error err = KIM_NO_ERROR; + Boolean is_front_process; + pid_t task_pid; + ProcessSerialNumber task_psn, front_psn; + + NSBundle *bundle = [NSBundle bundleWithPath: in_path]; + if (bundle) { + NSString *identifier = [bundle bundleIdentifier]; + if (identifier && + ([identifier compare: @"edu.mit.Kerberos.KerberosMenu"] == NSOrderedSame || + [identifier compare: @"com.apple.systemuiserver"] == NSOrderedSame)) { + return TRUE; + } + } + + if (!err) { + err = pid_for_task (in_task, &task_pid); + } + + if (!err) { + err = GetProcessForPID (task_pid, &task_psn); + } + + if (!err) { + err = GetFrontProcess (&front_psn); + } + + if (!err) { + err = SameProcess (&task_psn, &front_psn, &is_front_process); + } + + return !err ? is_front_process : FALSE; +} + +#pragma mark - + +/* ------------------------------------------------------------------------ */ + +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) +{ + kern_return_t err = 0; + ServerThread *sthread = NULL; + + if (!err) { + sthread = [ServerThread sharedServerThread]; + if (!sthread) { err = KIM_OUT_OF_MEMORY_ERR; } + } + + if (!err) { + kim_mipc_error result = KIM_NO_ERROR; + NSString *name = NULL; + NSString *path = NULL; + + if (in_application_name) { + name = [NSString stringWithUTF8String: in_application_name]; + } + + 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; + } + + 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) +{ + kern_return_t err = 0; + kim_error result = KIM_NO_ERROR; + ClientConnection *client = 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) { + 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; } + } + } + + if (!err) { + identity = [client enterIdentityWithError: &result]; + } + + 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 && !result) { + memmove (identity_buf, identity_string, identity_len); + *out_identity = identity_buf; + *out_identityCnt = identity_len; + identity_buf = NULL; + } + + if (!err) { + *out_error = result; + } + + if (identity_buf) { vm_deallocate (mach_task_self (), (vm_address_t) identity_buf, identity_len); } + kim_string_free (&identity_string); + kim_identity_free (&identity); + + return err; +} + +/* ------------------------------------------------------------------------ */ + +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) +{ + kern_return_t err = 0; + kim_error result = KIM_NO_ERROR; + ClientConnection *client = NULL; + 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); + } + + 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); + } + + if (!err) { + err = kim_selection_hints_set_explanation (hints, in_explanation); + } + + if (!err && in_service_identity_hint) { + err = kim_selection_hints_set_hint (hints, + kim_hint_key_service_identity, + in_service_identity_hint); + } + + if (!err && in_client_realm_hint) { + err = kim_selection_hints_set_hint (hints, + kim_hint_key_client_realm, + in_client_realm_hint); + } + + if (!err && in_user_hint) { + err = kim_selection_hints_set_hint (hints, + kim_hint_key_user, + in_user_hint); + } + + if (!err && in_service_realm_hint) { + err = kim_selection_hints_set_hint (hints, + kim_hint_key_service_realm, + in_service_realm_hint); + } + + if (!err && in_service_hint) { + err = kim_selection_hints_set_hint (hints, + kim_hint_key_service, + in_service_hint); + } + + if (!err && in_server_hint) { + err = kim_selection_hints_set_hint (hints, + kim_hint_key_server, + in_server_hint); + } + + 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; } + } + } + + if (!err) { + identity = [client selectIdentityWithHints: hints + error: &result]; + } + + 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 && !result) { + memmove (identity_buf, identity_string, identity_len); + *out_identity = identity_buf; + *out_identityCnt = identity_len; + identity_buf = NULL; + } + + if (!err) { + *out_error = result; + } + + 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; +} + +/* ------------------------------------------------------------------------ */ + +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) +{ + 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; } + } + } + + if (!err) { + err = kim_identity_create_from_string (&identity, in_identity); + } + + 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]; + } + + 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 && !result) { + memmove (response_buf, response_string, response_len); + *out_response = response_buf; + *out_responseCnt = response_len; + response_buf = NULL; + } + + if (!err) { + *out_error = result; + } + + if (response_buf) { vm_deallocate (mach_task_self (), + (vm_address_t) response_buf, + response_len); } + kim_identity_free (&identity); + + return err; +} + +/* ------------------------------------------------------------------------ */ + +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) +{ + 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; } + } + } + + if (!err) { + err = kim_identity_create_from_string (&identity, in_identity); + } + + if (!err) { + passwords = [client changePasswordWithIdentity: identity + oldPasswordIsExpired: in_old_password_expired + error: &result]; + } + + 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 && !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); + + } + + 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 && !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) { + *out_error = result; + } + + 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); + + return err; +} + +/* ------------------------------------------------------------------------ */ + +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) +{ + 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; } + } + } + + if (!err) { + err = kim_identity_create_from_string (&identity, in_identity); + } + + 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]; + } + + if (!err) { + *out_error = result; + } + + kim_identity_free (&identity); + + return err; +} + +/* ------------------------------------------------------------------------ */ + +kern_return_t kim_mipc_srv_fini (mach_port_t in_server_port, + kim_mipc_error *out_error) +{ + kern_return_t err = 0; + ServerThread *sthread = NULL; + + if (!err) { + sthread = [ServerThread sharedServerThread]; + if (!sthread) { err = KIM_OUT_OF_MEMORY_ERR; } + } + + if (!err) { + [sthread removeConnectionWithPort: in_server_port]; + } + + if (!err) { + *out_error = KIM_NO_ERROR; + } + + return err; +} diff --git a/src/kim/agent/mac/ServerThread.h b/src/kim/agent/mac/ServerThread.h new file mode 100644 index 000000000..4457f2a62 --- /dev/null +++ b/src/kim/agent/mac/ServerThread.h @@ -0,0 +1,92 @@ +/* + * 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 new file mode 100644 index 000000000..6d5ba5ed5 --- /dev/null +++ b/src/kim/agent/mac/ServerThread.m @@ -0,0 +1,221 @@ +/* + * 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/lib/kim-lite.exports b/src/kim/lib/kim-lite.exports index b548cfc24..27db51926 100644 --- a/src/kim/lib/kim-lite.exports +++ b/src/kim/lib/kim-lite.exports @@ -12,6 +12,7 @@ kim_identity_get_string kim_identity_get_display_string kim_identity_get_realm kim_identity_get_number_of_components +kim_identity_get_components kim_identity_get_component_at_index kim_identity_get_krb5_principal kim_identity_change_password diff --git a/src/kim/lib/kim.exports b/src/kim/lib/kim.exports index a41f48109..126ed9879 100644 --- a/src/kim/lib/kim.exports +++ b/src/kim/lib/kim.exports @@ -13,6 +13,7 @@ kim_identity_get_display_string kim_identity_get_realm kim_identity_get_number_of_components kim_identity_get_component_at_index +kim_identity_get_components kim_identity_get_krb5_principal kim_identity_change_password kim_identity_free diff --git a/src/kim/lib/kim_identity.c b/src/kim/lib/kim_identity.c index 1308c3d7a..333067bc5 100644 --- a/src/kim/lib/kim_identity.c +++ b/src/kim/lib/kim_identity.c @@ -598,7 +598,7 @@ static kim_error kim_identity_change_password_with_credential (kim_identity i message_data.length); } else { err = kim_os_string_create_localized (&rejected_message, - "KLStringChangePasswordFailed"); + "Kerberos Change Password Failed:"); } if (!err) { @@ -608,7 +608,7 @@ static kim_error kim_identity_change_password_with_credential (kim_identity i description_data.length); } else { err = kim_os_string_create_localized (&rejected_description, - "KLStringPasswordRejected"); + "New password rejected."); } } diff --git a/src/kim/lib/kim_identity_private.h b/src/kim/lib/kim_identity_private.h index 44f8c631d..4b1adeb48 100644 --- a/src/kim/lib/kim_identity_private.h +++ b/src/kim/lib/kim_identity_private.h @@ -31,9 +31,6 @@ #include "kim_library_private.h" #include "kim_ui_private.h" -kim_error kim_identity_get_components (kim_identity in_identity, - kim_string *out_components); - kim_error kim_identity_is_tgt_service (kim_identity in_identity, kim_boolean *out_is_tgt_service); diff --git a/src/kim/lib/kim_selection_hints.c b/src/kim/lib/kim_selection_hints.c index a4d7d666a..6903afb86 100644 --- a/src/kim/lib/kim_selection_hints.c +++ b/src/kim/lib/kim_selection_hints.c @@ -314,6 +314,28 @@ kim_error kim_selection_hints_get_explanation (kim_selection_hints in_selection /* ------------------------------------------------------------------------ */ +kim_error kim_selection_hints_get_application_id (kim_selection_hints in_selection_hints, + kim_string *out_application_id) +{ + kim_error err = KIM_NO_ERROR; + + if (!err && !in_selection_hints) { err = check_error (KIM_NULL_PARAMETER_ERR); } + if (!err && !out_application_id) { err = check_error (KIM_NULL_PARAMETER_ERR); } + + if (!err) { + if (in_selection_hints->application_identifier) { + err = kim_string_copy (out_application_id, + in_selection_hints->application_identifier); + } else { + *out_application_id = NULL; + } + } + + return check_error (err); +} + +/* ------------------------------------------------------------------------ */ + kim_error kim_selection_hints_set_options (kim_selection_hints io_selection_hints, kim_options in_options) { diff --git a/src/kim/lib/kim_selection_hints_private.h b/src/kim/lib/kim_selection_hints_private.h index 9a59ba4f1..34694893e 100644 --- a/src/kim/lib/kim_selection_hints_private.h +++ b/src/kim/lib/kim_selection_hints_private.h @@ -39,6 +39,8 @@ typedef struct kim_selection_hints_preference_strings { kim_string server; } kim_selection_hints_preference_strings; +kim_error kim_selection_hints_get_application_id (kim_selection_hints in_selection_hints, + kim_string *out_application_id); kim_error kim_selection_hints_get_preference_strings (kim_selection_hints in_selection_hints, kim_selection_hints_preference_strings *io_preference_strings); diff --git a/src/kim/lib/kim_string_private.h b/src/kim/lib/kim_string_private.h index 4b1cc1839..9ee4846c2 100644 --- a/src/kim/lib/kim_string_private.h +++ b/src/kim/lib/kim_string_private.h @@ -29,6 +29,14 @@ #include +/* ------------------------------------------------------------------------ */ + +static inline kim_count kim_string_buflen (kim_string in_string) +{ + return in_string ? strlen (in_string) + 1 : 0; +} + +/* ------------------------------------------------------------------------ */ kim_error kim_string_create_from_format (kim_string *out_string, kim_string in_format, diff --git a/src/kim/lib/kim_ui.c b/src/kim/lib/kim_ui.c index 5060fb049..819efbf5b 100644 --- a/src/kim/lib/kim_ui.c +++ b/src/kim/lib/kim_ui.c @@ -343,17 +343,17 @@ kim_error kim_ui_handle_kim_error (kim_ui_context *in_context, switch (in_type) { case kim_ui_error_type_authentication: - key = "KLStringLoginFailed"; + key = "Kerberos Login Failed:"; break; case kim_ui_error_type_change_password: - key = "KLStringChangePasswordFailed"; + key = "Kerberos Change Password Failed:"; break; case kim_ui_error_type_selection: case kim_ui_error_type_generic: default: - key = "KLStringKerberosOperationFailed"; + key = "Kerberos Operation Failed:"; break; } diff --git a/src/kim/lib/kim_ui_cli.c b/src/kim/lib/kim_ui_cli.c index 0b0188854..f26e32882 100644 --- a/src/kim/lib/kim_ui_cli.c +++ b/src/kim/lib/kim_ui_cli.c @@ -111,7 +111,7 @@ kim_error kim_ui_cli_enter_identity (kim_ui_context *in_context, if (!err) { err = kim_os_string_create_localized (&enter_identity_string, - "KLStringEnterPrincipal"); + "Please enter your Kerberos identity"); } if (!err) { @@ -170,7 +170,7 @@ kim_error kim_ui_cli_auth_prompt (kim_ui_context *in_context, kim_string identity_string = NULL; err = kim_os_string_create_localized (&enter_password_format, - "KLStringEnterPassword"); + "Please enter the password for %s"); if (!err) { err = kim_identity_get_display_string (in_identity, @@ -234,35 +234,26 @@ static kim_error kim_ui_cli_ask_change_password (kim_string in_identity_string) if (!err) { err = kim_os_string_create_localized (&ask_change_password, - "KLStringPasswordExpired"); + "Your password has expired, would you like to change it? (yes/no)"); } if (!err) { - err = kim_os_string_create_localized (&answer_options, - "KLStringYesOrNoAnswerOptions"); + err = kim_os_string_create_localized (&yes, "yes"); } if (!err) { - err = kim_os_string_create_localized (&yes, - "KLStringYes"); - } - - if (!err) { - err = kim_os_string_create_localized (&no, - "KLStringNo"); + err = kim_os_string_create_localized (&no, "no"); } if (!err) { err = kim_os_string_create_localized (&unknown_response, - "KLStringUnknownResponse"); + "%s is not a response I understand. Please try again."); } while (!err && !done) { kim_string answer = NULL; - err = kim_ui_cli_read_string (&answer, - 0, "%s %s", - ask_change_password, answer_options); + err = kim_ui_cli_read_string (&answer, 0, ask_change_password); if (!err) { err = kim_os_string_compare (answer, no, @@ -335,17 +326,17 @@ kim_error kim_ui_cli_change_password (kim_ui_context *in_context, if (!err) { err = kim_os_string_create_localized (&enter_old_password_format, - "KLStringEnterOldPassword"); + "Please enter the old password for %s"); } if (!err) { err = kim_os_string_create_localized (&enter_new_password_format, - "KLStringEnterNewPassword"); + "Please enter the new password for %s"); } if (!err) { err = kim_os_string_create_localized (&enter_verify_password_format, - "KLStringEnterVerifyPassword"); + "Verifying, please re-enter the new password for %s again"); } while (!err && !done) { diff --git a/src/kim/lib/mac/kim_os_ui_gui.c b/src/kim/lib/mac/kim_os_ui_gui.c index 184558439..4f629105d 100644 --- a/src/kim/lib/mac/kim_os_ui_gui.c +++ b/src/kim/lib/mac/kim_os_ui_gui.c @@ -41,7 +41,6 @@ struct kim_ui_gui_context { mach_port_t port; }; - /* ------------------------------------------------------------------------ */ static void kim_os_ui_gui_context_free (kim_ui_gui_context *io_context) @@ -86,6 +85,7 @@ 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 && !io_context) { err = check_error (KIM_NULL_PARAMETER_ERR); } @@ -95,29 +95,27 @@ kim_error kim_os_ui_gui_init (kim_ui_context *io_context) } if (!err) { - err = kipc_client_lookup_server (kim_os_agent_bundle_id, - 1 /* launch */, - 0 /* don't use cached port */, - &context->port); + err = kim_library_get_application_name (&name); } if (!err) { err = kim_os_library_get_application_path (&path); } + + if (!err) { + err = kipc_client_lookup_server (kim_os_agent_bundle_id, + 1 /* launch */, + 0 /* don't use cached port */, + &context->port); + } if (!err) { - kim_mipc_in_string application_name = NULL; - mach_msg_type_number_t application_name_len = 0; - kim_mipc_in_string application_path = path; - mach_msg_type_number_t application_path_len = strlen (path) + 1; kim_mipc_error result = 0; err = kim_mipc_cli_init (context->port, mach_task_self (), - application_name, - application_name_len, - application_path, - application_path_len, + name, kim_string_buflen (name), + path, kim_string_buflen (path), &result); if (!err) { err = check_error (result); } } @@ -127,6 +125,7 @@ kim_error kim_os_ui_gui_init (kim_ui_context *io_context) context = NULL; } + kim_string_free (&name); kim_string_free (&path); kim_os_ui_gui_context_free (&context); @@ -139,16 +138,30 @@ 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; 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 = kim_mipc_cli_enter_identity (context->port, + &identity, + &identity_len, + &result); + if (!err) { err = check_error (result); } + } + + if (!err) { + err = kim_identity_create_from_string (out_identity, identity); } + if (identity) { vm_deallocate (mach_task_self (), + (vm_address_t) identity, identity_len); } + return check_error (err); } @@ -159,16 +172,176 @@ 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); } 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); + } + } + + if (!err) { + err = kim_options_get_start_time (options, &start_time); + } + + if (!err) { + err = kim_options_get_lifetime (options, &lifetime); + } + + if (!err) { + err = kim_options_get_renewable (options, &renewable); + } + + if (!err) { + err = kim_options_get_renewal_lifetime (options, &renewal_lifetime); + } + + if (!err) { + err = kim_options_get_forwardable (options, &forwardable); + } + + if (!err) { + err = kim_options_get_proxiable (options, &proxiable); + } + + if (!err) { + err = kim_options_get_addressless (options, &addressless); + } + + if (!err) { + err = kim_options_get_service_name (options, &service_name); + } + + if (!err) { + err = kim_selection_hints_get_explanation (in_hints, &explanation); + } + + if (!err) { + err = kim_selection_hints_get_application_id (in_hints, &application_id); + } + + if (!err) { + err = kim_selection_hints_get_hint (in_hints, + kim_hint_key_service_identity, + &service_identity_hint); + } + + if (!err) { + err = kim_selection_hints_get_hint (in_hints, + kim_hint_key_client_realm, + &client_realm_hint); + } + + if (!err) { + err = kim_selection_hints_get_hint (in_hints, + kim_hint_key_user, + &user_hint); + } + + if (!err) { + err = kim_selection_hints_get_hint (in_hints, + kim_hint_key_service_realm, + &service_realm_hint); + } + + if (!err) { + err = kim_selection_hints_get_hint (in_hints, + kim_hint_key_service, + &service_hint); + } + + if (!err) { + err = kim_selection_hints_get_hint (in_hints, + kim_hint_key_server, + &server_hint); + } + 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); } + } + + if (!err) { + err = kim_identity_create_from_string (out_identity, identity); } + 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); } @@ -184,17 +357,47 @@ kim_error kim_os_ui_gui_auth_prompt (kim_ui_context *in_context, 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); + } + 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); + if (!err) { err = check_error (result); } + } + + if (!err) { + err = kim_string_copy ((kim_string *) out_reply, reply); } + if (reply) { vm_deallocate (mach_task_self (), (vm_address_t) reply, reply_len); } + kim_string_free (&identity_string); + return check_error (err); } @@ -208,18 +411,82 @@ kim_error kim_os_ui_gui_change_password (kim_ui_context *in_context, char **out_verify_password) { kim_error err = KIM_NO_ERROR; + 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; + 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) { + 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); } + } + + if (!err) { + err = kim_string_copy (&old_password, old_password_buf); + } + + if (!err) { + err = kim_string_copy (&new_password, new_password_buf); + } + + if (!err) { + err = kim_string_copy (&verify_password, verify_password_buf); + } + + 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); } + kim_string_free (&identity_string); + kim_string_free (&old_password); + kim_string_free (&new_password); + kim_string_free (&verify_password); + return check_error (err); } @@ -232,16 +499,34 @@ kim_error kim_os_ui_gui_handle_error (kim_ui_context *in_context, kim_string in_error_description) { kim_error err = KIM_NO_ERROR; + 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); } + 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_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); } } + kim_string_free (&identity_string); + return check_error (err); } @@ -263,6 +548,11 @@ kim_error kim_os_ui_gui_fini (kim_ui_context *io_context) if (!err) { kim_ui_gui_context context = (kim_ui_gui_context) io_context->tcontext; + kim_mipc_error result = 0; + + err = kim_mipc_cli_fini (context->port, &result); + if (!err) { err = check_error (result); } + if (!err) { kim_os_ui_gui_context_free (&context); diff --git a/src/kim/mac/kim_mig.defs b/src/kim/mac/kim_mig.defs index ad10c7418..8d041cf40 100644 --- a/src/kim/mac/kim_mig.defs +++ b/src/kim/mac/kim_mig.defs @@ -57,6 +57,7 @@ routine enter_identity (in_server_port : mach_port_t; 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; @@ -81,7 +82,7 @@ routine select_identity (in_server_port : mach_port_t; routine auth_prompt (in_server_port : mach_port_t; in_identity : kim_mipc_in_string; in_prompt_type : kim_mipc_prompt_type; - in_hidden : kim_mipc_boolean; + in_hide_reply : kim_mipc_boolean; in_title : kim_mipc_in_string; in_message : kim_mipc_in_string; in_description : kim_mipc_in_string;