ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid/src/parse_aline.c
Revision: 851
Committed: Mon Feb 19 21:55:24 2007 UTC (19 years, 5 months ago) by bear
Content type: text/x-csrc
File size: 13150 byte(s)
Log Message:
Move some logic from m_kline.c to conf/kill.c, integrate stuff with new csvlib,
clean up / simplify / centralize some code.

parse_aline.c should really be called aline.c or so now

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 adx 801 #include "server.h"
30 db 91 #include "channel.h"
31     #include "client.h"
32     #include "common.h"
33     #include "hash.h"
34     #include "ircd.h"
35     #include "listener.h"
36     #include "numeric.h"
37     #include "send.h"
38     #include "userhost.h"
39 adx 801 #include "user.h"
40 db 91
41     static int find_user_host(struct Client *, char *, char *, char *, unsigned int);
42    
43 adx 747 int
44     valid_wild_card_simple(const char *data)
45     {
46     const unsigned char *p = (const unsigned char *)data;
47     int nonwild = 0;
48    
49     while (*p != '\0')
50     {
51     if ((*p == '\\' && *++p) || (*p && !IsMWildChar(*p)))
52     if (++nonwild == General.min_nonwildcard_simple)
53     return 1;
54     if (*p != '\0')
55     ++p;
56     }
57    
58     return 0;
59     }
60    
61 db 91 /* parse_aline
62     *
63     * input - pointer to cmd name being used
64     * - pointer to client using cmd
65     * - parc parameter count
66     * - parv[] list of parameters to parse
67 adx 745 * - parse_flags bit map of things to test
68     * - pointer to user or string to parse into
69 db 91 * - pointer to host or NULL to parse into if non NULL
70     * - pointer to optional tkline time or NULL
71     * - pointer to target_server to parse into if non NULL
72     * - pointer to reason to parse into
73     *
74     * output - 1 if valid, -1 if not valid
75     * side effects - A generalised k/d/x etc. line parser,
76     * "ALINE [time] user@host|string [ON] target :reason"
77     * will parse returning a parsed user, host if
78     * h_p pointer is non NULL, string otherwise.
79     * if tkline_time pointer is non NULL a tk line will be set
80     * to non zero if found.
81     * if tkline_time pointer is NULL and tk line is found,
82     * error is reported.
83     * if target_server is NULL and an "ON" is found error
84     * is reported.
85     * if reason pointer is NULL ignore pointer,
86     * this allows usee of parse_a_line in unkline etc.
87     *
88     * - Dianora
89     */
90     int
91     parse_aline(const char *cmd, struct Client *source_p,
92     int parc, char **parv,
93     int parse_flags, char **up_p, char **h_p, time_t *tkline_time,
94     char **target_server, char **reason)
95     {
96 michael 359 int found_tkline_time = 0;
97 db 91 static char def_reason[] = "No Reason";
98 michael 359 static char user[USERLEN * 4 + 1];
99     static char host[HOSTLEN * 4 + 1];
100 db 91
101 michael 359 ++parv;
102     --parc;
103 db 91
104     found_tkline_time = valid_tkline(*parv, TK_MINUTES);
105    
106     if (found_tkline_time != 0)
107     {
108 michael 359 ++parv;
109     --parc;
110 db 91
111     if (tkline_time != NULL)
112     *tkline_time = found_tkline_time;
113     else
114     {
115     sendto_one(source_p, ":%s NOTICE %s :temp_line not supported by %s",
116     me.name, source_p->name, cmd);
117     return -1;
118     }
119     }
120    
121 michael 359 if (parc == 0 || EmptyString(*parv))
122 db 91 {
123     sendto_one(source_p, form_str(ERR_NEEDMOREPARAMS),
124     me.name, source_p->name, cmd);
125     return -1;
126     }
127    
128     if (h_p == NULL)
129     *up_p = *parv;
130     else
131     {
132     if (find_user_host(source_p, *parv, user, host, parse_flags) == 0)
133     return -1;
134    
135     *up_p = user;
136     *h_p = host;
137     }
138    
139 michael 359 --parc;
140     ++parv;
141 db 91
142     if (parc != 0)
143     {
144 michael 359 if (!irccmp(*parv, "ON"))
145 db 91 {
146 michael 359 --parc;
147     ++parv;
148 db 91
149     if (target_server == NULL)
150     {
151 adx 745 sendto_one(source_p, ":%s NOTICE %s :ON server not supported by %s",
152 db 91 me.name, source_p->name, cmd);
153 adx 745 return -1;
154 db 91 }
155    
156     if (!IsOperRemoteBan(source_p))
157     {
158     sendto_one(source_p, form_str(ERR_NOPRIVS),
159     me.name, source_p->name, "remoteban");
160     return -1;
161     }
162    
163     if (parc == 0 || EmptyString(*parv))
164     {
165 adx 745 sendto_one(source_p, form_str(ERR_NEEDMOREPARAMS),
166     me.name, source_p->name, cmd);
167     return -1;
168 db 91 }
169    
170     *target_server = *parv;
171 michael 359 --parc;
172     ++parv;
173 db 91 }
174     else
175     {
176     /* Make sure target_server *is* NULL if no ON server found
177     * caller probably NULL'd it first, but no harm to do it again -db
178     */
179     if (target_server != NULL)
180 adx 745 *target_server = NULL;
181 db 91 }
182     }
183    
184     if (h_p != NULL)
185     {
186     if (strchr(user, '!') != NULL)
187     {
188     sendto_one(source_p, ":%s NOTICE %s :Invalid character '!' in kline",
189     me.name, source_p->name);
190     return -1;
191     }
192    
193     if ((parse_flags & AWILD) && !valid_wild_card(source_p, YES, 2, *up_p, *h_p))
194     return -1;
195     }
196     else
197     if ((parse_flags & AWILD) && !valid_wild_card(source_p, YES, 1, *up_p))
198     return -1;
199    
200     if (reason != NULL)
201     {
202 michael 359 if (parc != 0 && !EmptyString(*parv))
203 db 91 {
204     *reason = *parv;
205     if (!valid_comment(source_p, *reason, YES))
206 adx 745 return -1;
207 db 91 }
208     else
209     *reason = def_reason;
210     }
211    
212     return 1;
213     }
214    
215     /*
216     * cluster_a_line
217     *
218     * inputs - client sending the cluster
219     * - command name "KLINE" "XLINE" etc.
220 adx 801 * - capab -- CAP_KLN etc. from server.h
221 db 91 * - cluster type -- CLUSTER_KLINE etc. from s_conf.h
222     * - pattern and args to send along
223     * output - none
224     * side effects - Take source_p send the pattern with args given
225     * along to all servers that match capab and cluster type
226     */
227     void
228     cluster_a_line(struct Client *source_p, const char *command,
229 michael 261 int capab, int cluster_type, const char *pattern, ...)
230 db 91 {
231     va_list args;
232     char buffer[IRCD_BUFSIZE];
233 michael 261 dlink_node *ptr = NULL;
234 db 91
235     va_start(args, pattern);
236     vsnprintf(buffer, sizeof(buffer), pattern, args);
237     va_end(args);
238    
239 adx 745 DLINK_FOREACH(ptr, cluster_confs.head)
240 db 91 {
241 adx 745 const struct ClusterConf *conf = ptr->data;
242 db 91
243 adx 745 if ((conf->type & cluster_type))
244     sendto_match_servs(source_p, conf->server, CAP_CLUSTER|capab,
245     "%s %s %s", command, conf->server, buffer);
246 db 91 }
247     }
248    
249 bear 851 void
250     announce_a_line(struct Client *source_p, char *type, int expires,
251     char *reason, char *oper_reason, char *pattern, ...)
252     {
253     va_list args;
254     char what[IRCD_BUFSIZE], buf[IRCD_BUFSIZE];
255    
256     va_start(args, pattern);
257     vsnprintf(what, sizeof(what), pattern, args);
258     va_end(args);
259    
260     if (expires)
261     {
262     snprintf(buf, sizeof(buf), "temporary %d min. %s", expires/60, type);
263     type=buf;
264    
265     // Permanent ones have been announced when they were stored
266     sendto_one(source_p, ":%s NOTICE %s :Added %s [%s]", type, what);
267     }
268    
269     sendto_realops_flags(UMODE_ALL, L_ALL, "%s added %s for [%s] [%s%s%s]",
270     get_oper_name(source_p), type, what, reason,
271     oper_reason?"|":"", oper_reason?oper_reason:"");
272     ilog(L_TRACE, "%s added %s for [%s] [%s%s%s]",
273     get_oper_name(source_p), type, what, reason,
274     oper_reason?"|":"", oper_reason?oper_reason:"");
275    
276     // TODO: Fix _TYPE here (add a param)
277     log_oper_action(LOG_KLINE_TYPE, source_p, "[%s] [%s%s%s]\n", what, reason,
278     oper_reason?"|":"", oper_reason?oper_reason:"");
279     }
280    
281     char *
282     a_line_format_reason(char *reason, char *type, int tkline_time)
283     {
284     char buf[IRCD_BUFSIZE], *result;
285     if (tkline_time)
286     ircsprintf(buf, "Temporary %s %d min. - %s (%s)",
287     type, tkline_time/60, reason, smalldate(CurrentTime));
288     else
289     ircsprintf(buf, "%s (%s)",
290     reason, smalldate(CurrentTime));
291    
292     DupString(result, reason);
293     return result;
294     }
295    
296 db 91 /* valid_comment()
297     *
298 adx 745 * inputs - pointer to client
299 db 91 * - pointer to comment
300     * output - 0 if no valid comment,
301     * - 1 if valid
302     * side effects - truncates reason where necessary
303     */
304     int
305     valid_comment(struct Client *source_p, char *comment, int warn)
306     {
307     if (strchr(comment, '"'))
308     {
309     if (warn)
310     sendto_one(source_p, ":%s NOTICE %s :Invalid character '\"' in comment",
311     me.name, source_p->name);
312     return 0;
313     }
314    
315     if (strlen(comment) > REASONLEN)
316     comment[REASONLEN-1] = '\0';
317    
318     return 1;
319     }
320    
321     /* find_user_host()
322     *
323     * inputs - pointer to client placing kline
324     * - pointer to user_host_or_nick
325     * - pointer to user buffer
326     * - pointer to host buffer
327     * output - 0 if not ok to kline, 1 to kline i.e. if valid user host
328     * side effects -
329     */
330     static int
331     find_user_host(struct Client *source_p, char *user_host_or_nick,
332     char *luser, char *lhost, unsigned int flags)
333     {
334 michael 360 char lnick[NICKLEN];
335     struct split_nuh_item nuh;
336 db 91
337     if (lhost == NULL)
338     {
339     strlcpy(luser, user_host_or_nick, USERLEN*4 + 1);
340     return 1;
341     }
342    
343 michael 360 nuh.nuhmask = user_host_or_nick;
344     nuh.nickptr = lnick;
345     nuh.userptr = luser;
346     nuh.hostptr = lhost;
347 db 91
348 michael 360 nuh.nicksize = NICKLEN;
349     nuh.usersize = USERLEN*4+1;
350     nuh.hostsize = HOSTLEN*4+1;
351 michael 359
352 michael 360 split_nuh(&nuh);
353 michael 359
354 michael 360 if (!(flags & NOUSERLOOKUP) && irccmp(lnick, "*"))
355     {
356 metalrock 362 const struct Client *target_p = NULL;
357 michael 359
358 adx 745 // Try to find user@host mask from nick
359 michael 605 if ((target_p = find_chasing(source_p, lnick, NULL)) == NULL)
360 db 91 return 0;
361    
362     if (IsExemptKline(target_p))
363     {
364     if (!IsServer(source_p))
365 michael 360 sendto_one(source_p, ":%s NOTICE %s :%s is E-lined",
366     me.name, source_p->name, target_p->name);
367 db 91 return 0;
368     }
369    
370     /*
371     * turn the "user" bit into "*user", blow away '~'
372     * if found in original user name (non-idented)
373     */
374     strlcpy(luser, target_p->username, USERLEN*4 + 1);
375    
376     if (target_p->username[0] == '~')
377     luser[0] = '*';
378    
379 michael 360 if (target_p->sockhost[0] == '\0' || !irccmp(target_p->sockhost, "0"))
380 db 91 strlcpy(lhost, target_p->host, HOSTLEN*4 + 1);
381     else
382     strlcpy(lhost, target_p->sockhost, HOSTLEN*4 + 1);
383     return 1;
384     }
385    
386 michael 360 return 1;
387 db 91 }
388    
389     /*
390     * valid_tkline()
391     *
392     * inputs - pointer to ascii string to check
393     * - whether the specified time is in seconds or minutes
394     * output - -1 not enough parameters
395     * - 0 if not an integer number, else the number
396     * side effects - none
397     * Originally written by Dianora (Diane, db@db.net)
398     */
399     time_t
400 michael 359 valid_tkline(const char *in, int minutes)
401 db 91 {
402     time_t result = 0;
403 michael 359 const unsigned char *p = (const unsigned char *)in;
404 db 91
405 michael 359 for (; *p != '\0'; ++p)
406 db 91 {
407 michael 359 if (!IsDigit(*p))
408 db 91 return 0;
409 michael 359
410     result *= 10;
411     result += (*p & 0xF);
412 db 91 }
413    
414 michael 359 /*
415     * In the degenerate case where oper does a /quote kline 0 user@host :reason
416 db 91 * i.e. they specifically use 0, I am going to return 1 instead
417     * as a return value of non-zero is used to flag it as a temporary kline
418     */
419     if (result == 0)
420     result = 1;
421    
422     /*
423     * If the incoming time is in seconds convert it to minutes for the purpose
424     * of this calculation
425     */
426     if (!minutes)
427     result = result / (time_t)60;
428    
429     if (result > MAX_TDKLINE_TIME)
430     result = MAX_TDKLINE_TIME;
431    
432     result = result * (time_t)60; /* turn it into seconds */
433    
434     return result;
435     }
436    
437     /* valid_wild_card()
438     *
439     * input - pointer to client
440     * - int flag, 0 for no warning oper 1 for warning oper
441     * - count of following varargs to check
442     * output - 0 if not valid, 1 if valid
443     * side effects - NOTICE is given to source_p if warn is 1
444     */
445     int
446     valid_wild_card(struct Client *source_p, int warn, int count, ...)
447     {
448     char *p;
449     char tmpch;
450     int nonwild = 0;
451 stu 838 int anywild = 0;
452 db 91 va_list args;
453    
454     /*
455     * Now we must check the user and host to make sure there
456     * are at least NONWILDCHARS non-wildcard characters in
457     * them, otherwise assume they are attempting to kline
458     * *@* or some variant of that. This code will also catch
459     * people attempting to kline *@*.tld, as long as NONWILDCHARS
460     * is greater than 3. In that case, there are only 3 non-wild
461     * characters (tld), so if NONWILDCHARS is 4, the kline will
462     * be disallowed.
463     * -wnder
464     */
465     va_start(args, count);
466    
467     while (count--)
468     {
469     p = va_arg(args, char *);
470     if (p == NULL)
471     continue;
472    
473     while ((tmpch = *p++))
474     {
475     if (!IsKWildChar(tmpch))
476     {
477     /*
478     * If we find enough non-wild characters, we can
479     * break - no point in searching further.
480     */
481 adx 745 if (++nonwild >= General.min_nonwildcard)
482 db 91 return 1;
483     }
484 stu 838 else
485     anywild = 1;
486 db 91 }
487     }
488    
489 stu 838 /* There are no wild characters in the ban, allow it */
490     if(!anywild)
491     return 1;
492    
493 db 91 if (warn)
494 adx 745 sendto_one(source_p, ":%s NOTICE %s :Please include at least %d "
495     "non-wildcard characters with the mask",
496     me.name, source_p->name, General.min_nonwildcard);
497 db 91 return 0;
498     }

Properties

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