/* src/bandbi.c * An interface to the ban db. * * Copyright (C) 2006 Lee Hardy <lee -at- leeh.co.uk> * Copyright (C) 2006 ircd-ratbox development team * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * 1.Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * 2.Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3.The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * * $Id$ */#include "stdinc.h"#include "ratbox_lib.h"#include "client.h"#include "s_conf.h"#include "logger.h"#include "match.h"#include "bandbi.h"#include "parse.h"#include "channel.h"#include "hostmask.h"#include "hash.h"#include "s_newconf.h"#include "reject.h"#include "send.h"#include "ircd.h"#include "msg.h" /* XXX: MAXPARA */staticcharbandb_add_letter[LAST_BANDB_TYPE]={'K','D','X','R'};rb_dlink_listbandb_pending;staticrb_helper*bandb_helper;staticintstart_bandb(void);staticvoidbandb_parse(rb_helper*);staticvoidbandb_restart_cb(rb_helper*);staticchar*bandb_path;voidinit_bandb(void){if(start_bandb()){ilog(L_MAIN,"Unable to start bandb helper: %s",strerror(errno));exit(0);}}staticintstart_bandb(void){charfullpath[PATH_MAX+1];#ifdef _WIN32constchar*suffix=".exe";#elseconstchar*suffix="";#endifrb_setenv("BANDB_DPATH",ConfigFileEntry.dpath,1);if(bandb_path==NULL){rb_snprintf(fullpath,sizeof(fullpath),"%s/bandb%s",BINPATH,suffix);if(access(fullpath,X_OK)==-1){rb_snprintf(fullpath,sizeof(fullpath),"%s/bin/bandb%s",ConfigFileEntry.dpath,suffix);if(access(fullpath,X_OK)==-1){ilog(L_MAIN,"Unable to execute bandb in %s or %s/bin",BINPATH,ConfigFileEntry.dpath);return0;}}bandb_path=rb_strdup(fullpath);}bandb_helper=rb_helper_start("bandb",bandb_path,bandb_parse,bandb_restart_cb);if(bandb_helper==NULL){ilog(L_MAIN,"Unable to start bandb: %s",strerror(errno));sendto_realops_snomask(SNO_GENERAL,L_ALL,"Unable to start bandb: %s",strerror(errno));return1;}rb_helper_run(bandb_helper);return0;}voidbandb_add(bandb_typetype,structClient*source_p,constchar*mask1,constchar*mask2,constchar*reason,constchar*oper_reason,intperm){staticcharbuf[BUFSIZE];rb_snprintf(buf,sizeof(buf),"%c %s ",bandb_add_letter[type],mask1);if(!EmptyString(mask2))rb_snprintf_append(buf,sizeof(buf),"%s ",mask2);rb_snprintf_append(buf,sizeof(buf),"%s %ld %d :%s",get_oper_name(source_p),(longint)rb_current_time(),perm,reason);if(!EmptyString(oper_reason))rb_snprintf_append(buf,sizeof(buf),"|%s",oper_reason);rb_helper_write(bandb_helper,"%s",buf);}staticcharbandb_del_letter[LAST_BANDB_TYPE]={'k','d','x','r'};voidbandb_del(bandb_typetype,constchar*mask1,constchar*mask2){staticcharbuf[BUFSIZE];buf[0]='\0';rb_snprintf_append(buf,sizeof(buf),"%c %s",bandb_del_letter[type],mask1);if(!EmptyString(mask2))rb_snprintf_append(buf,sizeof(buf)," %s",mask2);rb_helper_write(bandb_helper,"%s",buf);}staticvoidbandb_handle_ban(char*parv[],intparc){structConfItem*aconf;char*p;intpara=1;aconf=make_conf();aconf->port=0;if(parv[0][0]=='K')aconf->user=rb_strdup(parv[para++]);aconf->host=rb_strdup(parv[para++]);/* We do not have the 'oper' field yet. */para++;switch(parv[0][0]){case'K':aconf->status=CONF_KILL;break;case'D':aconf->status=CONF_DLINE;break;case'X':aconf->status=CONF_XLINE;break;case'R':if(IsChannelName(aconf->host))aconf->status=CONF_RESV_CHANNEL;elseaconf->status=CONF_RESV_NICK;break;}if((p=strchr(parv[para],'|'))){*p++='\0';aconf->spasswd=rb_strdup(p);}aconf->passwd=rb_strdup(parv[para]);rb_dlinkAddAlloc(aconf,&bandb_pending);}staticintbandb_check_kline(structConfItem*aconf){structrb_sockaddr_storagedaddr;structConfItem*kconf=NULL;intaftype;constchar*p;aftype=parse_netmask(aconf->host,(structsockaddr*)&daddr,NULL);if(aftype!=HM_HOST){#ifdef RB_IPV6if(aftype==HM_IPV6)aftype=AF_INET6;else#endifaftype=AF_INET;kconf=find_conf_by_address(aconf->host,NULL,NULL,(structsockaddr*)&daddr,CONF_KILL,aftype,aconf->user,NULL);}elsekconf=find_conf_by_address(aconf->host,NULL,NULL,NULL,CONF_KILL,0,aconf->user,NULL);if(kconf&&((kconf->flags&CONF_FLAGS_TEMPORARY)==0))return0;for(p=aconf->user;*p;p++){if(!IsUserChar(*p)&&!IsKWildChar(*p))return0;}for(p=aconf->host;*p;p++){if(!IsHostChar(*p)&&!IsKWildChar(*p))return0;}return1;}staticintbandb_check_dline(structConfItem*aconf){structrb_sockaddr_storagedaddr;/* struct ConfItem *dconf; */intbits;if(!parse_netmask(aconf->host,(structsockaddr*)&daddr,&bits))return0;return1;}staticintbandb_check_xline(structConfItem*aconf){structConfItem*xconf;/* XXX perhaps convert spaces to \s? -- jilles */xconf=find_xline_mask(aconf->host);if(xconf!=NULL&&!(xconf->flags&CONF_FLAGS_TEMPORARY))return0;return1;}staticintbandb_check_resv_channel(structConfItem*aconf){constchar*p;if(hash_find_resv(aconf->host)||strlen(aconf->host)>CHANNELLEN)return0;for(p=aconf->host;*p;p++){if(!IsChanChar(*p))return0;}return1;}staticintbandb_check_resv_nick(structConfItem*aconf){if(!clean_resv_nick(aconf->host))return0;if(find_nick_resv(aconf->host))return0;return1;}staticvoidbandb_handle_clear(void){rb_dlink_node*ptr,*next_ptr;RB_DLINK_FOREACH_SAFE(ptr,next_ptr,bandb_pending.head){free_conf(ptr->data);rb_dlinkDestroy(ptr,&bandb_pending);}}staticvoidbandb_handle_finish(void){structConfItem*aconf;rb_dlink_node*ptr,*next_ptr;clear_out_address_conf_bans();clear_s_newconf_bans();RB_DLINK_FOREACH_SAFE(ptr,next_ptr,bandb_pending.head){aconf=ptr->data;rb_dlinkDestroy(ptr,&bandb_pending);switch(aconf->status){caseCONF_KILL:if(bandb_check_kline(aconf))add_conf_by_address(aconf->host,CONF_KILL,aconf->user,NULL,aconf);elsefree_conf(aconf);break;caseCONF_DLINE:if(bandb_check_dline(aconf))add_conf_by_address(aconf->host,CONF_DLINE,aconf->user,NULL,aconf);elsefree_conf(aconf);break;caseCONF_XLINE:if(bandb_check_xline(aconf))rb_dlinkAddAlloc(aconf,&xline_conf_list);elsefree_conf(aconf);break;caseCONF_RESV_CHANNEL:if(bandb_check_resv_channel(aconf))add_to_resv_hash(aconf->host,aconf);elsefree_conf(aconf);break;caseCONF_RESV_NICK:if(bandb_check_resv_nick(aconf))rb_dlinkAddAlloc(aconf,&resv_conf_list);elsefree_conf(aconf);break;}}check_banned_lines();}staticvoidbandb_handle_failure(rb_helper*helper,char**parv,intparc){if(server_state_foreground)fprintf(stderr,"bandb - bandb failure: %s\n",parv[1]);ilog(L_MAIN,"bandb - bandb failure: %s",parv[1]);sendto_realops_snomask(SNO_GENERAL,L_ALL,"bandb - bandb failure: %s",parv[1]);exit(1);}staticvoidbandb_parse(rb_helper*helper){staticcharbuf[READBUF_SIZE];char*parv[MAXPARA+1];intlen,parc;while((len=rb_helper_read(helper,buf,sizeof(buf)))){parc=rb_string_to_array(buf,parv,MAXPARA);if(parc<1)continue;switch(parv[0][0]){case'!':bandb_handle_failure(helper,parv,parc);break;case'K':case'D':case'X':case'R':bandb_handle_ban(parv,parc);break;case'C':bandb_handle_clear();case'F':bandb_handle_finish();break;}}}voidbandb_rehash_bans(void){if(bandb_helper!=NULL)rb_helper_write(bandb_helper,"L");}staticvoidbandb_restart_cb(rb_helper*helper){ilog(L_MAIN,"bandb - bandb_restart_cb called, bandb helper died?");sendto_realops_snomask(SNO_GENERAL,L_ALL,"bandb - bandb_restart_cb called, bandb helper died?");if(helper!=NULL){rb_helper_close(helper);bandb_helper=NULL;}start_bandb();return;}