1#!/usr/bin/perl 2 3use strict; 4 5my @rewritesyms = ( 6 "krb5_cc_end_seq_get", 7 "krb5_config_get_string", 8 "krb5_set_default_in_tkt_etypes", 9 "krb5_get_pw_salt", 10 "krb5_free_salt", 11 "krb5_string_to_key_data_salt", 12 "krb5_free_keyblock_contents", 13 "krb5_set_real_time", 14 "krb5_mk_req_extended", 15 "krb5_free_keyblock", 16 "krb5_auth_con_getremotesubkey", 17 "krb5_auth_con_getlocalsubkey", 18 "krb5_set_password", 19 "krb5_set_password_using_ccache", 20 "krb5_realm_compare", 21 "krb5_get_renewed_creds", 22 "krb5_get_validated_creds", 23 "krb5_get_init_creds_keytab", 24 "krb5_prompter_posix", 25 "krb5_string_to_deltat", 26 "krb5_get_all_client_addrs", 27 "krb5_kt_get_type", 28 "krb5_kt_add_entry", 29 "krb5_kt_remove_entry", 30 "krb5_mk_req", 31 "krb5_kt_get_name", 32 "krb5_rd_req", 33 "krb5_free_ticket", 34 "krb5_build_principal_va", 35 "krb5_build_principal_va_ext", 36 "krb5_cc_cache_match", 37 "krb5_cc_close", 38 "krb5_cc_default", 39 "krb5_cc_get_config", 40 "krb5_cc_get_full_name", 41 "krb5_cc_get_name", 42 "krb5_cc_get_principal", 43 "krb5_cc_get_type", 44 "krb5_cc_initialize", 45 "krb5_cc_move", 46 "krb5_cc_new_unique", 47 "krb5_cc_resolve", 48 "krb5_cc_store_cred", 49 "krb5_cc_switch", 50 "krb5_cc_retrieve_cred", 51 "krb5_cc_remove_cred", 52 "krb5_cc_get_kdc_offset", 53 "krb5_cc_set_kdc_offset", 54 "krb5_cc_next_cred", 55 "krb5_cccol_last_change_time", 56 "krb5_crypto_init", 57 "krb5_crypto_getblocksize", 58 "krb5_crypto_destroy", 59 "krb5_decrypt_ivec", 60 "krb5_encrypt_ivec", 61 "krb5_crypto_getenctype", 62 "krb5_generate_random_keyblock", 63 "krb5_get_wrapped_length", 64 "krb5_copy_creds_contents", 65 "krb5_copy_data", 66 "krb5_copy_principal", 67 "krb5_data_copy", 68 "krb5_data_free", 69 "krb5_data_zero", 70 "krb5_free_context", 71 "krb5_free_cred_contents", 72 "krb5_free_creds", 73 "krb5_free_principal", 74 "krb5_sname_to_principal", 75 "krb5_get_credentials", 76 "krb5_get_error_string", 77 "krb5_get_default_principal", 78 "krb5_get_error_message", 79 "krb5_get_init_creds_opt_alloc", 80 "krb5_get_init_creds_opt_free", 81 "krb5_get_init_creds_opt_set_canonicalize", 82 "krb5_get_init_creds_opt_set_forwardable", 83 "krb5_get_init_creds_opt_set_proxiable", 84 "krb5_get_init_creds_opt_set_renew_life", 85 "krb5_get_init_creds_opt_set_tkt_life", 86 "krb5_get_init_creds_password", 87 "krb5_get_kdc_cred", 88 "krb5_get_kdc_sec_offset", 89 "krb5_init_context", 90 "krb5_init_context_flags", 91 "krb5_make_principal", 92 "krb5_parse_name", 93 "krb5_parse_name_flags", 94 "krb5_principal_compare", 95 "krb5_principal_get_realm", 96 "krb5_timeofday", 97 "krb5_unparse_name", 98 "krb5_us_timeofday", 99 "krb5_kt_start_seq_get", 100 "krb5_kt_end_seq_get", 101 "krb5_xfree", 102 "krb5_kt_next_entry", 103 "krb5_kt_free_entry", 104 "gsskrb5_extract_authz_data_from_sec_context", 105 "krb5_sendauth", 106 "krb5_free_ap_rep_enc_part", 107 "krb5_free_error", 108 "krb5_recvauth", 109 "krb5_recvauth_match_version", 110 "krb5_mk_priv", 111 "krb5_rd_priv", 112 "krb5_mk_safe", 113 "krb5_rd_safe", 114 "krb5_set_home_dir_access", 115 "krb5_verify_init_creds", 116 "krb5_verify_init_creds_opt_init", 117 "krb5_verify_init_creds_opt_set_ap_req_nofail", 118 "krb5_kuserok", 119 "com_right", 120 "com_right_r", 121 "gss_import_name", 122 "krb5_appdefault_boolean", 123 "krb5_appdefault_string", 124 ); 125 126my @proxysyms = ( 127 "gss_accept_sec_context", 128 "gss_acquire_cred", 129 "gss_add_cred", 130 "gss_add_oid_set_member", 131 "gss_canonicalize_name", 132 "gss_compare_name", 133 "gss_context_time", 134 "gss_create_empty_oid_set", 135 "gss_delete_sec_context", 136 "gss_display_name", 137 "gss_display_status", 138 "gss_duplicate_name", 139 "gss_export_name", 140 "gss_export_sec_context", 141 "gss_get_mic", 142 "gss_import_sec_context", 143 "gss_indicate_mechs", 144 "gss_init_sec_context", 145 "gss_inquire_context", 146 "gss_inquire_cred", 147 "gss_inquire_cred_by_mech", 148 "gss_inquire_names_for_mech", 149 "gss_krb5_ccache_name", 150 "gss_krb5_copy_ccache", 151 "gss_krb5_export_lucid_sec_context", 152 "gss_krb5_free_lucid_sec_context", 153 "gss_krb5_set_allowable_enctypes", 154 "gss_oid_equal", 155 "gss_oid_to_str", 156 "gss_process_context_token", 157 "gss_release_buffer", 158 "gss_release_cred", 159 "gss_release_name", 160 "gss_release_oid", 161 "gss_release_oid_set", 162 "gss_seal", 163 "gss_test_oid_set_member", 164 "gss_unseal", 165 "gss_unwrap", 166 "gss_verify_mic", 167 "gss_wrap", 168 "gss_wrap_size_limit", 169 "krb5_cc_start_seq_get", 170 "krb5_cc_default_name", 171 "krb5_cc_destroy", 172 "krb5_cccol_cursor_free", 173 "krb5_cccol_cursor_new", 174 "krb5_cccol_cursor_next", 175 "krb5_free_host_realm", 176 "krb5_get_default_realm", 177 "krb5_get_host_realm", 178 "krb5_gss_register_acceptor_identity", 179 "krb5_cc_set_default_name", 180 "krb5_kt_resolve", 181 "krb5_kt_default", 182 "krb5_kt_default_name", 183 "krb5_kt_close", 184 "krb5_kt_destroy", 185 "krb5_auth_con_free", 186 "krb5_auth_con_init", 187 "krb5_auth_con_genaddrs", 188 "krb5_auth_con_getlocalseqnumber", 189 "krb5_auth_con_getremoteseqnumber", 190 "krb5_auth_con_setflags", 191 "krb5_auth_con_getflags", 192 "krb5_clear_error_message", 193 "krb5_free_error_message", 194 "krb5_set_default_realm", 195 "krb5_set_error_message", 196 "krb5_vset_error_message", 197 "com_err", 198 "com_err_va", 199 "reset_com_err_hook", 200 "set_com_err_hook", 201 ); 202 203 204sub gen_header { 205 my $sym; 206 my $syms = shift; 207 print "void __attribute__((constructor)) heim_load_frameworks(void);\n"; 208 print "void heim_load_functions(void);\n"; 209 foreach $sym (@$syms) { 210 print "extern void (*fun_${sym})();\n"; 211 } 212} 213 214sub gen_loader { 215 my $sym; 216 my $syms = shift; 217 print "#include <dlfcn.h>\n"; 218 print "#include <stdio.h>\n"; 219 print "#include <stdlib.h>\n"; 220 print "#include <syslog.h>\n"; 221 print "#include <dispatch/dispatch.h>\n"; 222 print "#include \"heim-sym.h\"\n"; 223 print "\n"; 224 print "static void *hf = NULL;\n"; 225 print "static void *gf = NULL;\n"; 226 print "void heim_load_frameworks(void) {\n"; 227 print "hf = dlopen(\"/System/Library/PrivateFrameworks/Heimdal.framework/Heimdal\", RTLD_LAZY|RTLD_LOCAL);\n"; 228 print "gf = dlopen(\"/System/Library/Frameworks/GSS.framework/GSS\", RTLD_LAZY|RTLD_LOCAL);\n"; 229 printf "}\n"; 230 printf "\n"; 231 232 print "void load_functions(void) {\n"; 233 foreach $sym (@$syms) { 234 my $lib; 235 if ($sym =~ /gss/) { 236 $lib = "gf"; 237 } else { 238 $lib = "hf"; 239 } 240 print "fun_${sym} = dlsym(${lib}, \"$sym\");\n"; 241 print "if (!fun_${sym}) { syslog(LOG_ERR, \"${sym} failed loading\"); }\n"; 242 } 243 printf "}\n"; 244 printf "\n"; 245 print "void heim_load_functions(void) {\n"; 246 print "static dispatch_once_t once = 0;\n"; 247 print "dispatch_once(&once, ^{ load_functions(); });\n"; 248 print ("}\n\n"); 249} 250 251sub gen_32 { 252 253 my $sym; 254 my $syms = shift; 255 my $prefix = shift; 256 257 my $num = 0; 258 259 print "#ifdef __i386__\n"; 260 print " .text\n\n"; 261 262 foreach $sym (@$syms) { 263 $num++; 264 print ".globl ${prefix}_${sym}\n"; 265 print "${prefix}_${sym}:\n"; 266 print "\tpushl %ebp\n"; 267 print "\tmovl %esp, %ebp\n"; 268 print "\tsubl \$72, %esp\n"; 269 print "\tcall _heim_load_functions\n"; 270 print "\taddl \$72, %esp\n"; 271 print "\tmovl %ebp, %esp\n"; 272 print "\popl %ebp\n"; 273 print "\tcall L0${num}\n"; 274 print "L0${num}:\n"; 275 print "\tpopl %edx\n"; 276 print "\tleal L_fun_${sym}\$non_lazy_ptr-\"L0${num}\"(%edx), %eax\n"; 277 print "\tmovl (%eax), %edx\n"; 278 print "\tmovl (%edx), %edx\n"; 279 print "\tjmp *%edx\n"; 280 print "\n"; 281 } 282 283 foreach $sym (@$syms) { 284 print ".comm _fun_${sym},4,2\n"; 285 } 286 print " .section __IMPORT,__pointers,non_lazy_symbol_pointers\n"; 287 foreach $sym (@$syms) { 288 print "L_fun_${sym}\$non_lazy_ptr:\n"; 289 print " .indirect_symbol _fun_${sym}\n"; 290 print "\t.long 0\n"; 291 } 292 print "\t.subsections_via_symbols\n"; 293 294 print "#endif\n"; 295} 296 297sub gen_64 { 298 299 my $sym; 300 my $syms = shift; 301 my $prefix = shift; 302 303 print "#ifdef __x86_64__\n"; 304 print ".text\n\n"; 305 306 foreach $sym (@$syms) { 307 print " .globl ${prefix}_${sym}\n"; 308 print "${prefix}_${sym}:\n"; 309 print "\tpushq %rbp\n"; 310 print "\tmovq %rsp, %rbp\n"; 311 print "\tsubq \$208, %rsp\n"; 312 print "\tpushq %rdi\n"; 313 print "\tpushq %rsi\n"; 314 print "\tpushq %rdx\n"; 315 print "\tpushq %rcx\n"; 316 print "\tpushq %r8\n"; 317 print "\tpushq %r9\n"; 318 print "\tcall _heim_load_functions\n"; 319 print "\tpopq %r9\n"; 320 print "\tpopq %r8\n"; 321 print "\tpopq %rcx\n"; 322 print "\tpopq %rdx\n"; 323 print "\tpopq %rsi\n"; 324 print "\tpopq %rdi\n"; 325 print "\taddq \$208, %rsp\n"; 326 print "\tmovq %rbp, %rsp\n"; 327 print "\tpopq %rbp\n"; 328 print "\tmovq _fun_${sym}\@GOTPCREL(%rip), %r11\n"; 329 print "\tmovq (%r11), %r11\n"; 330 print "\tjmp *%r11\n"; 331 print "\n"; 332 } 333 334 foreach $sym (@$syms) { 335 print ".comm _fun_${sym},8,3\n"; 336 } 337 print "#endif\n"; 338} 339 340sub gen_ppc { 341 342 my $sym; 343 my $syms = shift; 344 my $prefix = shift; 345 346 print "#ifdef __ppc__\n"; 347 print ".section __TEXT,__text,regular,pure_instructions\n"; 348 print ".section __TEXT,__picsymbolstub1,symbol_stubs,pure_instructions,32\n"; 349 print ".machine ppc7400\n"; 350 print ".text\n"; 351 352 foreach $sym (@$syms) { 353 print ".globl ${prefix}_${sym}\n"; 354 print "${prefix}_${sym}:\n"; 355 print "\tbl _abort\n"; 356 print "\n"; 357 } 358 359 foreach $sym (@$syms) { 360 print ".comm _fun_${sym},4,2\n"; 361 } 362 363 print "#endif\n"; 364} 365 366 367print "/* generated file, no dont edit */\n"; 368 369my @all = (@rewritesyms, @proxysyms); 370 371gen_32(\@rewritesyms, "_heim") if ($ARGV[0] eq '3'); 372gen_64(\@rewritesyms, "_heim") if ($ARGV[0] eq '6'); 373gen_ppc(\@rewritesyms, "_heim") if ($ARGV[0] eq 'p'); 374gen_32(\@proxysyms, "") if ($ARGV[0] eq '3p'); 375gen_64(\@proxysyms, "") if ($ARGV[0] eq '6p'); 376gen_ppc(\@proxysyms, "") if ($ARGV[0] eq 'pp'); 377 378gen_header(\@all) if ($ARGV[0] eq 'h'); 379gen_loader(\@all) if ($ARGV[0] eq 'l'); 380 381