00001 /* <@LICENSE> 00002 * Licensed to the Apache Software Foundation (ASF) under one or more 00003 * contributor license agreements. See the NOTICE file distributed with 00004 * this work for additional information regarding copyright ownership. 00005 * The ASF licenses this file to you under the Apache License, Version 2.0 00006 * (the "License"); you may not use this file except in compliance with 00007 * the License. You may obtain a copy of the License at: 00008 * 00009 * http://www.apache.org/licenses/LICENSE-2.0 00010 * 00011 * Unless required by applicable law or agreed to in writing, software 00012 * distributed under the License is distributed on an "AS IS" BASIS, 00013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 00014 * See the License for the specific language governing permissions and 00015 * limitations under the License. 00016 * </@LICENSE> 00017 */ 00018 #ifndef LIBSPAMC_H 00019 #define LIBSPAMC_H 1 00020 00021 #include <stdio.h> 00022 #include <stdarg.h> 00023 #include <sys/types.h> 00024 #ifdef _WIN32 00025 #ifdef _MSC_VER 00026 /* ignore MSVC++ warnings that are annoying and hard to remove: 00027 4115 named type definition in parentheses 00028 4127 conditional expression is constant 00029 4514 unreferenced inline function removed 00030 4996 deprecated "unsafe" functions (bug 4855) 00031 */ 00032 #pragma warning( disable : 4115 4127 4514 ) 00033 #if (_MSC_VER >= 1400) /* VC8+ */ 00034 #pragma warning( disable : 4996 ) 00035 #endif 00036 00037 #endif 00038 #include <winsock.h> 00039 #else 00040 #include <netdb.h> 00041 #include <sys/socket.h> 00042 #include <netinet/in.h> 00043 /* some platforms (Cygwin) don't implement getaddrinfo */ 00044 #ifdef EAI_AGAIN 00045 #define SPAMC_HAS_ADDRINFO 1 00046 #endif 00047 #endif 00048 00049 #if (defined(_WIN32) || !defined(_SYSEXITS_H)) 00050 /* FIXME: This stuff has to go somewhere else */ 00051 00052 #define EX_OK 0 00053 #define EX_USAGE 64 00054 #define EX_DATAERR 65 00055 #define EX_NOINPUT 66 00056 #define EX_NOUSER 67 00057 #define EX_NOHOST 68 00058 #define EX_UNAVAILABLE 69 00059 #define EX_SOFTWARE 70 00060 #define EX_OSERR 71 00061 #define EX_OSFILE 72 00062 #define EX_CANTCREAT 73 00063 #define EX_IOERR 74 00064 #define EX_TEMPFAIL 75 00065 #define EX_PROTOCOL 76 00066 #define EX_NOPERM 77 00067 #define EX_CONFIG 78 00068 00069 #define STDIN_FILENO 0 00070 #define STDOUT_FILENO 1 00071 00072 /* FIXME: This doesn't belong here either */ 00073 #define LOG_EMERG 0 /* system is unusable */ 00074 #define LOG_ALERT 1 /* action must be taken immediately */ 00075 #define LOG_CRIT 2 /* critical conditions */ 00076 #define LOG_ERR 3 /* error conditions */ 00077 #define LOG_WARNING 4 /* warning conditions */ 00078 #define LOG_NOTICE 5 /* normal but significant condition */ 00079 #define LOG_INFO 6 /* informational */ 00080 #define LOG_DEBUG 7 /* debug-level messages */ 00081 00082 #endif 00083 00084 #define EX_NOTSPAM 0 00085 #define EX_ISSPAM 1 00086 #define EX_TOOBIG 866 00087 00088 /* Aug 14, 2002 bj: Bitflags instead of lots of bool parameters */ 00089 #define SPAMC_MODE_MASK 1 00090 #define SPAMC_RAW_MODE 0 00091 #define SPAMC_BSMTP_MODE 1 00092 00093 #define SPAMC_USE_SSL (1<<27) 00094 #define SPAMC_SAFE_FALLBACK (1<<28) 00095 #define SPAMC_CHECK_ONLY (1<<29) 00096 00097 /* Jan 30, 2003 ym: added reporting options */ 00098 #define SPAMC_REPORT (1<<26) 00099 #define SPAMC_REPORT_IFSPAM (1<<25) 00100 00101 /* Feb 1 2003 jm: might as well fix bug 191 as well */ 00102 #define SPAMC_SYMBOLS (1<<24) 00103 00104 /* 2003/04/16 SJF: randomize hostname order (quasi load balancing) */ 00105 #define SPAMC_RANDOMIZE_HOSTS (1<<23) 00106 00107 /* log to stderr */ 00108 #define SPAMC_LOG_TO_STDERR (1<<22) 00109 00110 /* Nov 24, 2004 NP: added learning support */ 00111 #define SPAMC_LEARN (1<<21) 00112 00113 /* May 5, 2005 NP: added list reporting support */ 00114 #define SPAMC_REPORT_MSG (1<<20) 00115 00116 /* Oct 21, 2005 sidney: added ping test */ 00117 #define SPAMC_PING (1<<19) 00118 00119 /* Jan 1, 2007 sidney: added SSL protocol versions */ 00120 /* no flags means use default of SSL_v23 */ 00121 /* Set both flags to specify TSL_v1 */ 00122 #define SPAMC_SSLV2 (1<<18) 00123 #define SPAMC_SSLV3 (1<<17) 00124 00125 /* Nov 30, 2006 jm: add -z, zlib support */ 00126 #define SPAMC_USE_ZLIB (1<<16) 00127 00128 /* Jan 16, 2007 jm: get markup headers from spamd */ 00129 #define SPAMC_HEADERS (1<<15) 00130 00131 #define SPAMC_MESSAGE_CLASS_SPAM 1 00132 #define SPAMC_MESSAGE_CLASS_HAM 2 00133 00134 #define SPAMC_SET_LOCAL 1 00135 #define SPAMC_SET_REMOTE 2 00136 00137 #define SPAMC_REMOVE_LOCAL 4 00138 #define SPAMC_REMOVE_REMOTE 8 00139 00140 #define SPAMC_MAX_MESSAGE_LEN (256 * 1024 * 1024) /* see bug 4928 */ 00141 00142 /* Aug 14, 2002 bj: A struct for storing a message-in-progress */ 00143 typedef enum 00144 { 00145 MESSAGE_NONE, 00146 MESSAGE_ERROR, 00147 MESSAGE_RAW, 00148 MESSAGE_BSMTP, 00149 MAX_MESSAGE_TYPE 00150 } message_type_t; 00151 00152 struct libspamc_private_message; 00153 00154 struct message 00155 { 00156 /* Set before passing the struct on! */ 00157 unsigned int max_len; /* messages larger than this will return EX_TOOBIG */ 00158 int timeout; /* timeout for read() system calls */ 00159 00160 /* Filled in by message_read */ 00161 message_type_t type; 00162 char *raw; 00163 int raw_len; /* Raw message buffer */ 00164 /* note: do not make "raw_len" in particular unsigned! see bug 4593 */ 00165 char *pre; 00166 int pre_len; /* Pre-message data (e.g. SMTP commands) */ 00167 char *msg; 00168 int msg_len; /* The message */ 00169 char *post; 00170 int post_len; /* Post-message data (e.g. SMTP commands) */ 00171 int content_length; 00172 00173 /* Filled in by filter_message */ 00174 int is_spam; /* EX_ISSPAM if the message is spam, EX_NOTSPAM 00175 if not */ 00176 float score, threshold; /* score and threshold */ 00177 char *outbuf; /* Buffer for output from spamd */ 00178 char *out; 00179 int out_len; /* Output from spamd. Either the filtered 00180 message, or the check-only response. Or else, 00181 a pointer to msg above. */ 00182 00183 /* these members added in SpamAssassin version 2.60: */ 00184 struct libspamc_private_message *priv; 00185 }; 00186 00187 /*------------------------------------------------------------------------ 00188 * TRANSPORT (2004/04/16 - SJF) 00189 * 00190 * The code to connect with the daemon has gotten more complicated: support 00191 * for SSL, fallback to multiple hosts, and using UNIX domain sockets. The 00192 * code has gotten ugly with way too many parameters being passed all around. 00193 * 00194 * So we've created this object to hold all the info required to connect with 00195 * the remote site, including a self-contained list of all the IP addresses 00196 * in the event this is using TCP sockets. These multiple IPs can be obtained 00197 * only from DNS returning more than one A record for a single name, and 00198 * this allows for fallback. 00199 * 00200 * We also allow a kind of quasi-load balancing, where we take the list of 00201 * A records from DNS and randomize them before starting out - this lets 00202 * us spread the load out among multiple servers if desired. The idea for 00203 * load balancing goes to Jeremy Zawodny. 00204 * 00205 * By putting all our data here, we remove "fallback" from being a special 00206 * case. We may find ourselves with several IP addresses, but if the user 00207 * disables fallback, we set the IP address count to one. Now the connect 00208 * code just loops over that same address. 00209 */ 00210 #define TRANSPORT_LOCALHOST 0x01 /* TCP to localhost only */ 00211 #define TRANSPORT_TCP 0x02 /* standard TCP socket */ 00212 #define TRANSPORT_UNIX 0x03 /* UNIX domain socket */ 00213 00214 #define TRANSPORT_MAX_HOSTS 256 /* max hosts we can failover between */ 00215 00216 struct transport 00217 { 00218 int type; 00219 00220 const char *socketpath; /* for UNIX dommain socket */ 00221 const char *hostname; /* for TCP sockets */ 00222 00223 unsigned short port; /* for TCP sockets */ 00224 00225 #ifdef SPAMC_HAS_ADDRINFO 00226 struct addrinfo *hosts[TRANSPORT_MAX_HOSTS]; 00227 #else 00228 struct in_addr hosts[TRANSPORT_MAX_HOSTS]; 00229 #endif 00230 int nhosts; 00231 int flags; 00232 00233 /* added in SpamAssassin 3.2.0 */ 00234 int connect_retries; 00235 int retry_sleep; 00236 }; 00237 00238 /* Initialise and setup transport-specific context for the connection 00239 * to spamd. Note that this may leak a small amount of string data for 00240 * the remote hostname (bug 5531) if called repeatedly; SpamAssassin 00241 * 3.3.0 will include a new API to free this leakage. */ 00242 extern void transport_init(struct transport *tp); 00243 extern int transport_setup(struct transport *tp, int flags); 00244 00245 /* Aug 14, 2002 bj: New interface functions */ 00246 00247 /* Read in a message from the fd, with the mode specified in the flags. 00248 * Returns EX_OK on success, EX_otherwise on failure. On failure, m may be 00249 * either MESSAGE_NONE or MESSAGE_ERROR. */ 00250 int message_read(int in_fd, int flags, struct message *m); 00251 00252 /* Write out a message to the fd, as specified by m->type. Note that 00253 * MESSAGE_NONE messages have nothing to write. Also note that if you ran the 00254 * message through message_filter with SPAMC_CHECK_ONLY, it will only output 00255 * the "score/threshold" line. */ 00256 long message_write(int out_fd, struct message *m); 00257 00258 /* Process the message through the spamd filter, making as many connection 00259 * attempts as are implied by the transport structure. To make this do 00260 * failover, more than one host is defined, but if there is only one there, 00261 * no failover is done. 00262 */ 00263 int message_filter(struct transport *tp, const char *username, 00264 int flags, struct message *m); 00265 00266 /* Process the message through the spamd tell command, making as many 00267 * connection attempts as are implied by the transport structure. To make 00268 * this do failover, more than one host is defined, but if there is only 00269 * one there, no failover is done. 00270 */ 00271 int message_tell(struct transport *tp, const char *username, int flags, 00272 struct message *m, int msg_class, 00273 unsigned int tellflags, unsigned int *didtellflags); 00274 00275 /* Dump the message. If there is any data in the message (typically, m->type 00276 * will be MESSAGE_ERROR) it will be message_writed. Then, fd_in will be piped 00277 * to fd_out intol EOF. This is particularly useful if you get back an 00278 * EX_TOOBIG. */ 00279 void message_dump(int in_fd, int out_fd, struct message *m); 00280 00281 /* Do a message_read->message_filter->message_write sequence, handling errors 00282 * appropriately with dump_message or appropriate CHECK_ONLY output. Returns 00283 * EX_OK or EX_ISSPAM/EX_NOTSPAM on success, some error EX on error. */ 00284 int message_process(struct transport *trans, char *username, int max_size, 00285 int in_fd, int out_fd, const int flags); 00286 00287 /* Cleanup the resources we allocated for storing the message. Call after 00288 * you're done processing. */ 00289 void message_cleanup(struct message *m); 00290 00291 /* Aug 14, 2002 bj: This is now legacy, don't use it. */ 00292 int process_message(struct transport *tp, char *username, 00293 int max_size, int in_fd, int out_fd, 00294 const int check_only, const int safe_fallback); 00295 00296 void libspamc_log(int flags, int level, char *msg, ...); 00297 00298 #endif