1 /* -*- C -*-
2  * Spamtest connection library
3  * File: spamtest.h
4  *      (C)  Alex Tutubalin <lexa@lexa.ru>
5  *	and
6  *	Mike Patutin <patutin@vist-v.ru>
7  *	Apr-May 2003
8  *
9  * Created: Wed Apr 23 22:08:08 2003
10  */
11 
12 #include <stdio.h>
13 #include <stdlib.h>
14 #include <sys/time.h>
15 
16 #include "msgstore.h"
17 
18 #ifndef SPAM_FILTER_LIBRARY
19 #define SPAM_FILTER_LIBRARY
20 
21 #ifdef __cplusplus
22 extern "C"
23 {
24 #endif
25 
26 /* filter actions modes - change message/bounce message */
27 typedef enum
28 {
29     STS_ACTION_CHANGE=	1,
30     STS_ACTION_BOUNCE=	2
31 } spamtest_reply_t;
32 
33 /* change action types */
34 typedef enum
35 {
36     STS_HEADER_NONE=	0,
37     STS_HEADER_DEL=	1,
38     STS_HEADER_CHG=	2,
39     STS_HEADER_ADD=	3,
40     STS_HEADER_NEW=	4,
41     STS_HEADER_PREPEND=	5
42 } spamtest_action_t;
43 
44 #define STS_ABUF_S 4096
45 /* timeouts in milliseconds */
46 #define STS_DEFAULT_CONNECT_TIMEOUT	1000
47 #define STS_DEFAULT_SND_RCV_TIMEOUT	50000
48 
49 /* error codes */
50 /* if you add new code - don't forget to change sts_strerror function */
51 #define STS_ERR_NO_ERR			0
52 #define STS_ERR_OUT_OF_MEMORY		-1
53 #define STS_ERR_ILLEGAL_ADDRESS		-2
54 #define STS_ERR_UNABLE_TO_CONNECT	-3
55 #define STS_ERR_CONNECT_TIMEOUT		-4
56 #define STS_ERR_SND_RCV_TIMEOUT		-5
57 #define STS_ERR_INCORRECT_PROTOCOL	-6
58 #define STS_ERR_LIBRARY_ERR		-7
59 #define STS_ERR_UNABLE_TO_RESOLVE	-8
60 #define STS_ERR_SELECT_FD_ERR		-9
61 #define STS_ERR_READ_ERR	        -10
62 #define STS_ERR_ILLEGAL_CONFIG		-11
63 #define STS_ERR_BUFFER_NOT_PRESENT	-12
64 #define STS_ERR_BUFFER_IS_FULL		-14
65 #define STS_ERR_WRITE_ERR		-15
66 #define STS_ERR_GET_RECORD_SIZE		-16
67 #define STS_ERR_RECORD_TOO_LARGE	-17
68 #define STS_ERR_INVALID_PARAMS		-18
69 #define STS_ERR_NOT_INITED		-19
70 
71 /* sts_prepare_envelope status codes */
72 #define STS_PREPARE_OK	  	  0
73 #define STS_ERR_ILLEGAL_RELAY	  1
74 #define STS_ERR_ILLEGAL_RCPT	  2
75 #define STS_ERR_ILLEGAL_MAIL_FROM 4
76 
77 
78 /* flags for sts_send_body/sts_send_envelope */
79 #define STS_REINIT_TIMEOUT	16
80 #define STS_FLUSH_DATA		32
81 #define STS_FINAL_CHUNK		64
82 
83 /* flags for spamtest_session_t->flags */
84 #define STS_USE_POLL		1
85 
86 
87 /* session status types */
88 typedef enum
89 {
90     STS_SENDERROR = -2,	/* I/O or other error */
91     STS_CONTINUE = -1,	/* should continue sending message */
92     STS_ACCEPT=0,		/* message accepted, result should be analyzed
93 			   and actions on message performed */
94     STS_FILTER_ERROR=1,	/* filter returns an error, message should be
95 			   rejected with 45x code */
96     STS_REJECT=8,		/* filter rejects message, 55x code should be
97 			   returned to sender */
98     STS_BLACKHOLE=16,	/* message blackholed - 220 code to sender, no
99 			   actions on message itself */
100     STS_SMTP_ACCEPT=128	/* filter accepts message and have sent it by
101 			   SMTP - 220 OK to sender, no actions on message */
102 }
103 session_status_t;
104 
105 typedef enum
106 {
107     STS_SMTP_MODE=	254,
108     STS_ACTIONS_MODE=	253
109 }
110 filter_mode_t;
111 
112 /* logger procedure definition */
113 struct __spamtest_session_t;
114 struct __msg_heap_t;
115 typedef int (* logger_proc)(struct __spamtest_session_t *s,int loglevel,const char * fmt,...);
116 
117 
118 /* this data structure describes header actions to be performed */
119 
120 typedef struct hdraction_t
121 {
122     spamtest_action_t	type;		/* STS_HEADER_ADD/DEL/NEW/CHG */
123     char		*header;	/* header name */
124     char		*value;		/* header value (not useful
125 					   with STS_HEADER_DEL */
126 }
127 hdraction_t;
128 
129 
130 /* describes message status returned by filter */
131 
132 typedef struct message_status_t
133 {
134     spamtest_reply_t	action;		/* STS_ACTION_CHANGE/BOUNCE */
135     char		*mailfrom;	/* Envelope mail from for
136 					   generated message */
137     recipient_list_t	*rcpts;		/* RCPT TO list for message */
138     int			action_count;	/* count for header actions */
139     hdraction_t		*act_array;	/* array of header actions */
140     message_text_t	*bouncemsg;	/* message body for
141 					   STS_ACTION_BOUNCE */
142     /* for internal use */
143     int			action_alloc;
144 } message_status_t;
145 
146 
147 /* this data structure describes spamtest session status */
148 
149 typedef struct
150 {
151     session_status_t	status;		/* CONTINUE/ACCEPT/... */
152 
153     char		*reason;	/* for REJECT/ERROR - message
154 					   to be sent to sender in
155 					   SMTP chat */
156 
157     int			errorcode;	/* filter error code (use
158 					   sts_strerror() for
159 					   explanation */
160 
161     int			count;		/* for ACCEPT status - count
162 					   of generated messages */
163 
164     message_status_t	*ms_array;	/* array of generated message
165 					   statuses */
166     /* for internal use */
167     int			alloc;
168     struct __msg_heap_t *storeptr;
169 }spamtest_status_t;
170 
171 
172 struct __bufio_t;
173 
174 /* spam session definition */
175 typedef struct __spamtest_session_t {
176 
177     /* == THESE PARAMETERS ARE SET BY USER === */
178 
179     char *access_address;	/* "unix:/path/to/socket" or
180 				   "tcp:host:port" */
181     char *mail_domain;		/* default mail domain for address
182 				 * canonification */
183 
184     size_t bufsize;		/* size of read/write buffers, default
185 				 * is 64k */
186 
187     logger_proc logp;		/* logger procedure */
188 
189     long rw_timeout;		/* read/write timeout in milliseconds */
190     long connect_timeout;	/* connect timeout in milliseconds */
191 
192     unsigned int flags;		/* STS_USE_POLL and so on */
193 
194 
195     /* == THESE PARAMETERS SHOULD BE USED BY USER === */
196 
197     spamtest_status_t status;	/* session state (see spamtest_status_t
198 				 * definition for filed description */
199 
200 
201     int recomended_size;	/* recommended data size to send in
202 				   sts_send_body at once */
203 
204     int should_store_message;	/* should user store local copy of
205 				 * message or filter will send mail by
206 				 * itself */
207 
208     char *message_id;		/* Message-ID generated by filter
209 				 * module */
210 
211     /* internal filter data, do not touch */
212     int		filter_fd;
213 //    char	*relay_IP;
214     char	*mail_from;
215     long	timeout_curr;
216     int		timeout_nq;
217     filter_mode_t filter_mode; 		/* SMTP or ACTIONS */
218     recipient_list_t *rcpts;
219     recipient_list_t *attrs;
220     char *record_buf;
221 
222     /* flags */
223     int envelope_sent;			/* 1=envelope already sent to filter*/
224     int header_sent;			/* 1=header already sent to filter*/
225     int body_sent;			/* 1=message body sent to
226 					 * filter (no more
227 					 * transmissions) */
228     int chunk_sent;
229     int rb_ptr;
230     int line_complete;
231     struct timeval tvs;			/* time when current operation
232 					 * start (do not modify!) */
233     /* buffers */
234     struct __bufio_t *bufio;
235     struct __msg_heap_t *store;
236     unsigned char attr_buf[STS_ABUF_S];
237 
238     unsigned int magic;			/* sentinel */
239 } spamtest_session_t;
240 
241 
242 /* ==== LIBRARY CALLS ==== */
243 
244 /* converts numeric STS_* error code into string */
245 const char *sts_strerror(int ercode);
246 
247 /* initialinig and start connection */
248 int sts_init(spamtest_session_t *session);
249 int sts_reuse(spamtest_session_t *session);
250 
251 // use poll instead of select()
252 
253 /*
254    sts_prepare_envelope and others:
255    Initializes part (or full) of message envelope
256    DOES NOT SEND anything to filter, prepare data only
257    sts_prepare_envelope returns additional status in *status field
258 */
259 int sts_set_sender(spamtest_session_t *s, const char *mail_from);
260 int sts_add_recipient(spamtest_session_t *s, const char *rcpt);
261 int sts_set_relay(spamtest_session_t *s, const char *relay_IP);
262 /* all of the above */
263 int sts_prepare_envelope(spamtest_session_t *s,
264 			 const char* mail_from,
265 			 const char * rcpt,
266 			 const char *relay_IP,
267 			 int *stat);
268 
269 int sts_add_attribute(spamtest_session_t *s, const char *attrname, const char *attrval);
270 
271 /*
272   sts_send_body:
273   sends part of mail message to filtering engine.
274 
275   Returns:
276   NULL if invalid or uninitialized session data specified
277   spamtest_status_t* structure overwise
278 
279   msgbody points to part of message data (headers and body),
280   msglen  sets data length
281   flags   parameter is a bit mask with fields:
282 		STS_REINIT_TIMEOUT - reinit timeout, discard old
283 		execution statistics
284 		STS_FLUSH_DATA - force flushing of data to filter and
285 				reanalysing
286 		STS_FINAL_CHUNK - this call of sts_send_body is final
287 		(calls sts_body_end internally)
288 
289 */
290 spamtest_status_t* sts_send_body(spamtest_session_t *session,
291 				 const char *msgbody,
292 				 size_t msglen,
293 				 int flags);
294 
295 /*
296   sts_body_end:
297   flushes I/O buffers and forces filter to return message status
298 
299   Returns:
300   NULL if invalid or uninitialized session data specified
301   spamtest_status_t* structure overwise
302   flags   parameter is a bit mask with fields:
303 		STS_REINIT_TIMEOUT - reinit timeout, discard old
304 		execution statistics
305 		STS_FLUSH_DATA - force flushing of data to filter and
306 				reanalysing
307 
308 */
309 spamtest_status_t* sts_body_end(spamtest_session_t *session,
310 				int flags);
311 
312 /*
313   sts_close:
314   closes all sockets, deallocates all memory.
315   Returns:
316   STS_ERR_ code (use sts_strerror for explanation)
317 */
318 
319 int sts_close(spamtest_session_t *session);
320 void sts_library_init(void);
321 
322 
323 /* === Utility and diagnostic functions === */
324 
325 /* actions/status manip */
326 
327 void dump_message_status(spamtest_status_t *smsg);
328 headers_list_t* make_changed_headers(message_status_t * sts, message_t *message);
329 spamtest_status_t* glue_actions(spamtest_status_t *s);
330 
331 
332 extern int sts_default_logger_log_level;
333 
334 int rfc822_unquote_one(char *dest,unsigned int size, char *from, char *defdomain);
335 int rfc822_quote_one(char *dest,unsigned int size, char *from, char *defdomain);
336 recipient_list_t *rfc822_unquote_list(recipient_list_t *from,char *defdomain);
337 recipient_list_t *rfc822_quote_list(recipient_list_t *from,char *defdomain);
338 
339 
340 #ifdef __cplusplus
341 }
342 #endif
343 
344 #endif /* SPAM_FILTER_LIBRARY */
345