diff -urN Local.orig/kas_exim.c Local/kas_exim.c --- Local.orig/kas_exim.c Wed Jan 3 00:02:52 2007 +++ Local/kas_exim.c Wed Jan 3 00:11:12 2007 @@ -0,0 +1,871 @@ + +#include "local_scan.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include "spamtest.h" +#include "msgstore.h" + +//#define SPAMTEST_USE_SYSLOG + +/* Default values for configuration options */ +#define KAS_CONNECT_TIMEOUT 60000 +#define KAS_DEFAULT_DOMAIN "" +#define KAS_LOG_LEVEL 0 +#define KAS_ON_ERROR "tempfail" +#define KAS_DATA_TIMEOUT 60000 +#define KAS_CONNECT_TO "tcp:127.0.0.1:2277" +#define KAS_FILTERING_SIZE_LIMIT 512 + +/* Result variables for configuration options */ +static uschar *result_default_domain; +static uschar *result_connect_to; +static uschar *result_on_error_str; +static int result_on_error; + +/* Configuration options */ +//old +static int st_connect_timeout = 0; +static int debug_level = 0; +static int st_rw_timeout = 0; +static int filtering_size_limit=0; +static uschar *st_mail_domain; +static uschar *st_on_error; +static uschar *st_address; +//new +static int kas_connect_timeout = 0; +static int kas_log_level = 0; +static int kas_data_timeout = 0; +static int kas_filtering_size_limit = 0; +static uschar *kas_default_domain; +static uschar *kas_on_error; +static uschar *kas_connect_to; + +optionlist local_scan_options[] = +{/* The entries must appear in alphabetical order */ + { "connect_timeout", opt_int, &st_connect_timeout }, + { "kas_connect_timeout", opt_int, &kas_connect_timeout }, + { "kas_connect_to", opt_stringptr, &kas_connect_to }, + { "kas_data_timeout", opt_int, &kas_data_timeout }, + { "kas_default_domain", opt_stringptr, &kas_default_domain }, + { "kas_filtering_size_limit", opt_int, &kas_filtering_size_limit }, + { "kas_log_level",opt_int,&kas_log_level}, + { "kas_on_error",opt_stringptr,&kas_on_error}, + { "local_mail_domain", opt_stringptr, &st_mail_domain }, + { "log_level",opt_int,&debug_level}, + { "on_spamtest_error",opt_stringptr,&st_on_error}, + { "rw_timeout", opt_int, &st_rw_timeout }, + { "spamtest_address", opt_stringptr, &st_address }, + { "spamtest_filtering_size_limit", opt_int, &filtering_size_limit }, +}; + +int local_scan_options_count = sizeof(local_scan_options)/sizeof(optionlist); + + +int check_results(spamtest_session_t *s,spamtest_status_t *status,int *res,int fd,uschar **return_text); +int proceed_accept(spamtest_status_t *status,int fd); +void logger(const int log_level,const char *fmt,...); +void prepare_config_parameters(); +void free_conf(); + + +int local_scan(int fd, uschar **return_text) +{ + int myfd; + char buf[4096]; + int cnt = 0; + int totalcnt = 0; + int i; + header_line * tmp; + spamtest_session_t s; + int errorcode = STS_ERR_NO_ERR; + spamtest_status_t *status = NULL; + int rcpt_sent = 0; + int res = 0; + int rest = 0; + char *ctmp; + + /* Initialize spamtest session */ + + prepare_config_parameters(); + + if(filtering_size_limit > 0) + { + struct stat sb; + fstat(fd,&sb); + if(sb.st_size > filtering_size_limit * 1024) + { + logger(LOG_DEBUG," Message larger than filtering_size_limit, accepting"); + free_conf(); + return LOCAL_SCAN_ACCEPT; + } + } + + bzero(&s,sizeof(s)); + s.access_address = result_connect_to; + s.rw_timeout = st_rw_timeout; + s.connect_timeout = st_connect_timeout; + s.mail_domain = result_default_domain; + + if ( s.access_address == NULL || s.access_address[0] == '\0' ) + { + logger(LOG_ERR," Spamtest access address not defined, cannot process mail by spam filtering"); + free_conf(); + return LOCAL_SCAN_ACCEPT; + } + + logger(LOG_DEBUG," Spam test session: %s %s %d %d",s.access_address,s.mail_domain,s.connect_timeout,s.rw_timeout); + + if ( (errorcode = sts_init(&s)) < 0 ) + { + logger(LOG_ERR," Unable to connect to %s (%s)",s.access_address,sts_strerror(errorcode)); + free_conf(); + return result_on_error; + }; + + if ( ! s.should_store_message ) + { + /* SMTP mode, blackholing message because filter will send message */ + logger(LOG_ERR," Filter in SMTP mode, Incorrect situation."); + //recipients_count = 0; + sts_close(&s); + free_conf(); + return result_on_error; + } + + if ( sender_address != NULL && sender_address[0] != '\0' ) + { + if ( (errorcode = sts_set_sender(&s,sender_address)) != STS_ERR_NO_ERR ) + { + logger(LOG_ERR," Unable to pass sender address %s(%d)",sender_address,errorcode); + free_conf(); + return result_on_error; + } + } + + if ( sender_host_address != NULL && sender_host_address[0] != '\0' ) + { + if ( ( errorcode = sts_set_relay(&s,sender_host_address) ) != STS_ERR_NO_ERR ) + { + logger(LOG_ERR," Unable to pass relay IP"); + if(errorcode == STS_ERR_OUT_OF_MEMORY){ + free_conf(); + return result_on_error; + } + } + } + + rcpt_sent = 0; + for ( i = 0;itype != '*') + { + logger(LOG_DEBUG,"Iterating a , %c %d %s|%d",tmp->type,tmp->slen,tmp->text,tmp->text[tmp->slen-1]); + if ( ( status = sts_send_body(&s,tmp->text,tmp->slen,STS_REINIT_TIMEOUT) ) == NULL ) + { + /* failure. finish proceed */ + logger(LOG_ERR," NULL status after sending header %s",tmp->text); + sts_close(&s); + } + else + { /* check status and finish if need */ + logger(LOG_DEBUG," header %s sent to filter",tmp->text); + if ( check_results(&s,status,&res,fd,return_text) > 0 ){ + free_conf(); + return res; + } + } + } + if(tmp==header_last) + break; + tmp = tmp->next; + } + + logger(LOG_DEBUG," Headers sent"); + + if ( ( status = sts_send_body(&s,"\n",1,STS_REINIT_TIMEOUT) ) == NULL ) + { + /* failure. finish proceed */ + logger(LOG_ERR," NULL status after sending empty string(end of headers)"); + sts_close(&s); + } + else + { /* check status and finish if need */ + logger(LOG_DEBUG," empty string (end of headers) sent to filter"); + if ( check_results(&s,status,&res,fd,return_text) > 0 ){ + free_conf(); + return res; + } + } + + logger(LOG_DEBUG," Enter sent"); + + i = 0; + ctmp = buf; + while ( (cnt = read(fd,ctmp,buf + sizeof(buf) - ctmp)) > 0 ) + { + logger(LOG_DEBUG,"sending %d bytes to filter",cnt); + status = sts_send_body(&s,buf,cnt,STS_REINIT_TIMEOUT); + logger(LOG_DEBUG,"send"); + if ( status == NULL ) + { + // failure. finish proceed + logger(LOG_ERR," NULL status after sending part of body"); + sts_close(&s); + } + else + { // check status and finish if need + logger(LOG_DEBUG," part of body sent to filter"); + if ( check_results(&s,status,&res,fd,return_text) > 0 ){ + free_conf(); + return res; + } + } + }; + + logger(LOG_DEBUG," Total sent %d bytes of message",totalcnt); + + status = sts_body_end(&s,STS_FLUSH_DATA); + logger(LOG_DEBUG," Body sent"); + + + if ( check_results(&s,status,&res,fd,return_text) > 0 ){ + free_conf(); + return res; + } + else + sts_close(&s); + + logger(LOG_DEBUG," EOF"); + + free_conf(); + return LOCAL_SCAN_ACCEPT; + +} + + +int check_results(spamtest_session_t *s,spamtest_status_t *status,int *res,int fd,uschar **return_text) +{ + logger(LOG_DEBUG," Check results started."); + switch ( status->status ) + { + case STS_SMTP_ACCEPT: + case STS_BLACKHOLE: + logger(LOG_DEBUG," SMTP_ACCEPT or BLACK_HOLE."); + recipients_count = 0; + sts_close(s); + *res = LOCAL_SCAN_ACCEPT; + return 1; + case STS_REJECT: + logger(LOG_DEBUG," REJECT"); + *return_text=(uschar *)status->reason; + sts_close(s); + *res = LOCAL_SCAN_REJECT; + return 1; + case STS_FILTER_ERROR: + logger(LOG_DEBUG," FILTER_ERROR"); + sts_close(s); + *res = result_on_error; + return 1; + case STS_ACCEPT: + logger(LOG_DEBUG," ACCEPT"); + if ( proceed_accept(status,fd) != 0 ) + *res = result_on_error; + else + *res = LOCAL_SCAN_ACCEPT; + sts_close(s); + return 1; + case STS_CONTINUE: + logger(LOG_DEBUG," CONTINUE"); + return 0; + } + +} + +extern int recipients_list_max; +int proceed_accept(spamtest_status_t *status,int fd) +{ + spamtest_status_t *st; + message_status_t *mst; + int i; + int rcptn; + int good_rcpt_cnt = 0,k; + int found = 0; + + logger(LOG_DEBUG," accept_message started."); + + st = glue_actions(status); + + if (st==NULL) { + logger(LOG_ERR," glue_actions return NULL" ); + return -1; + } + + mst = &st->ms_array[0] ; + + rcptn = rcptlist_count(mst->rcpts); + for( k=0; krcpts, k))>0) + good_rcpt_cnt++; + if(good_rcpt_cnt <1) + { + logger(LOG_INFO," Empty recipient list"); + recipients_count = 0; + return 0; + } + + if ( (mst != NULL) && (mst->action == STS_ACTION_CHANGE) ) + { + logger(LOG_DEBUG," spamtest status returned STS_ACTION_CHANGE for message."); + + // cleanup old rcpts list + recipients_count = 0; + recipients_list = NULL; + recipients_list_max = 0; + for (i = 0; ircpts);i++) + { + char *rcpt = rcptlist_getn(mst->rcpts,i); + if(rcpt) + { + logger(LOG_DEBUG,"Adding recipient: %s",rcpt); + receive_add_recipient(string_copy(US rcpt),-1); + } + } + + logger(LOG_DEBUG," new recipients_count=%d",recipients_count); + + if ( sender_address[0] != '\0' ) + { + if (strcasecmp(mst->mailfrom,sender_address) != 0 ) + { /* changing sender address */ + logger(LOG_DEBUG," senders different"); + sender_address = string_copy( US mst->mailfrom ); + } + else + { + logger(LOG_DEBUG," senders equivalented"); + } + } + logger(LOG_DEBUG," Actions count = %d",mst->action_count); + for (i=0;iaction_count;i++) + { + header_line * tmp; + header_line * matched; + header_line * last; + int deleted_count = 0; + int matched_count = 0; + int hdrlen = strlen(mst->act_array[i].header); + + switch ( mst->act_array[i].type ) + { + case STS_HEADER_DEL: + logger(LOG_DEBUG," Delete header %s",mst->act_array[i].header); + tmp = header_list; + while ( tmp != NULL ) + { + if ( (tmp->type != '*') && + (tmp->slen > 0) && + (strncasecmp(tmp->text, + mst->act_array[i].header, + hdrlen < tmp->slen ? hdrlen:tmp->slen) == 0 ) + ) + { + deleted_count++; + tmp->type = '*'; + } + tmp = tmp->next; + } + logger(LOG_DEBUG," deleted %d headers",deleted_count); + break; + case STS_HEADER_ADD: + logger(LOG_DEBUG," Add value to header %s %s",mst->act_array[i].header,mst->act_array[i].value); + tmp = header_list; + matched = NULL; + while ( tmp != NULL ) + { + logger(LOG_DEBUG,"Iterating, %c %d %s",tmp->type,tmp->slen,tmp->text); + if ( (tmp->slen > 0) && + (strncasecmp(tmp->text, + mst->act_array[i].header, + hdrlen < tmp->slen ? hdrlen:tmp->slen) == 0 ) + ) + { + if ( matched != NULL ) + { + if ( (tmp->type != '*') || ( matched->type == '*' ) ) + matched = tmp; + } + else + { + matched = tmp; + } + } + tmp = tmp->next; + if(matched) + break; + } + if ( matched != NULL ) + { /* adding value to exits header */ + logger(LOG_DEBUG,"Found matched header, %c %d %s",matched->type,matched->slen,matched->text); + if ( matched->type == '*' ) + { + matched->text = string_sprintf("%s: %s\n",mst->act_array[i].header,mst->act_array[i].value); + matched->slen = strlen(matched->text); + matched->type = ' '; + matched->type = header_checkname(matched,0); + } + else + { + logger(LOG_DEBUG,"Appending value to existing header value"); + matched->text = string_sprintf("%s %s\n",matched->text,mst->act_array[i].value); + matched->slen += (strlen(mst->act_array[i].value) + 2); + } + } + else + { /* add new header in case when this header not found */ + logger(LOG_DEBUG," We must add value to header %s but this header not found.",mst->act_array[i].header); + header_add(' ',"%s: %s\n",mst->act_array[i].header,mst->act_array[i].value); + } + logger(LOG_DEBUG," Add header %s %s",mst->act_array[i].header,mst->act_array[i].value); + break; + + + case STS_HEADER_PREPEND: + logger(LOG_DEBUG," Prepend value to header %s %s",mst->act_array[i].header,mst->act_array[i].value); + tmp = header_list; + matched = NULL; + while ( tmp != NULL ) + { + logger(LOG_DEBUG,"Iterating, %c %d %s",tmp->type,tmp->slen,tmp->text); + if ( (tmp->slen > 0) && + (strncasecmp(tmp->text, + mst->act_array[i].header, + hdrlen < tmp->slen ? hdrlen:tmp->slen) == 0 ) + ) + { + if ( matched != NULL ) + { + if ( (tmp->type != '*') || ( matched->type == '*' ) ) + matched = tmp; + } + else + { + matched = tmp; + } + } + tmp = tmp->next; + if(matched) + break; + } + if ( matched != NULL ) + { /* adding value to exits header */ + logger(LOG_DEBUG,"Found matched header, %c %d %s",matched->type,matched->slen,matched->text); + if ( matched->type == '*' ) + { + matched->text = string_sprintf("%s: %s\n",mst->act_array[i].header,mst->act_array[i].value); + matched->slen = strlen(matched->text); + matched->type = ' '; + matched->type = header_checkname(matched,0); + } + else + { + int l = strlen(mst->act_array[i].header); + char *p = matched->text+l+2; + matched->text[l]=0; + matched->text = string_sprintf("%s: %s %s",matched->text, + mst->act_array[i].value,p); + matched->slen += (strlen(mst->act_array[i].value) + 1); + logger(LOG_DEBUG,"Prepending value %s to existing header value %s|", + mst->act_array[i].value, matched->text); + + } + } + else + { /* add new header in case when this header not found */ + logger(LOG_DEBUG," We must add value to header %s but this header not found.",mst->act_array[i].header); + header_add(' ',"%s: %s\n",mst->act_array[i].header,mst->act_array[i].value); + } + logger(LOG_DEBUG," Prepend header %s %s",mst->act_array[i].header,mst->act_array[i].value); + break; + + case STS_HEADER_CHG: + logger(LOG_DEBUG," Change header %s %s",mst->act_array[i].header,mst->act_array[i].value); + tmp = header_list; + matched = NULL; + matched_count = 0; + while ( tmp != NULL ) + { + int hdrlen = strlen(mst->act_array[i].header); + if ( (tmp->type != '*') && + (tmp->slen > 0) && + (strncasecmp(tmp->text, + mst->act_array[i].header, + hdrlen < tmp->slen ? hdrlen:tmp->slen) == 0 ) + ) + { + matched = tmp; + matched_count++; + } + tmp = tmp->next; + } + if ( matched != NULL ) + { + matched->text = string_sprintf("%s: %s\n",mst->act_array[i].header,mst->act_array[i].value); + matched->slen += (strlen(mst->act_array[i].value) + strlen(mst->act_array[i].header) + 3); + if ( matched_count > 1 ) + { + tmp = header_list; + while ( (tmp != NULL) && matched_count > 1 ) + { + if ( (tmp->type != '*') && + (tmp->slen > 0) && + (strncasecmp(tmp->text, + mst->act_array[i].header, + hdrlen < tmp->slen ? hdrlen:tmp->slen) == 0 ) && + (tmp != matched) + ) + { + tmp->type = '*'; + matched_count--; + } + tmp = tmp->next; + } + } + + } + else + { + logger(LOG_DEBUG," We must change value for header %s but this header not found.Adding new",mst->act_array[i].header); + header_add(' ',"%s: %s\n",mst->act_array[i].header,mst->act_array[i].value); + } + break; + case STS_HEADER_NEW: + logger(LOG_DEBUG," New header %s: %s",mst->act_array[i].header,mst->act_array[i].value); + + tmp = header_list; + matched = NULL; + while ( tmp != NULL ) + { + if ( (tmp->type != '*') && + (tmp->slen > 0) && + (strncasecmp(tmp->text, + mst->act_array[i].header, + hdrlen < tmp->slen ? hdrlen:tmp->slen) == 0 ) + ) + { + matched = tmp; + } + tmp = tmp->next; + } + if ( matched != NULL && matched != header_last ) + { + if(matched == header_last) + { + logger(LOG_DEBUG,"Header %s is last in message, adding below", + mst->act_array[i].header); + header_add(' ',"%s: %s\n",mst->act_array[i].header,mst->act_array[i].value); + } + else + { /* adding value after last header with this name */ + logger(LOG_DEBUG,"Some headers %s found",mst->act_array[i].header); + tmp = header_last; + header_add(' ',"%s: %s\n",mst->act_array[i].header,mst->act_array[i].value); + tmp->next->next = matched->next; + matched->next = tmp->next; + tmp->next = NULL; + header_last = tmp; + } + } + else + { /* add new header at the end of headers list */ + logger(LOG_DEBUG,"Headers %s not found",mst->act_array[i].header); + header_add(' ',"%s: %s\n",mst->act_array[i].header,mst->act_array[i].value); + } + + break; + default: + logger(LOG_INFO," Invalid action type %d",mst->act_array[i].type); + } + } + } + else if ( (mst != NULL) && (mst->action == STS_ACTION_BOUNCE) ) + { /* bounce message */ + header_line *tmp; + message_t *bounced_mess; + + logger(LOG_DEBUG," bouncing message."); + + /* preparing bounced message */ + bounced_mess = message_init(); + if ( bounced_mess == NULL ) + { + logger(LOG_ERR," Unable to allocate memory for bounced message"); + return -1; + } + logger(LOG_DEBUG," new message allocated."); + + /* copying data from filter to prepared message (for automatically creating headers list ) */ + for (i=0;ibouncemsg);i++ ) + { + if ( message_put_body(bounced_mess,msgtext_get_chunk(mst->bouncemsg,i),msgtext_chunk_len(mst->bouncemsg,i)) == -1 ) + { + logger(LOG_ERR," unable to copy data from filter to bounced message"); + message_free(bounced_mess); + return -1; + } + else + { + logger(LOG_DEBUG," message_put_body - ok."); + } + } + + /* deleting exim old headers */ + tmp = header_list; + while ( tmp != NULL ) + { + tmp->type = '*'; + tmp = tmp->next; + }; + logger(LOG_DEBUG," headers deleted."); + + /* adding new headers */ + for ( i = 0;i < bounced_mess->headers->used; i++ ) + { + header_add(' ',"%s: %s",bounced_mess->headers->array[i].header.hptr,bounced_mess->headers->array[i].value.hptr); + logger(LOG_DEBUG," added header: %s: %s",bounced_mess->headers->array[i].header.hptr,bounced_mess->headers->array[i].value.hptr); + } + + /* replacing rcpts */ + recipients_count = 0; + recipients_list = NULL; + recipients_list_max = 0; + + if ( rcptlist_count(bounced_mess->recipients) > 0 ) + { + for (i = 0; irecipients);i++) + { + char *rcpt = rcptlist_getn(bounced_mess->recipients,i); + if ( rcpt == NULL ) + { + logger(LOG_ERR," unable to get recipient %d",i); + message_free(bounced_mess); + return -1; + } + logger(LOG_DEBUG," rcpt = %s",rcpt); + receive_add_recipient(string_copy(US rcpt),-1); + } + } + else + { + if ( sender_address[0] != '\0' ) + receive_add_recipient(string_copy(US sender_address),-1); + else + { + logger(LOG_ERR," Unable to get sender address to bounce, failed"); + return -1; + } + } + /* cleaning sender ( must be empty string ) */ + logger(LOG_DEBUG," sender address emptied"); + sender_address = ""; + + /* writing new message body */ + lseek(fd,SPOOL_DATA_START_OFFSET,SEEK_SET); + + if ( get_message_bodychunks_count(bounced_mess) > 0 ) + { + for (i=0;iaction); + else + logger(LOG_ERR," mst is NULL"); + } + + logger(LOG_DEBUG," Message accepted."); + return 0; + +} + + +void logger(const int log_level,const char *fmt,...) +{ + va_list params; + char buf[512]; + /* LOG_ERR == 3 is minimum level for us */ + if (log_level <= (debug_level+3)) + { + va_start(params,fmt); + vsnprintf(buf,(size_t)512,fmt,params); + debug_printf("-ls- %s\n",buf); +#ifdef SPAMTEST_USE_SYSLOG + va_start(params,fmt); + vsyslog(log_level>LOG_DEBUG?LOG_DEBUG:log_level,fmt,params); +#else + log_write(0,LOG_MAIN,"spamtest: %s",buf); +#endif + va_end(params); + } +} + +void prepare_config_parameters() +{ + int len; + /* + * Firstly we are looking for new parameter, + * then - for old parameter, else - we use + * default value. + */ + if (kas_log_level != 0) + debug_level = kas_log_level; + if (debug_level == 0) + debug_level = KAS_LOG_LEVEL; + + if (kas_connect_timeout != 0) + st_connect_timeout = kas_connect_timeout*1000; + if (st_connect_timeout == 0) + st_connect_timeout = KAS_CONNECT_TIMEOUT; + + if (kas_data_timeout != 0) + st_rw_timeout = kas_data_timeout*1000; + if (st_rw_timeout == 0) + st_rw_timeout = KAS_DATA_TIMEOUT; + + if (kas_filtering_size_limit != 0) + filtering_size_limit = kas_filtering_size_limit; + if (filtering_size_limit == 0) + filtering_size_limit = KAS_FILTERING_SIZE_LIMIT; + + + if (kas_default_domain != NULL){ + len = strlen(kas_default_domain); + result_default_domain = malloc(len+1); + strncpy(result_default_domain,kas_default_domain,len); + result_default_domain[len]='\0'; + } + else if (st_mail_domain != NULL){ + len = strlen(st_mail_domain); + result_default_domain = malloc(len+1); + strncpy(result_default_domain,st_mail_domain,len); + result_default_domain[len]='\0'; + } + else{ + len = strlen(KAS_DEFAULT_DOMAIN); + result_default_domain = malloc(len+1); + strncpy(result_default_domain,KAS_DEFAULT_DOMAIN,len); + result_default_domain[len]='\0'; + } + + if (kas_connect_to != NULL){ + len = strlen(kas_connect_to); + result_connect_to = malloc(len+1); + strncpy(result_connect_to,kas_connect_to,len); + result_connect_to[len]='\0'; + } + else if (st_address != NULL){ + len = strlen(st_address); + result_connect_to = malloc(len+1); + strncpy(result_connect_to,st_address,len); + result_connect_to[len]='\0'; + }/* one parameter have no default, + * because else we can't disable kas-exim in config file*/ + + if (kas_on_error != NULL){ + len = strlen(kas_on_error); + result_on_error_str = malloc(len+1); + strncpy(result_on_error_str,kas_on_error,len); + result_on_error_str[len]='\0'; + } + else if (st_on_error != NULL){ + len = strlen(st_on_error); + result_on_error_str = malloc(len+1); + strncpy(result_on_error_str,st_on_error,len); + result_on_error_str[len]='\0'; + } + else{ + len = strlen(KAS_ON_ERROR); + result_on_error_str = malloc(len+1); + strncpy(result_on_error_str,KAS_ON_ERROR,len); + result_on_error_str[len]='\0'; + } + + if ( strcasecmp(result_on_error_str,"accept") == 0 ){ + result_on_error = LOCAL_SCAN_ACCEPT; + } + else if ( strcasecmp(result_on_error_str,"reject") == 0 ){ + result_on_error = LOCAL_SCAN_REJECT; + } + else if ( strcasecmp(result_on_error_str,"tempfail") == 0 ){ + result_on_error = LOCAL_SCAN_TEMPREJECT; + } + else{ + logger(LOG_ERR,"Invalid value for parameter on_spamtest_error. Will use 'accept'"); + result_on_error = LOCAL_SCAN_ACCEPT; + } +} + +void free_conf(){ + free(result_default_domain); + free(result_connect_to); + free(result_on_error_str); +} + diff -urN src.orig/EDITME src/EDITME --- src.orig/EDITME Wed Jan 3 00:00:47 2007 +++ src/EDITME Wed Jan 3 00:10:03 2007 @@ -1117,3 +1117,12 @@ # SUPPORT_MOVE_FROZEN_MESSAGES=yes # End of EDITME for Exim 4. + + +#------------------------------------------------------------------------------ +# KAS support + +CFLAGS += -I/usr/local/ap-mailfilter3/include +EXTRALIBS_EXIM += -L/usr/local/ap-mailfilter3/lib -lspamtest +LOCAL_SCAN_SOURCE=Local/kas_exim.c +LOCAL_SCAN_HAS_OPTIONS=yes