ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid/src/parse_aline.c
Revision: 741
Committed: Sun Jul 23 13:49:20 2006 UTC (20 years ago) by adx
Content type: text/x-csrc
File size: 18428 byte(s)
Log Message:
+ removed s_conf.h and superseded parts of s_conf.c

File Contents

# User Rev Content
1 db 91 /*
2     * ircd-hybrid: an advanced Internet Relay Chat Daemon(ircd).
3     * parse_aline.c: All the functions needed for klining etc.
4     *
5     * Copyright (C) 2005 by the past and present ircd coders, and others.
6     *
7     * This program is free software; you can redistribute it and/or modify
8     * it under the terms of the GNU General Public License as published by
9     * the Free Software Foundation; either version 2 of the License, or
10     * (at your option) any later version.
11     *
12     * This program is distributed in the hope that it will be useful,
13     * but WITHOUT ANY WARRANTY; without even the implied warranty of
14     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15     * GNU General Public License for more details.
16     *
17     * You should have received a copy of the GNU General Public License
18     * along with this program; if not, write to the Free Software
19     * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
20     * USA
21     *
22     * $Id$
23     */
24    
25     #include "stdinc.h"
26 adx 719 #include "conf/conf.h"
27 db 91 #include "ircd_defs.h"
28     #include "parse_aline.h"
29     #include "s_serv.h"
30     #include "resv.h"
31     #include "channel.h"
32     #include "client.h"
33     #include "common.h"
34     #include "hash.h"
35     #include "ircd.h"
36     #include "listener.h"
37     #include "hostmask.h"
38     #include "numeric.h"
39     #include "send.h"
40     #include "userhost.h"
41     #include "s_user.h"
42    
43     static void expire_tklines(dlink_list *);
44     static int find_user_host(struct Client *, char *, char *, char *, unsigned int);
45    
46    
47     dlink_list temporary_klines = { NULL, NULL, 0 };
48     dlink_list temporary_dlines = { NULL, NULL, 0 };
49     dlink_list temporary_xlines = { NULL, NULL, 0 };
50     dlink_list temporary_rklines = { NULL, NULL, 0 };
51     dlink_list temporary_glines = { NULL, NULL, 0 };
52     dlink_list temporary_rxlines = { NULL, NULL, 0 };
53 michael 359 dlink_list temporary_resv = { NULL, NULL, 0 };
54 db 91
55     /* parse_aline
56     *
57     * input - pointer to cmd name being used
58     * - pointer to client using cmd
59     * - parc parameter count
60     * - parv[] list of parameters to parse
61     * - parse_flags bit map of things to test
62     * - pointer to user or string to parse into
63     * - pointer to host or NULL to parse into if non NULL
64     * - pointer to optional tkline time or NULL
65     * - pointer to target_server to parse into if non NULL
66     * - pointer to reason to parse into
67     *
68     * output - 1 if valid, -1 if not valid
69     * side effects - A generalised k/d/x etc. line parser,
70     * "ALINE [time] user@host|string [ON] target :reason"
71     * will parse returning a parsed user, host if
72     * h_p pointer is non NULL, string otherwise.
73     * if tkline_time pointer is non NULL a tk line will be set
74     * to non zero if found.
75     * if tkline_time pointer is NULL and tk line is found,
76     * error is reported.
77     * if target_server is NULL and an "ON" is found error
78     * is reported.
79     * if reason pointer is NULL ignore pointer,
80     * this allows usee of parse_a_line in unkline etc.
81     *
82     * - Dianora
83     */
84     int
85     parse_aline(const char *cmd, struct Client *source_p,
86     int parc, char **parv,
87     int parse_flags, char **up_p, char **h_p, time_t *tkline_time,
88     char **target_server, char **reason)
89     {
90 michael 359 int found_tkline_time = 0;
91 db 91 static char def_reason[] = "No Reason";
92 michael 359 static char user[USERLEN * 4 + 1];
93     static char host[HOSTLEN * 4 + 1];
94 db 91
95 michael 359 ++parv;
96     --parc;
97 db 91
98     found_tkline_time = valid_tkline(*parv, TK_MINUTES);
99    
100     if (found_tkline_time != 0)
101     {
102 michael 359 ++parv;
103     --parc;
104 db 91
105     if (tkline_time != NULL)
106     *tkline_time = found_tkline_time;
107     else
108     {
109     sendto_one(source_p, ":%s NOTICE %s :temp_line not supported by %s",
110     me.name, source_p->name, cmd);
111     return -1;
112     }
113     }
114    
115 michael 359 if (parc == 0 || EmptyString(*parv))
116 db 91 {
117     sendto_one(source_p, form_str(ERR_NEEDMOREPARAMS),
118     me.name, source_p->name, cmd);
119     return -1;
120     }
121    
122     if (h_p == NULL)
123     *up_p = *parv;
124     else
125     {
126     if (find_user_host(source_p, *parv, user, host, parse_flags) == 0)
127     return -1;
128    
129     *up_p = user;
130     *h_p = host;
131     }
132    
133 michael 359 --parc;
134     ++parv;
135 db 91
136     if (parc != 0)
137     {
138 michael 359 if (!irccmp(*parv, "ON"))
139 db 91 {
140 michael 359 --parc;
141     ++parv;
142 db 91
143     if (target_server == NULL)
144     {
145     sendto_one(source_p, ":%s NOTICE %s :ON server not supported by %s",
146     me.name, source_p->name, cmd);
147     return -1;
148     }
149    
150     if (!IsOperRemoteBan(source_p))
151     {
152     sendto_one(source_p, form_str(ERR_NOPRIVS),
153     me.name, source_p->name, "remoteban");
154     return -1;
155     }
156    
157     if (parc == 0 || EmptyString(*parv))
158     {
159     sendto_one(source_p, form_str(ERR_NEEDMOREPARAMS),
160     me.name, source_p->name, cmd);
161     return -1;
162     }
163    
164     *target_server = *parv;
165 michael 359 --parc;
166     ++parv;
167 db 91 }
168     else
169     {
170     /* Make sure target_server *is* NULL if no ON server found
171     * caller probably NULL'd it first, but no harm to do it again -db
172     */
173     if (target_server != NULL)
174     *target_server = NULL;
175     }
176     }
177    
178     if (h_p != NULL)
179     {
180     if (strchr(user, '!') != NULL)
181     {
182     sendto_one(source_p, ":%s NOTICE %s :Invalid character '!' in kline",
183     me.name, source_p->name);
184     return -1;
185     }
186    
187     if ((parse_flags & AWILD) && !valid_wild_card(source_p, YES, 2, *up_p, *h_p))
188     return -1;
189     }
190     else
191     if ((parse_flags & AWILD) && !valid_wild_card(source_p, YES, 1, *up_p))
192     return -1;
193    
194     if (reason != NULL)
195     {
196 michael 359 if (parc != 0 && !EmptyString(*parv))
197 db 91 {
198     *reason = *parv;
199     if (!valid_comment(source_p, *reason, YES))
200     return -1;
201     }
202     else
203     *reason = def_reason;
204     }
205    
206     return 1;
207     }
208    
209     /*
210     * cluster_a_line
211     *
212     * inputs - client sending the cluster
213     * - command name "KLINE" "XLINE" etc.
214     * - capab -- CAP_KLN etc. from s_serv.h
215     * - cluster type -- CLUSTER_KLINE etc. from s_conf.h
216     * - pattern and args to send along
217     * output - none
218     * side effects - Take source_p send the pattern with args given
219     * along to all servers that match capab and cluster type
220     */
221     void
222     cluster_a_line(struct Client *source_p, const char *command,
223 michael 261 int capab, int cluster_type, const char *pattern, ...)
224 db 91 {
225     va_list args;
226     char buffer[IRCD_BUFSIZE];
227 michael 261 dlink_node *ptr = NULL;
228 db 91
229     va_start(args, pattern);
230     vsnprintf(buffer, sizeof(buffer), pattern, args);
231     va_end(args);
232    
233     DLINK_FOREACH(ptr, cluster_items.head)
234     {
235 michael 261 const struct ConfItem *conf = ptr->data;
236 db 91
237 michael 261 if (conf->conf.MatchItem.action & cluster_type)
238 db 91 sendto_match_servs(source_p, conf->name, CAP_CLUSTER|capab,
239     "%s %s %s", command, conf->name, buffer);
240     }
241     }
242    
243     /* valid_comment()
244     *
245     * inputs - pointer to client
246     * - pointer to comment
247     * output - 0 if no valid comment,
248     * - 1 if valid
249     * side effects - truncates reason where necessary
250     */
251     int
252     valid_comment(struct Client *source_p, char *comment, int warn)
253     {
254     if (strchr(comment, '"'))
255     {
256     if (warn)
257     sendto_one(source_p, ":%s NOTICE %s :Invalid character '\"' in comment",
258     me.name, source_p->name);
259     return 0;
260     }
261    
262     if (strlen(comment) > REASONLEN)
263     comment[REASONLEN-1] = '\0';
264    
265     return 1;
266     }
267    
268     /* find_user_host()
269     *
270     * inputs - pointer to client placing kline
271     * - pointer to user_host_or_nick
272     * - pointer to user buffer
273     * - pointer to host buffer
274     * output - 0 if not ok to kline, 1 to kline i.e. if valid user host
275     * side effects -
276     */
277     static int
278     find_user_host(struct Client *source_p, char *user_host_or_nick,
279     char *luser, char *lhost, unsigned int flags)
280     {
281 michael 360 char lnick[NICKLEN];
282     struct split_nuh_item nuh;
283 db 91
284     if (lhost == NULL)
285     {
286     strlcpy(luser, user_host_or_nick, USERLEN*4 + 1);
287     return 1;
288     }
289    
290 michael 360 nuh.nuhmask = user_host_or_nick;
291     nuh.nickptr = lnick;
292     nuh.userptr = luser;
293     nuh.hostptr = lhost;
294 db 91
295 michael 360 nuh.nicksize = NICKLEN;
296     nuh.usersize = USERLEN*4+1;
297     nuh.hostsize = HOSTLEN*4+1;
298 michael 359
299 michael 360 split_nuh(&nuh);
300 michael 359
301 michael 360 if (!(flags & NOUSERLOOKUP) && irccmp(lnick, "*"))
302     {
303 metalrock 362 const struct Client *target_p = NULL;
304 michael 359
305 db 91 /* Try to find user@host mask from nick */
306 michael 605 if ((target_p = find_chasing(source_p, lnick, NULL)) == NULL)
307 db 91 return 0;
308    
309     if (IsExemptKline(target_p))
310     {
311     if (!IsServer(source_p))
312 michael 360 sendto_one(source_p, ":%s NOTICE %s :%s is E-lined",
313     me.name, source_p->name, target_p->name);
314 db 91 return 0;
315     }
316    
317     /*
318     * turn the "user" bit into "*user", blow away '~'
319     * if found in original user name (non-idented)
320     */
321     strlcpy(luser, target_p->username, USERLEN*4 + 1);
322    
323     if (target_p->username[0] == '~')
324     luser[0] = '*';
325    
326 michael 360 if (target_p->sockhost[0] == '\0' || !irccmp(target_p->sockhost, "0"))
327 db 91 strlcpy(lhost, target_p->host, HOSTLEN*4 + 1);
328     else
329     strlcpy(lhost, target_p->sockhost, HOSTLEN*4 + 1);
330     return 1;
331     }
332    
333 michael 360 return 1;
334 db 91 }
335    
336     /*
337     * valid_tkline()
338     *
339     * inputs - pointer to ascii string to check
340     * - whether the specified time is in seconds or minutes
341     * output - -1 not enough parameters
342     * - 0 if not an integer number, else the number
343     * side effects - none
344     * Originally written by Dianora (Diane, db@db.net)
345     */
346     time_t
347 michael 359 valid_tkline(const char *in, int minutes)
348 db 91 {
349     time_t result = 0;
350 michael 359 const unsigned char *p = (const unsigned char *)in;
351 db 91
352 michael 359 for (; *p != '\0'; ++p)
353 db 91 {
354 michael 359 if (!IsDigit(*p))
355 db 91 return 0;
356 michael 359
357     result *= 10;
358     result += (*p & 0xF);
359 db 91 }
360    
361 michael 359 /*
362     * In the degenerate case where oper does a /quote kline 0 user@host :reason
363 db 91 * i.e. they specifically use 0, I am going to return 1 instead
364     * as a return value of non-zero is used to flag it as a temporary kline
365     */
366     if (result == 0)
367     result = 1;
368    
369     /*
370     * If the incoming time is in seconds convert it to minutes for the purpose
371     * of this calculation
372     */
373     if (!minutes)
374     result = result / (time_t)60;
375    
376     if (result > MAX_TDKLINE_TIME)
377     result = MAX_TDKLINE_TIME;
378    
379     result = result * (time_t)60; /* turn it into seconds */
380    
381     return result;
382     }
383    
384     /* valid_wild_card()
385     *
386     * input - pointer to client
387     * - int flag, 0 for no warning oper 1 for warning oper
388     * - count of following varargs to check
389     * output - 0 if not valid, 1 if valid
390     * side effects - NOTICE is given to source_p if warn is 1
391     */
392     int
393     valid_wild_card(struct Client *source_p, int warn, int count, ...)
394     {
395     char *p;
396     char tmpch;
397     int nonwild = 0;
398     va_list args;
399    
400     /*
401     * Now we must check the user and host to make sure there
402     * are at least NONWILDCHARS non-wildcard characters in
403     * them, otherwise assume they are attempting to kline
404     * *@* or some variant of that. This code will also catch
405     * people attempting to kline *@*.tld, as long as NONWILDCHARS
406     * is greater than 3. In that case, there are only 3 non-wild
407     * characters (tld), so if NONWILDCHARS is 4, the kline will
408     * be disallowed.
409     * -wnder
410     */
411    
412     va_start(args, count);
413    
414     while (count--)
415     {
416     p = va_arg(args, char *);
417     if (p == NULL)
418     continue;
419    
420     while ((tmpch = *p++))
421     {
422     if (!IsKWildChar(tmpch))
423     {
424     /*
425     * If we find enough non-wild characters, we can
426     * break - no point in searching further.
427     */
428     if (++nonwild >= ConfigFileEntry.min_nonwildcard)
429     return 1;
430     }
431     }
432     }
433    
434     if (warn)
435     sendto_one(source_p, ":%s NOTICE %s :Please include at least %d non-wildcard characters with the mask",
436     me.name, source_p->name, ConfigFileEntry.min_nonwildcard);
437     return 0;
438     }
439    
440     /* find_kill()
441     *
442     * inputs - pointer to client structure
443     * output - pointer to struct AccessItem if found
444     * side effects - See if this user is klined already,
445     * and if so, return struct AccessItem pointer
446     */
447     struct AccessItem *
448     find_kill(struct Client *client_p)
449     {
450     struct AccessItem *aconf = NULL;
451     const char *uhi[3];
452    
453     uhi[0] = client_p->username;
454     uhi[1] = client_p->host;
455     uhi[2] = client_p->sockhost;
456    
457     assert(client_p != NULL);
458    
459     aconf = find_kline_conf(client_p->host, client_p->username,
460     &client_p->localClient->ip,
461     client_p->localClient->aftype);
462     if (aconf == NULL)
463     aconf = find_regexp_kline(uhi);
464    
465     if (aconf && (aconf->status & CONF_KLINE))
466     return aconf;
467    
468     return NULL;
469     }
470    
471     struct AccessItem *
472     find_gline(struct Client *client_p)
473     {
474     struct AccessItem *aconf;
475    
476     assert(client_p != NULL);
477    
478     aconf = find_gline_conf(client_p->host, client_p->username,
479     &client_p->localClient->ip,
480     client_p->localClient->aftype);
481    
482     if (aconf && (aconf->status & CONF_GLINE))
483     return aconf;
484    
485     return NULL;
486     }
487    
488     /* add_temp_line()
489     *
490     * inputs - pointer to struct ConfItem
491     * output - none
492     * Side effects - links in given struct ConfItem into
493     * temporary *line link list
494     */
495     void
496     add_temp_line(struct ConfItem *conf)
497     {
498     struct AccessItem *aconf;
499    
500     if (conf->type == DLINE_TYPE)
501     {
502 db 139 aconf = &conf->conf.AccessItem;
503 db 91 SetConfTemporary(aconf);
504     dlinkAdd(conf, &conf->node, &temporary_dlines);
505     MyFree(aconf->user);
506     aconf->user = NULL;
507     add_conf_by_address(CONF_DLINE, aconf);
508     }
509     else if (conf->type == KLINE_TYPE)
510     {
511 db 139 aconf = &conf->conf.AccessItem;
512 db 91 SetConfTemporary(aconf);
513     dlinkAdd(conf, &conf->node, &temporary_klines);
514     add_conf_by_address(CONF_KILL, aconf);
515     }
516     else if (conf->type == GLINE_TYPE)
517     {
518 db 139 aconf = &conf->conf.AccessItem;
519 db 91 SetConfTemporary(aconf);
520     dlinkAdd(conf, &conf->node, &temporary_glines);
521     add_conf_by_address(CONF_GLINE, aconf);
522     }
523     else if (conf->type == XLINE_TYPE)
524     {
525     conf->flags |= CONF_FLAGS_TEMPORARY;
526     dlinkAdd(conf, make_dlink_node(), &temporary_xlines);
527     }
528     else if (conf->type == RXLINE_TYPE)
529     {
530     conf->flags |= CONF_FLAGS_TEMPORARY;
531     dlinkAdd(conf, make_dlink_node(), &temporary_rxlines);
532     }
533     else if (conf->type == RKLINE_TYPE)
534     {
535     conf->flags |= CONF_FLAGS_TEMPORARY;
536     dlinkAdd(conf, make_dlink_node(), &temporary_rklines);
537     }
538     else if ((conf->type == NRESV_TYPE) || (conf->type == CRESV_TYPE))
539     {
540     conf->flags |= CONF_FLAGS_TEMPORARY;
541     dlinkAdd(conf, make_dlink_node(), &temporary_resv);
542     }
543     }
544    
545     /* cleanup_tklines()
546     *
547     * inputs - NONE
548     * output - NONE
549     * side effects - call function to expire temporary k/d lines
550     * This is an event started off in ircd.c
551     */
552     void
553     cleanup_tklines(void *notused)
554     {
555     expire_tklines(&temporary_glines);
556     expire_tklines(&temporary_klines);
557     expire_tklines(&temporary_dlines);
558     expire_tklines(&temporary_xlines);
559     expire_tklines(&temporary_rxlines);
560     expire_tklines(&temporary_rklines);
561     expire_tklines(&temporary_resv);
562     }
563    
564     /* expire_tklines()
565     *
566     * inputs - tkline list pointer
567     * output - NONE
568     * side effects - expire tklines
569     */
570     static void
571     expire_tklines(dlink_list *tklist)
572     {
573     dlink_node *ptr;
574     dlink_node *next_ptr;
575     struct ConfItem *conf;
576     struct MatchItem *xconf;
577     struct MatchItem *nconf;
578     struct AccessItem *aconf;
579     struct ResvChannel *cconf;
580    
581     DLINK_FOREACH_SAFE(ptr, next_ptr, tklist->head)
582     {
583     conf = ptr->data;
584     if (conf->type == GLINE_TYPE ||
585     conf->type == KLINE_TYPE ||
586     conf->type == DLINE_TYPE)
587     {
588 db 139 aconf = &conf->conf.AccessItem;
589 db 91 if (aconf->hold <= CurrentTime)
590     {
591     /* XXX - Do we want GLINE expiry notices?? */
592     /* Alert opers that a TKline expired - Hwy */
593     if (ConfigFileEntry.tkline_expire_notices)
594     {
595     if (aconf->status & CONF_KILL)
596     {
597     sendto_realops_flags(UMODE_ALL, L_ALL,
598     "Temporary K-line for [%s@%s] expired",
599     (aconf->user) ? aconf->user : "*",
600     (aconf->host) ? aconf->host : "*");
601     }
602     else if (conf->type == DLINE_TYPE)
603     {
604     sendto_realops_flags(UMODE_ALL, L_ALL,
605     "Temporary D-line for [%s] expired",
606     (aconf->host) ? aconf->host : "*");
607     }
608     }
609    
610     delete_one_address_conf(aconf->host, aconf);
611     dlinkDelete(ptr, tklist);
612     }
613     }
614     else if (conf->type == XLINE_TYPE ||
615     conf->type == RXLINE_TYPE)
616     {
617 db 139 xconf = &conf->conf.MatchItem;
618 db 91 if (xconf->hold <= CurrentTime)
619     {
620     if (ConfigFileEntry.tkline_expire_notices)
621     sendto_realops_flags(UMODE_ALL, L_ALL,
622     "Temporary X-line for [%s] %sexpired", conf->name,
623     conf->type == RXLINE_TYPE ? "(REGEX) " : "");
624     dlinkDelete(ptr, tklist);
625     free_dlink_node(ptr);
626     delete_conf_item(conf);
627     }
628     }
629     else if (conf->type == RKLINE_TYPE)
630     {
631 db 139 aconf = &conf->conf.AccessItem;
632 db 91 if (aconf->hold <= CurrentTime)
633     {
634     if (ConfigFileEntry.tkline_expire_notices)
635     sendto_realops_flags(UMODE_ALL, L_ALL,
636     "Temporary K-line for [%s@%s] (REGEX) expired",
637     (aconf->user) ? aconf->user : "*",
638     (aconf->host) ? aconf->host : "*");
639     dlinkDelete(ptr, tklist);
640     free_dlink_node(ptr);
641     delete_conf_item(conf);
642     }
643     }
644     else if (conf->type == NRESV_TYPE)
645     {
646 db 139 nconf = &conf->conf.MatchItem;
647 db 91 if (nconf->hold <= CurrentTime)
648     {
649     if (ConfigFileEntry.tkline_expire_notices)
650     sendto_realops_flags(UMODE_ALL, L_ALL,
651     "Temporary RESV for [%s] expired", conf->name);
652     dlinkDelete(ptr, tklist);
653     free_dlink_node(ptr);
654     delete_conf_item(conf);
655     }
656     }
657     else if (conf->type == CRESV_TYPE)
658     {
659 db 139 cconf = &conf->conf.ResvChannel;
660 db 91 if (cconf->hold <= CurrentTime)
661     {
662     if (ConfigFileEntry.tkline_expire_notices)
663     sendto_realops_flags(UMODE_ALL, L_ALL,
664     "Temporary RESV for [%s] expired", cconf->name);
665     dlinkDelete(ptr, tklist);
666     free_dlink_node(ptr);
667     delete_conf_item(conf);
668     }
669     }
670     }
671     }
672    
673     /*
674     * find_regexp_kline
675     *
676     * inputs -
677     * output - return a pointer to an AccessItem if present
678     * NULL if not
679     * side effects - none
680     */
681     struct AccessItem *
682     find_regexp_kline(const char *uhi[])
683     {
684     const dlink_node *ptr = NULL;
685    
686     DLINK_FOREACH(ptr, rkconf_items.head)
687     {
688 db 139 struct AccessItem *aptr = &((struct ConfItem *)ptr->data)->conf.AccessItem;
689 db 91
690     assert(aptr->regexuser);
691     assert(aptr->regexhost);
692    
693     if (!ircd_pcre_exec(aptr->regexuser, uhi[0]) &&
694     (!ircd_pcre_exec(aptr->regexhost, uhi[1]) ||
695     !ircd_pcre_exec(aptr->regexhost, uhi[2])))
696     return aptr;
697     }
698    
699     return NULL;
700     }

Properties

Name Value
svn:eol-style native
svn:keywords "Author Date Id Revision"