void __kim_debug_printf (kim_string in_function, kim_string in_format, ...) { kim_error err = KIM_NO_ERROR; kim_string format = NULL; kim_string string = NULL; if (!err && !in_function) { err = check_error (KIM_NULL_PARAMETER_ERR); } if (!err && !in_format ) { err = check_error (KIM_NULL_PARAMETER_ERR); } if (!err) { err = kim_string_create_from_format (&format, "%s(): %s", in_function, in_format); } if (!err) { va_list args; va_start (args, in_format); err = kim_string_create_from_format_va (&string, format, args); va_end (args); } if (!err) { kim_os_debug_print (string); } kim_string_free (&format); kim_string_free (&string); }
kim_error kim_ui_handle_kim_error (kim_ui_context *in_context, kim_identity in_identity, enum kim_ui_error_type in_type, kim_error in_error) { kim_error err = KIM_NO_ERROR; kim_string message = NULL; kim_string description = NULL; if (!err) { /* Do this first so last error doesn't get overwritten */ err = kim_string_create_for_last_error (&description, in_error); } if (!err && !in_context) { err = check_error (KIM_NULL_PARAMETER_ERR); } if (!err) { kim_string key = NULL; switch (in_type) { case kim_ui_error_type_authentication: key = "Kerberos Login Failed:"; break; case kim_ui_error_type_change_password: key = "Kerberos Change Password Failed:"; break; case kim_ui_error_type_selection: case kim_ui_error_type_generic: default: key = "Kerberos Operation Failed:"; break; } err = kim_os_string_create_localized (&message, key); } if (!err) { err = kim_ui_handle_error (in_context, in_identity, in_error, message, description); } kim_string_free (&description); kim_string_free (&message); return check_error (err); }
kim_error kim_identity_get_components_string (kim_identity in_identity, kim_string *out_components) { kim_error err = KIM_NO_ERROR; kim_string components = NULL; kim_count count, i; if (!err && !in_identity ) { err = check_error (KIM_NULL_PARAMETER_ERR); } if (!err && !out_components) { err = check_error (KIM_NULL_PARAMETER_ERR); } if (!err) { err = kim_identity_get_number_of_components (in_identity, &count); } if (!err) { err = kim_identity_get_component_at_index (in_identity, 0, &components); } for (i = 1; !err && i < count; i++) { kim_string new_components = NULL; kim_string component = NULL; err = kim_identity_get_component_at_index (in_identity, i, &component); if (!err) { err = kim_string_create_from_format (&new_components, "%s/%s", components, component); } if (!err) { kim_string_free (&components); components = new_components; new_components = NULL; } if (component ) { kim_string_free (&component); } if (new_components) { kim_string_free (&new_components); } } if (!err) { *out_components = components; components = NULL; } if (components) { kim_string_free (&components); } return check_error (err); }
kim_error kim_string_create_from_buffer (kim_string *out_string, const char *in_buffer, kim_count in_length) { kim_error err = kim_library_init (); kim_string string = NULL; if (!err && !out_string) { err = check_error (KIM_NULL_PARAMETER_ERR); } if (!err && !in_buffer ) { err = check_error (KIM_NULL_PARAMETER_ERR); } if (!err) { string = calloc (in_length + 1, sizeof (char *)); if (!string) { err = check_error (KIM_OUT_OF_MEMORY_ERR); } } if (!err) { memcpy ((char *) string, in_buffer, in_length * sizeof (char)); *out_string = string; string = NULL; } kim_string_free (&string); return check_error (err); }
kim_error kim_string_copy (kim_string *out_string, kim_string in_string) { kim_error err = kim_library_init (); kim_string string = 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) { if (in_string[0]) { string = calloc (strlen (in_string) + 1, sizeof (char *)); if (!string) { err = check_error (KIM_OUT_OF_MEMORY_ERR); } if (!err) { strncpy ((char *) string, in_string, strlen (in_string) + 1); } } else { string = kim_empty_string; } } if (!err) { *out_string = string; string = NULL; } kim_string_free (&string); return check_error (err); }
kim_error kim_string_create_from_format_va (kim_string *out_string, kim_string in_format, va_list in_args) { kim_error err = kim_library_init (); kim_string string = NULL; if (!err && !out_string) { err = check_error (KIM_NULL_PARAMETER_ERR); } if (!err && !in_format ) { err = check_error (KIM_NULL_PARAMETER_ERR); } if (!err) { err = kim_string_create_from_format_va_retcode (&string, in_format, in_args); } if (!err) { *out_string = string; string = NULL; } if (string) { kim_string_free (&string); } return check_error (err); }
kim_error kim_ui_fini (kim_ui_context *io_context) { kim_error err = KIM_NO_ERROR; if (!err && !io_context) { err = check_error (KIM_NULL_PARAMETER_ERR); } if (!err && io_context->initialized) { if (io_context->type == kim_ui_type_gui_plugin) { err = kim_ui_plugin_fini (io_context); #ifdef KIM_BUILTIN_UI } else if (io_context->type == kim_ui_type_gui_builtin) { err = kim_os_ui_gui_fini (io_context); } else if (io_context->type == kim_ui_type_cli) { err = kim_ui_cli_fini (io_context); #endif /* KIM_BUILTIN_UI */ } else { err = check_error (KIM_NO_UI_ERR); } kim_string_free (&io_context->password_to_save); } return check_error (err); }
static kim_error kim_os_selection_hints_get_dictionary_identity (CFDictionaryRef in_dictionary, kim_identity *out_identity) { kim_error err = KIM_NO_ERROR; CFStringRef identity_cfstr = NULL; kim_string identity_string = NULL; identity_cfstr = CFDictionaryGetValue (in_dictionary, KIM_IDENTITY_HINT); if (!identity_cfstr || CFGetTypeID (identity_cfstr) != CFStringGetTypeID ()) { kim_debug_printf ("%s: Malformed hints dictionary (invalid identity).", __FUNCTION__); err = check_error (KIM_PREFERENCES_READ_ERR); } if (!err) { err = kim_os_string_create_from_cfstring (&identity_string, identity_cfstr); } if (!err) { err = kim_identity_create_from_string (out_identity, identity_string); } kim_string_free (&identity_string); return check_error (err); }
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_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); }
void krb5int_vset_error_fl (struct errinfo *ep, long code, const char *file, int line, const char *fmt, va_list args) { va_list args2; char *str = NULL, *str2, *slash; #ifdef USE_KIM kim_string loc_fmt = NULL; /* Try to localize the format string */ if (kim_os_string_create_localized(&loc_fmt, fmt) == KIM_NO_ERROR) fmt = loc_fmt; #endif /* try vasprintf first */ va_copy(args2, args); if (vasprintf(&str, fmt, args2) < 0) { str = NULL; } va_end(args2); if (str && line) { /* Try to add file and line suffix. */ slash = strrchr(file, '/'); if (slash) file = slash + 1; if (asprintf(&str2, "%s (%s: %d)", str, file, line) > 0) { free(str); str = str2; } } /* If that failed, try using scratch_buf */ if (str == NULL) { vsnprintf(ep->scratch_buf, sizeof(ep->scratch_buf), fmt, args); str = strdup(ep->scratch_buf); /* try allocating again */ } /* free old string before setting new one */ if (ep->msg && ep->msg != ep->scratch_buf) { krb5int_free_error (ep, ep->msg); ep->msg = NULL; } ep->code = code; ep->msg = str ? str : ep->scratch_buf; #ifdef USE_KIM kim_string_free(&loc_fmt); #endif }
kim_error kim_os_string_create_from_cfstring (kim_string *out_string, CFStringRef in_cfstring) { kim_error err = KIM_NO_ERROR; kim_string string = NULL; CFIndex length = 0; if (!err && !out_string ) { err = check_error (KIM_NULL_PARAMETER_ERR); } if (!err && !in_cfstring) { err = check_error (KIM_NULL_PARAMETER_ERR); } if (!err) { char *ptr = NULL; /* check if in_cfstring is a C string internally so we can * avoid using CFStringGetMaximumSizeForEncoding which is wasteful */ ptr = (char *) CFStringGetCStringPtr(in_cfstring, kCFStringEncodingUTF8); if (ptr) { string = strdup (ptr); if (!string) { err = check_error (KIM_OUT_OF_MEMORY_ERR); } } else { length = CFStringGetMaximumSizeForEncoding (CFStringGetLength (in_cfstring), kCFStringEncodingUTF8) + 1; string = (char *) calloc (length, sizeof (char)); if (!string) { err = check_error (KIM_OUT_OF_MEMORY_ERR); } if (!err) { if (!CFStringGetCString (in_cfstring, (char *) string, length, kCFStringEncodingUTF8)) { err = KIM_OUT_OF_MEMORY_ERR; } } } } if (!err) { *out_string = string; string = NULL; } kim_string_free (&string); return check_error (err); }
kim_error kim_identity_compare (kim_identity in_identity, kim_identity in_compare_to_identity, kim_comparison *out_comparison) { kim_error err = KIM_NO_ERROR; if (!err && !in_identity ) { err = check_error (KIM_NULL_PARAMETER_ERR); } if (!err && !in_compare_to_identity) { err = check_error (KIM_NULL_PARAMETER_ERR); } if (!err && !out_comparison ) { err = check_error (KIM_NULL_PARAMETER_ERR); } if (!err) { if (krb5_principal_compare (in_identity->context, in_identity->principal, in_compare_to_identity->principal)) { *out_comparison = 0; } else { kim_string string = NULL; kim_string compare_to_string = NULL; err = kim_identity_get_string (in_identity, &string); if (!err) { err = kim_identity_get_string (in_compare_to_identity, &compare_to_string); } if (!err) { err = kim_string_compare (string, compare_to_string, out_comparison); } kim_string_free (&string); kim_string_free (&compare_to_string); } } return check_error (err); }
kim_error kim_ui_cli_enter_identity (kim_ui_context *in_context, kim_options io_options, kim_identity *out_identity, kim_boolean *out_change_password) { kim_error err = KIM_NO_ERROR; kim_string enter_identity_string = NULL; kim_string identity_string = NULL; if (!err && !io_options ) { err = check_error (KIM_NULL_PARAMETER_ERR); } if (!err && !out_identity ) { err = check_error (KIM_NULL_PARAMETER_ERR); } if (!err && !out_change_password) { err = check_error (KIM_NULL_PARAMETER_ERR); } if (!err) { err = kim_os_string_create_localized (&enter_identity_string, "Please enter your Kerberos identity"); } if (!err) { err = kim_ui_cli_read_string (&identity_string, 0, enter_identity_string); } if (!err) { err = kim_identity_create_from_string (out_identity, identity_string); } if (!err) { *out_change_password = 0; } kim_string_free (&identity_string); kim_string_free (&enter_identity_string); 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_os_preferences_get_identity_for_key (kim_preference_key in_key, kim_identity in_hardcoded_default, kim_identity *out_identity) { kim_error err = KIM_NO_ERROR; kim_string string = NULL; CFStringRef value = NULL; if (!err && !out_identity) { err = check_error (KIM_NULL_PARAMETER_ERR); } if (!err) { err = kim_os_preferences_copy_value (in_key, CFStringGetTypeID (), (CFPropertyListRef *) &value); } if (!err && !value) { err = kim_os_preferences_copy_value_compat (in_key, CFStringGetTypeID (), (CFPropertyListRef *) &value); } if (!err) { if (value) { err = kim_os_string_create_from_cfstring (&string, value); if (!err) { if (!strcmp (kim_os_preference_any_identity, string)) { *out_identity = KIM_IDENTITY_ANY; } else { err = kim_identity_create_from_string (out_identity, string); } } } else { err = kim_identity_copy (out_identity, in_hardcoded_default); } } kim_string_free (&string); if (value) { CFRelease (value); } return check_error (err); }
kim_error kim_identity_get_display_string (kim_identity in_identity, kim_string *out_display_string) { kim_error err = KIM_NO_ERROR; kim_string string = NULL; if (!err && !in_identity ) { err = check_error (KIM_NULL_PARAMETER_ERR); } if (!err && !out_display_string) { err = check_error (KIM_NULL_PARAMETER_ERR); } if (!err) { err = kim_identity_get_string (in_identity, &string); } if (!err) { kim_count i, j; kim_count length = strlen (string) + 1; /* Copy the '\0' */ char *display_string = (char *) string; /* so we can modify it */ /* In place copy, skipping escaped separators. * Note that we do not want to remove other escaped characters * (tab, break, newline, NULL) because they are less readable * when unescaped (and NULL isn't a valid string character). */ for (i = 0, j = 0; i < length; i++) { if (string[i] == '\\') { switch (string[i + 1]) { case '/': /* component separator */ case '@': /* realm separator */ continue; /* skip the '\' */ } } display_string[j++] = string[i]; /* Copy this char */ } *out_display_string = string; string = NULL; } if (string) { kim_string_free (&string); } return check_error (err); }
void kim_options_free (kim_options *io_options) { if (io_options && *io_options) { kim_string_free (&(*io_options)->service_name); if ((*io_options)->init_cred_context) { if ((*io_options)->init_cred_options) { if ((*io_options)->init_cred_options->address_list) { krb5_free_addresses ((*io_options)->init_cred_context, (*io_options)->init_cred_options->address_list); } krb5_get_init_creds_opt_free ((*io_options)->init_cred_context, (*io_options)->init_cred_options); } krb5_free_context ((*io_options)->init_cred_context); } free (*io_options); *io_options = NULL; } }
kim_error kim_error_set_message_for_code_va (kim_error in_code, va_list in_args) { kim_error err = KIM_NO_ERROR; kim_error code = kim_error_remap (in_code); if (!kim_error_is_builtin (code)) { kim_string message = NULL; err = kim_string_create_from_format_va_retcode (&message, error_message (code), in_args); if (!err) { err = kim_error_set_message (code, message); } kim_string_free (&message); } return err ? err : code; }
int print_ccache (kim_ccache in_ccache, int *out_found_valid_tgt) { kim_error err = 0; kim_credential_iterator iterator = NULL; kim_identity ccache_identity = NULL; kim_string type = NULL; kim_string name = NULL; kim_string ccache_identity_string = NULL; int found_tickets = 0; *out_found_valid_tgt = 0; if (!err) { err = kim_ccache_get_type (in_ccache, &type); printiferr (err, "while getting the ccache type"); } if (!err) { err = kim_ccache_get_name (in_ccache, &name); printiferr (err, "while getting the ccache name"); } if (!err) { err = kim_ccache_get_client_identity (in_ccache, &ccache_identity); printiferr (err, "while getting the ccache principal"); } if (!err) { err = kim_identity_get_display_string (ccache_identity, &ccache_identity_string); printiferr (err, "while unparsing the ccache principal name"); } if (!err) { printmsg ("Kerberos 5 ticket cache: '%s:%s'\nDefault principal: %s\n\n", type, name, ccache_identity_string); printmsg ("Valid Starting"); printfiller (' ', get_timestamp_width () - sizeof ("Valid Starting") + 3); printmsg ("Expires"); printfiller (' ', get_timestamp_width () - sizeof ("Expires") + 3); printmsg ("Service Principal\n"); err = kim_credential_iterator_create (&iterator, in_ccache); } while (!err) { kim_credential credential = NULL; kim_identity client = NULL; kim_identity service = NULL; kim_string client_string = NULL; kim_string service_string = NULL; krb5_creds *creds = NULL; int extra_field = 0; err = kim_credential_iterator_next (iterator, &credential); if (!err && !credential) { break; } if (!err) { err = kim_credential_get_client_identity (credential, &client); printiferr (err, "while getting the client principal"); } if (!err) { err = kim_identity_get_display_string (client, &client_string); printiferr (err, "while unparsing the client principal name"); } if (!err) { err = kim_credential_get_service_identity (credential, &service); printiferr (err, "while getting the service principal"); } if (!err) { err = kim_identity_get_display_string (service, &service_string); printiferr (err, "while unparsing the service principal name"); } if (!err) { err = kim_credential_get_krb5_creds (credential, kcontext, &creds); printiferr (err, "while getting krb5 creds"); } if (!err && krb5_is_config_principal(kcontext, creds->server)) goto next; if (!err) { found_tickets = 1; printtime (creds->times.starttime ? creds->times.starttime : creds->times.authtime); printmsg (" "); printtime (creds->times.endtime); printmsg (" "); printmsg ("%s\n", service_string); if (strcmp (ccache_identity_string, client_string)) { if (!extra_field) { printmsg ("\t"); } printmsg ("for client %s", client_string); extra_field++; } if (creds->ticket_flags & TKT_FLG_RENEWABLE) { printmsg (extra_field ? ", " : "\t"); printmsg ("renew until "); printtime (creds->times.renew_till); extra_field += 2; } if (extra_field > 2) { printmsg ("\n"); extra_field = 0; } if (show_flags) { printmsg (extra_field ? ", " : "\t"); printflags (creds->ticket_flags); extra_field++; } if (extra_field > 2) { printmsg ("\n"); extra_field = 0; } if (show_enctypes) { krb5_ticket *ticket_rep; if (krb5_decode_ticket (&creds->ticket, &ticket_rep) == 0) { if (!extra_field) { printmsg ("\t"); } else { printmsg (", "); } printmsg ("Etype (skey, tkt): %s, ", enctype_to_string (creds->keyblock.enctype)); printmsg ("%s ", enctype_to_string (ticket_rep->enc_part.enctype)); extra_field++; krb5_free_ticket (kcontext, ticket_rep); } } if (extra_field) { printmsg ("\n"); } if (show_address_list) { printmsg ("\tAddresses: "); if (!creds->addresses || !creds->addresses[0]) { printmsg ("(none)\n"); } else { int i; for (i = 0; creds->addresses[i]; i++) { if (i > 0) { printmsg (", "); } printaddress (*creds->addresses[i]); } printmsg ("\n"); } } if (extra_field) { printmsg ("\n"); } } if (!err) { kim_boolean is_tgt = 0; kim_credential_state state; err = kim_credential_is_tgt (credential, &is_tgt); printiferr (err, "while checking if creds are valid"); if (!err) { err = kim_credential_get_state (credential, &state); } if (!err && is_tgt && state == kim_credentials_state_valid) { *out_found_valid_tgt = 1; } } next: if (creds) { krb5_free_creds (kcontext, creds); } kim_string_free (&client_string); kim_string_free (&service_string); kim_identity_free (&client); kim_identity_free (&service); kim_credential_free (&credential); } kim_string_free (&type); kim_string_free (&name); kim_string_free (&ccache_identity_string); kim_identity_free (&ccache_identity); kim_credential_iterator_free (&iterator); if (!err) { if (!found_tickets) { printerr ("No Kerberos 5 tickets in credentials cache\n"); } else { printmsg ("\n"); } } return 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); }
kim_error kim_os_library_get_caller_name (kim_string *out_application_name) { kim_error err = KIM_NO_ERROR; kim_string name = NULL; CFBundleRef bundle = CFBundleGetMainBundle (); CFStringRef cfname = NULL; if (!err && !out_application_name) { err = check_error (KIM_NULL_PARAMETER_ERR); } if (!err && bundle) { cfname = CFBundleGetValueForInfoDictionaryKey (bundle, kCFBundleNameKey); if (!cfname || CFGetTypeID (cfname) != CFStringGetTypeID ()) { cfname = CFBundleGetValueForInfoDictionaryKey (bundle, kCFBundleExecutableKey); } if (cfname) { cfname = CFStringCreateCopy (kCFAllocatorDefault, cfname); } } if (!err && !cfname) { kim_string path = NULL; CFURLRef cfpath = NULL; CFURLRef cfpathnoext = NULL; err = kim_os_library_get_application_path (&path); if (!err) { cfpath = CFURLCreateFromFileSystemRepresentation (kCFAllocatorDefault, (const UInt8 *) path, strlen (path), 0); if (cfpath) { cfpathnoext = CFURLCreateCopyDeletingPathExtension (kCFAllocatorDefault, cfpath); } if (cfpathnoext) { cfname = CFURLCopyLastPathComponent (cfpathnoext); } else { cfname = CFURLCopyLastPathComponent (cfpath); } } if (cfpathnoext) { CFRelease (cfpathnoext); } if (cfpath ) { CFRelease (cfpath); } kim_string_free (&path); } if (!err && cfname) { err = kim_os_string_create_from_cfstring (&name, cfname); } if (!err) { *out_application_name = name; name = NULL; } if (cfname) { CFRelease (cfname); } kim_string_free (&name); 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_ui_cli_auth_prompt (kim_ui_context *in_context, kim_identity in_identity, kim_prompt_type in_type, kim_boolean in_allow_save_reply, kim_boolean in_hide_reply, kim_string in_title, kim_string in_message, kim_string in_description, char **out_reply, kim_boolean *out_save_reply) { kim_error err = KIM_NO_ERROR; 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) { if (in_type == kim_prompt_type_password) { kim_string enter_password_format = NULL; kim_string identity_string = NULL; err = kim_os_string_create_localized (&enter_password_format, "Please enter the password for %s"); if (!err) { err = kim_identity_get_display_string (in_identity, &identity_string); } if (!err) { err = kim_ui_cli_read_string ((kim_string *) out_reply, 1, enter_password_format, identity_string); } kim_string_free (&identity_string); kim_string_free (&enter_password_format); } else { krb5_context k5context = NULL; krb5_prompt prompts[1]; krb5_data reply_data; char reply_string [BUFSIZ]; prompts[0].prompt = (char *) in_description; prompts[0].hidden = in_hide_reply; prompts[0].reply = &reply_data; prompts[0].reply->data = reply_string; prompts[0].reply->length = sizeof (reply_string); err = krb5_init_context (&k5context); if (!err) { err = krb5_prompter_posix (k5context, in_context, in_title, in_message, 1, prompts); if (err == KRB5_LIBOS_PWDINTR || err == KRB5_LIBOS_CANTREADPWD) { err = check_error (KIM_USER_CANCELED_ERR); } } if (!err) { err = kim_string_create_from_buffer ((kim_string *) out_reply, prompts[0].reply->data, prompts[0].reply->length); if (!err) { /* always allow password saving */ *out_save_reply = (in_allow_save_reply && in_type == kim_prompt_type_password); } } if (k5context) { krb5_free_context (k5context); } } } return check_error (err); }
static kim_error kim_ui_cli_ask_change_password (kim_string in_identity_string) { kim_error err = KIM_NO_ERROR; kim_string ask_change_password = NULL; kim_string yes = NULL; kim_string no = NULL; kim_string unknown_response = NULL; kim_boolean done = 0; kim_comparison no_comparison, yes_comparison; if (!err) { err = kim_os_string_create_localized (&ask_change_password, "Your password has expired, would you like to change it? (yes/no)"); } if (!err) { err = kim_os_string_create_localized (&yes, "yes"); } if (!err) { err = kim_os_string_create_localized (&no, "no"); } if (!err) { err = kim_os_string_create_localized (&unknown_response, "%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, ask_change_password); if (!err) { err = kim_os_string_compare (answer, no, 1 /* case insensitive */, &no_comparison); } if (!err && kim_comparison_is_equal_to (no_comparison)) { err = check_error (KIM_USER_CANCELED_ERR); } if (!err) { err = kim_os_string_compare (answer, yes, 1 /* case insensitive */, &yes_comparison); } if (!err) { if (kim_comparison_is_equal_to (yes_comparison)) { done = 1; } else { fprintf (stdout, unknown_response, answer); fprintf (stdout, "\n"); } } kim_string_free (&answer); } kim_string_free (&ask_change_password); kim_string_free (&yes); kim_string_free (&no); kim_string_free (&unknown_response); return check_error (err); }
kim_error kim_ui_cli_change_password (kim_ui_context *in_context, kim_identity in_identity, kim_boolean in_old_password_expired, char **out_old_password, char **out_new_password, char **out_verify_password) { kim_error err = KIM_NO_ERROR; kim_string enter_old_password_format = NULL; kim_string enter_new_password_format = NULL; kim_string enter_verify_password_format = NULL; kim_string identity_string = NULL; kim_string old_password = NULL; kim_string new_password = NULL; kim_string verify_password = NULL; kim_boolean done = 0; 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_display_string (in_identity, &identity_string); } if (!err && in_old_password_expired) { err = kim_ui_cli_ask_change_password (identity_string); } if (!err) { err = kim_os_string_create_localized (&enter_old_password_format, "Please enter the old password for %s"); } if (!err) { err = kim_os_string_create_localized (&enter_new_password_format, "Please enter the new password for %s"); } if (!err) { err = kim_os_string_create_localized (&enter_verify_password_format, "Verifying, please re-enter the new password for %s again"); } while (!err && !done) { kim_boolean was_prompted = 0; /* ignore because we always prompt */ kim_string_free (&old_password); err = kim_ui_cli_read_string (&old_password, 1, enter_old_password_format, identity_string); if (!err && strlen (old_password) < 1) { /* Empty password: Synthesize bad password err */ err = KRB5KRB_AP_ERR_BAD_INTEGRITY; } if (!err) { err = kim_credential_create_for_change_password ((kim_credential *) &in_context->tcontext, in_identity, old_password, in_context, &was_prompted); } if (err && err != KIM_USER_CANCELED_ERR) { /* new creds failed, report error to user */ err = kim_ui_handle_kim_error (in_context, in_identity, kim_ui_error_type_change_password, err); } else { done = 1; } } if (!err) { err = kim_ui_cli_read_string (&new_password, 1, enter_new_password_format, identity_string); } if (!err) { err = kim_ui_cli_read_string (&verify_password, 1, enter_verify_password_format, identity_string); } 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; } kim_string_free (&old_password); kim_string_free (&new_password); kim_string_free (&verify_password); kim_string_free (&identity_string); kim_string_free (&enter_old_password_format); kim_string_free (&enter_new_password_format); kim_string_free (&enter_verify_password_format); return check_error (err); }
void kim_ui_cli_free_string (kim_ui_context *in_context, char **io_string) { kim_string_free ((kim_string *) io_string); }
kim_error kim_identity_change_password_with_credential (kim_identity in_identity, kim_credential in_credential, kim_string in_new_password, kim_ui_context *in_ui_context, kim_error *out_rejected_err, kim_string *out_rejected_message, kim_string *out_rejected_description) { kim_error err = KIM_NO_ERROR; krb5_creds *creds = NULL; int rejected_err = 0; krb5_data message_data; krb5_data description_data; if (!err && !in_identity ) { err = check_error (KIM_NULL_PARAMETER_ERR); } if (!err && !in_credential ) { err = check_error (KIM_NULL_PARAMETER_ERR); } if (!err && !in_new_password ) { err = check_error (KIM_NULL_PARAMETER_ERR); } if (!err && !in_ui_context ) { err = check_error (KIM_NULL_PARAMETER_ERR); } if (!err && !out_rejected_err) { err = check_error (KIM_NULL_PARAMETER_ERR); } if (!err) { err = kim_credential_get_krb5_creds (in_credential, in_identity->context, &creds); } if (!err) { if (krb5_principal_compare (in_identity->context, in_identity->principal, creds->client)) { /* Same principal, change the password normally */ err = krb5_error (in_identity->context, krb5_change_password (in_identity->context, creds, (char *) in_new_password, &rejected_err, &message_data, &description_data)); } else { /* Different principal, use set change password protocol */ err = krb5_error (in_identity->context, krb5_set_password (in_identity->context, creds, (char *) in_new_password, in_identity->principal, &rejected_err, &message_data, &description_data)); } } if (!err && rejected_err) { kim_string rejected_message = NULL; kim_string rejected_description = NULL; if (message_data.data && message_data.length > 0) { err = kim_string_create_from_buffer (&rejected_message, message_data.data, message_data.length); } else { err = kim_os_string_create_localized (&rejected_message, "Kerberos Change Password Failed:"); } if (!err) { if (description_data.data && description_data.length > 0) { err = kim_string_create_from_buffer (&rejected_description, description_data.data, description_data.length); } else { err = kim_os_string_create_localized (&rejected_description, "New password rejected."); } } if (!err && in_ui_context->type != kim_ui_type_cli) { char *c; // replace all \n and \r characters with spaces for (c = (char *) rejected_message; *c != '\0'; c++) { if ((*c == '\n') || (*c == '\r')) { *c = ' '; } } for (c = (char *) rejected_description; *c != '\0'; c++) { if ((*c == '\n') || (*c == '\r')) { *c = ' '; } } } if (!err) { if (out_rejected_message) { *out_rejected_message = rejected_message; rejected_message = NULL; } if (out_rejected_description) { *out_rejected_description = rejected_description; rejected_description = NULL; } } kim_string_free (&rejected_message); kim_string_free (&rejected_description); krb5_free_data_contents (in_identity->context, &message_data); krb5_free_data_contents (in_identity->context, &description_data); } if (!err) { /* do this after reporting errors so we don't double report rejection */ *out_rejected_err = rejected_err; } if (creds) { krb5_free_creds (in_identity->context, creds); } 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); }