]> jfr.im git - irc/quakenet/newserv.git/blob - glines2/gline.c
gline->glines2, trusts_search->trusts2_search, trusts_newsearch->trusts2_newsearch
[irc/quakenet/newserv.git] / glines2 / gline.c
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <stdarg.h>
4 #include <string.h>
5 #include <time.h>
6 #include <assert.h>
7 #include <sys/socket.h>
8 #include <netinet/in.h>
9 #include <arpa/inet.h>
10
11 #include "../control/control.h"
12 #include "../nick/nick.h"
13 #include "../localuser/localuserchannel.h"
14 #include "../core/hooks.h"
15 #include "../server/server.h"
16 #include "../parser/parser.h"
17 #include "../core/schedule.h"
18 #include "../lib/array.h"
19 #include "../lib/base64.h"
20 #include "../lib/irc_string.h"
21 #include "../lib/splitline.h"
22 #include "../core/nsmalloc.h"
23
24 #include "gline.h"
25
26 gline* glinelist = 0, *glinelistnonnode = 0;
27
28 int glinecount = 0;
29 int badchancount = 0;
30 int rnglinecount = 0;
31 int gl_nodeext = -1;
32
33 /*
34 <prefix> GL <target> [!][+|-|>|<]<mask> [<expiration>] [<lastmod>]
35 [<lifetime>] [:<reason>]
36
37 */
38
39 void _init() {
40 gl_nodeext = registernodeext("gline");
41
42 if ( gl_nodeext == -1 ) {
43 Error("gline", ERR_FATAL, "Could not register a required node extension (gline)");
44 return;
45 }
46
47 registerserverhandler("GL", &handleglinemsg, 6);
48
49 /* send reburst command to get glines from before we registered handler */
50 irc_send("%s RB G", mynumeric->content);
51 }
52
53 void _fini() {
54 gline *gl, *ngl;
55
56 deregisterserverhandler("GL", &handleglinemsg);
57
58 for (gl=glinelist;gl;gl=ngl) {
59 ngl=gl->next;
60 freegline(gl);
61 }
62 glinelist = NULL;
63
64 if (gl_nodeext != -1)
65 releasenodeext(gl_nodeext);
66
67 nsfreeall(POOL_GLINE);
68 }
69
70 int gline_setnick(nick *np, int duration, char *reason ) {
71
72 }
73
74 int gline_setnode(patricia_node_t *node ) {
75
76 }
77
78 int gline_setmask(char *mask, int duration, char *reason ) {
79
80 }
81
82 gline* gline_add(long creatornum, sstring *creator, char *mask, char *reason, time_t expires, time_t lastmod, time_t lifetime) {
83 gline* gl;
84 char glineiddata[1024];
85
86 if ( !(gl=gline_processmask(mask))) { /* sets up nick,user,host,node and flags */
87 /* couldn't process gline mask */
88 Error("gline", ERR_WARNING, "Tried to add malformed G-Line %s!", mask);
89 return 0;
90 }
91
92 gl->creator = creator;
93 gl->numeric = creatornum;
94
95 /* it's not unreasonable to assume gline is active, if we're adding a deactivated gline, we can remove this later */
96 gl->flags = GLINE_ACTIVE;
97
98
99 /* set up gline id */
100 snprintf(glineiddata, sizeof(glineiddata), "gline %s %s", mask, reason);
101 gl->glineid = crc32(glineiddata);
102
103 gl->reason = getsstring(reason, 255); /*TODO@@@ */
104 gl->expires = expires;
105 gl->lastmod = lastmod;
106 gl->lifetime = lifetime;
107
108 /* Storage of glines */
109 /* ipbased glines are stored at node->ext[gl_nodeext]
110 * other glines are stored in seperate linked list (for now) */
111 if (gl->flags & GLINE_IPMASK) {
112 gl->nextbynode = gl->node->exts[gl_nodeext];
113 gl->node->exts[gl_nodeext] = gl;
114 } else {
115 gl->nextbynonnode = glinelistnonnode;
116 glinelistnonnode = gl;
117 }
118
119 gl->next = glinelist;
120 glinelist = gl;
121
122 return gl;
123 }
124
125 /* returns 1 on success, 0 on a bad mask */
126 gline* gline_processmask(char *mask) {
127 /* populate gl-> user,host,node,nick and set appropriate flags */
128 int len;
129 int foundat=-1,foundbang=-1;
130 int foundwild=0;
131 int i;
132 struct irc_in_addr sin;
133 unsigned char bits;
134 gline *gl = NULL;
135
136 if (!(gl = newgline())) {
137 Error("gline", ERR_ERROR, "Failed to allocate new gline");
138 return 0;
139 }
140
141 len=strlen(mask);
142
143 switch (*mask ) {
144 case '#':
145 case '&':
146 gl->flags |= GLINE_BADCHAN;
147 gl->user = getsstring(mask, CHANNELLEN);
148 return gl;
149 case '$':
150 switch (mask[1]) {
151 case 'R':
152 gl->flags |= GLINE_REALNAME;
153 break;
154 default:
155 Error("gline", ERR_WARNING, "Tried to add malformed G-Line %s!", mask);
156 return 0;
157 }
158 gl->user = getsstring(mask,REALLEN);
159 return gl;
160 default:
161 /* Default case of some host/ip/cidr mask */
162 for (i=(len-1);i>=0;i--) {
163 if (mask[i]=='@') {
164 /* host */
165 if ((len-i)-1 > HOSTLEN) {
166 /* host too long */
167 return 0;
168 } else if (i==(len-1)) {
169 /* no host supplied aka gline ends @ */
170 return 0;
171 } else if (i==(len-2) && mask[i+1]=='*') {
172 /* Special case: "@*" */
173 gl->flags |= GLINE_HOSTANY;
174 gl->host=NULL;
175 } else {
176 if (ipmask_parse(&mask[i+1], &sin, &bits) == 0) {
177 /* we have some host string */
178 gl->host=getsstring(&mask[i+1],HOSTLEN);
179 if (foundwild) {
180 gl->flags |= GLINE_HOSTMASK;
181 } else {
182 gl->flags |= GLINE_HOSTEXACT;
183 }
184 } else {
185 /* we have a / so cidr gline */
186 Error("gline", ERR_WARNING, "CIDR: %s", &mask[i+1]);
187 gl->node = refnode(iptree, &sin, bits);
188 gl->flags |= GLINE_IPMASK;
189 }
190 }
191 foundat=i;
192 break;
193 } else if (mask[i]=='?' || mask[i]=='*') {
194 if (!foundwild) /* Mark last wildcard in string */
195 foundwild=i;
196 }
197 }
198 }
199 /*TODO set hostexact/hostmask */
200 if (foundat<0) {
201 /* If there wasn't an @, this ban matches any host */
202 gl->host=NULL;
203 gl->flags |= GLINE_HOSTANY;
204 }
205
206 foundwild=0;
207
208 for (i=0;i<foundat;i++) {
209 if (mask[i]=='!') {
210 if (i==0) {
211 /* Invalid mask: nick is empty */
212 gl->flags |= GLINE_NICKNULL;
213 gl->nick=NULL;
214 } else if (i==1 && mask[0]=='*') {
215 /* matches any nick */
216 gl->flags |= GLINE_NICKANY;
217 gl->nick=NULL;
218 } else {
219 if (i>NICKLEN) {
220 /* too long: just take the first NICKLEN chars */
221 gl->nick=getsstring(mask,NICKLEN);
222 } else {
223 gl->nick=getsstring(mask,i);
224 }
225 if (foundwild)
226 gl->flags |= GLINE_NICKMASK;
227 else
228 gl->flags |= GLINE_NICKEXACT;
229 }
230 foundbang=i;
231 break;
232 } else if (mask[i]=='?' || mask[i]=='*') {
233 if (i<NICKLEN) {
234 foundwild=1;
235 }
236 }
237 }
238
239 if (foundbang<0) {
240 /* We didn't find a !, what we do now depends on what happened
241 * with the @ */
242 if (foundat<0) {
243 /* A gline with no ! or @ is treated as a nick ban only */
244 /* Note that we've special-cased "*" at the top, so we can only
245 * hit the MASK or EXACT case here. */
246 if (len>NICKLEN)
247 gl->nick=getsstring(mask,NICKLEN);
248 else
249 gl->nick=getsstring(mask,len);
250
251 if (foundwild)
252 gl->flags |= GLINE_NICKMASK;
253 else
254 gl->flags |= GLINE_NICKEXACT;
255
256 gl->flags |= (GLINE_USERANY | GLINE_HOSTANY);
257 gl->host=NULL;
258 gl->user=NULL;
259 } else {
260 /* A gline with @ only is treated as user@host */
261 gl->nick=NULL;
262 gl->flags |= GLINE_NICKANY;
263 }
264 }
265
266 if (foundat>=0) {
267 /* We found an @, so everything between foundbang+1 and foundat-1 is supposed to be ident */
268 /* This is true even if there was no !.. */
269 if (foundat==(foundbang+1)) {
270 /* empty ident matches nothing */ /*@@@TODO: * for glines? */
271 gl->flags |= (/*GLINE_INVALID |*/ GLINE_USERNULL);
272 gl->user=NULL;
273 } else if (foundat - foundbang - 1 > USERLEN) {
274 /* It's too long.. */
275 return 0;
276 } else if ((foundat - foundbang - 1 == 1) && mask[foundbang+1]=='*') {
277 gl->user=NULL;
278 gl->flags |= GLINE_USERANY;
279 } else {
280 gl->user=getsstring(&mask[foundbang+1],(foundat-foundbang-1));
281 if (strchr(gl->user->content,'*') || strchr(gl->user->content,'?'))
282 gl->flags |= GLINE_USERMASK;
283 else
284 gl->flags |= GLINE_USEREXACT;
285 }
286 /* Username part can't contain an @ */
287 if (gl->user && strchr(gl->user->content,'@')) {
288 //gl->flags |= CHANBAN_INVALID;
289 }
290 }
291
292 assert(gl->flags & (GLINE_USEREXACT | GLINE_USERMASK | GLINE_USERANY | GLINE_USERNULL));
293 assert(gl->flags & (GLINE_NICKEXACT | GLINE_NICKMASK | GLINE_NICKANY | GLINE_NICKNULL));
294 assert(gl->flags & (GLINE_HOSTEXACT | GLINE_HOSTMASK | GLINE_HOSTANY | GLINE_HOSTNULL | GLINE_IPMASK));
295
296 return gl;
297 }
298
299 gline *gline_find( char *mask) {
300 gline *gl;
301 gline *globalgline;
302
303 if( !(globalgline=gline_processmask(mask))) {
304 /* gline mask couldn't be processed */
305 return 0;
306 }
307
308 if (globalgline->flags & GLINE_IPMASK) {
309 gl = globalgline->node->exts[gl_nodeext];
310 while (gl) {
311 if ( gline_match( globalgline, gl) ) {
312 freegline(globalgline);
313 return gl;
314 }
315 gl = gl->nextbynode;
316 }
317 } else {
318 gl = glinelist;
319 while (gl) {
320 if ( gline_match( globalgline, gl ) ) {
321 freegline(globalgline);
322 return gl;
323 }
324 gl = gl->nextbynonnode;
325 }
326 }
327 freegline(globalgline);
328 return 0;
329 }
330
331 /* returns non-zero on match */
332 int gline_match ( gline *gla, gline *glb) {
333 if ((!gla->nick && glb->nick) || (gla->nick && !glb->nick))
334 return 0;
335
336 if (gla->nick && ircd_strcmp(gla->nick->content,glb->nick->content))
337 return 0;
338
339 if ((!gla->user && glb->user) || (gla->user && !glb->user))
340 return 0;
341
342 if (gla->user && ircd_strcmp(gla->user->content,glb->user->content))
343 return 0;
344
345 if ((!gla->host && glb->host) || (gla->host && !glb->host))
346 return 0;
347
348 if (gla->host && ircd_strcmp(gla->host->content,glb->host->content))
349 return 0;
350
351 /* TODO @@@ match bits flags */
352 return 1;
353 }
354
355 void gline_send(gline *gl) {
356
357 }