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

# Content
1 /*
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 #include "conf/conf.h"
27 #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 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 /* 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 * - parse_flags bit map of things to test
68 * - pointer to user or string to parse into
69 * - 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 int found_tkline_time = 0;
97 static char def_reason[] = "No Reason";
98 static char user[USERLEN * 4 + 1];
99 static char host[HOSTLEN * 4 + 1];
100
101 ++parv;
102 --parc;
103
104 found_tkline_time = valid_tkline(*parv, TK_MINUTES);
105
106 if (found_tkline_time != 0)
107 {
108 ++parv;
109 --parc;
110
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 if (parc == 0 || EmptyString(*parv))
122 {
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 --parc;
140 ++parv;
141
142 if (parc != 0)
143 {
144 if (!irccmp(*parv, "ON"))
145 {
146 --parc;
147 ++parv;
148
149 if (target_server == NULL)
150 {
151 sendto_one(source_p, ":%s NOTICE %s :ON server not supported by %s",
152 me.name, source_p->name, cmd);
153 return -1;
154 }
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 sendto_one(source_p, form_str(ERR_NEEDMOREPARAMS),
166 me.name, source_p->name, cmd);
167 return -1;
168 }
169
170 *target_server = *parv;
171 --parc;
172 ++parv;
173 }
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 *target_server = NULL;
181 }
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 if (parc != 0 && !EmptyString(*parv))
203 {
204 *reason = *parv;
205 if (!valid_comment(source_p, *reason, YES))
206 return -1;
207 }
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 int capab, int cluster_type, const char *pattern, ...)
230 {
231 va_list args;
232 char buffer[IRCD_BUFSIZE];
233 dlink_node *ptr = NULL;
234
235 va_start(args, pattern);
236 vsnprintf(buffer, sizeof(buffer), pattern, args);
237 va_end(args);
238
239 DLINK_FOREACH(ptr, cluster_confs.head)
240 {
241 const struct ClusterConf *conf = ptr->data;
242
243 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 }
247 }
248
249 /* valid_comment()
250 *
251 * inputs - pointer to client
252 * - 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 char lnick[NICKLEN];
288 struct split_nuh_item nuh;
289
290 if (lhost == NULL)
291 {
292 strlcpy(luser, user_host_or_nick, USERLEN*4 + 1);
293 return 1;
294 }
295
296 nuh.nuhmask = user_host_or_nick;
297 nuh.nickptr = lnick;
298 nuh.userptr = luser;
299 nuh.hostptr = lhost;
300
301 nuh.nicksize = NICKLEN;
302 nuh.usersize = USERLEN*4+1;
303 nuh.hostsize = HOSTLEN*4+1;
304
305 split_nuh(&nuh);
306
307 if (!(flags & NOUSERLOOKUP) && irccmp(lnick, "*"))
308 {
309 const struct Client *target_p = NULL;
310
311 // Try to find user@host mask from nick
312 if ((target_p = find_chasing(source_p, lnick, NULL)) == NULL)
313 return 0;
314
315 if (IsExemptKline(target_p))
316 {
317 if (!IsServer(source_p))
318 sendto_one(source_p, ":%s NOTICE %s :%s is E-lined",
319 me.name, source_p->name, target_p->name);
320 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 if (target_p->sockhost[0] == '\0' || !irccmp(target_p->sockhost, "0"))
333 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 return 1;
340 }
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 valid_tkline(const char *in, int minutes)
354 {
355 time_t result = 0;
356 const unsigned char *p = (const unsigned char *)in;
357
358 for (; *p != '\0'; ++p)
359 {
360 if (!IsDigit(*p))
361 return 0;
362
363 result *= 10;
364 result += (*p & 0xF);
365 }
366
367 /*
368 * In the degenerate case where oper does a /quote kline 0 user@host :reason
369 * 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 if (++nonwild >= General.min_nonwildcard)
434 return 1;
435 }
436 }
437 }
438
439 if (warn)
440 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 return 0;
444 }

Properties

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