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