ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid-8/contrib/m_spoof.c
Revision: 1156
Committed: Tue Aug 9 20:29:20 2011 UTC (15 years, 2 months ago) by michael
Content type: text/x-csrc
File size: 14497 byte(s)
Log Message:
- create ircd-hybrid-8 "branch"

File Contents

# User Rev Content
1 adx 30 /*
2     * ircd-hybrid: an advanced Internet Relay Chat Daemon(ircd).
3     * m_spoof.c: Supports dynamic auth{} creation/deletion.
4     *
5     * Copyright (C) 2002 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 knight 31 * $Id$
23 adx 30 */
24    
25     /* MODULE CONFIGURATION FOLLOWS -- please read!! */
26    
27     /*
28     * change to #define if you want to propagate received SPOOF/DELSPOOF messages
29     * to other servers. This allows you create subnets inside which spoofs are
30     * propagated. By manipulating PROPAGATE_SPOOF and RECEIVE_SPOOF, you can
31     * prepare boundary hubs of such subnets.
32     *
33     * I realize a shared{} could be better, but I don't want to touch core code.
34     *
35     * If you decide to enable this, remember to load m_spoof on all servers
36     * I am connected to, or you'll get plenty of "Unknown command" errors...
37     */
38     #undef PROPAGATE_SPOOF
39    
40     /*
41     * this server is allowed to receive spoofs/delspoofs from other servers.
42     * Use in conjunction with PROPAGATE_SPOOF (on target servers).
43     */
44     #undef RECEIVE_SPOOF
45    
46     /* where to put dynamic auth's -- this must be included from ircd.conf!
47     * Ideally put .include "spoof.conf" before all other auths.
48     * #undef if you want only a propagating hub server, not storing any data */
49     #define SPOOF_FILE "etc/spoof.conf"
50    
51     /* disable if you don't want opers notices/logs */
52     #define LOG_SPOOF
53    
54    
55     /* END OF MODULE CONFIGURATION */
56    
57     /* Usage: SPOOF <umask@hmask> <free.form.spoof|-> [flags|- [password]]
58     * -- Appends an auth{} block. Flags consist of characters:
59     * t (no_tilde), i (need_ident), k (kline_exempt),
60     * g (gline_exempt), l (exceed_limit), o (class = "opers"),
61     * f (can_flood), p (need_password), everything other is ignored.
62     * DELSPOOF <umask@hmask>
63     * -- Removes an auth{} block of exact umask@hmask, if found
64     *
65     * These commands are restricted to admins, so make sure your oper{} block
66     * has admin = yes or so.
67     */
68    
69     #if !defined(PROPAGATE_SPOOF) && !defined(SPOOF_FILE)
70     #error You disabled both SPOOF_FILE and PROPAGATE_SPOOF, what do you expect me to do?
71     #endif
72    
73     /* List of ircd includes from ../include/ */
74     #include "stdinc.h"
75 michael 1011 #include "list.h"
76 adx 30 #include "handlers.h"
77     #include "client.h"
78     #include "common.h" /* FALSE bleah */
79     #include "hash.h"
80     #include "hostmask.h"
81     #include "ircd.h"
82     #include "irc_string.h"
83     #include "sprintf_irc.h"
84     #include "numeric.h"
85     #include "fdlist.h"
86     #include "s_bsd.h"
87     #include "s_conf.h"
88     #include "s_log.h"
89     #include "s_serv.h"
90     #include "send.h"
91     #include "msg.h"
92     #include "parse.h"
93     #include "modules.h"
94    
95     static void mo_spoof(struct Client *, struct Client *, int, char *[]);
96     static void mo_delspoof(struct Client *, struct Client *, int, char *[]);
97    
98     struct Message spoof_msgtab = {
99     "SPOOF", 0, 0, 3, 0, MFLG_SLOW, 0,
100     #ifdef RECEIVE_SPOOF
101     {m_unregistered, m_not_oper, mo_spoof, m_ignore, mo_spoof, m_ignore}
102     #else
103     {m_unregistered, m_not_oper, m_ignore, m_ignore, mo_spoof, m_ignore}
104     #endif
105     };
106    
107     struct Message delspoof_msgtab = {
108     "DELSPOOF", 0, 0, 1, 0, MFLG_SLOW, 0,
109     #ifdef RECEIVE_SPOOF
110     {m_unregistered, m_not_oper, mo_delspoof, m_ignore, mo_delspoof, m_ignore}
111     #else
112     {m_unregistered, m_not_oper, m_ignore, m_ignore, mo_delspoof, m_ignore}
113     #endif
114     };
115    
116     void
117     _modinit(void)
118     {
119     mod_add_cmd(&spoof_msgtab);
120     mod_add_cmd(&delspoof_msgtab);
121     }
122    
123     void
124     _moddeinit(void)
125     {
126     mod_del_cmd(&delspoof_msgtab);
127     mod_del_cmd(&spoof_msgtab);
128     }
129    
130 knight 31 const char *_version = "$Revision$";
131 adx 30
132     #ifdef SPOOF_FILE
133     static void
134     try_flag(FBFILE *f, int *flags, int flag, const char *string)
135     {
136     if ((*flags & flag))
137     {
138     fbputs(string, f, strlen(string));
139    
140     *flags &= ~flag;
141     fbputs(*flags ? ", " : ";\n", f, 2);
142     }
143     }
144     #endif
145    
146     static void
147     mo_spoof(struct Client *client_p, struct Client *source_p,
148     int parc, char *parv[])
149     {
150     char *host, *spoof, *password;
151     const char *tmp = NULL;
152     const char *user = NULL;
153     const char *flags = NULL;
154     int i = 0;
155     #ifdef SPOOF_FILE
156     int class_opers;
157     FBFILE *f;
158     char buffer[1024];
159     struct AddressRec *arec;
160     #endif
161    
162     if (MyConnect(source_p) && !IsOperAdmin(source_p))
163     {
164     sendto_one(source_p, form_str(ERR_NOPRIVS),
165     me.name, source_p->name, "SPOOF");
166     return;
167     }
168    
169     /* check the user@host mask */
170     if (strchr(parv[1], '!') != NULL)
171     {
172     syntax:
173     if (MyConnect(source_p))
174     sendto_one(source_p, ":%s NOTICE %s :Syntax: SPOOF <umask@hmask> "
175     "<spoof/-> [flags/- [password]]", me.name, source_p->name);
176     return;
177     }
178    
179     (void) collapse(parv[1]);
180    
181     for (tmp = parv[1]; *tmp; tmp++)
182     if (!IsKWildChar(*tmp))
183     if (++i >= ConfigFileEntry.min_nonwildcard)
184     break;
185     if (i < ConfigFileEntry.min_nonwildcard)
186     {
187     if (MyConnect(source_p))
188     sendto_one(source_p, ":%s NOTICE %s :Not enough non-wildcard characters "
189     "in user@host mask",
190     me.name, source_p->name);
191     return;
192     }
193    
194     host = strchr(parv[1], '@');
195     if (host)
196     {
197     user = parv[1];
198     *host = '\0';
199     host++;
200     }
201     else
202     {
203     user = "*";
204     host = parv[1];
205     }
206    
207     /* check the spoof field */
208     spoof = parv[2];
209     if (spoof == NULL || !*spoof)
210     goto syntax;
211    
212     if (spoof[0] != '-' || spoof[1] != '\0')
213     {
214     for (tmp = spoof; *tmp; tmp++)
215     if (!IsHostChar(*tmp)) {
216     if (MyConnect(source_p))
217     sendto_one(source_p, ":%s NOTICE %s :The spoof [%s] is invalid",
218     me.name, source_p->name, spoof);
219     return;
220     }
221     if (strlen(spoof) >= HOSTLEN) {
222     if (MyConnect(source_p))
223     sendto_one(source_p, ":%s NOTICE %s :Spoofs must be less than %d.."
224     "ignoring it", me.name, source_p->name, HOSTLEN);
225     return;
226     }
227     }
228    
229     flags = (parc > 3) ? parv[3] : "-";
230     password = (parc > 4 && parv[4][0]) ? parv[4] : NULL;
231    
232     #ifdef PROPAGATE_SPOOF
233 michael 885 sendto_server(client_p, NULL, NOCAPS, NOCAPS,
234 adx 30 ":%s SPOOF %s@%s %s %s :%s",
235     source_p->name, user, host, spoof, flags, password ? password : "");
236     #endif
237    
238     #ifdef SPOOF_FILE
239     /* Walk through auth {} items and check if we have another auth block
240     * for this hostname */
241     for (i = 0; i < ATABLE_SIZE; i++)
242     for (arec = atable[i]; arec; arec = arec->next)
243     if (arec->type == CONF_CLIENT && !irccmp(arec->aconf->host, host) &&
244     !irccmp(arec->aconf->user, user))
245     {
246     /* auth entry already exists */
247     if (MyConnect(source_p))
248     sendto_one(source_p,
249     ":%s NOTICE %s :auth for %s@%s already exists, you need "
250     "to use /DELSPOOF first", me.name, source_p->name, user, host);
251     #ifdef LOG_SPOOF
252     sendto_realops_flags(UMODE_ALL, L_ALL,
253     "%s attemped to re-add auth for %s@%s "
254     "[spoof: %s, flags: %s]", source_p->name, user, host,
255     spoof, flags);
256     #endif
257     return;
258     }
259    
260     /* Add the spoof to the the spoof file */
261     if ((f = fbopen(SPOOF_FILE, "a")) == NULL)
262     {
263     sendto_realops_flags(UMODE_ALL, L_ALL,
264     "Could not open %s file, auth for %s@%s "
265     "[spoof: %s, flags: %s, requested by %s] not added",
266     SPOOF_FILE, user, host, spoof, flags, source_p->name);
267     return;
268     }
269    
270     /* write the auth {} block */
271     fbputs("auth {\n", f, 7);
272     i = ircsprintf(buffer, "\tuser = \"%s@%s\";\n", user, host);
273     fbputs(buffer, f, i);
274     if (spoof[0] != '-' || spoof[1] != '\0')
275     {
276     i = ircsprintf(buffer, "\tspoof = \"%s\";\n", spoof);
277     fbputs(buffer, f, i);
278     }
279     if (password)
280     {
281     i = ircsprintf(buffer, "\tpassword = \"%s\";\n", password);
282     fbputs(buffer, f, i);
283     }
284    
285     /* process given flags */
286     i = class_opers = 0;
287     for (tmp = flags; *tmp; ++tmp)
288     switch (*tmp)
289     {
290     case 't': i |= CONF_FLAGS_NO_TILDE; /* no_tilde = yes; */
291     break;
292     case 'i': i |= CONF_FLAGS_NEED_IDENTD; /* need_ident = yes; */
293     break;
294     case 'k': i |= CONF_FLAGS_EXEMPTKLINE; /* kline_exempt = yes; */
295     break;
296     case 'g': i |= CONF_FLAGS_EXEMPTGLINE; /* gline_exempt = yes; */
297     break;
298     case 'l': i |= CONF_FLAGS_NOLIMIT; /* exceed_limit = yes; */
299     break;
300     case 'o': class_opers = 1; /* class = "opers"; */
301     break;
302     case 'f': i |= CONF_FLAGS_CAN_FLOOD; /* can_flood = yes; */
303     break;
304     case 'p': i|= CONF_FLAGS_NEED_PASSWORD; /* need_password = yes; */
305     }
306    
307     if (i)
308     {
309     fbputs("\tflags = ", f, 9);
310     try_flag(f, &i, CONF_FLAGS_NO_TILDE, "no_tilde");
311     try_flag(f, &i, CONF_FLAGS_NEED_IDENTD, "need_ident");
312     try_flag(f, &i, CONF_FLAGS_EXEMPTKLINE, "kline_exempt");
313     try_flag(f, &i, CONF_FLAGS_EXEMPTGLINE, "gline_exempt");
314     try_flag(f, &i, CONF_FLAGS_NOLIMIT, "exceed_limit");
315     try_flag(f, &i, CONF_FLAGS_CAN_FLOOD, "can_flood");
316     try_flag(f, &i, CONF_FLAGS_NEED_PASSWORD, "need_password");
317     }
318    
319     if (class_opers)
320     fbputs("\tclass = \"opers\";\n", f, 18);
321     else
322     fbputs("\tclass = \"users\";\n", f, 18);
323    
324     fbputs("};\n\n", f, 4);
325     fbclose(f);
326    
327     rehash(0);
328     #endif
329    
330     #ifdef LOG_SPOOF
331     sendto_realops_flags(UMODE_ALL, L_ALL,
332     "%s added auth for %s@%s [spoof: %s, flags: %s]",
333     source_p->name, user, host, spoof, flags);
334     ilog(L_TRACE, "%s added auth for %s@%s [spoof: %s, flags: %s]",
335     source_p->name, user, host, spoof, flags);
336     #endif
337     }
338    
339     /* Now, our job is a bit harder. I will scan through the SPOOF_FILE
340     * and read all auths{} (assuming they are written in our line formatting..),
341     * then rewrite them skipping the one to delete. --adx */
342     static void
343     mo_delspoof(struct Client *client_p, struct Client *source_p,
344     int parc, char *parv[])
345     {
346     #ifdef SPOOF_FILE
347     FBFILE *f, *fout;
348     int ignore_it = 1, spoof_found = 0;
349     char buffer[1024], *tmp;
350     #endif
351     const char *user = NULL;
352     char *host = NULL;
353    
354     if (MyConnect(source_p) && !IsOperAdmin(source_p))
355     {
356     sendto_one(source_p, form_str(ERR_NOPRIVS), me.name, parv[0], "DELSPOOF");
357     return;
358     }
359    
360     if (parv[1] == NULL || !*parv[1])
361     {
362     if (MyConnect(source_p))
363     sendto_one(source_p, ":%s NOTICE %s :Syntax: /DELSPOOF <user@host>",
364     me.name, source_p->name);
365     return;
366     }
367    
368     /* check user@host mask */
369     (void) collapse(parv[1]);
370    
371     host = strchr(parv[1], '@');
372     if (host != NULL)
373     {
374     user = parv[1];
375     *host = '\0';
376     host++;
377     }
378     else
379     {
380     user = "*";
381     host = parv[1];
382     }
383    
384     #ifdef PROPAGATE_SPOOF
385 michael 885 sendto_server(client_p, NULL, NOCAPS, NOCAPS,
386     ":%s DELSPOOF %s@%s", source_p->name, user, host);
387 adx 30 #endif
388    
389     #ifdef SPOOF_FILE
390     if ((f = fbopen(SPOOF_FILE, "r")) == NULL)
391     {
392     sendto_realops_flags(UMODE_ALL, L_ALL,
393     "Could not open %s file, auth for %s@%s not deleted "
394     "(requested by %s)",
395     SPOOF_FILE, user, host, source_p->name);
396     return;
397     }
398    
399     if ((fout = fbopen(SPOOF_FILE ".new", "w")) == NULL)
400     {
401     sendto_realops_flags(UMODE_ALL, L_ALL,
402     "Could not create %s.new file, auth for %s@%s not "
403     "deleted (requested by %s)",
404     SPOOF_FILE, user, host, source_p->name);
405     return;
406     }
407    
408     while (fbgets(buffer, 1024, f))
409     {
410     if (!ircncmp(buffer, "auth {", 6))
411     {
412     /* don't process it yet.. we have to check whether the user="..."; field
413     * matches the user@host mask which is being deleted
414     */
415     ignore_it = 1;
416     continue;
417     }
418    
419     /* a simple parser substitute... */
420     for (tmp = buffer; *tmp == '\t' || *tmp == ' '; tmp++)
421     ;
422     if (!ircncmp(tmp, "user", 4))
423     {
424     for (tmp += 4; *tmp == '\t' || *tmp == ' '; tmp++)
425     ;
426     if (*tmp == '=') {
427     for (++tmp; *tmp == '\t' || *tmp == ' '; tmp++)
428     ;
429     if (*tmp == '\"')
430     {
431     /* yuppi, we've just reached the user="..."; field */
432     int matches;
433     char *tmp2 = strchr(++tmp, '\"');
434    
435     if (tmp2 != NULL)
436     *tmp2 = '\0';
437     tmp2 = strchr(tmp, '@');
438    
439     /* is it matching our mask? */
440     if (tmp2 == NULL)
441     matches = !irccmp(user, "*") && !irccmp(host, tmp);
442     else
443     {
444     *tmp2++ = '\0';
445     matches = !irccmp(user, tmp) && !irccmp(host, tmp2);
446     }
447    
448     if (!matches)
449     {
450     /* no.. so leave it unchanged */
451     if (ignore_it)
452     {
453     ignore_it = 0;
454     fbputs("auth {\n", fout, 7);
455     /* user="..." should be the first field in the auth {}; block,
456     * otherwise we could have problems...
457     */
458     }
459    
460     fbputs("\tuser = \"", fout, 9);
461     if (tmp2 == NULL)
462     fbputs("*", fout, 1);
463     else
464     fbputs(tmp, fout, strlen(tmp));
465     fbputs("@", fout, 1);
466     fbputs(tmp2, fout, strlen(tmp2));
467     fbputs("\";\n", fout, 3);
468     }
469     else
470     {
471     /* we've got it! - omit and continue working */
472     spoof_found = 1;
473     }
474    
475     continue;
476     }
477     }
478     }
479    
480     if (!ignore_it)
481     fbputs(buffer, fout, strlen(buffer));
482     }
483    
484     fbclose(f);
485     fbclose(fout);
486    
487     if (!spoof_found)
488     {
489     if (MyConnect(source_p))
490     sendto_one(source_p, ":%s NOTICE %s :No auth for %s@%s found",
491     me.name, source_p->name, user, host);
492     unlink(SPOOF_FILE ".new");
493     return;
494     }
495    
496     unlink(SPOOF_FILE);
497     rename(SPOOF_FILE ".new", SPOOF_FILE);
498     rehash(0);
499     #endif
500    
501     #ifdef LOG_SPOOF
502     sendto_realops_flags(UMODE_ALL, L_ALL, "%s deleted auth for %s@%s",
503     source_p->name, user, host);
504     #endif
505     }

Properties

Name Value
svn:eol-style native
svn:keywords Id Revision