ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid/src/parse_aline.c
Revision: 747
Committed: Mon Jul 24 22:14:17 2006 UTC (20 years ago) by adx
Content type: text/x-csrc
File size: 11523 byte(s)
Log Message:
+ fixed everything except m_gline and m_spoof.
+ still to do: ban storage, limits, iphash, parser, conf_connect_allowed

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 "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     #include "s_user.h"
40    
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     * - capab -- CAP_KLN etc. from s_serv.h
221     * - 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     /* valid_comment()
250     *
251 adx 745 * inputs - pointer to client
252 db 91 * - pointer to comment
253     * output - 0 if no valid comment,
254     * - 1 if valid
255     * side effects - truncates reason where necessary
256     */
257     int
258     valid_comment(struct Client *source_p, char *comment, int warn)
259     {
260     if (strchr(comment, '"'))
261     {
262     if (warn)
263     sendto_one(source_p, ":%s NOTICE %s :Invalid character '\"' in comment",
264     me.name, source_p->name);
265     return 0;
266     }
267    
268     if (strlen(comment) > REASONLEN)
269     comment[REASONLEN-1] = '\0';
270    
271     return 1;
272     }
273    
274     /* find_user_host()
275     *
276     * inputs - pointer to client placing kline
277     * - pointer to user_host_or_nick
278     * - pointer to user buffer
279     * - pointer to host buffer
280     * output - 0 if not ok to kline, 1 to kline i.e. if valid user host
281     * side effects -
282     */
283     static int
284     find_user_host(struct Client *source_p, char *user_host_or_nick,
285     char *luser, char *lhost, unsigned int flags)
286     {
287 michael 360 char lnick[NICKLEN];
288     struct split_nuh_item nuh;
289 db 91
290     if (lhost == NULL)
291     {
292     strlcpy(luser, user_host_or_nick, USERLEN*4 + 1);
293     return 1;
294     }
295    
296 michael 360 nuh.nuhmask = user_host_or_nick;
297     nuh.nickptr = lnick;
298     nuh.userptr = luser;
299     nuh.hostptr = lhost;
300 db 91
301 michael 360 nuh.nicksize = NICKLEN;
302     nuh.usersize = USERLEN*4+1;
303     nuh.hostsize = HOSTLEN*4+1;
304 michael 359
305 michael 360 split_nuh(&nuh);
306 michael 359
307 michael 360 if (!(flags & NOUSERLOOKUP) && irccmp(lnick, "*"))
308     {
309 metalrock 362 const struct Client *target_p = NULL;
310 michael 359
311 adx 745 // Try to find user@host mask from nick
312 michael 605 if ((target_p = find_chasing(source_p, lnick, NULL)) == NULL)
313 db 91 return 0;
314    
315     if (IsExemptKline(target_p))
316     {
317     if (!IsServer(source_p))
318 michael 360 sendto_one(source_p, ":%s NOTICE %s :%s is E-lined",
319     me.name, source_p->name, target_p->name);
320 db 91 return 0;
321     }
322    
323     /*
324     * turn the "user" bit into "*user", blow away '~'
325     * if found in original user name (non-idented)
326     */
327     strlcpy(luser, target_p->username, USERLEN*4 + 1);
328    
329     if (target_p->username[0] == '~')
330     luser[0] = '*';
331    
332 michael 360 if (target_p->sockhost[0] == '\0' || !irccmp(target_p->sockhost, "0"))
333 db 91 strlcpy(lhost, target_p->host, HOSTLEN*4 + 1);
334     else
335     strlcpy(lhost, target_p->sockhost, HOSTLEN*4 + 1);
336     return 1;
337     }
338    
339 michael 360 return 1;
340 db 91 }
341    
342     /*
343     * valid_tkline()
344     *
345     * inputs - pointer to ascii string to check
346     * - whether the specified time is in seconds or minutes
347     * output - -1 not enough parameters
348     * - 0 if not an integer number, else the number
349     * side effects - none
350     * Originally written by Dianora (Diane, db@db.net)
351     */
352     time_t
353 michael 359 valid_tkline(const char *in, int minutes)
354 db 91 {
355     time_t result = 0;
356 michael 359 const unsigned char *p = (const unsigned char *)in;
357 db 91
358 michael 359 for (; *p != '\0'; ++p)
359 db 91 {
360 michael 359 if (!IsDigit(*p))
361 db 91 return 0;
362 michael 359
363     result *= 10;
364     result += (*p & 0xF);
365 db 91 }
366    
367 michael 359 /*
368     * In the degenerate case where oper does a /quote kline 0 user@host :reason
369 db 91 * i.e. they specifically use 0, I am going to return 1 instead
370     * as a return value of non-zero is used to flag it as a temporary kline
371     */
372     if (result == 0)
373     result = 1;
374    
375     /*
376     * If the incoming time is in seconds convert it to minutes for the purpose
377     * of this calculation
378     */
379     if (!minutes)
380     result = result / (time_t)60;
381    
382     if (result > MAX_TDKLINE_TIME)
383     result = MAX_TDKLINE_TIME;
384    
385     result = result * (time_t)60; /* turn it into seconds */
386    
387     return result;
388     }
389    
390     /* valid_wild_card()
391     *
392     * input - pointer to client
393     * - int flag, 0 for no warning oper 1 for warning oper
394     * - count of following varargs to check
395     * output - 0 if not valid, 1 if valid
396     * side effects - NOTICE is given to source_p if warn is 1
397     */
398     int
399     valid_wild_card(struct Client *source_p, int warn, int count, ...)
400     {
401     char *p;
402     char tmpch;
403     int nonwild = 0;
404     va_list args;
405    
406     /*
407     * Now we must check the user and host to make sure there
408     * are at least NONWILDCHARS non-wildcard characters in
409     * them, otherwise assume they are attempting to kline
410     * *@* or some variant of that. This code will also catch
411     * people attempting to kline *@*.tld, as long as NONWILDCHARS
412     * is greater than 3. In that case, there are only 3 non-wild
413     * characters (tld), so if NONWILDCHARS is 4, the kline will
414     * be disallowed.
415     * -wnder
416     */
417     va_start(args, count);
418    
419     while (count--)
420     {
421     p = va_arg(args, char *);
422     if (p == NULL)
423     continue;
424    
425     while ((tmpch = *p++))
426     {
427     if (!IsKWildChar(tmpch))
428     {
429     /*
430     * If we find enough non-wild characters, we can
431     * break - no point in searching further.
432     */
433 adx 745 if (++nonwild >= General.min_nonwildcard)
434 db 91 return 1;
435     }
436     }
437     }
438    
439     if (warn)
440 adx 745 sendto_one(source_p, ":%s NOTICE %s :Please include at least %d "
441     "non-wildcard characters with the mask",
442     me.name, source_p->name, General.min_nonwildcard);
443 db 91 return 0;
444     }

Properties

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