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.
--- /dev/null
+/*
+ * 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;
+}
--- /dev/null
+/*
+ * 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 <Kerberos/kim.h>
+#include <Kerberos/kim_ui_plugin.h>
+
+@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
--- /dev/null
+/*
+ * 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 <Kerberos/kim.h>
+#import <Kerberos/kipc_server.h>
+#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
+
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
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
message_data.length);
} else {
err = kim_os_string_create_localized (&rejected_message,
- "KLStringChangePasswordFailed");
+ "Kerberos Change Password Failed:");
}
if (!err) {
description_data.length);
} else {
err = kim_os_string_create_localized (&rejected_description,
- "KLStringPasswordRejected");
+ "New password rejected.");
}
}
#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);
/* ------------------------------------------------------------------------ */
+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)
{
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);
#include <kim/kim.h>
+/* ------------------------------------------------------------------------ */
+
+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,
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;
}
if (!err) {
err = kim_os_string_create_localized (&enter_identity_string,
- "KLStringEnterPrincipal");
+ "Please enter your Kerberos identity");
}
if (!err) {
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,
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,
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) {
mach_port_t port;
};
-
/* ------------------------------------------------------------------------ */
static void kim_os_ui_gui_context_free (kim_ui_gui_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); }
}
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); }
}
context = NULL;
}
+ kim_string_free (&name);
kim_string_free (&path);
kim_os_ui_gui_context_free (&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);
}
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);
}
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);
}
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);
}
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);
}
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);
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;
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;