2 * Licensed to the Apache Software Foundation (ASF) under one or more
3 * contributor license agreements. See the NOTICE file distributed with
4 * this work for additional information regarding copyright ownership.
5 * The ASF licenses this file to you under the Apache License, Version 2.0
6 * (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at:
9 * http://www.apache.org/licenses/LICENSE-2.0
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
23 #include <sys/types.h>
26 /* ignore MSVC++ warnings that are annoying and hard to remove:
27 4115 named type definition in parentheses
28 4127 conditional expression is constant
29 4514 unreferenced inline function removed
30 4996 deprecated "unsafe" functions (bug 4855)
32 #pragma warning( disable : 4115 4127 4514 )
33 #if (_MSC_VER >= 1400) /* VC8+ */
34 #pragma warning( disable : 4996 )
41 #include <sys/socket.h>
42 #include <netinet/in.h>
43 /* some platforms (Cygwin) don't implement getaddrinfo */
45 #define SPAMC_HAS_ADDRINFO 1
49 #if (defined(_WIN32) || !defined(_SYSEXITS_H))
50 /* FIXME: This stuff has to go somewhere else */
58 #define EX_UNAVAILABLE 69
59 #define EX_SOFTWARE 70
62 #define EX_CANTCREAT 73
64 #define EX_TEMPFAIL 75
65 #define EX_PROTOCOL 76
69 #define STDIN_FILENO 0
70 #define STDOUT_FILENO 1
72 /* FIXME: This doesn't belong here either */
73 #define LOG_EMERG 0 /* system is unusable */
74 #define LOG_ALERT 1 /* action must be taken immediately */
75 #define LOG_CRIT 2 /* critical conditions */
76 #define LOG_ERR 3 /* error conditions */
77 #define LOG_WARNING 4 /* warning conditions */
78 #define LOG_NOTICE 5 /* normal but significant condition */
79 #define LOG_INFO 6 /* informational */
80 #define LOG_DEBUG 7 /* debug-level messages */
88 /* Aug 14, 2002 bj: Bitflags instead of lots of bool parameters */
89 #define SPAMC_MODE_MASK 1
90 #define SPAMC_RAW_MODE 0
91 #define SPAMC_BSMTP_MODE 1
93 #define SPAMC_USE_INET6 (1<<31)
94 #define SPAMC_USE_INET4 (1<<30)
96 #define SPAMC_CHECK_ONLY (1<<29)
97 #define SPAMC_SAFE_FALLBACK (1<<28)
98 #define SPAMC_USE_SSL (1<<27)
100 /* Jan 30, 2003 ym: added reporting options */
101 #define SPAMC_REPORT (1<<26)
102 #define SPAMC_REPORT_IFSPAM (1<<25)
104 /* Feb 1 2003 jm: might as well fix bug 191 as well */
105 #define SPAMC_SYMBOLS (1<<24)
107 /* 2003/04/16 SJF: randomize hostname order (quasi load balancing) */
108 #define SPAMC_RANDOMIZE_HOSTS (1<<23)
111 #define SPAMC_LOG_TO_STDERR (1<<22)
113 /* Nov 24, 2004 NP: added learning support */
114 #define SPAMC_LEARN (1<<21)
116 /* May 5, 2005 NP: added list reporting support */
117 #define SPAMC_REPORT_MSG (1<<20)
119 /* Oct 21, 2005 sidney: added ping test */
120 #define SPAMC_PING (1<<19)
122 /* Jan 1, 2007 sidney: added SSL protocol versions */
123 /* no flags means use default of SSL_v23 */
124 /* Set both flags to specify TSL_v1 */
125 #define SPAMC_TLSV1 (1<<18)
126 #define SPAMC_SSLV3 (1<<17)
128 /* Nov 30, 2006 jm: add -z, zlib support */
129 #define SPAMC_USE_ZLIB (1<<16)
131 /* Jan 16, 2007 jm: get markup headers from spamd */
132 #define SPAMC_HEADERS (1<<15)
134 /* December 5, 2007 duncf: send log messages to callback */
135 #define SPAMC_LOG_TO_CALLBACK (1<<14)
137 /* December 6, 2011 Sebastian Wiesinger <sebastian@karotte.org>:
138 * Turn EX_UNAVAILABLE into EX_TEMPFAIL - bug 6717
140 #define SPAMC_UNAVAIL_TEMPFAIL (1<<13)
142 #define SPAMC_MESSAGE_CLASS_SPAM 1
143 #define SPAMC_MESSAGE_CLASS_HAM 2
145 #define SPAMC_SET_LOCAL 1
146 #define SPAMC_SET_REMOTE 2
148 #define SPAMC_REMOVE_LOCAL 4
149 #define SPAMC_REMOVE_REMOTE 8
151 #define SPAMC_MAX_MESSAGE_LEN (256 * 1024 * 1024) /* see bug 4928 */
153 /* Aug 14, 2002 bj: A struct for storing a message-in-progress */
163 struct libspamc_private_message
;
167 /* Set before passing the struct on! */
168 unsigned int max_len
; /* messages larger than this will return EX_TOOBIG */
169 int timeout
; /* timeout for read() system calls */
170 int connect_timeout
; /* Sep 8, 2008 mrgus: timeout for opening sockets */
172 /* Filled in by message_read */
175 int raw_len
; /* Raw message buffer */
176 /* note: do not make "raw_len" in particular unsigned! see bug 4593 */
178 int pre_len
; /* Pre-message data (e.g. SMTP commands) */
180 int msg_len
; /* The message */
182 int post_len
; /* Post-message data (e.g. SMTP commands) */
185 /* Filled in by filter_message */
186 int is_spam
; /* EX_ISSPAM if the message is spam, EX_NOTSPAM
188 float score
, threshold
; /* score and threshold */
189 char *outbuf
; /* Buffer for output from spamd */
191 int out_len
; /* Output from spamd. Either the filtered
192 message, or the check-only response. Or else,
193 a pointer to msg above. */
195 /* these members added in SpamAssassin version 2.60: */
196 struct libspamc_private_message
*priv
;
199 /*------------------------------------------------------------------------
200 * TRANSPORT (2004/04/16 - SJF)
202 * The code to connect with the daemon has gotten more complicated: support
203 * for SSL, fallback to multiple hosts, and using UNIX domain sockets. The
204 * code has gotten ugly with way too many parameters being passed all around.
206 * So we've created this object to hold all the info required to connect with
207 * the remote site, including a self-contained list of all the IP addresses
208 * in the event this is using TCP sockets. These multiple IPs can be obtained
209 * only from DNS returning more than one A record for a single name, and
210 * this allows for fallback.
212 * We also allow a kind of quasi-load balancing, where we take the list of
213 * A records from DNS and randomize them before starting out - this lets
214 * us spread the load out among multiple servers if desired. The idea for
215 * load balancing goes to Jeremy Zawodny.
217 * By putting all our data here, we remove "fallback" from being a special
218 * case. We may find ourselves with several IP addresses, but if the user
219 * disables fallback, we set the IP address count to one. Now the connect
220 * code just loops over that same address.
222 #define TRANSPORT_LOCALHOST 0x01 /* TCP to localhost only */
223 #define TRANSPORT_TCP 0x02 /* standard TCP socket */
224 #define TRANSPORT_UNIX 0x03 /* UNIX domain socket */
226 #define TRANSPORT_MAX_HOSTS 256 /* max hosts we can failover between */
232 const char *socketpath
; /* for UNIX dommain socket */
233 const char *hostname
; /* for TCP sockets */
235 unsigned short port
; /* for TCP sockets */
237 #ifdef SPAMC_HAS_ADDRINFO
238 struct addrinfo
*hosts
[TRANSPORT_MAX_HOSTS
];
240 struct in_addr hosts
[TRANSPORT_MAX_HOSTS
];
245 /* added in SpamAssassin 3.2.0 */
249 /* Added for filterloop */
251 int filter_retry_sleep
;
254 /* Initialise and setup transport-specific context for the connection
255 * to spamd. Note that this may leak a small amount of string data for
256 * the remote hostname (bug 5531) if called repeatedly; use
257 * transport_cleanup() to clean this up. */
258 extern void transport_init(struct transport
*tp
);
259 extern int transport_setup(struct transport
*tp
, int flags
);
261 /* Aug 14, 2002 bj: New interface functions */
263 /* Read in a message from the fd, with the mode specified in the flags.
264 * Returns EX_OK on success, EX_otherwise on failure. On failure, m may be
265 * either MESSAGE_NONE or MESSAGE_ERROR. */
266 int message_read(int in_fd
, int flags
, struct message
*m
);
268 /* Write out a message to the fd, as specified by m->type. Note that
269 * MESSAGE_NONE messages have nothing to write. Also note that if you ran the
270 * message through message_filter with SPAMC_CHECK_ONLY, it will only output
271 * the "score/threshold" line. */
272 long message_write(int out_fd
, struct message
*m
);
274 /* Process the message through the spamd filter, making as many connection
275 * attempts as are implied by the transport structure. To make this do
276 * failover, more than one host is defined, but if there is only one there,
277 * no failover is done.
279 int message_filter(struct transport
*tp
, const char *username
,
280 int flags
, struct message
*m
);
282 /* Process the message through the spamd tell command, making as many
283 * connection attempts as are implied by the transport structure. To make
284 * this do failover, more than one host is defined, but if there is only
285 * one there, no failover is done.
287 int message_tell(struct transport
*tp
, const char *username
, int flags
,
288 struct message
*m
, int msg_class
,
289 unsigned int tellflags
, unsigned int *didtellflags
);
291 /* Dump the message. If there is any data in the message (typically, m->type
292 * will be MESSAGE_ERROR) it will be message_writed. Then, fd_in will be piped
293 * to fd_out intol EOF. This is particularly useful if you get back an
295 void message_dump(int in_fd
, int out_fd
, struct message
*m
, int flags
);
297 /* Do a message_read->message_filter->message_write sequence, handling errors
298 * appropriately with dump_message or appropriate CHECK_ONLY output. Returns
299 * EX_OK or EX_ISSPAM/EX_NOTSPAM on success, some error EX on error. */
300 int message_process(struct transport
*trans
, char *username
, int max_size
,
301 int in_fd
, int out_fd
, const int flags
);
303 /* Cleanup the resources we allocated for storing the message. Call after
304 * you're done processing. */
305 void message_cleanup(struct message
*m
);
307 /* Aug 14, 2002 bj: This is now legacy, don't use it. */
308 int process_message(struct transport
*tp
, char *username
,
309 int max_size
, int in_fd
, int out_fd
,
310 const int check_only
, const int safe_fallback
);
312 void register_spamc_header_callback(const struct message
*m
, void (*func
)(struct message
*m
, int flags
, char *buf
, int len
));
313 void register_spamd_header_callback(const struct message
*m
, void (*func
)(struct message
*m
, int flags
, const char *buf
, int len
));
315 void register_libspamc_log_callback(void (*function
)(int flags
, int level
, char *msg
, va_list args
));
317 void libspamc_log(int flags
, int level
, char *msg
, ...);
319 /* Cleanup the resources allocated for storing details of the transport.
320 * Added in SpamAssassin 3.3.0. */
321 void transport_cleanup(struct transport
*tp
);
323 /* define a preprocessor symbol so that calling code can tell if the
324 * transport_cleanup() API function is available. */
325 #define SPAMC_HAS_TRANSPORT_CLEANUP