kim_error kim_os_preferences_set_identity_for_key (kim_preference_key in_key, kim_identity in_identity) { kim_error err = KIM_NO_ERROR; CFStringRef value = NULL; kim_string string = NULL; /* in_identity can be KIM_IDENTITY_ANY */ if (!err) { if (in_identity) { err = kim_identity_get_string (in_identity, &string); } else { err = kim_string_copy (&string, kim_os_preference_any_identity); } } if (!err) { err = kim_os_string_get_cfstring (string, &value); } if (!err) { err = kim_os_preferences_set_value (in_key, value); } if (value) { CFRelease (value); } kim_string_free (&string); return check_error (err); }
kim_error kim_os_string_create_localized (kim_string *out_string, kim_string in_string) { kim_error lock_err = kim_os_library_lock_for_bundle_lookup (); kim_error err = lock_err; kim_string string = NULL; CFStringRef cfkey = NULL; if (!err && !out_string) { err = check_error (KIM_NULL_PARAMETER_ERR); } if (!err && !in_string ) { err = check_error (KIM_NULL_PARAMETER_ERR); } if (!err) { err = kim_os_string_get_cfstring (in_string, &cfkey); } if (!err && kim_library_allow_home_directory_access ()) { CFStringRef cfstring = NULL; CFBundleRef framework = CFBundleGetBundleWithIdentifier (CFSTR ("edu.mit.Kerberos")); CFBundleRef main_bundle = CFBundleGetMainBundle (); if (framework) { cfstring = CFCopyLocalizedStringFromTableInBundle (cfkey, CFSTR ("InfoPlist"), framework, ""); } if (main_bundle && !cfstring) { cfstring = CFCopyLocalizedStringFromTableInBundle (cfkey, CFSTR ("InfoPlist"), main_bundle, ""); } if (!err && cfstring) { err = kim_os_string_create_from_cfstring (&string, cfstring); } if (cfstring) { CFRelease (cfstring); } } if (!err && !string) { err = kim_string_copy (&string, in_string); } if (!err) { *out_string = string; string = NULL; } if (cfkey) { CFRelease (cfkey); } kim_string_free (&string); if (!lock_err) { kim_os_library_unlock_for_bundle_lookup (); } return check_error (err); }
kim_error kim_string_create_for_last_error (kim_string *out_string, kim_error in_error) { kim_error err = kim_library_init (); err = kim_string_copy (out_string, kim_error_message (in_error)); return check_error (err); }
kim_error kim_options_read_from_stream (kim_options io_options, k5_ipc_stream io_stream) { kim_error err = KIM_NO_ERROR; if (!err && !io_options) { err = check_error (KIM_NULL_PARAMETER_ERR); } if (!err && !io_stream ) { err = check_error (KIM_NULL_PARAMETER_ERR); } if (!err) { err = k5_ipc_stream_read_int64 (io_stream, &io_options->start_time); } if (!err) { err = k5_ipc_stream_read_int64 (io_stream, &io_options->lifetime); } if (!err) { err = k5_ipc_stream_read_int32 (io_stream, &io_options->renewable); } if (!err) { err = k5_ipc_stream_read_int64 (io_stream, &io_options->renewal_lifetime); } if (!err) { err = k5_ipc_stream_read_int32 (io_stream, &io_options->forwardable); } if (!err) { err = k5_ipc_stream_read_int32 (io_stream, &io_options->proxiable); } if (!err) { err = k5_ipc_stream_read_int32 (io_stream, &io_options->addressless); } if (!err) { char *service_name = NULL; err = k5_ipc_stream_read_string (io_stream, &service_name); if (!err) { kim_string_free (&io_options->service_name); if (service_name[0]) { err = kim_string_copy (&io_options->service_name, service_name); } else { io_options->service_name = kim_empty_string; } } k5_ipc_stream_free_string (service_name); } return check_error (err); }
kim_error kim_options_set_service_name (kim_options io_options, kim_string in_service_name) { kim_error err = KIM_NO_ERROR; if (!err && !io_options) { err = check_error (KIM_NULL_PARAMETER_ERR); } if (!err) { kim_string_free (&io_options->service_name); if (in_service_name) { err = kim_string_copy (&io_options->service_name, in_service_name); } else { io_options->service_name = kim_empty_string; } } return check_error (err); }
kim_error kim_options_get_service_name (kim_options in_options, kim_string *out_service_name) { kim_error err = KIM_NO_ERROR; if (!err && !in_options ) { err = check_error (KIM_NULL_PARAMETER_ERR); } if (!err && !out_service_name) { err = check_error (KIM_NULL_PARAMETER_ERR); } if (!err) { if (in_options->service_name && in_options->service_name != kim_empty_string) { err = kim_string_copy (out_service_name, in_options->service_name); } else { *out_service_name = NULL; } } return check_error (err); }
kim_error kim_identity_get_string (kim_identity in_identity, kim_string *out_string) { kim_error err = KIM_NO_ERROR; char *unparsed_name = NULL; if (!err && !in_identity) { err = check_error (KIM_NULL_PARAMETER_ERR); } if (!err && !out_string ) { err = check_error (KIM_NULL_PARAMETER_ERR); } if (!err) { err = krb5_error (in_identity->context, krb5_unparse_name (in_identity->context, in_identity->principal, &unparsed_name)); } if (!err) { err = kim_string_copy (out_string, unparsed_name); } if (unparsed_name) { krb5_free_unparsed_name (in_identity->context, unparsed_name); } return check_error (err); }
kim_error kim_options_copy (kim_options *out_options, kim_options in_options) { kim_error err = KIM_NO_ERROR; kim_options options = KIM_OPTIONS_DEFAULT; if (!err && !out_options) { err = check_error (KIM_NULL_PARAMETER_ERR); } if (!err && in_options != KIM_OPTIONS_DEFAULT) { err = kim_options_allocate (&options); if (!err) { options->start_time = in_options->start_time; options->lifetime = in_options->lifetime; options->renewable = in_options->renewable; options->renewal_lifetime = in_options->renewal_lifetime; options->forwardable = in_options->forwardable; options->proxiable = in_options->proxiable; options->addressless = in_options->addressless; if (in_options->service_name) { err = kim_string_copy (&options->service_name, in_options->service_name); } } } if (!err) { *out_options = options; options = NULL; } kim_options_free (&options); return check_error (err); }
kim_error kim_os_library_get_application_path (kim_string *out_path) { kim_error err = KIM_NO_ERROR; kim_string path = NULL; CFBundleRef bundle = CFBundleGetMainBundle (); if (!err && !out_path) { err = check_error (KIM_NULL_PARAMETER_ERR); } /* Check if the caller is a bundle */ if (!err && bundle) { CFURLRef bundle_url = CFBundleCopyBundleURL (bundle); CFURLRef resources_url = CFBundleCopyResourcesDirectoryURL (bundle); CFURLRef executable_url = CFBundleCopyExecutableURL (bundle); CFURLRef absolute_url = NULL; CFStringRef cfpath = NULL; if (bundle_url && resources_url && !CFEqual (bundle_url, resources_url)) { absolute_url = CFURLCopyAbsoluteURL (bundle_url); } else if (executable_url) { absolute_url = CFURLCopyAbsoluteURL (executable_url); } if (absolute_url) { cfpath = CFURLCopyFileSystemPath (absolute_url, kCFURLPOSIXPathStyle); if (!cfpath) { err = check_error (KIM_OUT_OF_MEMORY_ERR); } } if (!err && cfpath) { err = kim_os_string_create_from_cfstring (&path, cfpath); } if (cfpath ) { CFRelease (cfpath); } if (absolute_url ) { CFRelease (absolute_url); } if (bundle_url ) { CFRelease (bundle_url); } if (resources_url ) { CFRelease (resources_url); } if (executable_url) { CFRelease (executable_url); } } /* Caller is not a bundle, try _NSGetExecutablePath */ /* Note: this does not work on CFM applications */ if (!err && !path) { char *buffer = NULL; uint32_t len = 0; /* Tiny stupid buffer to get the length of the path */ if (!err) { buffer = malloc (1); if (!buffer) { err = check_error (KIM_OUT_OF_MEMORY_ERR); } } /* Get the length of the path */ if (!err) { if (_NSGetExecutablePath (buffer, &len) != 0) { char *temp = realloc (buffer, len + 1); if (!temp) { err = check_error (KIM_OUT_OF_MEMORY_ERR); } else { buffer = temp; } } } /* Get the path */ if (!err) { if (_NSGetExecutablePath (buffer, &len) != 0) { err = check_error (KIM_OUT_OF_MEMORY_ERR); } else { err = kim_string_copy (&path, buffer); } } if (buffer) { free (buffer); } } if (!err) { *out_path = path; path = NULL; } kim_string_free (&path); return check_error (err); }
kim_error kim_identity_change_password_common (kim_identity in_identity, kim_boolean in_old_password_expired, kim_ui_context *in_ui_context, kim_string *out_new_password) { kim_error err = KIM_NO_ERROR; kim_boolean done = 0; if (!err && !in_identity ) { err = check_error (KIM_NULL_PARAMETER_ERR); } if (!err && !in_ui_context) { err = check_error (KIM_NULL_PARAMETER_ERR); } while (!err && !done) { char *old_password = NULL; char *new_password = NULL; char *verify_password = NULL; kim_error rejected_err = KIM_NO_ERROR; kim_string rejected_message = NULL; kim_string rejected_description = NULL; kim_boolean was_prompted = 0; /* ignore because we always prompt */ err = kim_ui_change_password (in_ui_context, in_identity, in_old_password_expired, &old_password, &new_password, &verify_password); if (!err) { kim_comparison comparison; err = kim_string_compare (new_password, verify_password, &comparison); if (!err && !kim_comparison_is_equal_to (comparison)) { err = check_error (KIM_PASSWORD_MISMATCH_ERR); } } if (!err) { kim_credential credential = NULL; if (in_ui_context->type == kim_ui_type_cli && in_ui_context->tcontext) { /* command line has already gotten the credentials for us */ credential = (kim_credential) in_ui_context->tcontext; } else { err = kim_credential_create_for_change_password (&credential, in_identity, old_password, in_ui_context, &was_prompted); } if (!err) { err = kim_identity_change_password_with_credential (in_identity, credential, new_password, in_ui_context, &rejected_err, &rejected_message, &rejected_description); } kim_credential_free (&credential); if (in_ui_context->type == kim_ui_type_cli) { in_ui_context->tcontext = NULL; /* just freed our creds */ } } if (!err && rejected_err) { /* Password rejected, report it to the user */ err = kim_ui_handle_error (in_ui_context, in_identity, rejected_err, rejected_message, rejected_description); } else if (err && err != KIM_USER_CANCELED_ERR && err != KIM_DUPLICATE_UI_REQUEST_ERR) { /* New creds failed, report error to user. * Overwrite error so we loop and let the user try again. * The user always gets prompted so we always loop. */ err = kim_ui_handle_kim_error (in_ui_context, in_identity, kim_ui_error_type_change_password, err); } else { /* password change succeeded or the user gave up */ done = 1; if (!err && out_new_password) { err = kim_string_copy (out_new_password, new_password); } if (!err) { kim_error terr = KIM_NO_ERROR; kim_string saved_password = NULL; terr = kim_os_identity_get_saved_password (in_identity, &saved_password); if (!terr) { /* We changed the password and the user had their * old password saved. Update it. */ terr = kim_os_identity_set_saved_password (in_identity, new_password); } kim_string_free (&saved_password); } if (err == KIM_DUPLICATE_UI_REQUEST_ERR) { err = KIM_NO_ERROR; } } kim_string_free (&rejected_message); kim_string_free (&rejected_description); kim_ui_free_string (in_ui_context, &old_password); kim_ui_free_string (in_ui_context, &new_password); kim_ui_free_string (in_ui_context, &verify_password); } return check_error (err); }
krb5_error_code kim_ui_prompter (krb5_context in_krb5_context, void *in_context, const char *in_name, const char *in_banner, int in_num_prompts, krb5_prompt in_prompts[]) { kim_error err = KIM_NO_ERROR; krb5_prompt_type *types = NULL; kim_ui_context *context = (kim_ui_context *) in_context; int i; if (!err && !in_krb5_context) { err = check_error (KIM_NULL_PARAMETER_ERR); } if (!err && !in_context ) { err = check_error (KIM_NULL_PARAMETER_ERR); } if (!err && !in_prompts ) { err = check_error (KIM_NULL_PARAMETER_ERR); } if (!err) { types = krb5_get_prompt_types (in_krb5_context); if (!types) { err = check_error (KIM_NULL_PARAMETER_ERR); } } for (i = 0; !err && i < in_num_prompts; i++) { char *reply = NULL; kim_prompt_type type = kim_ui_ptype2ktype (types[i]); kim_boolean got_saved_password = 0; if (type == kim_prompt_type_password) { /* Check for saved password on OSes that support it */ kim_error terr = KIM_NO_ERROR; terr = kim_os_identity_get_saved_password (context->identity, (kim_string *) &reply); if (!terr && reply) { got_saved_password = 1; } } if (!got_saved_password) { kim_boolean save_reply = FALSE; kim_boolean allow_save_password = kim_os_identity_allow_save_password (); context->prompt_count++; err = kim_ui_init_lazy (in_context); if (!err) { if (context->type == kim_ui_type_gui_plugin) { err = kim_ui_plugin_auth_prompt (context, context->identity, type, allow_save_password, in_prompts[i].hidden, in_name, in_banner, in_prompts[i].prompt, &reply, &save_reply); #ifdef KIM_BUILTIN_UI } else if (context->type == kim_ui_type_gui_builtin) { err = kim_os_ui_gui_auth_prompt (context, context->identity, type, allow_save_password, in_prompts[i].hidden, in_name, in_banner, in_prompts[i].prompt, &reply, &save_reply); } else if (context->type == kim_ui_type_cli) { err = kim_ui_cli_auth_prompt (context, context->identity, type, allow_save_password, in_prompts[i].hidden, in_name, in_banner, in_prompts[i].prompt, &reply, &save_reply); #endif /* KIM_BUILTIN_UI */ } else { err = check_error (KIM_NO_UI_ERR); } } if (!err && type == kim_prompt_type_password) { kim_string_free (&context->password_to_save); if (allow_save_password && save_reply) { err = kim_string_copy (&context->password_to_save, reply); } } } if (!err) { uint32_t reply_len = strlen (reply); if ((reply_len + 1) > in_prompts[i].reply->length) { kim_debug_printf ("%s(): reply %d is too long (is %d, should be %d)\n", __FUNCTION__, i, reply_len, in_prompts[i].reply->length); reply_len = in_prompts[i].reply->length; } memmove (in_prompts[i].reply->data, reply, reply_len + 1); in_prompts[i].reply->length = reply_len; } /* Clean up reply buffer. Saved passwords are allocated by KIM. */ if (reply) { if (got_saved_password) { memset (reply, '\0', strlen (reply)); kim_string_free ((kim_string *) &reply); } else { kim_ui_free_string (context, &reply); } } } return check_error (err); }