1#ifdef __cplusplus
2extern "C" {
3#endif
4#include "EXTERN.h"
5#include "perl.h"
6#include "XSUB.h"
7#include <krb5.h>
8#include <com_err.h>
9#include "krb5_constants.c"
10
11#ifdef __cplusplus
12}
13#endif
14
15/* change this if 10 hours doesn't suit you */
16#define KRB5_DEFAULT_LIFE 60*60*10
17
18typedef krb5_ccache		Authen__Krb5__Ccache;
19typedef krb5_principal		Authen__Krb5__Principal;
20typedef krb5_auth_context	Authen__Krb5__AuthContext;
21typedef krb5_rcache		Authen__Krb5__Rcache;
22typedef krb5_creds		*Authen__Krb5__Creds;
23typedef krb5_ap_rep_enc_part	*Authen__Krb5__ApRepEncPart;
24typedef krb5_ticket		*Authen__Krb5__Ticket;
25typedef krb5_keytab		Authen__Krb5__Keytab;
26typedef krb5_enc_tkt_part	*Authen__Krb5__EncTktPart;
27typedef krb5_error		*Authen__Krb5__Error;
28typedef krb5_address		*Authen__Krb5__Address;
29typedef krb5_keyblock		*Authen__Krb5__Keyblock;
30typedef krb5_keytab_entry	*Authen__Krb5__KeytabEntry;
31typedef krb5_kt_cursor          *Authen__Krb5__KeytabCursor;
32typedef krb5_cc_cursor          *Authen__Krb5__CcacheCursor;
33typedef krb5_keyblock		*Authen__Krb5__KeyBlock;
34
35static krb5_context context = 0;
36static krb5_error_code err;
37static krb5_keytab_entry keytab_entry_init;
38
39/*
40 * The following three routines implement a "safehouse" for nested Kerberos
41 * data structures which shouldn't be freed before their parent data
42 * structures are freed.  Without this, "Bad free() ignored" errors as well
43 * as core dumps could occur when the parent structures are eventually freed.
44 *
45 * If a method returns a newly allocated object, it calls can_free() to
46 * register the object as "freeable," since the memory was not in use
47 * beforehand.  This module will only free objects that have been registered
48 * with can_free(), and lets Kerberos free the others.
49 *
50 * Doing it the other way (registering objects which *shouldn't* be freed)
51 * is more complicated than it first seems, so I did it this way.
52 */
53
54
55HV *free_hash = NULL; /* might as well take advantage of Perl! */
56
57void can_free(SV *sv)
58{
59	char key[80];
60
61	sprintf(key,"%p",sv);
62	if (!free_hash) free_hash = newHV();
63	hv_store(free_hash,key,strlen(key),&PL_sv_yes,0);
64}
65
66int should_free(SV *sv)
67{
68	char key[80];
69
70	if (!free_hash) return 0;
71	sprintf(key,"%p",sv);
72	return hv_exists(free_hash,key,strlen(key));
73}
74
75void freed(SV *sv)
76{
77	char key[80];
78
79	if (!free_hash) return;
80	sprintf(key,"%p",sv);
81	hv_delete(free_hash,key,strlen(key),G_DISCARD);
82}
83
84
85MODULE = Authen::Krb5		PACKAGE = Authen::Krb5		PREFIX = krb5_
86
87double
88constant(name, arg)
89	char *name
90	int arg
91
92void
93krb5_error(e = 0)
94	krb5_error_code e;
95
96	CODE:
97	if (e) {
98		ST(0) = sv_2mortal(newSVpv((char *)error_message(e), 0));
99	}
100	else {
101		ST(0) = sv_2mortal(newSVpv((char *)error_message(err), 0));
102		SvUPGRADE(ST(0), SVt_PVIV);
103		SvIVX(ST(0)) = err;
104		SvIOK_on(ST(0));
105	}
106
107void
108krb5_init_context()
109
110	CODE:
111	if (context) croak("Authen::Krb5 already initialized");
112	err = krb5_init_context(&context);
113	if (err) XSRETURN_UNDEF;
114	XSRETURN_YES;
115
116void
117krb5_free_context()
118
119	CODE:
120	if (!context) croak("Authen::Krb5 not yet initialized");
121	krb5_free_context(context);
122
123void
124krb5_init_ets()
125
126	CODE:
127#if KRB5_DEPRECATED
128	krb5_init_ets(context);
129#endif /* KRB5_DEPRECATED */
130	XSRETURN_YES;
131
132void
133krb5_get_default_realm()
134
135	PREINIT:
136	char *realm;
137
138	PPCODE:
139	err = krb5_get_default_realm(context,&realm);
140	if (err || !realm) XSRETURN_UNDEF;
141	XPUSHs(sv_2mortal(newSVpv(realm,strlen(realm))));
142	Safefree(realm);
143
144void
145krb5_get_host_realm(host)
146	char *host
147
148	PREINIT:
149	char **realmlist;
150	int i;
151
152	PPCODE:
153	err = krb5_get_host_realm(context,host,&realmlist);
154	if (err || !realmlist) XSRETURN_UNDEF;
155	for (i = 0; realmlist[i]; i++) {
156		XPUSHs(sv_2mortal(newSVpv(realmlist[i],
157			strlen(realmlist[i]))));
158	}
159	krb5_free_host_realm(context,realmlist);
160
161void
162krb5_get_krbhst(realm)
163	char *realm
164
165	PREINIT:
166	krb5_data realm_data;
167	char **hostlist;
168	int i;
169
170	PPCODE:
171	realm_data.data = realm;
172	realm_data.length = strlen(realm);
173	err = krb5_get_krbhst(context,&realm_data,&hostlist);
174	if (err || !hostlist) XSRETURN_UNDEF;
175	for (i = 0; hostlist[i]; i++) {
176		XPUSHs(sv_2mortal(newSVpv(hostlist[i],
177			strlen(hostlist[i]))));
178	}
179	krb5_free_krbhst(context,hostlist);
180
181Authen::Krb5::Principal
182krb5_build_principal_ext(p)
183	Authen::Krb5::Principal p
184
185	CODE:
186	err = krb5_build_principal_ext(context, &RETVAL,
187		krb5_princ_realm(context, p)->length,
188		krb5_princ_realm(context, p)->data,
189		KRB5_TGS_NAME_SIZE, KRB5_TGS_NAME,
190		krb5_princ_realm(context, p)->length,
191		krb5_princ_realm(context, p)->data,
192		0);
193
194	if (err) XSRETURN_UNDEF;
195
196	can_free((SV *)RETVAL);
197
198	OUTPUT:
199	RETVAL
200
201Authen::Krb5::Principal
202krb5_parse_name(name)
203	char *name
204
205	CODE:
206	err = krb5_parse_name(context,name,&RETVAL);
207	if (err) XSRETURN_UNDEF;
208
209	can_free((SV *)RETVAL);
210
211	OUTPUT:
212	RETVAL
213
214Authen::Krb5::Principal
215krb5_sname_to_principal(hostname,sname,type)
216	char *hostname
217	char *sname
218	krb5_int32 type
219
220	CODE:
221	err = krb5_sname_to_principal(context,hostname,sname,type,&RETVAL);
222	if (err) XSRETURN_UNDEF;
223
224	can_free((SV *)RETVAL);
225
226	OUTPUT:
227	RETVAL
228
229Authen::Krb5::Ccache
230krb5_cc_resolve(string_name)
231	char *string_name
232
233	CODE:
234	err = krb5_cc_resolve(context, string_name, &RETVAL);
235	if (err) XSRETURN_UNDEF;
236
237	can_free((SV *)RETVAL);
238
239	OUTPUT:
240	RETVAL
241
242char *
243krb5_cc_default_name()
244
245	CODE:
246	RETVAL = (char *)krb5_cc_default_name(context);
247
248	OUTPUT:
249	RETVAL
250
251Authen::Krb5::Ccache
252krb5_cc_default()
253
254	CODE:
255	err = krb5_cc_default(context, &RETVAL);
256	if (err) XSRETURN_UNDEF;
257
258	can_free((SV *)RETVAL);
259
260	OUTPUT:
261	RETVAL
262
263Authen::Krb5::Keytab
264krb5_kt_resolve(string_name)
265	char *string_name
266
267	CODE:
268	err = krb5_kt_resolve(context, string_name, &RETVAL);
269	if (err) XSRETURN_UNDEF;
270
271	can_free((SV *)RETVAL);
272
273	OUTPUT:
274	RETVAL
275
276char *
277krb5_kt_default_name()
278        CODE:
279        char name[BUFSIZ];
280        err = krb5_kt_default_name(context, name, sizeof name - 1);
281	if (err)
282                XSRETURN_UNDEF;
283        name[sizeof name - 1] = '\0';
284	ST(0) = sv_2mortal(newSVpv(name, 0));
285
286Authen::Krb5::Keytab
287krb5_kt_default()
288        CODE:
289        err = krb5_kt_default(context, &RETVAL);
290	if (err)
291                XSRETURN_UNDEF;
292
293        OUTPUT:
294        RETVAL
295
296Authen::Krb5::Keyblock
297krb5_kt_read_service_key(name, principal, kvno = 0, enctype = 0)
298        char *name
299        Authen::Krb5::Principal principal
300        krb5_kvno kvno
301        krb5_enctype enctype
302
303        CODE:
304        err = krb5_kt_read_service_key(context, name, principal, kvno, enctype,
305            &RETVAL);
306        if (err)
307                XSRETURN_UNDEF;
308        can_free((SV *)RETVAL);
309
310        OUTPUT:
311        RETVAL
312
313void
314krb5_get_in_tkt_with_password(client, server, password, cc)
315	Authen::Krb5::Principal client
316	Authen::Krb5::Principal server
317	char *password
318	Authen::Krb5::Ccache cc
319
320	PREINIT:
321	krb5_creds cr;
322	krb5_timestamp now;
323	krb5_deltat lifetime = 0;
324
325	CODE:
326	memset((char *)&cr,0,sizeof(krb5_creds));
327	krb5_timeofday(context, &now);
328	cr.client = client;
329	cr.server = server;
330	cr.times.starttime = now;
331	cr.times.endtime = now + KRB5_DEFAULT_LIFE;
332	cr.times.renew_till = 0;
333
334	err = krb5_get_in_tkt_with_password(context, 0, 0, NULL, NULL,
335		password, cc, &cr, 0);
336
337	if (err) XSRETURN_UNDEF;
338	XSRETURN_YES;
339
340void
341krb5_get_in_tkt_with_keytab(client, server, keytab, cc)
342	Authen::Krb5::Principal client
343	Authen::Krb5::Principal server
344	Authen::Krb5::Keytab    keytab
345	Authen::Krb5::Ccache cc
346
347	PREINIT:
348	krb5_creds cr;
349	krb5_timestamp now;
350	krb5_deltat lifetime = 0;
351
352	CODE:
353	memset((char *)&cr,0,sizeof(krb5_creds));
354	krb5_timeofday(context, &now);
355	cr.client = client;
356	cr.server = server;
357	cr.times.starttime = now;
358	cr.times.endtime = now + KRB5_DEFAULT_LIFE;
359	cr.times.renew_till = 0;
360
361	err = krb5_get_in_tkt_with_keytab(context, 0, 0, NULL, NULL,
362		keytab, cc, &cr, 0);
363
364	if (err) XSRETURN_UNDEF;
365	XSRETURN_YES;
366
367SV *
368krb5_mk_req(auth_context, ap_req_options, service, hostname, in, cc)
369	Authen::Krb5::AuthContext auth_context
370	krb5_flags ap_req_options
371	char *service
372	char *hostname
373	SV *in
374	Authen::Krb5::Ccache cc
375
376	PREINIT:
377	krb5_data in_data, out_data;
378
379	CODE:
380	in_data.data = SvPV(in,in_data.length);
381	err = krb5_mk_req(context,&auth_context,ap_req_options,service,hostname,
382		&in_data,cc,&out_data);
383	if (err) XSRETURN_UNDEF;
384	RETVAL = newSVpv(out_data.data,out_data.length);
385
386	OUTPUT:
387	RETVAL
388
389Authen::Krb5::Ticket
390krb5_rd_req(auth_context,in,server,keytab=0)
391	Authen::Krb5::AuthContext auth_context
392	SV *in
393	Authen::Krb5::Principal server
394	Authen::Krb5::Keytab keytab
395
396	PREINIT:
397	krb5_data in_data;
398	krb5_ticket *t;
399	krb5_flags ap_req_options;
400
401	CODE:
402	if (!New(0,t,1,krb5_ticket)) XSRETURN_UNDEF;
403	in_data.data = SvPV(in,in_data.length);
404	err = krb5_rd_req(context,&auth_context,&in_data,server,keytab,
405		NULL,&t);
406	if (err) XSRETURN_UNDEF;
407	RETVAL = t;
408
409	can_free((SV *)RETVAL);
410
411	OUTPUT:
412	RETVAL
413
414Authen::Krb5::Address
415gen_portaddr(addr,port)
416	Authen::Krb5::Address addr
417	unsigned short port
418
419	CODE:
420	err = krb5_gen_portaddr(context,addr,(krb5_pointer)&port,&RETVAL);
421	if (err) XSRETURN_UNDEF;
422
423	OUTPUT:
424	RETVAL
425
426void
427genaddrs(auth_context,fh,flags)
428	Authen::Krb5::AuthContext auth_context
429	FILE *fh;
430	krb5_flags flags
431
432	PREINIT:
433	int fd;
434
435	CODE:
436	fd = fileno(fh);
437	err = krb5_auth_con_genaddrs(context,auth_context,fd,flags);
438	if (err) XSRETURN_UNDEF;
439	XSRETURN_YES;
440
441char *
442gen_replay_name(addr,uniq)
443	Authen::Krb5::Address addr
444	char *uniq
445
446	CODE:
447	err = krb5_gen_replay_name(context,addr,uniq,&RETVAL);
448	if (err) XSRETURN_UNDEF;
449
450	OUTPUT:
451	RETVAL
452
453void
454krb5_mk_priv(auth_context,in)
455	Authen::Krb5::AuthContext auth_context
456	SV *in
457
458	PREINIT:
459	krb5_data in_data, out_data;
460
461	PPCODE:
462	in_data.data = SvPV(in,in_data.length);
463	err = krb5_mk_priv(context,auth_context,&in_data,&out_data,NULL);
464	if (err) XSRETURN_UNDEF;
465	XPUSHs(sv_2mortal(newSVpv(out_data.data,out_data.length)));
466	/* krb5_free_data(context,&out_data); */
467
468void
469krb5_rd_priv(auth_context,in)
470	Authen::Krb5::AuthContext auth_context
471	SV *in
472
473	PREINIT:
474	krb5_data in_data, out_data;
475
476	PPCODE:
477	in_data.data = SvPV(in,in_data.length);
478	err = krb5_rd_priv(context,auth_context,&in_data,&out_data,NULL);
479	if (err) XSRETURN_UNDEF;
480	XPUSHs(sv_2mortal(newSVpv(out_data.data,out_data.length)));
481
482Authen::Krb5::Rcache
483krb5_get_server_rcache(piece)
484	SV *piece
485
486	PREINIT:
487	krb5_data rc_data;
488
489	CODE:
490	rc_data.data=SvPV(piece,rc_data.length);
491	err = krb5_get_server_rcache(context,&rc_data,&RETVAL);
492
493	if (err) XSRETURN_UNDEF;
494
495	OUTPUT:
496	RETVAL
497
498void
499krb5_sendauth(auth_context,fh,version,client,server,options,in,in_creds,cc)
500	Authen::Krb5::AuthContext auth_context
501	FILE *fh
502	char *version
503	Authen::Krb5::Principal client
504	Authen::Krb5::Principal server
505	int options
506	SV *in
507	Authen::Krb5::Creds in_creds
508	Authen::Krb5::Ccache cc
509
510	PREINIT:
511	krb5_data in_data;
512	krb5_creds *out_creds = NULL;
513	int fd;
514
515	PPCODE:
516	fd = fileno(fh);
517	in_data.data = SvPV(in,in_data.length);
518	err = krb5_sendauth(context,&auth_context,&fd,version,client,server,
519		options,&in_data,in_creds,cc,NULL,NULL,&out_creds);
520	if (err) XSRETURN_UNDEF;
521	XSRETURN_YES;
522
523void
524krb5_recvauth(auth_context,fh,version,server,keytab)
525	Authen::Krb5::AuthContext auth_context
526	FILE *fh
527	char *version
528	Authen::Krb5::Principal server
529	Authen::Krb5::Keytab keytab
530
531	PREINIT:
532	krb5_ticket *ticket = NULL;
533	int fd;
534
535	PPCODE:
536	fd = fileno(fh);
537	err = krb5_recvauth(context,&auth_context,&fd,version,server,0,
538		keytab,&ticket);
539	if (err) XSRETURN_UNDEF;
540	ST(0) = sv_newmortal();
541	sv_setref_pv(ST(0),"Authen::Krb5::Ticket",(void*)ticket);
542	XSRETURN(1);
543
544
545MODULE = Authen::Krb5	PACKAGE = Authen::Krb5::Principal
546
547void
548realm(p)
549	Authen::Krb5::Principal p
550
551	CODE:
552	ST(0) = sv_2mortal(newSVpv(p->realm.data,p->realm.length));
553
554krb5_int32
555type(p)
556	Authen::Krb5::Principal p
557
558	CODE:
559	RETVAL = p->type;
560
561	OUTPUT:
562	RETVAL
563
564void
565data(p)
566	Authen::Krb5::Principal p
567
568	PPCODE:
569	if (p->length > 0) {
570		int len = p->length;
571		krb5_data *data;
572
573		EXTEND(sp,len);
574		for (data = p->data; len--; data++) {
575			PUSHs(sv_2mortal(newSVpv(data->data,data->length)));
576		}
577	}
578
579void
580DESTROY(p)
581	Authen::Krb5::Principal p
582
583	CODE:
584	if (p && should_free((SV *)p)) {
585		krb5_free_principal(context,p);
586		freed((SV *)p);
587	}
588
589
590MODULE = Authen::Krb5	PACKAGE = Authen::Krb5::Ccache
591
592void
593initialize(cc, p)
594	Authen::Krb5::Ccache cc
595	Authen::Krb5::Principal p
596
597	CODE:
598	err = krb5_cc_initialize(context, cc, p);
599	if (err) XSRETURN_UNDEF;
600	else {
601		can_free((SV *)cc);
602		XSRETURN_YES;
603	}
604
605const char *
606get_name(cc)
607	Authen::Krb5::Ccache cc
608
609	CODE:
610	RETVAL = krb5_cc_get_name(context, cc);
611
612	OUTPUT:
613	RETVAL
614
615Authen::Krb5::Principal
616get_principal(cc)
617	Authen::Krb5::Ccache cc
618
619	CODE:
620	err = krb5_cc_get_principal(context, cc, &RETVAL);
621	if (err) XSRETURN_UNDEF;
622
623	can_free((SV *)RETVAL);
624
625	OUTPUT:
626	RETVAL
627
628void
629destroy(cc)
630	Authen::Krb5::Ccache cc
631
632	CODE:
633	if (!should_free((SV*)cc)) XSRETURN_UNDEF;
634
635	err = krb5_cc_destroy(context, cc);
636	if (err) {
637		XSRETURN_UNDEF;
638	}
639	else {
640		freed((SV*)cc);
641		XSRETURN_YES;
642	}
643
644krb5_cc_cursor *
645start_seq_get(cc)
646	Authen::Krb5::Ccache cc
647
648	CODE:
649	if (!New(0, RETVAL, 1, krb5_cc_cursor))
650		XSRETURN_UNDEF;
651        err = krb5_cc_start_seq_get(context, cc, RETVAL);
652	if (err)
653                XSRETURN_UNDEF;
654
655        OUTPUT:
656        RETVAL
657
658Authen::Krb5::Creds
659next_cred(cc, cursor)
660        krb5_cc_cursor *cursor
661        Authen::Krb5::Ccache cc
662
663        CODE:
664	if (!New(0, RETVAL, 1, krb5_creds))
665		XSRETURN_UNDEF;
666        err = krb5_cc_next_cred(context, cc, cursor, RETVAL);
667	if (err)
668                XSRETURN_UNDEF;
669        can_free((SV *)RETVAL);
670
671        OUTPUT:
672        RETVAL
673
674void
675end_seq_get(cc, cursor)
676        Authen::Krb5::Ccache cc
677        krb5_cc_cursor *cursor
678
679        CODE:
680        err = krb5_cc_end_seq_get(context, cc, cursor);
681        if (err)
682                XSRETURN_UNDEF;
683        XSRETURN_YES;
684
685void
686DESTROY(cc)
687	Authen::Krb5::Ccache cc
688
689	CODE:
690	if (should_free((SV *)cc)) {
691		krb5_cc_close(context, cc);
692		freed((SV *)cc);
693	}
694
695MODULE = Authen::Krb5	PACKAGE = Authen::Krb5::KeyBlock
696
697int
698length(kb)
699	Authen::Krb5::KeyBlock kb
700
701	CODE:
702	RETVAL = kb->length;
703
704	OUTPUT:
705	RETVAL
706
707void
708contents(kb)
709	Authen::Krb5::KeyBlock kb
710
711	PPCODE:
712	/* sv_2mortal here causes 'Attempt to free unreferenced scalar' later */
713	XPUSHs(newSVpvn((char*)(kb->contents), kb->length));
714
715int
716enctype(kb)
717	Authen::Krb5::KeyBlock kb
718
719	CODE:
720	RETVAL = (int)kb->enctype;
721
722	OUTPUT:
723	RETVAL
724
725void
726enctype_string(kb)
727	Authen::Krb5::KeyBlock kb
728
729	PREINIT:
730	char buf[256];
731
732	PPCODE:
733	err = krb5_enctype_to_string(kb->enctype, buf, 255);
734	if (err) {
735		XSRETURN_UNDEF;
736	}
737	XPUSHs(newSVpv(buf, 0));
738
739void
740DESTROY(kb)
741	Authen::Krb5::KeyBlock kb
742
743	CODE:
744	if (kb && should_free((SV *)kb)) {
745		krb5_free_keyblock(context,kb);
746		freed((SV *)kb);
747	}
748
749MODULE = Authen::Krb5	PACKAGE = Authen::Krb5::AuthContext
750
751Authen::Krb5::AuthContext
752new(class)
753	char *class
754
755	CODE:
756	err = krb5_auth_con_init(context, &RETVAL);
757	if (err) XSRETURN_UNDEF;
758
759	can_free((SV *)RETVAL);
760
761	OUTPUT:
762	RETVAL
763
764int
765getflags(auth_context)
766	Authen::Krb5::AuthContext auth_context
767
768	PREINIT:
769	krb5_int32 flags;
770
771	CODE:
772	err = krb5_auth_con_getflags(context,auth_context,&flags);
773	RETVAL = (int)flags;
774
775	OUTPUT:
776	RETVAL
777
778void
779setflags(auth_context,flags)
780	Authen::Krb5::AuthContext auth_context
781	krb5_int32 flags
782
783	CODE:
784	err = krb5_auth_con_setflags(context,auth_context,flags);
785
786	if(err) XSRETURN_UNDEF;
787	XSRETURN_YES;
788
789Authen::Krb5::Rcache
790getrcache(auth_context)
791	Authen::Krb5::AuthContext auth_context
792
793	CODE:
794	err = krb5_auth_con_getrcache(context,auth_context,&RETVAL);
795	if (err) XSRETURN_UNDEF;
796
797	OUTPUT:
798	RETVAL
799
800void
801setrcache(auth_context,rc)
802	Authen::Krb5::AuthContext auth_context
803	Authen::Krb5::Rcache rc
804
805	CODE:
806	err = krb5_auth_con_setrcache(context,auth_context,rc);
807	if (err) XSRETURN_UNDEF;
808	XSRETURN_YES;
809
810void
811getaddrs(auth_context)
812	Authen::Krb5::AuthContext auth_context
813
814	PREINIT:
815	krb5_address *local, *remote;
816
817	CODE:
818	err = krb5_auth_con_getaddrs(context,auth_context,&local,&remote);
819	if (err) XSRETURN_EMPTY;
820
821	ST(0) = sv_newmortal();
822	ST(1) = sv_newmortal();
823	sv_setref_pv(ST(0), "Authen::Krb5::Address", (void*)local);
824	sv_setref_pv(ST(1), "Authen::Krb5::Address", (void*)remote);
825	XSRETURN(2);
826
827void
828setaddrs(auth_context,laddr,raddr)
829	Authen::Krb5::AuthContext auth_context
830	Authen::Krb5::Address laddr
831	Authen::Krb5::Address raddr
832
833	CODE:
834	if (!SvOK((SV*)ST(1))) laddr = NULL;
835	if (!SvOK((SV*)ST(2))) raddr = NULL;
836	err = krb5_auth_con_setaddrs(context,auth_context,laddr,raddr);
837	if (err) XSRETURN_UNDEF;
838	XSRETURN_YES;
839
840void
841setports(auth_context,laddr,raddr)
842	Authen::Krb5::AuthContext auth_context
843	Authen::Krb5::Address laddr
844	Authen::Krb5::Address raddr
845
846	CODE:
847	if (!SvOK((SV*)ST(1))) laddr = NULL;
848	if (!SvOK((SV*)ST(2))) raddr = NULL;
849	err = krb5_auth_con_setports(context,auth_context,laddr,raddr);
850	if (err) XSRETURN_UNDEF;
851	XSRETURN_YES;
852
853Authen::Krb5::KeyBlock
854getkey(auth_context)
855	Authen::Krb5::AuthContext auth_context;
856
857	PREINIT:
858	SV *sv;
859
860	CODE:
861	err = krb5_auth_con_getkey(context, auth_context, &RETVAL);
862	if (err) XSRETURN_UNDEF;
863	can_free((SV *)RETVAL);
864
865	OUTPUT:
866	RETVAL
867
868void
869DESTROY(auth_context)
870	Authen::Krb5::AuthContext auth_context;
871
872	CODE:
873	if (auth_context) {
874		krb5_auth_con_free(context, auth_context);
875		freed((SV *)auth_context);
876	}
877
878MODULE = Authen::Krb5	PACKAGE = Authen::Krb5::Ticket
879
880Authen::Krb5::Principal
881server(t)
882	Authen::Krb5::Ticket t
883
884	CODE:
885	RETVAL = t->server;
886
887	OUTPUT:
888	RETVAL
889
890Authen::Krb5::EncTktPart
891enc_part2(t)
892	Authen::Krb5::Ticket t
893
894	CODE:
895	RETVAL = t->enc_part2;
896
897	OUTPUT:
898	RETVAL
899
900void
901DESTROY(t)
902	Authen::Krb5::Ticket t
903
904	CODE:
905	if (t) {
906		krb5_free_ticket(context,t);
907		freed((SV *)t);
908	}
909
910MODULE = Authen::Krb5	PACKAGE = Authen::Krb5::EncTktPart
911
912Authen::Krb5::Principal
913client(etp)
914	Authen::Krb5::EncTktPart etp
915
916	CODE:
917	RETVAL = etp->client;
918
919	OUTPUT:
920	RETVAL
921
922void
923DESTROY(etp)
924	Authen::Krb5::EncTktPart etp
925
926	CODE:
927	if (etp && should_free((SV *)etp)) {
928		krb5_free_enc_tkt_part(context,etp);
929		freed((SV *)etp);
930	}
931
932MODULE = Authen::Krb5	PACKAGE = Authen::Krb5::Address
933
934Authen::Krb5::Address
935new(class,addrtype,contents)
936	char *class
937	unsigned int addrtype
938	SV *contents
939
940	CODE:
941	if (!New(0,RETVAL,1,krb5_address)) XSRETURN_UNDEF;
942	RETVAL->addrtype = addrtype;
943	RETVAL->contents = (krb5_octet *)SvPV(contents,RETVAL->length);
944
945	OUTPUT:
946	RETVAL
947
948void
949DESTROY(addr)
950	Authen::Krb5::Address addr
951
952	CODE:
953	if (addr && should_free((SV *)addr)) {
954		krb5_free_address(context,addr);
955		freed((SV *)addr);
956	}
957
958MODULE = Authen::Krb5	PACKAGE = Authen::Krb5::Keyblock
959
960
961krb5_enctype
962enctype(keyblock)
963	Authen::Krb5::Keyblock keyblock
964
965        CODE:
966        RETVAL = keyblock->enctype;
967
968        OUTPUT:
969        RETVAL
970
971unsigned int
972length(keyblock)
973        Authen::Krb5::Keyblock keyblock
974
975        CODE:
976        RETVAL = keyblock->length;
977
978        OUTPUT:
979        RETVAL
980
981krb5_octet *
982contents(keyblock)
983        Authen::Krb5::Keyblock keyblock
984
985        CODE:
986        ST(0) = keyblock->contents
987	    ? sv_2mortal(newSVpv(keyblock->contents, keyblock->length))
988            : &PL_sv_undef;
989
990
991void
992DESTROY(keyblock)
993	Authen::Krb5::Keyblock	keyblock
994
995        CODE:
996	if (keyblock->contents) {
997		memset(keyblock->contents, 0, keyblock->length);
998		free(keyblock->contents);
999		keyblock->contents = NULL;
1000	}
1001
1002MODULE = Authen::Krb5   PACKAGE = Authen::Krb5::Keytab
1003
1004void
1005add_entry(keytab, entry)
1006        Authen::Krb5::Keytab keytab
1007        Authen::Krb5::KeytabEntry entry
1008
1009        CODE:
1010        err = krb5_kt_add_entry(context, keytab, entry);
1011	if (err)
1012                XSRETURN_UNDEF;
1013	XSRETURN_YES;
1014
1015void
1016end_seq_get(keytab, cursor)
1017        Authen::Krb5::Keytab keytab
1018        krb5_kt_cursor *cursor
1019
1020        CODE:
1021        err = krb5_kt_end_seq_get(context, keytab, cursor);
1022        if (err)
1023                XSRETURN_UNDEF;
1024        XSRETURN_YES;
1025
1026Authen::Krb5::KeytabEntry
1027get_entry(keytab, principal, vno = 0, enctype = 0)
1028        Authen::Krb5::Keytab keytab
1029        Authen::Krb5::Principal principal
1030        krb5_kvno vno
1031        krb5_enctype enctype
1032
1033        CODE:
1034	if (!New(0, RETVAL, 1, krb5_keytab_entry))
1035		XSRETURN_UNDEF;
1036        err = krb5_kt_get_entry(context, keytab, principal, vno, enctype,
1037            RETVAL);
1038	if (err)
1039		XSRETURN_UNDEF;
1040        can_free((SV *)RETVAL);
1041
1042	OUTPUT:
1043	RETVAL
1044
1045SV *
1046get_name(keytab)
1047        Authen::Krb5::Keytab keytab
1048
1049        PREINIT:
1050        char name[MAX_KEYTAB_NAME_LEN+1];
1051
1052        CODE:
1053        err = krb5_kt_get_name(context, keytab, name, MAX_KEYTAB_NAME_LEN);
1054	if (err)
1055                XSRETURN_UNDEF;
1056	RETVAL = sv_2mortal(newSVpv(name, 0));
1057        can_free((SV *)RETVAL);
1058
1059        OUTPUT:
1060        RETVAL
1061
1062Authen::Krb5::KeytabEntry
1063next_entry(keytab, cursor)
1064        krb5_kt_cursor *cursor
1065        Authen::Krb5::Keytab keytab
1066
1067        CODE:
1068	if (!New(0, RETVAL, 1, krb5_keytab_entry))
1069		XSRETURN_UNDEF;
1070        err = krb5_kt_next_entry(context, keytab, RETVAL, cursor);
1071	if (err)
1072                XSRETURN_UNDEF;
1073        can_free((SV *)RETVAL);
1074
1075        OUTPUT:
1076        RETVAL
1077
1078void
1079remove_entry(keytab, entry)
1080        Authen::Krb5::Keytab keytab
1081        Authen::Krb5::KeytabEntry entry
1082
1083        CODE:
1084        err = krb5_kt_remove_entry(context, keytab, entry);
1085	if (err)
1086                XSRETURN_UNDEF;
1087	XSRETURN_YES;
1088
1089krb5_kt_cursor *
1090start_seq_get(keytab)
1091        Authen::Krb5::Keytab keytab
1092
1093        CODE:
1094	if (!New(0, RETVAL, 1, krb5_kt_cursor))
1095		XSRETURN_UNDEF;
1096        err = krb5_kt_start_seq_get(context, keytab, RETVAL);
1097	if (err)
1098                XSRETURN_UNDEF;
1099
1100        OUTPUT:
1101        RETVAL
1102
1103void
1104DESTROY(keytab)
1105        Authen::Krb5::Keytab keytab
1106
1107        CODE:
1108        if (keytab && should_free((SV *)keytab)) {
1109                krb5_kt_close(context, keytab);
1110                freed((SV *)keytab);
1111        }
1112
1113MODULE = Authen::Krb5   PACKAGE = Authen::Krb5::KeytabEntry
1114
1115Authen::Krb5::KeytabEntry
1116new(class, principal, vno, key)
1117	char *class
1118	Authen::Krb5::Principal principal
1119	krb5_kvno vno
1120        Authen::Krb5::Keyblock key
1121
1122	CODE:
1123	if (!New(0, RETVAL, 1, krb5_keytab_entry))
1124		XSRETURN_UNDEF;
1125        *RETVAL = keytab_entry_init;
1126	RETVAL->principal = principal;
1127	RETVAL->vno = vno;
1128        RETVAL->key = *key;
1129
1130        can_free((SV *)RETVAL);
1131
1132	OUTPUT:
1133	RETVAL
1134
1135Authen::Krb5::Principal
1136principal(entry)
1137	Authen::Krb5::KeytabEntry entry
1138
1139        CODE:
1140        err = krb5_copy_principal(context, entry->principal, &RETVAL);
1141        if (err)
1142                XSRETURN_UNDEF;
1143        can_free((SV *)RETVAL);
1144
1145        OUTPUT:
1146        RETVAL
1147
1148krb5_timestamp
1149timestamp(entry)
1150	Authen::Krb5::KeytabEntry entry
1151
1152        CODE:
1153        RETVAL = entry->timestamp;
1154
1155        OUTPUT:
1156        RETVAL
1157
1158krb5_kvno
1159kvno(entry)
1160	Authen::Krb5::KeytabEntry entry
1161
1162        CODE:
1163        RETVAL = entry->vno;
1164
1165        OUTPUT:
1166        RETVAL
1167
1168Authen::Krb5::Keyblock
1169key(entry)
1170	Authen::Krb5::KeytabEntry entry
1171
1172        CODE:
1173        err = krb5_copy_keyblock(context, &entry->key, &RETVAL);
1174        if (err)
1175                XSRETURN_UNDEF;
1176        can_free((SV *)RETVAL);
1177
1178        OUTPUT:
1179        RETVAL
1180