| /* <@LICENSE> |
| * Licensed to the Apache Software Foundation (ASF) under one or more |
| * contributor license agreements. See the NOTICE file distributed with |
| * this work for additional information regarding copyright ownership. |
| * The ASF licenses this file to you under the Apache License, Version 2.0 |
| * (the "License"); you may not use this file except in compliance with |
| * the License. You may obtain a copy of the License at: |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| * </@LICENSE> |
| */ |
| #ifndef LIBSPAMC_H |
| #define LIBSPAMC_H 1 |
| |
| #include <stdio.h> |
| #include <stdarg.h> |
| #include <sys/types.h> |
| #ifdef _WIN32 |
| #ifdef _MSC_VER |
| /* ignore MSVC++ warnings that are annoying and hard to remove: |
| 4115 named type definition in parentheses |
| 4127 conditional expression is constant |
| 4514 unreferenced inline function removed |
| 4996 deprecated "unsafe" functions (bug 4855) |
| */ |
| #pragma warning( disable : 4115 4127 4514 ) |
| #if (_MSC_VER >= 1400) /* VC8+ */ |
| #pragma warning( disable : 4996 ) |
| #endif |
| |
| #endif |
| #include <winsock.h> |
| #else |
| #include <netdb.h> |
| #include <sys/socket.h> |
| #include <netinet/in.h> |
| /* some platforms (Cygwin) don't implement getaddrinfo */ |
| #ifdef EAI_AGAIN |
| #define SPAMC_HAS_ADDRINFO 1 |
| #endif |
| #endif |
| |
| #if (defined(_WIN32) || !defined(_SYSEXITS_H)) |
| /* FIXME: This stuff has to go somewhere else */ |
| |
| #define EX_OK 0 |
| #define EX_USAGE 64 |
| #define EX_DATAERR 65 |
| #define EX_NOINPUT 66 |
| #define EX_NOUSER 67 |
| #define EX_NOHOST 68 |
| #define EX_UNAVAILABLE 69 |
| #define EX_SOFTWARE 70 |
| #define EX_OSERR 71 |
| #define EX_OSFILE 72 |
| #define EX_CANTCREAT 73 |
| #define EX_IOERR 74 |
| #define EX_TEMPFAIL 75 |
| #define EX_PROTOCOL 76 |
| #define EX_NOPERM 77 |
| #define EX_CONFIG 78 |
| |
| #define STDIN_FILENO 0 |
| #define STDOUT_FILENO 1 |
| |
| /* FIXME: This doesn't belong here either */ |
| #define LOG_EMERG 0 /* system is unusable */ |
| #define LOG_ALERT 1 /* action must be taken immediately */ |
| #define LOG_CRIT 2 /* critical conditions */ |
| #define LOG_ERR 3 /* error conditions */ |
| #define LOG_WARNING 4 /* warning conditions */ |
| #define LOG_NOTICE 5 /* normal but significant condition */ |
| #define LOG_INFO 6 /* informational */ |
| #define LOG_DEBUG 7 /* debug-level messages */ |
| |
| #endif |
| |
| #define EX_NOTSPAM 0 |
| #define EX_ISSPAM 1 |
| #define EX_TOOBIG 866 |
| |
| /* Aug 14, 2002 bj: Bitflags instead of lots of bool parameters */ |
| #define SPAMC_MODE_MASK 1 |
| #define SPAMC_RAW_MODE 0 |
| #define SPAMC_BSMTP_MODE 1 |
| |
| #define SPAMC_USE_INET6 (1<<31) |
| #define SPAMC_USE_INET4 (1<<30) |
| |
| #define SPAMC_CHECK_ONLY (1<<29) |
| #define SPAMC_SAFE_FALLBACK (1<<28) |
| #define SPAMC_USE_SSL (1<<27) |
| |
| /* Jan 30, 2003 ym: added reporting options */ |
| #define SPAMC_REPORT (1<<26) |
| #define SPAMC_REPORT_IFSPAM (1<<25) |
| |
| /* Feb 1 2003 jm: might as well fix bug 191 as well */ |
| #define SPAMC_SYMBOLS (1<<24) |
| |
| /* 2003/04/16 SJF: randomize hostname order (quasi load balancing) */ |
| #define SPAMC_RANDOMIZE_HOSTS (1<<23) |
| |
| /* log to stderr */ |
| #define SPAMC_LOG_TO_STDERR (1<<22) |
| |
| /* Nov 24, 2004 NP: added learning support */ |
| #define SPAMC_LEARN (1<<21) |
| |
| /* May 5, 2005 NP: added list reporting support */ |
| #define SPAMC_REPORT_MSG (1<<20) |
| |
| /* Oct 21, 2005 sidney: added ping test */ |
| #define SPAMC_PING (1<<19) |
| |
| /* Jan 1, 2007 sidney: added SSL protocol versions */ |
| /* no flags means use default of SSL_v23 */ |
| /* Set both flags to specify TSL_v1 */ |
| #define SPAMC_TLSV1 (1<<18) |
| #define SPAMC_SSLV3 (1<<17) |
| |
| /* Nov 30, 2006 jm: add -z, zlib support */ |
| #define SPAMC_USE_ZLIB (1<<16) |
| |
| /* Jan 16, 2007 jm: get markup headers from spamd */ |
| #define SPAMC_HEADERS (1<<15) |
| |
| /* December 5, 2007 duncf: send log messages to callback */ |
| #define SPAMC_LOG_TO_CALLBACK (1<<14) |
| |
| /* December 6, 2011 Sebastian Wiesinger <sebastian@karotte.org>: |
| * Turn EX_UNAVAILABLE into EX_TEMPFAIL - bug 6717 |
| * */ |
| #define SPAMC_UNAVAIL_TEMPFAIL (1<<13) |
| |
| #define SPAMC_MESSAGE_CLASS_SPAM 1 |
| #define SPAMC_MESSAGE_CLASS_HAM 2 |
| |
| #define SPAMC_SET_LOCAL 1 |
| #define SPAMC_SET_REMOTE 2 |
| |
| #define SPAMC_REMOVE_LOCAL 4 |
| #define SPAMC_REMOVE_REMOTE 8 |
| |
| #define SPAMC_MAX_MESSAGE_LEN (256 * 1024 * 1024) /* see bug 4928 */ |
| |
| /* Aug 14, 2002 bj: A struct for storing a message-in-progress */ |
| typedef enum |
| { |
| MESSAGE_NONE, |
| MESSAGE_ERROR, |
| MESSAGE_RAW, |
| MESSAGE_BSMTP, |
| MAX_MESSAGE_TYPE |
| } message_type_t; |
| |
| struct libspamc_private_message; |
| |
| struct message |
| { |
| /* Set before passing the struct on! */ |
| unsigned int max_len; /* messages larger than this will return EX_TOOBIG */ |
| int timeout; /* timeout for read() system calls */ |
| int connect_timeout; /* Sep 8, 2008 mrgus: timeout for opening sockets */ |
| |
| /* Filled in by message_read */ |
| message_type_t type; |
| char *raw; |
| int raw_len; /* Raw message buffer */ |
| /* note: do not make "raw_len" in particular unsigned! see bug 4593 */ |
| char *pre; |
| int pre_len; /* Pre-message data (e.g. SMTP commands) */ |
| char *msg; |
| int msg_len; /* The message */ |
| char *post; |
| int post_len; /* Post-message data (e.g. SMTP commands) */ |
| int content_length; |
| |
| /* Filled in by filter_message */ |
| int is_spam; /* EX_ISSPAM if the message is spam, EX_NOTSPAM |
| if not */ |
| float score, threshold; /* score and threshold */ |
| char *outbuf; /* Buffer for output from spamd */ |
| char *out; |
| int out_len; /* Output from spamd. Either the filtered |
| message, or the check-only response. Or else, |
| a pointer to msg above. */ |
| |
| /* these members added in SpamAssassin version 2.60: */ |
| struct libspamc_private_message *priv; |
| }; |
| |
| /*------------------------------------------------------------------------ |
| * TRANSPORT (2004/04/16 - SJF) |
| * |
| * The code to connect with the daemon has gotten more complicated: support |
| * for SSL, fallback to multiple hosts, and using UNIX domain sockets. The |
| * code has gotten ugly with way too many parameters being passed all around. |
| * |
| * So we've created this object to hold all the info required to connect with |
| * the remote site, including a self-contained list of all the IP addresses |
| * in the event this is using TCP sockets. These multiple IPs can be obtained |
| * only from DNS returning more than one A record for a single name, and |
| * this allows for fallback. |
| * |
| * We also allow a kind of quasi-load balancing, where we take the list of |
| * A records from DNS and randomize them before starting out - this lets |
| * us spread the load out among multiple servers if desired. The idea for |
| * load balancing goes to Jeremy Zawodny. |
| * |
| * By putting all our data here, we remove "fallback" from being a special |
| * case. We may find ourselves with several IP addresses, but if the user |
| * disables fallback, we set the IP address count to one. Now the connect |
| * code just loops over that same address. |
| */ |
| #define TRANSPORT_LOCALHOST 0x01 /* TCP to localhost only */ |
| #define TRANSPORT_TCP 0x02 /* standard TCP socket */ |
| #define TRANSPORT_UNIX 0x03 /* UNIX domain socket */ |
| |
| #define TRANSPORT_MAX_HOSTS 256 /* max hosts we can failover between */ |
| |
| struct transport |
| { |
| int type; |
| |
| const char *socketpath; /* for UNIX dommain socket */ |
| const char *hostname; /* for TCP sockets */ |
| |
| unsigned short port; /* for TCP sockets */ |
| |
| #ifdef SPAMC_HAS_ADDRINFO |
| struct addrinfo *hosts[TRANSPORT_MAX_HOSTS]; |
| #else |
| struct in_addr hosts[TRANSPORT_MAX_HOSTS]; |
| #endif |
| int nhosts; |
| int flags; |
| |
| /* added in SpamAssassin 3.2.0 */ |
| int connect_retries; |
| int retry_sleep; |
| |
| /* Added for filterloop */ |
| int filter_retries; |
| int filter_retry_sleep; |
| }; |
| |
| /* Initialise and setup transport-specific context for the connection |
| * to spamd. Note that this may leak a small amount of string data for |
| * the remote hostname (bug 5531) if called repeatedly; use |
| * transport_cleanup() to clean this up. */ |
| extern void transport_init(struct transport *tp); |
| extern int transport_setup(struct transport *tp, int flags); |
| |
| /* Aug 14, 2002 bj: New interface functions */ |
| |
| /* Read in a message from the fd, with the mode specified in the flags. |
| * Returns EX_OK on success, EX_otherwise on failure. On failure, m may be |
| * either MESSAGE_NONE or MESSAGE_ERROR. */ |
| int message_read(int in_fd, int flags, struct message *m); |
| |
| /* Write out a message to the fd, as specified by m->type. Note that |
| * MESSAGE_NONE messages have nothing to write. Also note that if you ran the |
| * message through message_filter with SPAMC_CHECK_ONLY, it will only output |
| * the "score/threshold" line. */ |
| long message_write(int out_fd, struct message *m); |
| |
| /* Process the message through the spamd filter, making as many connection |
| * attempts as are implied by the transport structure. To make this do |
| * failover, more than one host is defined, but if there is only one there, |
| * no failover is done. |
| */ |
| int message_filter(struct transport *tp, const char *username, |
| int flags, struct message *m); |
| |
| /* Process the message through the spamd tell command, making as many |
| * connection attempts as are implied by the transport structure. To make |
| * this do failover, more than one host is defined, but if there is only |
| * one there, no failover is done. |
| */ |
| int message_tell(struct transport *tp, const char *username, int flags, |
| struct message *m, int msg_class, |
| unsigned int tellflags, unsigned int *didtellflags); |
| |
| /* Dump the message. If there is any data in the message (typically, m->type |
| * will be MESSAGE_ERROR) it will be message_writed. Then, fd_in will be piped |
| * to fd_out intol EOF. This is particularly useful if you get back an |
| * EX_TOOBIG. */ |
| void message_dump(int in_fd, int out_fd, struct message *m, int flags); |
| |
| /* Do a message_read->message_filter->message_write sequence, handling errors |
| * appropriately with dump_message or appropriate CHECK_ONLY output. Returns |
| * EX_OK or EX_ISSPAM/EX_NOTSPAM on success, some error EX on error. */ |
| int message_process(struct transport *trans, char *username, int max_size, |
| int in_fd, int out_fd, const int flags); |
| |
| /* Cleanup the resources we allocated for storing the message. Call after |
| * you're done processing. */ |
| void message_cleanup(struct message *m); |
| |
| /* Aug 14, 2002 bj: This is now legacy, don't use it. */ |
| int process_message(struct transport *tp, char *username, |
| int max_size, int in_fd, int out_fd, |
| const int check_only, const int safe_fallback); |
| |
| void register_spamc_header_callback(const struct message *m, void (*func)(struct message *m, int flags, char *buf, int len)); |
| void register_spamd_header_callback(const struct message *m, void (*func)(struct message *m, int flags, const char *buf, int len)); |
| |
| void register_libspamc_log_callback(void (*function)(int flags, int level, char *msg, va_list args)); |
| |
| void libspamc_log(int flags, int level, char *msg, ...); |
| |
| /* Cleanup the resources allocated for storing details of the transport. |
| * Added in SpamAssassin 3.3.0. */ |
| void transport_cleanup(struct transport *tp); |
| |
| /* define a preprocessor symbol so that calling code can tell if the |
| * transport_cleanup() API function is available. */ |
| #define SPAMC_HAS_TRANSPORT_CLEANUP |
| |
| #endif |