Author: Bleep <tomh@inxpress.net>
[ircu2.10.12-pk.git] / ircd / gline.c
1 /*
2  * IRC - Internet Relay Chat, ircd/gline.c
3  * Copyright (C) 1990 Jarkko Oikarinen and
4  *                    University of Oulu, Finland
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 1, or (at your option)
9  * any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19  *
20  * $Id$
21  */
22 #include "gline.h"
23 #include "client.h"
24 #include "ircd.h"
25 #include "ircd_alloc.h"
26 #include "ircd_string.h"
27 #include "match.h"
28 #include "numeric.h"
29 #include "s_bsd.h"
30 #include "s_misc.h"
31 #include "send.h"
32 #include "struct.h"
33 #include "sys.h"    /* FALSE bleah */
34
35 #include <assert.h>
36
37 struct Gline* GlobalGlineList  = 0;
38 struct Gline* BadChanGlineList = 0;
39
40
41 struct Gline *make_gline(int is_ipmask, char *host, char *reason,
42                          char *name, time_t expire)
43 {
44   struct Gline *agline;
45
46 #ifdef BADCHAN
47   int gtype = 0;
48   if ('#' == *host || '&' == *host || '+' == *host)
49     gtype = 1; /* BAD CHANNEL GLINE */
50 #endif
51
52   agline = (struct Gline*) MyMalloc(sizeof(struct Gline)); /* alloc memory */
53   assert(0 != agline);
54   DupString(agline->host, host);        /* copy vital information */
55   DupString(agline->reason, reason);
56   DupString(agline->name, name);
57   agline->expire = expire;
58   agline->gflags = GLINE_ACTIVE;        /* gline is active */
59   if (is_ipmask)
60     SetGlineIsIpMask(agline);
61 #ifdef BADCHAN
62   if (gtype)
63   { 
64     agline->next = BadChanGlineList;    /* link it into the list */
65     return (BadChanGlineList = agline);
66   }
67 #endif
68   agline->next = GlobalGlineList;       /* link it into the list */
69   return (GlobalGlineList = agline);
70 }
71
72 struct Gline *find_gline(struct Client *cptr, struct Gline **pgline)
73 {
74   struct Gline* gline = GlobalGlineList;
75   struct Gline* prev = 0;
76
77   while (gline) {
78     /*
79      * look through all glines
80      */
81     if (gline->expire <= TStime()) {
82       /*
83        * handle expired glines
84        */
85       free_gline(gline, prev);
86       gline = prev ? prev->next : GlobalGlineList;
87       if (!gline)
88         break;                  /* gline == NULL means gline == NULL */
89       continue;
90     }
91
92     /* Does gline match? */
93     /* Added a check against the user's IP address as well -Kev */
94     if ((GlineIsIpMask(gline) ?
95         match(gline->host, ircd_ntoa((const char*) &cptr->ip)) :
96         match(gline->host, cptr->sockhost)) == 0 &&
97         match(gline->name, cptr->user->username) == 0) {
98       if (pgline)
99         *pgline = prev; /* If they need it, give them the previous gline
100                                    entry (probably for free_gline, below) */
101       return gline;
102     }
103
104     prev = gline;
105     gline = gline->next;
106   }
107
108   return 0;                  /* found no glines */
109 }
110
111 void free_gline(struct Gline* gline, struct Gline* prev)
112 {
113   assert(0 != gline);
114   if (prev)
115     prev->next = gline->next;   /* squeeze agline out */
116   else { 
117 #ifdef BADCHAN
118     assert(0 != gline->host);
119     if ('#' == *gline->host ||
120         '&' == *gline->host ||
121         '+' == *gline->host) {
122       BadChanGlineList = gline->next;
123     }
124     else
125 #endif
126       GlobalGlineList = gline->next;
127   }
128
129   MyFree(gline->host);  /* and free up the memory */
130   MyFree(gline->reason);
131   MyFree(gline->name);
132   MyFree(gline);
133 }
134
135 void gline_remove_expired(time_t now)
136 {
137   struct Gline* gline;
138   struct Gline* prev = 0;
139   
140   for (gline = GlobalGlineList; gline; gline = gline->next) {
141     if (gline->expire < now) {
142       free_gline(gline, prev);
143       gline = (prev) ? prev : GlobalGlineList;
144       if (!gline)
145         break;
146       continue;
147     }
148     prev = gline;
149   }
150 }
151
152 #ifdef BADCHAN
153 int bad_channel(const char* name)
154
155   struct Gline* agline = BadChanGlineList;
156
157   while (agline)
158   { 
159     if ((agline->gflags & GLINE_ACTIVE) && (agline->expire > TStime()) && 
160          !mmatch(agline->host, name)) { 
161       return 1;
162     }
163     agline = agline->next;
164   }
165   return 0;
166 }
167
168 void bad_channel_remove_expired(time_t now)
169 {
170   struct Gline* gline;
171   struct Gline* prev = 0;
172   
173   for (gline = BadChanGlineList; gline; gline = gline->next) {
174     if (gline->expire < now) {
175       free_gline(gline, prev);
176       gline = (prev) ? prev : BadChanGlineList;
177       if (!gline)
178         break;
179       continue;
180     }
181     prev = gline;
182   }
183 }
184
185 #endif
186
187
188 void add_gline(struct Client *sptr, int ip_mask, char *host, char *comment,
189                char *user, time_t expire, int local)
190 {
191   struct Client *acptr;
192   struct Gline *agline;
193   int fd;
194   int gtype = 0;
195   assert(0 != host);
196
197 #ifdef BADCHAN
198   if ('#' == *host || '&' == *host || '+' == *host)
199     gtype = 1;   /* BAD CHANNEL */
200 #endif
201
202   /* Inform ops */
203   sendto_op_mask(SNO_GLINE,
204       "%s adding %s%s for %s@%s, expiring at " TIME_T_FMT ": %s", sptr->name,
205       local ? "local " : "",
206       gtype ? "BADCHAN" : "GLINE", user, host, expire, comment);
207
208 #ifdef GPATH
209   write_log(GPATH,
210       "# " TIME_T_FMT " %s adding %s %s for %s@%s, expiring at " TIME_T_FMT
211       ": %s\n", TStime(), sptr->name, local ? "local" : "global",
212       gtype ? "BADCHAN" : "GLINE", user, host, expire, comment);
213
214   /* this can be inserted into the conf */
215   if (!gtype)
216     write_log(GPATH, "%c:%s:%s:%s\n", ip_mask ? 'k' : 'K', host, comment, 
217       user);
218 #endif /* GPATH */
219
220   agline = make_gline(ip_mask, host, comment, user, expire);
221   if (local)
222     SetGlineIsLocal(agline);
223
224 #ifdef BADCHAN
225   if (gtype)
226     return;
227 #endif
228
229   for (fd = HighestFd; fd >= 0; --fd) { 
230     /*
231      * get the users!
232      */ 
233     if ((acptr = LocalClientArray[fd])) {
234       if (!acptr->user)
235         continue;
236 #if 0
237       /*
238        * whee!! :)
239        */
240       if (!acptr->user || strlen(acptr->sockhost) > HOSTLEN ||
241           (acptr->user->username ? strlen(acptr->user->username) : 0) > HOSTLEN)
242         continue;               /* these tests right out of
243                                    find_kill for safety's sake */
244 #endif
245
246       if ((GlineIsIpMask(agline) ?  match(agline->host, acptr->sock_ip) :
247           match(agline->host, acptr->sockhost)) == 0 &&
248           (!acptr->user->username ||
249           match(agline->name, acptr->user->username) == 0))
250       {
251
252         /* ok, he was the one that got G-lined */
253         sendto_one(acptr, ":%s %d %s :*** %s.", me.name,
254             ERR_YOUREBANNEDCREEP, acptr->name, agline->reason);
255
256         /* let the ops know about my first kill */
257         sendto_op_mask(SNO_GLINE, "G-line active for %s",
258             get_client_name(acptr, FALSE));
259
260         /* and get rid of him */
261         if (sptr != acptr)
262           exit_client(sptr->from, acptr, &me, "G-lined");
263       }
264     }
265   }
266 }
267