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