Back to index

citadel  8.12
serv_dspam.c
Go to the documentation of this file.
00001 /*
00002  * This module glues libDSpam to the Citadel server in order to implement
00003  * DSPAM Spamchecking 
00004  *
00005  * Copyright (c) 2012 by the citadel.org team
00006  *
00007  *  This program is open source software; you can redistribute it and/or modify
00008  *  it under the terms of the GNU General Public License version 3.
00009  *  
00010  *  
00011  *
00012  *  This program is distributed in the hope that it will be useful,
00013  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015  *  GNU General Public License for more details.
00016  *
00017  *  
00018  *  
00019  *  
00020  */
00021 
00022 #include "sysdep.h"
00023 #include <stdlib.h>
00024 #include <unistd.h>
00025 #include <stdio.h>
00026 #include <fcntl.h>
00027 #include <ctype.h>
00028 #include <pwd.h>
00029 #include <errno.h>
00030 #include <sys/types.h>
00031 
00032 #if TIME_WITH_SYS_TIME
00033 # include <sys/time.h>
00034 # include <time.h>
00035 #else
00036 # if HAVE_SYS_TIME_H
00037 #  include <sys/time.h>
00038 # else
00039 #  include <time.h>
00040 # endif
00041 #endif
00042 
00043 #include <sys/wait.h>
00044 #include <string.h>
00045 #include <limits.h>
00046 #include <libcitadel.h>
00047 #include "citadel.h"
00048 #include "server.h"
00049 #include "citserver.h"
00050 #include "support.h"
00051 #include "config.h"
00052 #include "database.h"
00053 #include "msgbase.h"
00054 #include "internet_addressing.h"
00055 
00056 
00057 #include "ctdl_module.h"
00058 
00059 
00060 #ifdef HAVE_LIBDSPAM
00061 #define CONFIG_DEFAULT file_dpsam_conf
00062 #define LOGDIR file_dspam_log
00063 
00064 
00065 //#define HAVE_CONFIG_H
00066 #include <dspam/libdspam.h>
00067 //#define HAVE_CONFIG_H
00068 
00069 typedef struct stringlist stringlist;
00070 
00071 struct stringlist {
00072        char *Str;
00073        long len;
00074        stringlist *Next;
00075 };
00076        
00077 
00078 /*
00079  * Citadel protocol to manage sieve scripts.
00080  * This is basically a simplified (read: doesn't resemble IMAP) version
00081  * of the 'managesieve' protocol.
00082  */
00083 void cmd_tspam(char *argbuf) {
00084        char buf[SIZ];
00085        long len;
00086        long count;
00087        stringlist *Messages; 
00088        stringlist *NextMsg; 
00089 
00090        Messages = NULL;
00091        NextMsg = NULL;
00092        count = 0;
00093        if (CtdlAccessCheck(ac_room_aide)) return;
00094        if (atoi(argbuf) == 0) {
00095               cprintf("%d Ok.\n", CIT_OK);
00096               return;
00097        }
00098        cprintf("%d Send info...\n", SEND_LISTING);
00099 
00100        do {
00101               len = client_getln(buf, sizeof buf);
00102               if (strcmp(buf, "000")) {
00103                      if (Messages == NULL) {
00104                             Messages = malloc (sizeof (stringlist));
00105                             NextMsg = Messages;
00106                      }
00107                      else {
00108                             Messages->Next = malloc (sizeof (stringlist));
00109                             NextMsg = NextMsg->Next;
00110                      }
00111                      NextMsg->Next = NULL;
00112                      NextMsg->Str = malloc (len+1);
00113                      NextMsg->len = len;
00114                      memcpy (NextMsg->Str, buf, len + 1);
00115                      count++;
00116               }
00117        } while (strcmp(buf, "000"));
00119        /* tag mails as spam or Ham */
00120        /* probably do: dspam_init(ctdl_dspam_dir); dspam_process dspam_addattribute; dspam_destroy*/
00121        // extract DSS_ERROR or DSS_CORPUS from the commandline. error->ham; corpus -> spam?
00123 }
00124 
00125 
00126 
00127 void ctdl_dspam_init(void) {
00128 
00130 
00131 }
00132 
00133 void dspam_do_msg(long msgnum, void *userdata) 
00134 {
00135        char *msgtext;
00136        DSPAM_CTX *CTX;                    /* DSPAM Context */
00137        struct CtdlMessage *msg;
00138        struct _ds_spam_signature SIG;        /* signature */
00139 
00140        CTX = *(DSPAM_CTX**) userdata;
00141        msg = CtdlFetchMessage(msgnum, 0);
00142        if (msg == NULL) return;
00143 
00144 
00145        /* Message */
00146        CC->redirect_buffer = malloc(SIZ);
00147        CC->redirect_len = 0;
00148        CC->redirect_alloc = SIZ;
00149        CtdlOutputPreLoadedMsg(msg, MT_RFC822, HEADERS_ALL, 0, 1, 0);
00150        msgtext = CC->redirect_buffer;
00151 // don't need?       msglen = CC->redirect_len;
00152        CC->redirect_buffer = NULL;
00153        CC->redirect_len = 0;
00154        CC->redirect_alloc = 0;
00155 
00156        /* Call DSPAM's processor with the message text */
00157        if (dspam_process (CTX, msgtext) != 0)
00158        {
00159               free(msgtext);
00160               syslog(LOG_CRIT, "ERROR: dspam_process failed");
00161               return;
00162        }
00163        if (CTX->signature == NULL)
00164        {
00165               syslog(LOG_CRIT,"No signature provided\n");
00166        }
00167        else
00168        {
00169 /* Copy to a safe place */
00170 
00171               msg->cm_fields['G'] = malloc (CTX->signature->length * 2);
00172               CtdlEncodeBase64(msg->cm_fields['G'], CTX->signature->data, CTX->signature->length, 0);
00173        }
00174        free(msgtext);
00175 
00176        SIG.length = CTX->signature->length;
00177        /* Print processing results */
00178        syslog(LOG_DEBUG, "Probability: %2.4f Confidence: %2.4f, Result: %s\n",
00179               CTX->probability,
00180               CTX->confidence,
00181               (CTX->result == DSR_ISSPAM) ? "Spam" : "Innocent");
00182 
00185 }
00186 
00187 int serv_dspam_room(struct ctdlroom *room)
00188 {
00189        DSPAM_CTX *CTX;                    /* DSPAM Context */
00190 
00191        /* scan for spam; do */
00192        /* probably do: dspam_init; dspam_process dspam_addattribute; dspam_destroy*/
00193 //DSS_NONE
00194 //#define     DSR_ISSPAM           0x01
00195 //#define DSR_ISINNOCENT           0x02
00196 // dspam_init (cc->username, NULL, ctdl_dspam_home, DSM_PROCESS,
00197        //                  DSF_SIGNATURE | DSF_NOISE);
00199        if ((room->QRflags & QR_PRIVATE) &&/* Are we sending to a private mailbox? */
00200            (strstr(room->QRname, ".Mail")!=NULL))
00201 
00202        {
00203               char User[64];
00204               // maybe we should better get our realname here?
00205               snprintf(User, 64, "%ld", room->QRroomaide);
00206               extract_token(User, room->QRname, 0, '.', sizeof(User));
00207               CTX = dspam_init(User, 
00208                              NULL,
00209                              ctdl_dspam_dir, 
00210                              DSM_PROCESS, 
00211                              DSF_SIGNATURE | DSF_NOISE);
00212        }
00213        else return 0;
00214 
00215        if (CTX == NULL)
00216        {
00217               syslog(LOG_CRIT, "ERROR: dspam_init failed!\n");
00218               return ERROR + INTERNAL_ERROR;
00219        }
00220        /* Use graham and robinson algorithms, graham's p-values */
00221        CTX->algorithms = DSA_GRAHAM | DSA_BURTON | DSP_GRAHAM;
00222 
00223        /* Use CHAIN tokenizer */
00224        CTX->tokenizer = DSZ_CHAIN;
00225 
00226        CtdlForEachMessage(MSGS_GT, 1, NULL, NULL, NULL,
00227                         dspam_do_msg,
00228                         (void *) &CTX);
00229 
00230        return 0;
00231 }
00232 
00233 void serv_dspam_shutdown (void)
00234 {
00235        libdspam_shutdown ();
00236 }
00237 #endif /* HAVE_LIBDSPAM */
00238 
00239 CTDL_MODULE_INIT(dspam)
00240 {
00241        return "disabled.";
00242        if (!threading)
00243        {
00244 #ifdef HAVE_LIBDSPAM
00245 
00246               ctdl_dspam_init();
00247               CtdlRegisterCleanupHook(serv_dspam_shutdown);
00248               CtdlRegisterProtoHook(cmd_tspam, "SPAM", "Tag Message as Spam/Ham to learn DSPAM");
00249 
00250                CtdlRegisterRoomHook(serv_dspam_room);
00251 
00253 
00254 #else  /* HAVE_LIBDSPAM */
00255 
00256               syslog(LOG_INFO, "This server is missing libdspam Spam filtering will be disabled.\n");
00257 
00258 #endif /* HAVE_LIBDSPAM */
00259        }
00260        
00261         /* return our module name for the log */
00262        return "dspam";
00263 }
00264