1 /*
2  * Copyright (c) 2000 Charles Ying. All rights reserved.
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the same terms as sendmail itself.
6  *
7  */
8 
9 #include "EXTERN.h"
10 #include "perl.h"
11 #include "XSUB.h"
12 
13 #include "intpools.h"
14 
15 #include "libmilter/mfapi.h"
16 #include "callbacks.h"
17 
18 
19 /* Conversion for an easier interface to the milter API. */
20 #define MI_BOOL_CVT(mi_bool) (((mi_bool) == MI_SUCCESS) ? TRUE : FALSE)
21 
22 typedef SMFICTX *Sendmail_Milter_Context;
23 
24 
25 /* Wrapper functions to do some real work. */
26 
milter_register(pTHX_ char * name,SV * milter_desc_ref,int flags)27 int milter_register(pTHX_ char *name, SV *milter_desc_ref, int flags)
28 {
29 	HV *milter_desc = (HV *)NULL;
30 	struct smfiDesc filter_desc;
31 
32 	if (!SvROK(milter_desc_ref) &&
33 	    (SvTYPE(SvRV(milter_desc_ref)) != SVt_PVHV))
34 		croak("expected reference to hash for milter descriptor.");
35 
36 	milter_desc = (HV *)SvRV(milter_desc_ref);
37 
38 	register_callbacks(&filter_desc, name, milter_desc, flags);
39 
40 	return smfi_register(filter_desc);
41 }
42 
milter_main(int max_interpreters,int max_requests)43 int milter_main(int max_interpreters, int max_requests)
44 {
45 	init_callbacks(max_interpreters, max_requests);
46 
47 	return smfi_main();
48 }
49 
50 
51 /* Constants from libmilter/mfapi.h */
52 
53 static int
not_here(char * s)54 not_here(char *s)
55 {
56     croak("%s not implemented on this architecture", s);
57     return -1;
58 }
59 
60 static double
constant_SMFIF_A(char * name,int len,int arg)61 constant_SMFIF_A(char *name, int len, int arg)
62 {
63     if (7 + 2 >= len ) {
64 	errno = EINVAL;
65 	return 0;
66     }
67     switch (name[7 + 2]) {
68     case 'H':
69 	if (strEQ(name + 7, "DDHDRS")) {	/* SMFIF_A removed */
70 #ifdef SMFIF_ADDHDRS
71 	    return SMFIF_ADDHDRS;
72 #else
73 	    goto not_there;
74 #endif
75 	}
76     case 'R':
77 	if (strEQ(name + 7, "DDRCPT")) {	/* SMFIF_A removed */
78 #ifdef SMFIF_ADDRCPT
79 	    return SMFIF_ADDRCPT;
80 #else
81 	    goto not_there;
82 #endif
83 	}
84     }
85     errno = EINVAL;
86     return 0;
87 
88 not_there:
89     errno = ENOENT;
90     return 0;
91 }
92 
93 static double
constant_SMFIF_C(char * name,int len,int arg)94 constant_SMFIF_C(char *name, int len, int arg)
95 {
96     if (7 + 2 >= len ) {
97 	errno = EINVAL;
98 	return 0;
99     }
100     switch (name[7 + 2]) {
101     case 'B':
102 	if (strEQ(name + 7, "HGBODY")) {	/* SMFIF_C removed */
103 #ifdef SMFIF_CHGBODY
104 	    return SMFIF_CHGBODY;
105 #else
106 	    goto not_there;
107 #endif
108 	}
109     case 'H':
110 	if (strEQ(name + 7, "HGHDRS")) {	/* SMFIF_C removed */
111 #ifdef SMFIF_CHGHDRS
112 	    return SMFIF_CHGHDRS;
113 #else
114 	    goto not_there;
115 #endif
116 	}
117     }
118     errno = EINVAL;
119     return 0;
120 
121 not_there:
122     errno = ENOENT;
123     return 0;
124 }
125 
126 static double
constant_SMFIF(char * name,int len,int arg)127 constant_SMFIF(char *name, int len, int arg)
128 {
129     if (5 + 1 >= len ) {
130 	errno = EINVAL;
131 	return 0;
132     }
133     switch (name[5 + 1]) {
134     case 'A':
135 	if (!strnEQ(name + 5,"_", 1))
136 	    break;
137 	return constant_SMFIF_A(name, len, arg);
138     case 'C':
139 	if (!strnEQ(name + 5,"_", 1))
140 	    break;
141 	return constant_SMFIF_C(name, len, arg);
142     case 'D':
143 	if (strEQ(name + 5, "_DELRCPT")) {	/* SMFIF removed */
144 #ifdef SMFIF_DELRCPT
145 	    return SMFIF_DELRCPT;
146 #else
147 	    goto not_there;
148 #endif
149 	}
150     case 'M':
151 	if (strEQ(name + 5, "_MODBODY")) {	/* SMFIF removed */
152 #ifdef SMFIF_MODBODY
153 	    return SMFIF_MODBODY;
154 #else
155 	    goto not_there;
156 #endif
157 	}
158     }
159     errno = EINVAL;
160     return 0;
161 
162 not_there:
163     errno = ENOENT;
164     return 0;
165 }
166 
167 static double
constant_SMFI_V(char * name,int len,int arg)168 constant_SMFI_V(char *name, int len, int arg)
169 {
170     switch (name[6 + 0]) {
171     case '1':
172 	if (strEQ(name + 6, "1_ACTS")) {	/* SMFI_V removed */
173 #ifdef SMFI_V1_ACTS
174 	    return SMFI_V1_ACTS;
175 #else
176 	    goto not_there;
177 #endif
178 	}
179     case '2':
180 	if (strEQ(name + 6, "2_ACTS")) {	/* SMFI_V removed */
181 #ifdef SMFI_V2_ACTS
182 	    return SMFI_V2_ACTS;
183 #else
184 	    goto not_there;
185 #endif
186 	}
187     }
188     errno = EINVAL;
189     return 0;
190 
191 not_there:
192     errno = ENOENT;
193     return 0;
194 }
195 
196 static double
constant_SMFI_(char * name,int len,int arg)197 constant_SMFI_(char *name, int len, int arg)
198 {
199     switch (name[5 + 0]) {
200     case 'C':
201 	if (strEQ(name + 5, "CURR_ACTS")) {	/* SMFI_ removed */
202 #ifdef SMFI_CURR_ACTS
203 	    return SMFI_CURR_ACTS;
204 #else
205 	    goto not_there;
206 #endif
207 	}
208     case 'V':
209 	return constant_SMFI_V(name, len, arg);
210     }
211     errno = EINVAL;
212     return 0;
213 
214 not_there:
215     errno = ENOENT;
216     return 0;
217 }
218 
219 static double
constant_SMFIS(char * name,int len,int arg)220 constant_SMFIS(char *name, int len, int arg)
221 {
222     if (5 + 1 >= len ) {
223 	errno = EINVAL;
224 	return 0;
225     }
226     switch (name[5 + 1]) {
227     case 'A':
228 	if (strEQ(name + 5, "_ACCEPT")) {	/* SMFIS removed */
229 #ifdef SMFIS_ACCEPT
230 	    return SMFIS_ACCEPT;
231 #else
232 	    goto not_there;
233 #endif
234 	}
235     case 'C':
236 	if (strEQ(name + 5, "_CONTINUE")) {	/* SMFIS removed */
237 #ifdef SMFIS_CONTINUE
238 	    return SMFIS_CONTINUE;
239 #else
240 	    goto not_there;
241 #endif
242 	}
243     case 'D':
244 	if (strEQ(name + 5, "_DISCARD")) {	/* SMFIS removed */
245 #ifdef SMFIS_DISCARD
246 	    return SMFIS_DISCARD;
247 #else
248 	    goto not_there;
249 #endif
250 	}
251     case 'R':
252 	if (strEQ(name + 5, "_REJECT")) {	/* SMFIS removed */
253 #ifdef SMFIS_REJECT
254 	    return SMFIS_REJECT;
255 #else
256 	    goto not_there;
257 #endif
258 	}
259     case 'T':
260 	if (strEQ(name + 5, "_TEMPFAIL")) {	/* SMFIS removed */
261 #ifdef SMFIS_TEMPFAIL
262 	    return SMFIS_TEMPFAIL;
263 #else
264 	    goto not_there;
265 #endif
266 	}
267     }
268     errno = EINVAL;
269     return 0;
270 
271 not_there:
272     errno = ENOENT;
273     return 0;
274 }
275 
276 static double
constant(char * name,int len,int arg)277 constant(char *name, int len, int arg)
278 {
279     errno = 0;
280     if (0 + 4 >= len ) {
281 	errno = EINVAL;
282 	return 0;
283     }
284     switch (name[0 + 4]) {
285     case 'F':
286 	if (!strnEQ(name + 0,"SMFI", 4))
287 	    break;
288 	return constant_SMFIF(name, len, arg);
289     case 'S':
290 	if (!strnEQ(name + 0,"SMFI", 4))
291 	    break;
292 	return constant_SMFIS(name, len, arg);
293     case '_':
294 	if (!strnEQ(name + 0,"SMFI", 4))
295 	    break;
296 	return constant_SMFI_(name, len, arg);
297     }
298     errno = EINVAL;
299     return 0;
300 
301 not_there:
302     errno = ENOENT;
303     return 0;
304 }
305 
306 
307 MODULE = Sendmail::Milter  PACKAGE = Sendmail::Milter  PREFIX = smfi_
308 
309 PROTOTYPES:	DISABLE
310 
311 double
312 constant(sv,arg)
313     PREINIT:
314 	STRLEN		len;
315     INPUT:
316 	SV *		sv
317 	char *		s = SvPV(sv, len);
318 	int		arg
319     CODE:
320 	RETVAL = constant(s,len,arg);
321     OUTPUT:
322 	RETVAL
323 
324 bool
325 smfi_register(name, milter_desc_ref, flags=0)
326 	char*		name;
327 	SV*		milter_desc_ref;
328 	int		flags;
329     CODE:
330 	RETVAL = MI_BOOL_CVT(milter_register(aTHX_ name, milter_desc_ref,
331 						flags));
332     OUTPUT:
333 	RETVAL
334 
335 bool
336 smfi_main(max_interpreters=0, max_requests=0)
337 	int		max_interpreters;
338 	int		max_requests;
339     CODE:
340 	RETVAL = MI_BOOL_CVT(milter_main(max_interpreters, max_requests));
341     OUTPUT:
342 	RETVAL
343 
344 bool
345 smfi_setdbg(dbg)
346 	int		dbg;
347     CODE:
348 	RETVAL = MI_BOOL_CVT(smfi_setdbg(dbg));
349     OUTPUT:
350 	RETVAL
351 
352 bool
353 smfi_setconn(conn)
354 	char*		conn;
355     CODE:
356 	RETVAL = MI_BOOL_CVT(smfi_setconn(conn));
357     OUTPUT:
358 	RETVAL
359 
360 bool
361 smfi_settimeout(timeout)
362 	int		timeout;
363     CODE:
364 	RETVAL = MI_BOOL_CVT(smfi_settimeout(timeout));
365     OUTPUT:
366 	RETVAL
367 
368 int
369 test_intpools(max_interp, max_requests, i_max, j_max, callback)
370 	int		max_interp;
371 	int		max_requests;
372 	int		i_max;
373 	int		j_max;
374 	SV*		callback;
375     CODE:
376 	RETVAL = test_intpools(aTHX_ max_interp, max_requests, i_max, j_max,
377 				     callback);
378     OUTPUT:
379 	RETVAL
380 
381 
382 MODULE = Sendmail::Milter  PACKAGE = Sendmail::Milter::Context  PREFIX = smfi_
383 
384 char *
385 smfi_getsymval(Sendmail_Milter_Context ctx, char* symname)
386 
387 bool
388 smfi_setreply(ctx, rcode, xcode, message)
389 	Sendmail_Milter_Context	ctx;
390 	char*		rcode;
391 	char*		xcode;
392 	char*		message;
393     CODE:
394 	RETVAL = MI_BOOL_CVT(smfi_setreply(ctx, rcode, xcode, message));
395     OUTPUT:
396 	RETVAL
397 
398 bool
399 smfi_addheader(ctx, headerf, headerv)
400 	Sendmail_Milter_Context	ctx;
401 	char*		headerf;
402 	char*		headerv;
403     CODE:
404 	RETVAL = MI_BOOL_CVT(smfi_addheader(ctx, headerf, headerv));
405     OUTPUT:
406 	RETVAL
407 
408 bool
409 smfi_chgheader(ctx, headerf, index, headerv)
410 	Sendmail_Milter_Context	ctx;
411 	char*		headerf;
412 	int		index;
413 	char*		headerv;
414     CODE:
415 	RETVAL = MI_BOOL_CVT(smfi_chgheader(ctx, headerf, index, headerv));
416     OUTPUT:
417 	RETVAL
418 
419 bool
420 smfi_addrcpt(ctx, rcpt)
421 	Sendmail_Milter_Context	ctx;
422 	char*		rcpt;
423     CODE:
424 	RETVAL = MI_BOOL_CVT(smfi_addrcpt(ctx, rcpt));
425     OUTPUT:
426 	RETVAL
427 
428 bool
429 smfi_delrcpt(ctx, rcpt)
430 	Sendmail_Milter_Context	ctx;
431 	char*		rcpt;
432     CODE:
433 	RETVAL = MI_BOOL_CVT(smfi_delrcpt(ctx, rcpt));
434     OUTPUT:
435 	RETVAL
436 
437 bool
438 smfi_replacebody(ctx, body_data)
439 	Sendmail_Milter_Context	ctx;
440 	SV*		body_data;
441     PREINIT:
442 	u_char *bodyp;
443 	int len;
444     CODE:
445 	bodyp = SvPV(body_data, len);
446 	RETVAL = MI_BOOL_CVT(smfi_replacebody(ctx, bodyp, len));;
447     OUTPUT:
448 	RETVAL
449 
450 bool
451 smfi_setpriv(ctx, data)
452 	Sendmail_Milter_Context	ctx;
453 	SV*		data;
454     CODE:
455 	if (SvTRUE(data))
456 		RETVAL = MI_BOOL_CVT(smfi_setpriv(ctx, (void *)newSVsv(data)));
457 	else
458 		RETVAL = MI_BOOL_CVT(smfi_setpriv(ctx, NULL));
459     OUTPUT:
460 	RETVAL
461 
462 SV *
463 smfi_getpriv(ctx)
464 	Sendmail_Milter_Context	ctx;
465     CODE:
466 	RETVAL = (SV *) smfi_getpriv(ctx);
467     OUTPUT:
468 	RETVAL
469