1 /*
2  * This module is Copyright 2012 Khera Communications, Inc.
3  * Copyright 2015 Matthew Seaman
4  * It is licensed under the same terms as Perl itself.
5  */
6 #include "EXTERN.h"
7 #include "perl.h"
8 #include "XSUB.h"
9 
10 #include <opendkim/dkim.h>
11 
12 /* h2xs -A -n Mail::OpenDKIM */
13 
14 /* callbacks */
15 static SV *dns_callback = (SV *)NULL;
16 static SV *final_callback = (SV *)NULL;
17 static SV *key_lookup_callback = (SV *)NULL;
18 static SV *prescreen_callback = (SV *)NULL;
19 static SV *signature_handle_callback = (SV *)NULL;
20 static SV *signature_handle_free_callback = (SV *)NULL;
21 static SV *signature_tagvalues_callback = (SV *)NULL;
22 static SV *dns_query_cancel_callback = (SV *)NULL;
23 static SV *dns_query_service_callback = (SV *)NULL;
24 static SV *dns_query_start_callback = (SV *)NULL;
25 static SV *dns_query_waitreply_callback = (SV *)NULL;
26 
27 /*
28  * dkim.h doesn't specify the contents of the DKIM and DKIM_SIGINFO structures, it just
29  * declares them :-(
30  * So this is an overkill size, that SHOULD be large enough.  See dkim-types.h for more
31  * information about the structures
32  */
33 #define	SIZEOF_DKIM		4096
34 #define	SIZEOF_DKIM_SIGINFO	1024
35 
36 /*
37  * These routines allow us to call callbacks that are written in and supplied using Perl that
38  * are maintained and called from within the OpenDKIM library
39  *
40  * e.g.
41  * sub dns_callback {
42  *  my $context = shift;
43  *
44  *   print "DNS called back with context $context\n";
45  * }
46  *
47  * set_dns_callback({ function => \&callback, interval => 1 });
48  *
49  * These are all dummy callbacks that we pass to OpenDKIM, and when OpenDKIM calls them they
50  * call the Perl routines supplied by the caller
51  */
52 
53 /*
54  * called when the OpenDKIMlibrary wants to call the callback function provided to
55  * dkim_set_dns_callback
56  */
57 static void
call_dns_callback(const void * context)58 call_dns_callback(const void *context)
59 {
60 	dSP;
61 	SV *sv = dns_callback;
62 
63 	if(sv == NULL) {
64 		croak("Internal error: call_dns_callback called, but nothing to call");
65 		return;
66 	}
67 
68 	PUSHMARK(SP);
69 	XPUSHs(sv_2mortal(newSVpv(context, 0)));
70 	PUTBACK;
71 
72 	call_sv(sv, G_DISCARD);
73 }
74 
75 /*
76  * called when the OpenDKIMlibrary wants to call the callback function provided to
77  * dkim_set_final
78  */
79 static DKIM_CBSTAT
call_final_callback(DKIM * dkim,DKIM_SIGINFO ** sigs,int nsigs)80 call_final_callback(DKIM *dkim, DKIM_SIGINFO **sigs, int nsigs)
81 {
82 	dSP;
83 	int count, status;
84 	SV *sv = final_callback;
85 
86 	if(sv == NULL) {
87 		croak("Internal error: call_final_callback called, but nothing to call");
88 		return DKIM_CBSTAT_ERROR;
89 	}
90 
91 	PUSHMARK(SP);
92 	XPUSHs(sv_2mortal(newSVpv((void *)dkim, SIZEOF_DKIM)));
93 	XPUSHs(sv_2mortal(newSVpv((void *)sigs, nsigs * SIZEOF_DKIM_SIGINFO)));
94 	XPUSHs(sv_2mortal(newSViv(nsigs)));
95 	PUTBACK;
96 
97 	count = call_sv(sv, G_SCALAR);
98 
99 	SPAGAIN;
100 
101 	if(count != 1) {
102 		croak("Internal error: final_callback routine returned %d items, 1 was expected",
103 			count);
104 		return DKIM_CBSTAT_ERROR;
105 	}
106 
107 	status = POPi;
108 
109 	PUTBACK;
110 	FREETMPS;
111 	LEAVE;
112 
113 	return status;
114 }
115 
116 /*
117  * called when the OpenDKIMlibrary wants to call the callback function provided to
118  * dkim_set_key_lookup
119  */
120 static DKIM_CBSTAT
call_key_lookup_callback(DKIM * dkim,DKIM_SIGINFO * siginfo,unsigned char * buf,size_t buflen)121 call_key_lookup_callback(DKIM *dkim, DKIM_SIGINFO *siginfo, unsigned char *buf, size_t buflen)
122 {
123 	dSP;
124 	int count, status;
125 	SV *sv = key_lookup_callback;
126 
127 	if(sv == NULL) {
128 		croak("Internal error: call_key_lookup_callback called, but nothing to call");
129 		return DKIM_CBSTAT_ERROR;
130 	}
131 
132 	PUSHMARK(SP);
133 	XPUSHs(sv_2mortal(newSVpv((void *)dkim, SIZEOF_DKIM)));
134 	XPUSHs(sv_2mortal(newSVpv((void *)siginfo, SIZEOF_DKIM_SIGINFO)));
135 	XPUSHs(sv_2mortal(newSVpv((void *)buf, buflen + 1)));
136 	XPUSHs(sv_2mortal(newSViv(buflen)));
137 	PUTBACK;
138 
139 	count = call_sv(sv, G_SCALAR);
140 
141 	SPAGAIN;
142 
143 	if(count != 1) {
144 		croak("Internal error: key_lookup_callback routine returned %d items, 1 was expected",
145 			count);
146 		return DKIM_CBSTAT_ERROR;
147 	}
148 
149 	status = POPi;
150 
151 	PUTBACK;
152 	FREETMPS;
153 	LEAVE;
154 
155 	return status;
156 }
157 
158 /*
159  * called when the OpenDKIMlibrary wants to call the callback function provided to
160  * dkim_set_prescreen
161  */
162 static DKIM_CBSTAT
call_prescreen_callback(DKIM * dkim,DKIM_SIGINFO ** sigs,int nsigs)163 call_prescreen_callback(DKIM *dkim, DKIM_SIGINFO **sigs, int nsigs)
164 {
165 	dSP;
166 	int count, status;
167 	SV *sv = prescreen_callback;
168 
169 	if(sv == NULL) {
170 		croak("Internal error: call_prescreen_callback called, but nothing to call");
171 		return DKIM_CBSTAT_ERROR;
172 	}
173 
174 	PUSHMARK(SP);
175 	XPUSHs(sv_2mortal(newSVpv((void *)dkim, SIZEOF_DKIM)));
176 	XPUSHs(sv_2mortal(newSVpv((void *)sigs, nsigs * SIZEOF_DKIM_SIGINFO)));
177 	XPUSHs(sv_2mortal(newSViv(nsigs)));
178 	PUTBACK;
179 
180 	count = call_sv(sv, G_SCALAR);
181 
182 	SPAGAIN;
183 
184 	if(count != 1) {
185 		croak("Internal error: prescreen_callback routine returned %d items, 1 was expected",
186 			count);
187 		return DKIM_CBSTAT_ERROR;
188 	}
189 
190 	status = POPi;
191 
192 	PUTBACK;
193 	FREETMPS;
194 	LEAVE;
195 
196 	return status;
197 }
198 
199 /*
200  * called when the OpenDKIMlibrary wants to call the callback function provided to
201  * dkim_set_signature_handle
202  */
203 static void *
call_signature_handle_callback(void * closure)204 call_signature_handle_callback(void *closure)
205 {
206 	dSP;
207 	int count;
208 	void *v;
209 	SV *sv = signature_handle_callback;
210 
211 	if(sv == NULL) {
212 		croak("Internal error: call_signature_handle_callback called, but nothing to call");
213 		return NULL;
214 	}
215 
216 	PUSHMARK(SP);
217 	/* libOpenDKIM doesn't tell us the size of closure, so use best guess :-( */
218 	XPUSHs(sv_2mortal(newSVpv((void *)closure, BUFSIZ)));
219 	PUTBACK;
220 
221 	count = call_sv(sv, G_SCALAR);
222 
223 	SPAGAIN;
224 
225 	if(count != 1) {
226 		croak("Internal error: signature_handle_callback routine returned %d items, 1 was expected",
227 			count);
228 		return NULL;
229 	}
230 
231 	v = POPp;
232 
233 	PUTBACK;
234 	FREETMPS;
235 	LEAVE;
236 
237 	return v;
238 }
239 
240 /*
241  * called when the OpenDKIMlibrary wants to call the callback function provided to
242  * dkim_set_signature_handle_free
243  */
244 static void
call_signature_handle_free_callback(void * closure,void * ptr)245 call_signature_handle_free_callback(void *closure, void *ptr)
246 {
247 	dSP;
248 	SV *sv = signature_handle_free_callback;
249 
250 	if(sv == NULL) {
251 		croak("Internal error: call_handle_free_callback called, but nothing to call");
252 		return;
253 	}
254 
255 	PUSHMARK(SP);
256 	/* libOpenDKIM doesn't tell us the size of closure, so use best guess :-( */
257 	XPUSHs(sv_2mortal(newSVpv((void *)closure, BUFSIZ)));
258 	XPUSHs(sv_2mortal(newSVpv((void *)ptr, BUFSIZ)));
259 	PUTBACK;
260 
261 	call_sv(sv, G_DISCARD);
262 }
263 
264 /*
265  * called when the OpenDKIMlibrary wants to call the callback function provided to
266  * dkim_set_signature_tagvalues
267  */
268 static void
call_signature_tagvalues_callback(void * user,dkim_param_t pcode,const unsigned char * param,const unsigned char * value)269 call_signature_tagvalues_callback(void *user, dkim_param_t pcode, const unsigned char *param, const unsigned char *value)
270 {
271 	dSP;
272 	SV *sv = signature_tagvalues_callback;
273 
274 	if(sv == NULL) {
275 		croak("Internal error: call_signature_tagvalues_callback called, but nothing to call");
276 		return;
277 	}
278 
279 	PUSHMARK(SP);
280 	/* libOpenDKIM doesn't tell us the size of user, so use best guess :-( */
281 	XPUSHs(sv_2mortal(newSVpv((void *)user, BUFSIZ)));
282 	XPUSHs(sv_2mortal(newSViv(pcode)));
283 	XPUSHs(sv_2mortal(newSVpv(param, 0)));
284 	XPUSHs(sv_2mortal(newSVpv(value, 0)));
285 	PUTBACK;
286 
287 	call_sv(sv, G_DISCARD);
288 }
289 
290 /*
291  * called when the OpenDKIMlibrary wants to call the callback function provided to
292  * dkim_set_query_cancel
293  */
294 static int
call_dns_query_cancel_callback(void * a,void * b)295 call_dns_query_cancel_callback(void *a, void *b)
296 {
297 	dSP;
298 	int count, ret;
299 	SV *sv = dns_query_cancel_callback;
300 
301 	if(sv == NULL) {
302 		croak("Internal error: call_dns_query_cancel called, but nothing to call");
303 		return -1;
304 	}
305 
306 	PUSHMARK(SP);
307 	XPUSHs(sv_2mortal(newSVpv(a, sizeof(void *))));
308 	XPUSHs(sv_2mortal(newSVpv(b, sizeof(void *))));
309 	PUTBACK;
310 
311 	count = call_sv(sv, G_SCALAR);
312 
313 	SPAGAIN;
314 
315 	if(count != 1) {
316 		croak("Internal error: dns_query_cancel_callback routine returned %d items, 1 was expected",
317 			count);
318 		return -1;
319 	}
320 
321 	ret = POPi;
322 
323 	PUTBACK;
324 	FREETMPS;
325 	LEAVE;
326 
327 	return ret;
328 }
329 
330 /*
331  * called when the OpenDKIMlibrary wants to call the callback function provided to
332  * dkim_set_query_service
333  */
334 static void
call_dns_query_service_callback(void * service)335 call_dns_query_service_callback(void *service)
336 {
337 	dSP;
338 	SV *sv = dns_query_service_callback;
339 
340 	if(sv == NULL) {
341 		croak("Internal error: call_dns_query_service called, but nothing to call");
342 		return;
343 	}
344 
345 	PUSHMARK(SP);
346 	XPUSHs(sv_2mortal(newSVpv(service, sizeof(void *))));
347 	PUTBACK;
348 
349 	call_sv(sv, G_DISCARD);
350 }
351 
352 /*
353  * called when the OpenDKIMlibrary wants to call the callback function provided to
354  * dkim_set_query_start
355  */
356 static int
call_dns_query_start_callback(void * a,int b,unsigned char * c,unsigned char * d,size_t e,void ** f)357 call_dns_query_start_callback(void *a, int b, unsigned char *c, unsigned char *d, size_t e, void **f)
358 {
359 	dSP;
360 	int count, ret;
361 	SV *sv = dns_query_start_callback;
362 
363 	if(sv == NULL) {
364 		croak("Internal error: call_dns_query_service called, but nothing to call");
365 		return -1;
366 	}
367 
368 	PUSHMARK(SP);
369 	XPUSHs(sv_2mortal(newSVpv(a, sizeof(void *))));
370 	XPUSHs(sv_2mortal(newSViv(b)));
371 	XPUSHs(sv_2mortal(newSVpv(c, 0)));
372 	XPUSHs(sv_2mortal(newSVpv(d, e + 1)));
373 	XPUSHs(sv_2mortal(newSViv(e)));
374 	XPUSHs(sv_2mortal(newSVpv((void *)f, sizeof(void **))));
375 	PUTBACK;
376 
377 	count = call_sv(sv, G_SCALAR);
378 
379 	SPAGAIN;
380 
381 	if(count != 1) {
382 		croak("Internal error: dns_query_start_callback routine returned %d items, 1 was expected",
383 			count);
384 		return -1;
385 	}
386 
387 	ret = POPi;
388 
389 	PUTBACK;
390 	FREETMPS;
391 	LEAVE;
392 
393 	return ret;
394 }
395 
396 /*
397  * called when the OpenDKIMlibrary wants to call the callback function provided to
398  * dkim_dns_set_query_waitreply
399  */
400 static int
call_dns_query_waitreply_callback(void * a,void * b,struct timeval * c,size_t * d,int * e,int * f)401 call_dns_query_waitreply_callback(void *a, void *b, struct timeval *c, size_t *d, int *e, int *f)
402 {
403 	dSP;
404 	int count, ret;
405 	SV *sv = dns_query_start_callback;
406 
407 	if(sv == NULL) {
408 		croak("Internal error: call_dns_query_service called, but nothing to call");
409 		return -1;
410 	}
411 
412 	PUSHMARK(SP);
413 	XPUSHs(sv_2mortal(newSVpv(a, sizeof(void *))));
414 	XPUSHs(sv_2mortal(newSVpv(b, sizeof(void *))));
415 	XPUSHs(sv_2mortal(newSVpv((void *)c, sizeof(struct timeval))));
416 	XPUSHs(sv_2mortal(newSVpv((void *)d, sizeof(size_t))));
417 	XPUSHs(sv_2mortal(newSVpv((void *)e, sizeof(int))));
418 	XPUSHs(sv_2mortal(newSVpv((void *)f, sizeof(int))));
419 	PUTBACK;
420 
421 	count = call_sv(sv, G_SCALAR);
422 
423 	SPAGAIN;
424 
425 	if(count != 1) {
426 		croak("Internal error: dns_query_waitreply_callback routine returned %d items, 1 was expected",
427 			count);
428 		return -1;
429 	}
430 
431 	ret = POPi;
432 
433 	PUTBACK;
434 	FREETMPS;
435 	LEAVE;
436 
437 	return ret;
438 }
439 
440 MODULE = Mail::OpenDKIM		PACKAGE = Mail::OpenDKIM
441 PROTOTYPES: DISABLE
442 
443 # These routines are called directly from the end user Perl code
444 unsigned long
445 dkim_ssl_version()
446 	CODE:
447 		RETVAL = dkim_ssl_version();
448 	OUTPUT:
449 		RETVAL
450 
451 unsigned long
452 dkim_libversion()
453 	CODE:
454 		RETVAL = dkim_libversion();
455 	OUTPUT:
456 		RETVAL
457 
458 const char *
459 dkim_getresultstr(result)
460 		DKIM_STAT result
461 	CODE:
462 		RETVAL = dkim_getresultstr(result);
463 	OUTPUT:
464 		RETVAL
465 
466 const char *
467 dkim_sig_geterrorstr(sigerr)
468 		DKIM_SIGERROR sigerr
469 	CODE:
470 		RETVAL = dkim_sig_geterrorstr(sigerr);
471 	OUTPUT:
472 		RETVAL
473 
474 int
475 dkim_mail_parse(line, user_out, domain_out)
476 		char *line
477 		unsigned char *user_out = NO_INIT
478 		unsigned char *domain_out = NO_INIT
479 	CODE:
480 		RETVAL = dkim_mail_parse(line, &user_out, &domain_out);
481 	OUTPUT:
482 		user_out
483 		domain_out
484 		RETVAL
485 
486 # These routines are called by the glue layer which supplies them with an OO interface
487 DKIM_LIB *
488 _dkim_init()
489 	CODE:
490 		RETVAL = dkim_init(NULL, NULL);
491 	OUTPUT:
492 		RETVAL
493 
494 void
495 _dkim_close(d)
496 		DKIM_LIB *d
497 	CODE:
498 		dkim_close(d);
499 
500 DKIM_STAT
501 _dkim_options(lib, op, opt, data, len)
502 		DKIM_LIB *lib
503 		int op
504 		int opt
505 		void *data
506 		size_t len
507 	CODE:
508 		RETVAL = dkim_options(lib, op, opt, data, len);
509 	OUTPUT:
510 		RETVAL
511 
512 _Bool
513 _dkim_libfeature(d, fc)
514 		DKIM_LIB *d
515 		unsigned int fc
516 	CODE:
517 		RETVAL = dkim_libfeature(d, fc);
518 	OUTPUT:
519 		RETVAL
520 
521 int
522 _dkim_flush_cache(d)
523 		DKIM_LIB *d
524 	CODE:
525 		RETVAL = dkim_flush_cache(d);
526 	OUTPUT:
527 		RETVAL
528 
529 #if OPENDKIM_LIB_VERSION >= 0x02080000
530 DKIM_STAT
531 _dkim_getcachestats(libhandle, queries, hits, expired, keys)
532 		DKIM_LIB *libhandle
533 		unsigned int queries = NO_INIT
534 		unsigned int hits = NO_INIT
535 		unsigned int expired = NO_INIT
536 		unsigned int keys = NO_INIT
537 	CODE:
538 		RETVAL = dkim_getcachestats(libhandle, &queries, &hits, &expired, &keys, 0);
539 	OUTPUT:
540 		queries
541 		hits
542 		expired
543 		keys
544 		RETVAL
545 
546 #else
547 DKIM_STAT
548 _dkim_getcachestats(queries, hits, expired)
549 		unsigned int queries = NO_INIT
550 		unsigned int hits = NO_INIT
551 		unsigned int expired = NO_INIT
552 	CODE:
553 		RETVAL = dkim_getcachestats(&queries, &hits, &expired);
554 	OUTPUT:
555 		queries
556 		hits
557 		expired
558 		RETVAL
559 
560 #endif
561 
562 DKIM *
563 _dkim_sign(libhandle, id, secretkey, selector, domain, hdrcanon_alg, bodycanon_alg, sign_alg, length, statp)
564 		DKIM_LIB *libhandle
565 		const char *id
566 		const char *secretkey
567 		const char *selector
568 		const char *domain
569 		dkim_canon_t hdrcanon_alg
570 		dkim_canon_t bodycanon_alg
571 		dkim_alg_t sign_alg
572 		off_t length
573 		DKIM_STAT statp = NO_INIT
574 	CODE:
575 		RETVAL = dkim_sign(libhandle, (const unsigned char *)id, NULL, (dkim_sigkey_t)secretkey, (const unsigned char *)selector, (const unsigned char *)domain, hdrcanon_alg, bodycanon_alg, sign_alg, length, &statp);
576 	OUTPUT:
577 		statp
578 		RETVAL
579 
580 # TODO: memclosure, if that is ever needed
581 DKIM *
582 _dkim_verify(libhandle, id,  statp)
583 		DKIM_LIB *libhandle
584 		const char *id
585 		DKIM_STAT statp = NO_INIT
586 	CODE:
587 		RETVAL = dkim_verify(libhandle, id, NULL, &statp);
588 	OUTPUT:
589 		statp
590 		RETVAL
591 
592 DKIM_STAT
593 _dkim_set_dns_callback(libopendkim, func, interval)
594 		DKIM_LIB *libopendkim
595 		SV *func
596 		unsigned int interval
597 	CODE:
598 		if(dns_callback == (SV *)NULL)
599 			dns_callback = newSVsv(func);
600 		else
601 			SvSetSV(dns_callback, func);
602 
603 		RETVAL = dkim_set_dns_callback(libopendkim, call_dns_callback, interval);
604 	OUTPUT:
605 		RETVAL
606 
607 DKIM_STAT
608 _dkim_set_final(libopendkim, func)
609 		DKIM_LIB *libopendkim
610 		SV *func
611 	CODE:
612 		if(final_callback == (SV *)NULL)
613 			final_callback = newSVsv(func);
614 		else
615 			SvSetSV(final_callback, func);
616 
617 		RETVAL = dkim_set_final(libopendkim, call_final_callback);
618 	OUTPUT:
619 		RETVAL
620 
621 DKIM_STAT
622 _dkim_set_key_lookup(libopendkim, func)
623 		DKIM_LIB *libopendkim
624 		SV *func
625 	CODE:
626 		if(key_lookup_callback == (SV *)NULL)
627 			key_lookup_callback = newSVsv(func);
628 		else
629 			SvSetSV(key_lookup_callback, func);
630 
631 		RETVAL = dkim_set_key_lookup(libopendkim, call_key_lookup_callback);
632 	OUTPUT:
633 		RETVAL
634 
635 DKIM_STAT
636 _dkim_set_prescreen(libopendkim, func)
637 		DKIM_LIB *libopendkim
638 		SV *func
639 	CODE:
640 		if(prescreen_callback == (SV *)NULL)
641 			prescreen_callback = newSVsv(func);
642 		else
643 			SvSetSV(prescreen_callback, func);
644 
645 		RETVAL = dkim_set_prescreen(libopendkim, call_prescreen_callback);
646 	OUTPUT:
647 		RETVAL
648 
649 DKIM_STAT
650 _dkim_set_signature_handle(libopendkim, func)
651 		DKIM_LIB *libopendkim
652 		SV *func
653 	CODE:
654 		if(signature_handle_callback == (SV *)NULL)
655 			signature_handle_callback = newSVsv(func);
656 		else
657 			SvSetSV(signature_handle_callback, func);
658 
659 		RETVAL = dkim_set_signature_handle(libopendkim, call_signature_handle_callback);
660 	OUTPUT:
661 		RETVAL
662 
663 DKIM_STAT
664 _dkim_set_signature_handle_free(libopendkim, func)
665 		DKIM_LIB *libopendkim
666 		SV *func
667 	CODE:
668 		if(signature_handle_free_callback == (SV *)NULL)
669 			signature_handle_free_callback = newSVsv(func);
670 		else
671 			SvSetSV(signature_handle_free_callback, func);
672 
673 		RETVAL = dkim_set_signature_handle_free(libopendkim, call_signature_handle_free_callback);
674 	OUTPUT:
675 		RETVAL
676 
677 DKIM_STAT
678 _dkim_set_signature_tagvalues(libopendkim, func)
679 		DKIM_LIB *libopendkim
680 		SV *func
681 	CODE:
682 		if(signature_tagvalues_callback == (SV *)NULL)
683 			signature_tagvalues_callback = newSVsv(func);
684 		else
685 			SvSetSV(signature_tagvalues_callback, func);
686 
687 		RETVAL = dkim_set_signature_tagvalues(libopendkim, call_signature_tagvalues_callback);
688 	OUTPUT:
689 		RETVAL
690 
691 void
692 _dkim_dns_set_query_cancel(libopendkim, func)
693 		DKIM_LIB *libopendkim
694 		SV *func
695 	CODE:
696 		if(dns_query_cancel_callback == (SV *)NULL)
697 			dns_query_cancel_callback = newSVsv(func);
698 		else
699 			SvSetSV(dns_query_cancel_callback, func);
700 
701 		dkim_dns_set_query_cancel(libopendkim, call_dns_query_cancel_callback);
702 
703 void
704 _dkim_dns_set_query_service(libopendkim, func)
705 		DKIM_LIB *libopendkim
706 		SV *func
707 	CODE:
708 		if(dns_query_service_callback == (SV *)NULL)
709 			dns_query_service_callback = newSVsv(func);
710 		else
711 			SvSetSV(dns_query_service_callback, func);
712 
713 		dkim_dns_set_query_service(libopendkim, call_dns_query_service_callback);
714 
715 void
716 _dkim_dns_set_query_start(libopendkim, func)
717 		DKIM_LIB *libopendkim
718 		SV *func
719 	CODE:
720 		if(dns_query_start_callback == (SV *)NULL)
721 			dns_query_start_callback = newSVsv(func);
722 		else
723 			SvSetSV(dns_query_start_callback, func);
724 
725 		dkim_dns_set_query_start(libopendkim, call_dns_query_start_callback);
726 
727 void
728 _dkim_dns_set_query_waitreply(libopendkim, func)
729 		DKIM_LIB *libopendkim
730 		SV *func
731 	CODE:
732 		if(dns_query_waitreply_callback == (SV *)NULL)
733 			dns_query_waitreply_callback = newSVsv(func);
734 		else
735 			SvSetSV(dns_query_waitreply_callback, func);
736 
737 		dkim_dns_set_query_waitreply(libopendkim, call_dns_query_waitreply_callback);
738 
739 DKIM_STAT
740 _dkim_free(d)
741 		DKIM *d
742 	CODE:
743 		RETVAL = dkim_free(d);
744 	OUTPUT:
745 		RETVAL
746 
747 DKIM_STAT
748 _dkim_header(dkim, header, len)
749 		DKIM *dkim
750 		unsigned char *header
751 		size_t len
752 	CODE:
753 		RETVAL = dkim_header(dkim, header, len);
754 	OUTPUT:
755 		RETVAL
756 
757 DKIM_STAT
758 _dkim_body(dkim, bodyp, len)
759 		DKIM *dkim
760 		unsigned char *bodyp
761 		size_t len
762 	CODE:
763 		RETVAL = dkim_body(dkim, bodyp, len);
764 	OUTPUT:
765 		RETVAL
766 
767 DKIM_STAT
768 _dkim_eoh(dkim)
769 		DKIM *dkim
770 	CODE:
771 		RETVAL = dkim_eoh(dkim);
772 	OUTPUT:
773 		RETVAL
774 
775 DKIM_STAT
776 _dkim_chunk(dkim, chunkp, len)
777 		DKIM *dkim
778 		unsigned char *chunkp
779 		size_t len
780 	CODE:
781 		RETVAL = dkim_chunk(dkim, chunkp, len);
782 	OUTPUT:
783 		RETVAL
784 
785 DKIM_STAT
786 _dkim_eom(dkim)
787 		DKIM *dkim
788 	CODE:
789 		RETVAL = dkim_eom(dkim, NULL);
790 	OUTPUT:
791 		RETVAL
792 
793 const char *
794 _dkim_getid(dkim)
795 		DKIM *dkim
796 	CODE:
797 		RETVAL = dkim_getid(dkim);
798 	OUTPUT:
799 		RETVAL
800 
801 #if OPENDKIM_LIB_VERSION < 0x02070000
802 
803 uint64_t
804 _dkim_get_msgdate(dkim)
805 		DKIM *dkim
806 	CODE:
807 		RETVAL = dkim_get_msgdate(dkim);
808 	OUTPUT:
809 		RETVAL
810 
811 #endif
812 
813 DKIM_STAT
814 _dkim_get_sigsubstring(dkim, sig, buf, buflen)
815 		DKIM *dkim
816 		DKIM_SIGINFO *sig
817 		char *buf
818 		size_t buflen
819 	CODE:
820 		RETVAL = dkim_get_sigsubstring(dkim, sig, buf, &buflen);
821 	OUTPUT:
822 		buflen
823 		RETVAL
824 
825 DKIM_STAT
826 _dkim_key_syntax(dkim, str, len)
827 		DKIM *dkim
828 		unsigned char *str
829 		size_t len
830 	CODE:
831 		RETVAL = dkim_key_syntax(dkim, str, len);
832 	OUTPUT:
833 		RETVAL
834 
835 unsigned char *
836 _dkim_get_signer(dkim)
837 		DKIM *dkim
838 	CODE:
839 		RETVAL = dkim_get_signer(dkim);
840 	OUTPUT:
841 		RETVAL
842 
843 DKIM_STAT
844 _dkim_set_signer(dkim, signer)
845 		DKIM *dkim
846 		const char *signer
847 	CODE:
848 		RETVAL = dkim_set_signer(dkim, signer);
849 	OUTPUT:
850 		RETVAL
851 
852 DKIM_STAT
853 _dkim_set_margin(dkim, margin)
854 		DKIM *dkim
855 		int margin
856 	CODE:
857 		RETVAL = dkim_set_margin(dkim, margin);
858 	OUTPUT:
859 		RETVAL
860 
861 void *
862 _dkim_get_user_context(dkim)
863 		DKIM *dkim
864 	CODE:
865 		RETVAL = dkim_get_user_context(dkim);
866 	OUTPUT:
867 		RETVAL
868 
869 DKIM_STAT
870 _dkim_set_user_context(dkim, ctx)
871 		DKIM *dkim
872 		void *ctx
873 	CODE:
874 		RETVAL = dkim_set_user_context(dkim, ctx);
875 	OUTPUT:
876 		RETVAL
877 
878 DKIM_STAT
879 _dkim_atps_check(dkim, sig, timeout, res)
880 		DKIM *dkim
881 		DKIM_SIGINFO *sig
882 		struct timeval *timeout
883 		dkim_atps_t res = NO_INIT;
884 	CODE:
885 		RETVAL = dkim_atps_check(dkim, sig, timeout, &res);
886 	OUTPUT:
887 		res
888 		RETVAL
889 
890 DKIM_STAT
891 _dkim_diffheaders(dkim, canon, maxcost, ohdrs, nohdrs, out, nout)
892 		DKIM *dkim
893 		dkim_canon_t canon
894 		int maxcost
895 		char *&ohdrs
896 		int nohdrs
897 		struct dkim_hdrdiff *out = NO_INIT
898 		int nout = NO_INIT
899 	CODE:
900 		RETVAL = dkim_diffheaders(dkim, canon, maxcost, &ohdrs, nohdrs, &out, &nout);
901 	OUTPUT:
902 		out
903 		nout
904 		RETVAL
905 
906 DKIM_STAT
907 _dkim_getsighdr(dkim, buf, len, initial)
908 		DKIM *dkim
909 		unsigned char *buf
910 		size_t len
911 		size_t initial
912 	CODE:
913 		RETVAL = dkim_getsighdr(dkim, buf, len, initial);
914 	OUTPUT:
915 		buf
916 		RETVAL
917 
918 DKIM_STAT
919 _dkim_getsighdr_d(dkim, initial, buf, len)
920 		DKIM *dkim
921 		size_t initial
922 		unsigned char *&buf = NO_INIT
923 		size_t len = NO_INIT
924 	CODE:
925 		RETVAL = dkim_getsighdr_d(dkim, initial, &buf, &len);
926 	OUTPUT:
927 		buf
928 		len
929 		RETVAL
930 
931 DKIM_SIGINFO *
932 _dkim_getsignature(dkim)
933 		DKIM *dkim
934 	CODE:
935 		RETVAL = dkim_getsignature(dkim);
936 	OUTPUT:
937 		RETVAL
938 
939 # Returns 3 values: $rc, $nsigs, @sigs
940 
941 void
942 _dkim_getsiglist(dkim)
943 		DKIM *dkim
944 	PPCODE:
945 		DKIM_SIGINFO **s = NULL;
946 		int nsigs;
947 		DKIM_STAT rc = dkim_getsiglist(dkim, &s, &nsigs);
948 
949 		/*
950 		 * Push the sigs on to the stack so that they appear to Perl as a @list
951 		 */
952 		XPUSHs(sv_2mortal(newSViv(rc)));
953 		if(rc == DKIM_STAT_OK) {
954 			int i;
955 
956 			XPUSHs(sv_2mortal(newSViv(nsigs)));
957 
958 			for(i = 0; i < nsigs; i++, s++)
959 				XPUSHs(sv_2mortal(newSVpv((char *)*s, sizeof(DKIM_SIGINFO *))));
960 
961 			XSRETURN(i + 2);	/* number of items put on the stack */
962 		} else {
963 			XPUSHs(sv_2mortal(newSViv(0)));
964 
965 			XSRETURN(2);
966 		}
967 
968 DKIM_STAT
969 _dkim_ohdrs(dkim, sig, ptrs, cnt)
970 		DKIM *dkim
971 		DKIM_SIGINFO *sig
972 		unsigned char &ptrs = NO_INIT
973 		int cnt
974 	CODE:
975 		RETVAL = dkim_ohdrs(dkim, sig, &ptrs, &cnt);
976 	OUTPUT:
977 		ptrs
978 		cnt
979 		RETVAL
980 
981 _Bool
982 _dkim_getpartial(dkim)
983 		DKIM *dkim
984 	CODE:
985 		RETVAL = dkim_getpartial(dkim);
986 	OUTPUT:
987 		RETVAL
988 
989 DKIM_STAT
990 _dkim_setpartial(dkim, value)
991 		DKIM *dkim
992 		_Bool value
993 	CODE:
994 		RETVAL = dkim_setpartial(dkim, value);
995 	OUTPUT:
996 		RETVAL
997 
998 const char *
999 _dkim_getdomain(dkim)
1000 		DKIM *dkim
1001 	CODE:
1002 		RETVAL = dkim_getdomain(dkim);
1003 	OUTPUT:
1004 		RETVAL
1005 
1006 const char *
1007 _dkim_getuser(dkim)
1008 		DKIM *dkim
1009 	CODE:
1010 		RETVAL = dkim_getuser(dkim);
1011 	OUTPUT:
1012 		RETVAL
1013 
1014 unsigned long
1015 _dkim_minbody(dkim)
1016 		DKIM *dkim
1017 	CODE:
1018 		RETVAL = dkim_minbody(dkim);
1019 	OUTPUT:
1020 		RETVAL
1021 
1022 int
1023 _dkim_getmode(dkim)
1024 		DKIM *dkim
1025 	CODE:
1026 		RETVAL = dkim_getmode(dkim);
1027 	OUTPUT:
1028 		RETVAL
1029 
1030 unsigned int
1031 _dkim_sig_getbh(sig)
1032 		DKIM_SIGINFO *sig
1033 	CODE:
1034 		RETVAL = dkim_sig_getbh(sig);
1035 	OUTPUT:
1036 		RETVAL
1037 
1038 DKIM_STAT
1039 _dkim_sig_getcanonlen(dkim, sig, msglen, canonlen, signlen)
1040 		DKIM *dkim
1041 		DKIM_SIGINFO *sig
1042 		off_t msglen = NO_INIT
1043 		off_t canonlen = NO_INIT
1044 		off_t signlen = NO_INIT
1045 	CODE:
1046 		RETVAL = dkim_sig_getcanonlen(dkim, sig, &msglen, &canonlen, &signlen);
1047 	OUTPUT:
1048 		msglen
1049 		canonlen
1050 		signlen
1051 		RETVAL
1052 
1053 DKIM_STAT
1054 _dkim_sig_getcanons(sig, hdr, body)
1055 		DKIM_SIGINFO *sig
1056 		dkim_canon_t hdr = NO_INIT
1057 		dkim_canon_t body = NO_INIT
1058 	CODE:
1059 		RETVAL = dkim_sig_getcanons(sig, &hdr, &body);
1060 	OUTPUT:
1061 		hdr
1062 		body
1063 		RETVAL
1064 
1065 void *
1066 _dkim_sig_getcontext(sig)
1067 		DKIM_SIGINFO *sig
1068 	CODE:
1069 		RETVAL = dkim_sig_getcontext(sig);
1070 	OUTPUT:
1071 		RETVAL
1072 
1073 int
1074 _dkim_sig_getdnssec(sig)
1075 		DKIM_SIGINFO *sig
1076 	CODE:
1077 		RETVAL = dkim_sig_getdnssec(sig);
1078 	OUTPUT:
1079 		RETVAL
1080 
1081 const char *
1082 _dkim_sig_getdomain(sig)
1083 		DKIM_SIGINFO *sig
1084 	CODE:
1085 		RETVAL = dkim_sig_getdomain(sig);
1086 	OUTPUT:
1087 		RETVAL
1088 
1089 int
1090 _dkim_sig_geterror(sig)
1091 		DKIM_SIGINFO *sig
1092 	CODE:
1093 		RETVAL = dkim_sig_geterror(sig);
1094 	OUTPUT:
1095 		RETVAL
1096 
1097 unsigned int
1098 _dkim_sig_getflags(sig)
1099 		DKIM_SIGINFO *sig
1100 	CODE:
1101 		RETVAL = dkim_sig_getflags(sig);
1102 	OUTPUT:
1103 		RETVAL
1104 
1105 void
1106 _dkim_sig_ignore(sig)
1107 		DKIM_SIGINFO *sig
1108 	CODE:
1109 		dkim_sig_ignore(sig);
1110 
1111 DKIM_STAT
1112 _dkim_sig_getidentity(dkim, sig, val, vallen)
1113 		DKIM *dkim
1114 		DKIM_SIGINFO *sig
1115 		char *val
1116 		size_t vallen
1117 	CODE:
1118 		RETVAL = dkim_sig_getidentity(dkim, sig, val, vallen);
1119 	OUTPUT:
1120 		RETVAL
1121 
1122 DKIM_STAT
1123 _dkim_sig_getkeysize(sig, bits)
1124 		DKIM_SIGINFO *sig
1125 		unsigned int bits = NO_INIT
1126 	CODE:
1127 		RETVAL = dkim_sig_getkeysize(sig, &bits);
1128 	OUTPUT:
1129 		bits
1130 		RETVAL
1131 
1132 DKIM_STAT
1133 _dkim_sig_getreportinfo(dkim, sig, hfd, bfd, addrbuf, addrlen, optsbuf, optslen, smtpbuf, smtplen, interval)
1134 		DKIM *dkim
1135 		DKIM_SIGINFO *sig
1136 		int *hfd
1137 		int *bfd
1138 		char *addrbuf
1139 		size_t addrlen
1140 		char *optsbuf
1141 		size_t optslen
1142 		char *smtpbuf
1143 		size_t smtplen
1144 		unsigned int interval = NO_INIT
1145 	CODE:
1146 		RETVAL = dkim_sig_getreportinfo(dkim, sig, hfd, bfd, addrbuf, addrlen, optsbuf, optslen, smtpbuf, smtplen, &interval);
1147 	OUTPUT:
1148 		interval
1149 		RETVAL
1150 
1151 const char *
1152 _dkim_sig_getselector(sig)
1153 		DKIM_SIGINFO *sig
1154 	CODE:
1155 		RETVAL = dkim_sig_getselector(sig);
1156 	OUTPUT:
1157 		RETVAL
1158 
1159 DKIM_STAT
1160 _dkim_sig_getsignalg(sig, alg)
1161 		DKIM_SIGINFO *sig
1162 		dkim_alg_t alg = NO_INIT
1163 	CODE:
1164 		RETVAL = dkim_sig_getsignalg(sig, &alg);
1165 	OUTPUT:
1166 		alg
1167 		RETVAL
1168 
1169 DKIM_STAT
1170 _dkim_sig_getsignedhdrs(dkim, sig, hdrs, hdrlen, nhdrs)
1171 		DKIM *dkim
1172 		DKIM_SIGINFO *sig
1173 		unsigned char *hdrs
1174 		size_t hdrlen
1175 		unsigned int nhdrs
1176 	CODE:
1177 		RETVAL = dkim_sig_getsignedhdrs(dkim, sig, hdrs, hdrlen, &nhdrs);
1178 	OUTPUT:
1179 		nhdrs
1180 		RETVAL
1181 
1182 DKIM_STAT
1183 _dkim_sig_getsigntime(sig, when)
1184 		DKIM_SIGINFO *sig
1185 		time_t when
1186 	CODE:
1187 		RETVAL = dkim_sig_getsigntime(sig, &when);
1188 	OUTPUT:
1189 		when
1190 		RETVAL
1191 
1192 bool
1193 _dkim_sig_hdrsigned(sig, hdr)
1194 		DKIM_SIGINFO *sig
1195 		char *hdr
1196 	CODE:
1197 		RETVAL = dkim_sig_hdrsigned(sig, hdr);
1198 	OUTPUT:
1199 		RETVAL
1200 
1201 DKIM_STAT
1202 _dkim_sig_process(dkim, sig)
1203 		DKIM *dkim
1204 		DKIM_SIGINFO *sig
1205 	CODE:
1206 		RETVAL = dkim_sig_process(dkim, sig);
1207 	OUTPUT:
1208 		RETVAL
1209 
1210 int
1211 _dkim_sig_syntax(dkim, str, len)
1212                 DKIM *dkim
1213                 unsigned char *str
1214                 size_t len
1215 	CODE:
1216 		RETVAL = dkim_sig_syntax(dkim, str, len);
1217 	OUTPUT:
1218                 RETVAL
1219 
1220 unsigned char *
1221 _dkim_sig_gettagvalue(sig, keytag, tag)
1222 		DKIM_SIGINFO *sig
1223 		_Bool keytag
1224 		char *tag
1225 	CODE:
1226 		RETVAL = dkim_sig_gettagvalue(sig, keytag, tag);
1227 	OUTPUT:
1228 		RETVAL
1229 
1230 const char *
1231 _dkim_geterror(dkim)
1232 		DKIM *dkim
1233 	CODE:
1234 		RETVAL = dkim_geterror(dkim);
1235 	OUTPUT:
1236 		RETVAL
1237