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_principal_compare", 94 "krb5_principal_get_realm", 95 "krb5_timeofday", 96 "krb5_unparse_name", 97 "krb5_us_timeofday", 98 "krb5_kt_start_seq_get", 99 "krb5_kt_end_seq_get", 100 "krb5_xfree", 101 "krb5_kt_next_entry", 102 "krb5_kt_free_entry", 103 "gsskrb5_extract_authz_data_from_sec_context", 104 "krb5_sendauth", 105 "krb5_free_ap_rep_enc_part", 106 "krb5_free_error", 107 "krb5_recvauth", 108 "krb5_recvauth_match_version", 109 "krb5_mk_priv", 110 "krb5_rd_priv", 111 "krb5_mk_safe", 112 "krb5_rd_safe", 113 "krb5_set_home_dir_access", 114 "krb5_verify_init_creds", 115 "krb5_verify_init_creds_opt_init", 116 "krb5_verify_init_creds_opt_set_ap_req_nofail", 117 "krb5_kuserok", 118 "com_right", 119 "com_right_r", 120 "gss_import_name", 121 "krb5_appdefault_boolean", 122 "krb5_appdefault_string", 123 ); 124 125my @proxysyms = ( 126 "gss_accept_sec_context", 127 "gss_acquire_cred", 128 "gss_add_cred", 129 "gss_add_oid_set_member", 130 "gss_canonicalize_name", 131 "gss_compare_name", 132 "gss_context_time", 133 "gss_create_empty_oid_set", 134 "gss_delete_sec_context", 135 "gss_display_name", 136 "gss_display_status", 137 "gss_duplicate_name", 138 "gss_export_name", 139 "gss_export_sec_context", 140 "gss_get_mic", 141 "gss_import_sec_context", 142 "gss_indicate_mechs", 143 "gss_init_sec_context", 144 "gss_inquire_context", 145 "gss_inquire_cred", 146 "gss_inquire_cred_by_mech", 147 "gss_inquire_names_for_mech", 148 "gss_krb5_ccache_name", 149 "gss_krb5_copy_ccache", 150 "gss_krb5_export_lucid_sec_context", 151 "gss_krb5_free_lucid_sec_context", 152 "gss_krb5_set_allowable_enctypes", 153 "gss_oid_equal", 154 "gss_oid_to_str", 155 "gss_process_context_token", 156 "gss_release_buffer", 157 "gss_release_cred", 158 "gss_release_name", 159 "gss_release_oid", 160 "gss_release_oid_set", 161 "gss_seal", 162 "gss_test_oid_set_member", 163 "gss_unseal", 164 "gss_unwrap", 165 "gss_verify_mic", 166 "gss_wrap", 167 "gss_wrap_size_limit", 168 "krb5_cc_start_seq_get", 169 "krb5_cc_default_name", 170 "krb5_cc_destroy", 171 "krb5_cccol_cursor_free", 172 "krb5_cccol_cursor_new", 173 "krb5_cccol_cursor_next", 174 "krb5_free_host_realm", 175 "krb5_get_default_realm", 176 "krb5_get_host_realm", 177 "krb5_gss_register_acceptor_identity", 178 "krb5_cc_set_default_name", 179 "krb5_kt_resolve", 180 "krb5_kt_default", 181 "krb5_kt_default_name", 182 "krb5_kt_close", 183 "krb5_kt_destroy", 184 "krb5_auth_con_free", 185 "krb5_auth_con_init", 186 "krb5_auth_con_genaddrs", 187 "krb5_auth_con_getlocalseqnumber", 188 "krb5_auth_con_getremoteseqnumber", 189 "krb5_auth_con_setflags", 190 "krb5_auth_con_getflags", 191 "krb5_clear_error_message", 192 "krb5_free_error_message", 193 "krb5_set_default_realm", 194 "krb5_set_error_message", 195 "krb5_vset_error_message", 196 "com_err", 197 "com_err_va", 198 "reset_com_err_hook", 199 "set_com_err_hook", 200 ); 201 202 203sub gen_header { 204 my $sym; 205 my $syms = shift; 206 print "void __attribute__((constructor)) heim_load_frameworks(void);\n"; 207 print "void heim_load_functions(void);\n"; 208 foreach $sym (@$syms) { 209 print "extern void (*fun_${sym})();\n"; 210 } 211} 212 213sub gen_loader { 214 my $sym; 215 my $syms = shift; 216 print "#include <dlfcn.h>\n"; 217 print "#include <stdio.h>\n"; 218 print "#include <stdlib.h>\n"; 219 print "#include <syslog.h>\n"; 220 print "#include <dispatch/dispatch.h>\n"; 221 print "#include \"heim-sym.h\"\n"; 222 print "\n"; 223 print "static void *hf = NULL;\n"; 224 print "static void *gf = NULL;\n"; 225 print "void heim_load_frameworks(void) {\n"; 226 print "hf = dlopen(\"/System/Library/PrivateFrameworks/Heimdal.framework/Heimdal\", RTLD_LAZY|RTLD_LOCAL);\n"; 227 print "gf = dlopen(\"/System/Library/Frameworks/GSS.framework/GSS\", RTLD_LAZY|RTLD_LOCAL);\n"; 228 printf "}\n"; 229 printf "\n"; 230 231 print "void load_functions(void) {\n"; 232 foreach $sym (@$syms) { 233 my $lib; 234 if ($sym =~ /gss/) { 235 $lib = "gf"; 236 } else { 237 $lib = "hf"; 238 } 239 print "fun_${sym} = dlsym(${lib}, \"$sym\");\n"; 240 print "if (!fun_${sym}) { syslog(LOG_ERR, \"${sym} failed loading\"); }\n"; 241 } 242 printf "}\n"; 243 printf "\n"; 244 print "void heim_load_functions(void) {\n"; 245 print "static dispatch_once_t once = 0;\n"; 246 print "dispatch_once(&once, ^{ load_functions(); });\n"; 247 print ("}\n\n"); 248} 249 250sub gen_32 { 251 252 my $sym; 253 my $syms = shift; 254 my $prefix = shift; 255 256 my $num = 0; 257 258 print "#ifdef __i386__\n"; 259 print " .text\n\n"; 260 261 foreach $sym (@$syms) { 262 $num++; 263 print ".globl ${prefix}_${sym}\n"; 264 print "${prefix}_${sym}:\n"; 265 print "\tpushl %ebp\n"; 266 print "\tmovl %esp, %ebp\n"; 267 print "\tsubl \$72, %esp\n"; 268 print "\tcall _heim_load_functions\n"; 269 print "\taddl \$72, %esp\n"; 270 print "\tmovl %ebp, %esp\n"; 271 print "\popl %ebp\n"; 272 print "\tcall L0${num}\n"; 273 print "L0${num}:\n"; 274 print "\tpopl %edx\n"; 275 print "\tleal L_fun_${sym}\$non_lazy_ptr-\"L0${num}\"(%edx), %eax\n"; 276 print "\tmovl (%eax), %edx\n"; 277 print "\tmovl (%edx), %edx\n"; 278 print "\tjmp *%edx\n"; 279 print "\n"; 280 } 281 282 foreach $sym (@$syms) { 283 print ".comm _fun_${sym},4,2\n"; 284 } 285 print " .section __IMPORT,__pointers,non_lazy_symbol_pointers\n"; 286 foreach $sym (@$syms) { 287 print "L_fun_${sym}\$non_lazy_ptr:\n"; 288 print " .indirect_symbol _fun_${sym}\n"; 289 print "\t.long 0\n"; 290 } 291 print "\t.subsections_via_symbols\n"; 292 293 print "#endif\n"; 294} 295 296sub gen_64 { 297 298 my $sym; 299 my $syms = shift; 300 my $prefix = shift; 301 302 print "#ifdef __x86_64__\n"; 303 print ".text\n\n"; 304 305 foreach $sym (@$syms) { 306 print " .globl ${prefix}_${sym}\n"; 307 print "${prefix}_${sym}:\n"; 308 print "\tpushq %rbp\n"; 309 print "\tmovq %rsp, %rbp\n"; 310 print "\tsubq \$208, %rsp\n"; 311 print "\tpushq %rdi\n"; 312 print "\tpushq %rsi\n"; 313 print "\tpushq %rdx\n"; 314 print "\tpushq %rcx\n"; 315 print "\tpushq %r8\n"; 316 print "\tpushq %r9\n"; 317 print "\tcall _heim_load_functions\n"; 318 print "\tpopq %r9\n"; 319 print "\tpopq %r8\n"; 320 print "\tpopq %rcx\n"; 321 print "\tpopq %rdx\n"; 322 print "\tpopq %rsi\n"; 323 print "\tpopq %rdi\n"; 324 print "\taddq \$208, %rsp\n"; 325 print "\tmovq %rbp, %rsp\n"; 326 print "\tpopq %rbp\n"; 327 print "\tmovq _fun_${sym}\@GOTPCREL(%rip), %r11\n"; 328 print "\tmovq (%r11), %r11\n"; 329 print "\tjmp *%r11\n"; 330 print "\n"; 331 } 332 333 foreach $sym (@$syms) { 334 print ".comm _fun_${sym},8,3\n"; 335 } 336 print "#endif\n"; 337} 338 339sub gen_ppc { 340 341 my $sym; 342 my $syms = shift; 343 my $prefix = shift; 344 345 print "#ifdef __ppc__\n"; 346 print ".section __TEXT,__text,regular,pure_instructions\n"; 347 print ".section __TEXT,__picsymbolstub1,symbol_stubs,pure_instructions,32\n"; 348 print ".machine ppc7400\n"; 349 print ".text\n"; 350 351 foreach $sym (@$syms) { 352 print ".globl ${prefix}_${sym}\n"; 353 print "${prefix}_${sym}:\n"; 354 print "\tbl _abort\n"; 355 print "\n"; 356 } 357 358 foreach $sym (@$syms) { 359 print ".comm _fun_${sym},4,2\n"; 360 } 361 362 print "#endif\n"; 363} 364 365 366print "/* generated file, no dont edit */\n"; 367 368my @all = (@rewritesyms, @proxysyms); 369 370gen_32(\@rewritesyms, "_heim") if ($ARGV[0] eq '3'); 371gen_64(\@rewritesyms, "_heim") if ($ARGV[0] eq '6'); 372gen_ppc(\@rewritesyms, "_heim") if ($ARGV[0] eq 'p'); 373gen_32(\@proxysyms, "") if ($ARGV[0] eq '3p'); 374gen_64(\@proxysyms, "") if ($ARGV[0] eq '6p'); 375gen_ppc(\@proxysyms, "") if ($ARGV[0] eq 'pp'); 376 377gen_header(\@all) if ($ARGV[0] eq 'h'); 378gen_loader(\@all) if ($ARGV[0] eq 'l'); 379 380