Back to index

citadel  8.12
serv_netfilter.c
Go to the documentation of this file.
00001 /*
00002  * A server-side module for Citadel designed to filter idiots off the network.
00003  * 
00004  * Copyright (c) 2002-2012 by the citadel.org team
00005  *
00006  *  This program is open source software; you can redistribute it and/or modify
00007  *  it under the terms of the GNU General Public License version 3.
00008  *  
00009  *  
00010  *
00011  *  This program is distributed in the hope that it will be useful,
00012  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014  *  GNU General Public License for more details.
00015  *
00016  *  
00017  *  
00018  *  
00019  */
00020 
00021 #include "sysdep.h"
00022 #include <stdlib.h>
00023 #include <unistd.h>
00024 #include <stdio.h>
00025 #include <fcntl.h>
00026 #include <signal.h>
00027 #include <pwd.h>
00028 #include <errno.h>
00029 #include <sys/types.h>
00030 
00031 #if TIME_WITH_SYS_TIME
00032 # include <sys/time.h>
00033 # include <time.h>
00034 #else
00035 # if HAVE_SYS_TIME_H
00036 #  include <sys/time.h>
00037 # else
00038 #  include <time.h>
00039 # endif
00040 #endif
00041 
00042 #include <sys/wait.h>
00043 #include <string.h>
00044 #include <limits.h>
00045 #include <libcitadel.h>
00046 #include "citadel.h"
00047 #include "server.h"
00048 #include "citserver.h"
00049 #include "support.h"
00050 #include "config.h"
00051 #include "control.h"
00052 #include "user_ops.h"
00053 #include "database.h"
00054 #include "msgbase.h"
00055 
00056 
00057 #include "ctdl_module.h"
00058 
00059 typedef struct FilterList FilterList;
00060 
00061 struct FilterList {
00062        FilterList *next;
00063        char fl_user[SIZ];
00064        char fl_room[SIZ];
00065        char fl_node[SIZ];
00066 };
00067 
00068 struct FilterList *filterlist = NULL;
00069 
00070 /*
00071  * Keep track of what messages to reject
00072  */
00073 FilterList *load_filter_list(void) {
00074        char *serialized_list = NULL;
00075        int i;
00076        char buf[SIZ];
00077        FilterList *newlist = NULL;
00078        FilterList *nptr;
00079 
00080        serialized_list = CtdlGetSysConfig(FILTERLIST);
00081        if (serialized_list == NULL) return(NULL); /* if null, no entries */
00082 
00083        /* Use the string tokenizer to grab one line at a time */
00084        for (i=0; i<num_tokens(serialized_list, '\n'); ++i) {
00085               extract_token(buf, serialized_list, i, '\n', sizeof buf);
00086               nptr = (FilterList *) malloc(sizeof(FilterList));
00087               extract_token(nptr->fl_user, buf, 0, '|', sizeof nptr->fl_user);
00088               striplt(nptr->fl_user);
00089               extract_token(nptr->fl_room, buf, 1, '|', sizeof nptr->fl_room);
00090               striplt(nptr->fl_room);
00091               extract_token(nptr->fl_node, buf, 2, '|', sizeof nptr->fl_node);
00092               striplt(nptr->fl_node);
00093 
00094               /* Cowardly refuse to add an any/any/any entry that would
00095                * end up filtering every single message.
00096                */
00097               if (IsEmptyStr(nptr->fl_user) && 
00098                   IsEmptyStr(nptr->fl_room) &&
00099                   IsEmptyStr(nptr->fl_node)) {
00100                      free(nptr);
00101               }
00102               else {
00103                      nptr->next = newlist;
00104                      newlist = nptr;
00105               }
00106        }
00107 
00108        free(serialized_list);
00109        return newlist;
00110 }
00111 
00112 
00113 void free_filter_list(FilterList *fl) {
00114        if (fl == NULL) return;
00115        free_filter_list(fl->next);
00116        free(fl);
00117 }
00118 
00119 void free_netfilter_list(void)
00120 {
00121        free_filter_list(filterlist);
00122        filterlist = NULL;
00123 }
00124 
00125 void load_network_filter_list(void)
00126 {
00127        filterlist = load_filter_list();
00128 }
00129 
00130 
00131 /*
00132  * This handler detects whether an incoming network message is from some
00133  * moron user who the site operator has elected to filter out.  If a match
00134  * is found, the message is rejected.
00135  */
00136 int filter_the_idiots(struct CtdlMessage *msg, char *target_room) {
00137        FilterList *fptr;
00138        int zap_user = 0;
00139        int zap_room = 0;
00140        int zap_node = 0;
00141 
00142        if ( (msg == NULL) || (filterlist == NULL) ) {
00143               return(0);
00144        }
00145 
00146        for (fptr = filterlist; fptr != NULL; fptr = fptr->next) {
00147 
00148               zap_user = 0;
00149               zap_room = 0;
00150               zap_node = 0;
00151 
00152               if (msg->cm_fields['A'] != NULL) {
00153                      if ( (!strcasecmp(msg->cm_fields['A'], fptr->fl_user))
00154                         || (fptr->fl_user[0] == 0) ) {
00155                             zap_user = 1;
00156                      }
00157               }
00158 
00159               if (msg->cm_fields['C'] != NULL) {
00160                      if ( (!strcasecmp(msg->cm_fields['C'], fptr->fl_room))
00161                         || (fptr->fl_room[0] == 0) ) {
00162                             zap_room = 1;
00163                      }
00164               }
00165 
00166               if (msg->cm_fields['O'] != NULL) {
00167                      if ( (!strcasecmp(msg->cm_fields['O'], fptr->fl_room))
00168                         || (fptr->fl_room[0] == 0) ) {
00169                             zap_room = 1;
00170                      }
00171               }
00172 
00173               if (msg->cm_fields['N'] != NULL) {
00174                      if ( (!strcasecmp(msg->cm_fields['N'], fptr->fl_node))
00175                         || (fptr->fl_node[0] == 0) ) {
00176                             zap_node = 1;
00177                      }
00178               }
00179        
00180               if (zap_user + zap_room + zap_node == 3) return(1);
00181 
00182        }
00183 
00184        return(0);
00185 }
00186 
00187 
00188 CTDL_MODULE_INIT(netfilter)
00189 {
00190        if (!threading)
00191        {
00192               CtdlRegisterNetprocHook(filter_the_idiots);
00193        }
00194        
00195        /* return our module name for the log */
00196        return "netfilter";
00197 }