#!/usr/bin/perl use strict; my @rewritesyms = ( "krb5_cc_end_seq_get", "krb5_config_get_string", "krb5_set_default_in_tkt_etypes", "krb5_get_pw_salt", "krb5_free_salt", "krb5_string_to_key_data_salt", "krb5_free_keyblock_contents", "krb5_set_real_time", "krb5_mk_req_extended", "krb5_free_keyblock", "krb5_auth_con_getremotesubkey", "krb5_auth_con_getlocalsubkey", "krb5_set_password", "krb5_set_password_using_ccache", "krb5_realm_compare", "krb5_get_renewed_creds", "krb5_get_validated_creds", "krb5_get_init_creds_keytab", "krb5_prompter_posix", "krb5_string_to_deltat", "krb5_get_all_client_addrs", "krb5_kt_get_type", "krb5_kt_add_entry", "krb5_kt_remove_entry", "krb5_mk_req", "krb5_kt_get_name", "krb5_rd_req", "krb5_free_ticket", "krb5_build_principal_va", "krb5_build_principal_va_ext", "krb5_cc_cache_match", "krb5_cc_close", "krb5_cc_default", "krb5_cc_get_config", "krb5_cc_get_full_name", "krb5_cc_get_name", "krb5_cc_get_principal", "krb5_cc_get_type", "krb5_cc_initialize", "krb5_cc_move", "krb5_cc_new_unique", "krb5_cc_resolve", "krb5_cc_store_cred", "krb5_cc_switch", "krb5_cc_retrieve_cred", "krb5_cc_remove_cred", "krb5_cc_get_kdc_offset", "krb5_cc_set_kdc_offset", "krb5_cc_next_cred", "krb5_cccol_last_change_time", "krb5_crypto_init", "krb5_crypto_getblocksize", "krb5_crypto_destroy", "krb5_decrypt_ivec", "krb5_encrypt_ivec", "krb5_crypto_getenctype", "krb5_generate_random_keyblock", "krb5_get_wrapped_length", "krb5_copy_creds_contents", "krb5_copy_data", "krb5_copy_principal", "krb5_data_copy", "krb5_data_free", "krb5_data_zero", "krb5_free_context", "krb5_free_cred_contents", "krb5_free_creds", "krb5_free_principal", "krb5_sname_to_principal", "krb5_get_credentials", "krb5_get_error_string", "krb5_get_default_principal", "krb5_get_error_message", "krb5_get_init_creds_opt_alloc", "krb5_get_init_creds_opt_free", "krb5_get_init_creds_opt_set_canonicalize", "krb5_get_init_creds_opt_set_forwardable", "krb5_get_init_creds_opt_set_proxiable", "krb5_get_init_creds_opt_set_renew_life", "krb5_get_init_creds_opt_set_tkt_life", "krb5_get_init_creds_password", "krb5_get_kdc_cred", "krb5_get_kdc_sec_offset", "krb5_init_context", "krb5_make_principal", "krb5_parse_name", "krb5_principal_compare", "krb5_principal_get_realm", "krb5_timeofday", "krb5_unparse_name", "krb5_us_timeofday", "krb5_kt_start_seq_get", "krb5_kt_end_seq_get", "krb5_xfree", "krb5_kt_next_entry", "krb5_kt_free_entry", "gsskrb5_extract_authz_data_from_sec_context", "krb5_sendauth", "krb5_free_ap_rep_enc_part", "krb5_free_error", "krb5_recvauth", "krb5_recvauth_match_version", "krb5_mk_priv", "krb5_rd_priv", "krb5_mk_safe", "krb5_rd_safe", "krb5_set_home_dir_access", "krb5_verify_init_creds", "krb5_verify_init_creds_opt_init", "krb5_verify_init_creds_opt_set_ap_req_nofail", "krb5_kuserok", "com_right", "com_right_r", "gss_import_name", "krb5_appdefault_boolean", "krb5_appdefault_string", ); my @proxysyms = ( "gss_accept_sec_context", "gss_acquire_cred", "gss_add_cred", "gss_add_oid_set_member", "gss_canonicalize_name", "gss_compare_name", "gss_context_time", "gss_create_empty_oid_set", "gss_delete_sec_context", "gss_display_name", "gss_display_status", "gss_duplicate_name", "gss_export_name", "gss_export_sec_context", "gss_get_mic", "gss_import_sec_context", "gss_indicate_mechs", "gss_init_sec_context", "gss_inquire_context", "gss_inquire_cred", "gss_inquire_cred_by_mech", "gss_inquire_names_for_mech", "gss_krb5_ccache_name", "gss_krb5_copy_ccache", "gss_krb5_export_lucid_sec_context", "gss_krb5_free_lucid_sec_context", "gss_krb5_set_allowable_enctypes", "gss_oid_equal", "gss_oid_to_str", "gss_process_context_token", "gss_release_buffer", "gss_release_cred", "gss_release_name", "gss_release_oid", "gss_release_oid_set", "gss_seal", "gss_test_oid_set_member", "gss_unseal", "gss_unwrap", "gss_verify_mic", "gss_wrap", "gss_wrap_size_limit", "krb5_cc_start_seq_get", "krb5_cc_default_name", "krb5_cc_destroy", "krb5_cccol_cursor_free", "krb5_cccol_cursor_new", "krb5_cccol_cursor_next", "krb5_free_host_realm", "krb5_get_default_realm", "krb5_get_host_realm", "krb5_gss_register_acceptor_identity", "krb5_cc_set_default_name", "krb5_kt_resolve", "krb5_kt_default", "krb5_kt_default_name", "krb5_kt_close", "krb5_kt_destroy", "krb5_auth_con_free", "krb5_auth_con_init", "krb5_auth_con_genaddrs", "krb5_auth_con_getlocalseqnumber", "krb5_auth_con_getremoteseqnumber", "krb5_auth_con_setflags", "krb5_auth_con_getflags", "krb5_clear_error_message", "krb5_free_error_message", "krb5_set_default_realm", "krb5_set_error_message", "krb5_vset_error_message", "com_err", "com_err_va", "reset_com_err_hook", "set_com_err_hook", ); sub gen_header { my $sym; my $syms = shift; print "void __attribute__((constructor)) heim_load_frameworks(void);\n"; print "void heim_load_functions(void);\n"; foreach $sym (@$syms) { print "extern void (*fun_${sym})();\n"; } } sub gen_loader { my $sym; my $syms = shift; print "#include \n"; print "#include \n"; print "#include \n"; print "#include \n"; print "#include \n"; print "#include \"heim-sym.h\"\n"; print "\n"; print "static void *hf = NULL;\n"; print "static void *gf = NULL;\n"; print "void heim_load_frameworks(void) {\n"; print "hf = dlopen(\"/System/Library/PrivateFrameworks/Heimdal.framework/Heimdal\", RTLD_LAZY|RTLD_LOCAL);\n"; print "gf = dlopen(\"/System/Library/Frameworks/GSS.framework/GSS\", RTLD_LAZY|RTLD_LOCAL);\n"; printf "}\n"; printf "\n"; print "void load_functions(void) {\n"; foreach $sym (@$syms) { my $lib; if ($sym =~ /gss/) { $lib = "gf"; } else { $lib = "hf"; } print "fun_${sym} = dlsym(${lib}, \"$sym\");\n"; print "if (!fun_${sym}) { syslog(LOG_ERR, \"${sym} failed loading\"); }\n"; } printf "}\n"; printf "\n"; print "void heim_load_functions(void) {\n"; print "static dispatch_once_t once = 0;\n"; print "dispatch_once(&once, ^{ load_functions(); });\n"; print ("}\n\n"); } sub gen_32 { my $sym; my $syms = shift; my $prefix = shift; my $num = 0; print "#ifdef __i386__\n"; print " .text\n\n"; foreach $sym (@$syms) { $num++; print ".globl ${prefix}_${sym}\n"; print "${prefix}_${sym}:\n"; print "\tpushl %ebp\n"; print "\tmovl %esp, %ebp\n"; print "\tsubl \$72, %esp\n"; print "\tcall _heim_load_functions\n"; print "\taddl \$72, %esp\n"; print "\tmovl %ebp, %esp\n"; print "\popl %ebp\n"; print "\tcall L0${num}\n"; print "L0${num}:\n"; print "\tpopl %edx\n"; print "\tleal L_fun_${sym}\$non_lazy_ptr-\"L0${num}\"(%edx), %eax\n"; print "\tmovl (%eax), %edx\n"; print "\tmovl (%edx), %edx\n"; print "\tjmp *%edx\n"; print "\n"; } foreach $sym (@$syms) { print ".comm _fun_${sym},4,2\n"; } print " .section __IMPORT,__pointers,non_lazy_symbol_pointers\n"; foreach $sym (@$syms) { print "L_fun_${sym}\$non_lazy_ptr:\n"; print " .indirect_symbol _fun_${sym}\n"; print "\t.long 0\n"; } print "\t.subsections_via_symbols\n"; print "#endif\n"; } sub gen_64 { my $sym; my $syms = shift; my $prefix = shift; print "#ifdef __x86_64__\n"; print ".text\n\n"; foreach $sym (@$syms) { print " .globl ${prefix}_${sym}\n"; print "${prefix}_${sym}:\n"; print "\tpushq %rbp\n"; print "\tmovq %rsp, %rbp\n"; print "\tsubq \$208, %rsp\n"; print "\tpushq %rdi\n"; print "\tpushq %rsi\n"; print "\tpushq %rdx\n"; print "\tpushq %rcx\n"; print "\tpushq %r8\n"; print "\tpushq %r9\n"; print "\tcall _heim_load_functions\n"; print "\tpopq %r9\n"; print "\tpopq %r8\n"; print "\tpopq %rcx\n"; print "\tpopq %rdx\n"; print "\tpopq %rsi\n"; print "\tpopq %rdi\n"; print "\taddq \$208, %rsp\n"; print "\tmovq %rbp, %rsp\n"; print "\tpopq %rbp\n"; print "\tmovq _fun_${sym}\@GOTPCREL(%rip), %r11\n"; print "\tmovq (%r11), %r11\n"; print "\tjmp *%r11\n"; print "\n"; } foreach $sym (@$syms) { print ".comm _fun_${sym},8,3\n"; } print "#endif\n"; } sub gen_ppc { my $sym; my $syms = shift; my $prefix = shift; print "#ifdef __ppc__\n"; print ".section __TEXT,__text,regular,pure_instructions\n"; print ".section __TEXT,__picsymbolstub1,symbol_stubs,pure_instructions,32\n"; print ".machine ppc7400\n"; print ".text\n"; foreach $sym (@$syms) { print ".globl ${prefix}_${sym}\n"; print "${prefix}_${sym}:\n"; print "\tbl _abort\n"; print "\n"; } foreach $sym (@$syms) { print ".comm _fun_${sym},4,2\n"; } print "#endif\n"; } print "/* generated file, no dont edit */\n"; my @all = (@rewritesyms, @proxysyms); gen_32(\@rewritesyms, "_heim") if ($ARGV[0] eq '3'); gen_64(\@rewritesyms, "_heim") if ($ARGV[0] eq '6'); gen_ppc(\@rewritesyms, "_heim") if ($ARGV[0] eq 'p'); gen_32(\@proxysyms, "") if ($ARGV[0] eq '3p'); gen_64(\@proxysyms, "") if ($ARGV[0] eq '6p'); gen_ppc(\@proxysyms, "") if ($ARGV[0] eq 'pp'); gen_header(\@all) if ($ARGV[0] eq 'h'); gen_loader(\@all) if ($ARGV[0] eq 'l');