ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid/contrib/m_operspy.c
Revision: 76
Committed: Tue Oct 4 19:38:49 2005 UTC (20 years, 10 months ago) by adx
Content type: text/x-csrc
File size: 17278 byte(s)
Log Message:
- fixed contrib #includes

File Contents

# User Rev Content
1 adx 30 /************************************************************************
2     * IRC - Internet Relay Chat, contrib/m_operspy.c
3     * Copyright (C) 2002 William Bierman III and the Hybrid Development Team
4     *
5     * This program is free software; you can redistribute it and/or modify
6     * it under the terms of the GNU General Public License as published by
7     * the Free Software Foundation; either version 1, or (at your option)
8     * any later version.
9     *
10     * This program is distributed in the hope that it will be useful,
11     * but WITHOUT ANY WARRANTY; without even the implied warranty of
12     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13     * GNU General Public License for more details.
14     *
15     * You should have received a copy of the GNU General Public License
16     * along with this program; if not, write to the Free Software
17     * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18     *
19 knight 31 * $Id$
20 adx 30 */
21    
22     /*** PLEASE READ ME ***/
23     /*
24     * This module gives an extraordinary amount of power to the opers
25     * who have the access to use it. It allows for users' privacy to
26     * be pretty much obliterated. The Hybrid Team assumes absolutely
27     * no responsibility for this file's (mis)use.
28     *
29     * - billy-jon
30     */
31    
32     #include "stdinc.h"
33     #include "handlers.h"
34     #include "channel.h"
35     #include "channel_mode.h"
36     #include "client.h"
37     #include "common.h" /* FALSE bleah */
38     #include "ircd.h"
39     #include "numeric.h"
40     #include "s_conf.h"
41     #include "s_serv.h"
42     #include "send.h"
43     #include "msg.h"
44     #include "parse.h"
45     #include "modules.h"
46     #include "hash.h"
47    
48     /* enable logging of OPERSPY functions */
49     #define OPERSPY_LOG
50    
51     /* enable this to log all local/remote operspy usage to a logfile */
52     #define OPERSPY_LOGFILE
53    
54     /* enable this to send incoming operspy usage to connected +y (UMODE_SPY) opers */
55     #define OPERSPY_NOTICE
56    
57     /* enable OPERSPY version of LIST */
58     #define OPERSPY_LIST
59    
60     /* enable OPERSPY version of MODE */
61     #define OPERSPY_MODE
62    
63     /* enable OPERSPY version of NAMES */
64     #define OPERSPY_NAMES
65    
66     /* enable OPERSPY version of WHO */
67     #define OPERSPY_WHO
68    
69     /* enable OPERSPY version of WHOIS */
70     #define OPERSPY_WHOIS
71    
72     /* enable OPERSPY version of TOPIC */
73     #define OPERSPY_TOPIC
74    
75     #define IsOperspy(x) (IsOper(x) && MyClient(x) && IsAdmin(x))
76    
77     /* The commands we will add */
78     static void ms_operspy(struct Client *, struct Client *, int, char *[]);
79     static void mo_operspy(struct Client *, struct Client *, int, char *[]);
80    
81     /* extensions for OPERSPY WHO */
82     static void do_who(struct Client *, struct Client *, char *, const char *);
83     static void who_global(struct Client *, char *, int);
84     static void do_who_on_channel(struct Client *, struct Channel *, char *);
85    
86     static void operspy_list(struct Client *, int, char *[]);
87     static void operspy_mode(struct Client *, int, char *[]);
88     static void operspy_names(struct Client *, int, char *[]);
89     static void operspy_topic(struct Client *, int, char *[]);
90     static void operspy_who(struct Client *, int, char *[]);
91     static void operspy_whois(struct Client *, int, char *[]);
92    
93    
94     struct Message operspy_msgtab = {
95     "OPERSPY", 0, 0, 3, 4, MFLG_SLOW, 0,
96     {m_ignore, m_not_oper, ms_operspy, ms_operspy, mo_operspy, m_ignore}
97     };
98    
99     static const struct operspy_s {
100     const char *const cmd;
101     void (*const func_p)(struct Client *, int, char *[]);
102     } operspy_table[] = {
103     #ifdef OPERSPY_LIST
104     { "LIST", operspy_list },
105     #endif
106     #ifdef OPERSPY_MODE
107     { "MODE", operspy_mode },
108     #endif
109     #ifdef OPERSPY_NAMES
110     { "NAMES", operspy_names },
111     #endif
112     #ifdef OPERSPY_TOPIC
113     { "TOPIC", operspy_topic },
114     #endif
115     #ifdef OPERSPY_WHO
116     { "WHO", operspy_who },
117     #endif
118     #ifdef OPERSPY_WHOIS
119     { "WHOIS", operspy_whois },
120     #endif
121     { NULL, NULL }
122     };
123    
124     #ifndef STATIC_MODULES
125     void
126     _modinit(void)
127     {
128     mod_add_cmd(&operspy_msgtab);
129     }
130    
131     void
132     _moddeinit(void)
133     {
134     mod_del_cmd(&operspy_msgtab);
135     }
136 knight 31 const char *_version = "$Revision$";
137 adx 30 #endif
138    
139     #ifdef OPERSPY_LOG
140     static void operspy_log(struct Client *, const char *, const char *);
141     #endif
142    
143     static void
144     ms_operspy(struct Client *client_p, struct Client *source_p,
145     int parc, char *parv[])
146     {
147     #ifdef OPERSPY_LOG
148     operspy_log(source_p, parv[1], parv[2]);
149     #endif
150     }
151    
152     /* mo_operspy()
153     * parv[1] = operspy command
154     * parv[2] = command parameter
155     */
156     static void
157     mo_operspy(struct Client *client_p, struct Client *source_p,
158     int parc, char *parv[])
159     {
160     char cmdbuf[IRCD_BUFSIZE] = "<NONE>"; /* in case everything is undef'd */
161     size_t bcnt = 0;
162     const struct operspy_s *optr = NULL;
163    
164     if (!IsOperspy(client_p))
165     {
166     sendto_one(client_p, form_str(ERR_NOPRIVILEGES),
167     me.name, client_p->name);
168     return;
169     }
170    
171     assert(client_p == source_p);
172    
173     for (optr = operspy_table; optr->cmd; ++optr)
174     {
175     if (!irccmp(optr->cmd, parv[1]))
176     {
177     (*optr->func_p)(client_p, parc, parv);
178     return;
179     }
180     }
181    
182     for (optr = operspy_table; optr->cmd; ++optr)
183     {
184     /* str*cat is slow and sucks */
185     bcnt += strlcpy(cmdbuf+bcnt, optr->cmd, sizeof(cmdbuf)-bcnt);
186     if ((optr + 1)->cmd != NULL && bcnt < (sizeof(cmdbuf)-2))
187     {
188     cmdbuf[bcnt++] = ',';
189     cmdbuf[bcnt++] = ' ';
190     }
191     }
192    
193     sendto_one(client_p, ":%s NOTICE %s :%s is not a valid option. Choose from %s",
194     me.name, client_p->name, parv[1], cmdbuf);
195     }
196    
197     static void
198     operspy_list(struct Client *client_p, int parc, char *parv[])
199     {
200     const dlink_node *ptr = NULL;
201     #ifdef OPERSPY_LOG
202     operspy_log(client_p, "LIST", parv[2]);
203     #endif
204    
205     if (*parv[2] == '\0')
206     return;
207    
208     sendto_one(client_p, form_str(RPL_LISTSTART),
209     me.name, client_p->name);
210    
211     DLINK_FOREACH(ptr, global_channel_list.head)
212     {
213     const struct Channel *chptr_list = ptr->data;
214    
215     if (match_chan(parv[2], chptr_list->chname))
216     {
217     sendto_one(client_p, form_str(RPL_LIST), me.name, client_p->name,
218     chptr_list->chname, dlink_list_length(&chptr_list->members),
219     chptr_list->topic == NULL ? "" : chptr_list->topic);
220     }
221     }
222    
223     sendto_one(client_p, form_str(RPL_LISTEND),
224     me.name, client_p->name);
225     }
226    
227     static void
228     operspy_mode(struct Client *client_p, int parc, char *parv[])
229     {
230     /* needed to preserve actual client status */
231     int c_status = 0;
232     char modebuf[MODEBUFLEN];
233     char parabuf[MODEBUFLEN];
234     struct Channel *chptr_mode = NULL;
235    
236     if ((chptr_mode = hash_find_channel(parv[2])) == NULL)
237     {
238     /*
239     * according to m_mode.c, the channel *could* exist on the uplink still,
240     * but I don't see how. Even if it does, we won't be able to spy without
241     * info.
242     */
243     sendto_one(client_p, form_str(ERR_NOSUCHCHANNEL),
244     me.name, client_p->name, parv[2]);
245     return;
246     }
247    
248     #ifdef OPERSPY_LOG
249     operspy_log(client_p, "MODE", parv[2]);
250     #endif
251    
252     /*
253     * XXX - this is a dirty nasty kludge to trick channel_modes()
254     * into giving us the key
255     */
256     c_status = client_p->status;
257     client_p->status = STAT_SERVER;
258    
259     channel_modes(chptr_mode, client_p, modebuf, parabuf);
260     client_p->status = c_status;
261    
262     sendto_one(client_p, form_str(RPL_CHANNELMODEIS),
263     me.name, client_p->name, parv[2], modebuf, parabuf);
264     sendto_one(client_p, form_str(RPL_CREATIONTIME),
265     me.name, client_p->name, parv[2], chptr_mode->channelts);
266     }
267    
268     static void
269     operspy_names(struct Client *client_p, int parc, char *parv[])
270     {
271     /* as with mode, must preserve channel modes */
272     struct Channel *chptr_names = NULL;
273    
274     if ((chptr_names = hash_find_channel(parv[2])) == NULL)
275     {
276     sendto_one(client_p, form_str(ERR_NOSUCHCHANNEL),
277     me.name, client_p->name, parv[2]);
278     return;
279     }
280    
281     #ifdef OPERSPY_LOG
282     operspy_log(client_p, "NAMES", parv[2]);
283     #endif
284    
285     /* the way to go with this, rather than temporarily setting -sp,
286     * is to temporarily add our client to the member list. then
287     * we can also list +i users. an unfortunate side-effect of this
288     * is that your nickname shows up in the list. for now, there is
289     * no easy way around it.
290     */
291     add_user_to_channel(chptr_names, client_p, CHFL_CHANOP, NO);
292     channel_member_names(client_p, chptr_names, 1);
293     remove_user_from_channel(find_channel_link(client_p, chptr_names));
294     }
295    
296     static void
297     operspy_topic(struct Client *client_p, int parc, char *parv[])
298     {
299     const struct Channel *chptr_topic = NULL;
300    
301     if ((chptr_topic = hash_find_channel(parv[2])) == NULL)
302     {
303     sendto_one(client_p, form_str(ERR_NOSUCHCHANNEL),
304     me.name, client_p->name, parv[2]);
305     return;
306     }
307    
308     #ifdef OPERSPY_LOG
309     operspy_log(client_p, "TOPIC", parv[2]);
310     #endif
311    
312     if (chptr_topic->topic == NULL)
313     sendto_one(client_p, form_str(RPL_NOTOPIC),
314     me.name, client_p->name, parv[2]);
315     else
316     {
317     sendto_one(client_p, form_str(RPL_TOPIC), me.name, client_p->name,
318     chptr_topic->chname, chptr_topic->topic);
319     sendto_one(client_p, form_str(RPL_TOPICWHOTIME), me.name,
320     client_p->name, chptr_topic->chname, chptr_topic->topic_info,
321     chptr_topic->topic_time);
322     }
323     }
324    
325     static void
326     operspy_who(struct Client *client_p, int parc, char *parv[])
327     {
328     char *mask = parc > 2 ? parv[2] : NULL;
329     int server_oper = parc > 3 ? (*parv[3] == 'o') : 0;
330     struct Channel *chptr_who = NULL;
331     struct Client *target_p_who = NULL;
332    
333     if (mask != NULL)
334     {
335     collapse(mask);
336    
337     if (*mask == '\0')
338     {
339     sendto_one(client_p, form_str(RPL_ENDOFWHO),
340     me.name, client_p->name, "*");
341     return;
342     }
343     }
344     else
345     {
346     #ifdef OPERSPY_LOG
347     operspy_log(client_p, "WHO", "*");
348     #endif
349     who_global(client_p, NULL, server_oper);
350     sendto_one(client_p, form_str(RPL_ENDOFWHO),
351     me.name, client_p->name, "*");
352     return;
353     }
354    
355     /* /who #channel */
356     if (IsChanPrefix(*mask))
357     {
358     if ((chptr_who = hash_find_channel(mask)) != NULL)
359     {
360     #ifdef OPERSPY_LOG
361     operspy_log(client_p, "WHO", mask);
362     #endif
363     do_who_on_channel(client_p, chptr_who, chptr_who->chname);
364     }
365    
366     sendto_one(client_p, form_str(RPL_ENDOFWHO),
367     me.name, client_p->name, mask);
368     return;
369     }
370    
371     /* /who nick */
372     if ((target_p_who = find_person(client_p, mask)) != NULL)
373     {
374     #ifdef OPERSPY_LOG
375     /* "nick!user@host server\0" */
376     char nuh[NICKLEN + 1 + USERLEN + 1 + HOSTLEN + 1 + HOSTLEN + 1];
377    
378     ircsprintf(nuh, "%s!%s@%s %s", target_p_who->name,
379     target_p_who->username, target_p_who->host,
380     target_p_who->servptr->name);
381     operspy_log(client_p, "WHO", nuh);
382     #endif
383    
384     if (target_p_who->channel.head != NULL)
385     {
386     chptr_who =
387     ((struct Membership *)target_p_who->channel.head->data)->chptr;
388    
389     do_who(client_p, target_p_who, chptr_who->chname,
390     get_member_status(target_p_who->channel.head->data, NO));
391     }
392     else
393     {
394     do_who(client_p, target_p_who, NULL, "");
395     }
396    
397     sendto_one(client_p, form_str(RPL_ENDOFWHO),
398     me.name, client_p->name, mask);
399     return;
400     }
401    
402     #ifdef OPERSPY_LOG
403     operspy_log(client_p, "WHO", parv[2]);
404     #endif
405    
406     /* /who 0 */
407     if ((*(mask + 1) == '\0') && (*mask == '0'))
408     who_global(client_p, NULL, server_oper);
409     else
410     who_global(client_p, mask, server_oper);
411    
412     /* nothing else? end of /who. */
413     sendto_one(client_p, form_str(RPL_ENDOFWHO),
414     me.name, client_p->name, mask);
415     }
416    
417     static void
418     operspy_whois(struct Client *client_p, int parc, char *parv[])
419     {
420     const dlink_node *lp;
421     struct Channel *chptr_whois = NULL;
422     struct Client *a2client_p;
423     struct Client *target_p = NULL;
424     char buf[IRCD_BUFSIZE];
425     #ifdef OPERSPY_LOG
426     /* "nick!user@host server\0" */
427     char nuh[NICKLEN + 1 + USERLEN + 1 + HOSTLEN + 1 + HOSTLEN + 1];
428     #endif
429     char *t = NULL;
430     int mlen, tlen;
431     int cur_len = 0;
432     int reply_to_send = NO;
433    
434     if (strchr(parv[2], '?') || strchr(parv[2], '*'))
435     {
436     sendto_one(client_p, ":%s NOTICE %s :Do not use wildcards with this.",
437     me.name, client_p->name);
438     return;
439     }
440    
441     if ((target_p = find_person(client_p, parv[2])) == NULL)
442     {
443     sendto_one(client_p, form_str(ERR_NOSUCHNICK),
444     me.name, client_p->name, parv[2]);
445     return;
446     }
447    
448     #ifdef OPERSPY_LOG
449     ircsprintf(nuh, "%s!%s@%s %s",
450     target_p->name, target_p->username, target_p->host,
451     target_p->servptr->name);
452     operspy_log(client_p, "WHOIS", nuh);
453     #endif
454    
455     a2client_p = target_p->servptr;
456    
457     sendto_one(client_p, form_str(RPL_WHOISUSER), me.name,
458     client_p->name, target_p->name, target_p->username,
459     target_p->host, target_p->info);
460     mlen = ircsprintf(buf, form_str(RPL_WHOISCHANNELS), me.name,
461     client_p->name, target_p->name, "");
462     cur_len = mlen;
463     t = buf + mlen;
464    
465     DLINK_FOREACH(lp, target_p->channel.head)
466     {
467     chptr_whois = ((struct Membership *)lp->data)->chptr;
468    
469     if ((cur_len + strlen(chptr_whois->chname) + 2) > (IRCD_BUFSIZE - 4))
470     {
471     sendto_one(client_p, "%s", buf);
472     cur_len = mlen;
473     t = buf + mlen;
474     }
475    
476     tlen = ircsprintf(t, "%s%s%s ",
477     ShowChannel(client_p, chptr_whois) ? "" : "%",
478     get_member_status((struct Membership *)lp->data, YES),
479     chptr_whois->chname);
480     t += tlen;
481     cur_len += tlen;
482     reply_to_send = YES;
483     }
484    
485     if (reply_to_send == YES)
486     sendto_one(client_p, "%s", buf);
487    
488     sendto_one(client_p, form_str(RPL_WHOISSERVER), me.name,
489     client_p->name, target_p->name, a2client_p->name,
490     a2client_p->info);
491    
492     if (IsOper(target_p))
493     sendto_one(client_p, form_str(IsAdmin(target_p) ? RPL_WHOISADMIN :
494     RPL_WHOISOPERATOR), me.name, client_p->name, target_p->name);
495    
496     if (MyConnect(target_p))
497     sendto_one(client_p, form_str(RPL_WHOISIDLE), me.name,
498     client_p->name, target_p->name, CurrentTime - target_p->localClient->last,
499     target_p->firsttime);
500     sendto_one(client_p, form_str(RPL_ENDOFWHOIS),
501     me.name, client_p->name, parv[2]);
502     }
503    
504     /* extensions for OPERSPY WHO */
505     static void
506     do_who(struct Client *source_p, struct Client *target_p,
507     char *chname, const char *op_flags)
508     {
509     char status[8];
510    
511     ircsprintf(status, "%c%s%s", target_p->away ? 'G' : 'H',
512     IsOper(target_p) ? "*" : "", op_flags);
513     sendto_one(source_p, form_str(RPL_WHOREPLY), me.name, source_p->name,
514     (chname) ? (chname) : "*",
515     target_p->username,
516     target_p->host, target_p->servptr->name, target_p->name,
517     status, target_p->hopcount, target_p->info);
518     }
519    
520     static void
521     who_global(struct Client *source_p, char *mask, int server_oper)
522     {
523     struct Client *target_p;
524     dlink_node *lp;
525     int maxmatches = 500;
526    
527     /* list all matching visible clients */
528     DLINK_FOREACH(lp, global_client_list.head)
529     {
530     target_p = lp->data;
531    
532     if (!IsClient(target_p))
533     continue;
534    
535     if (server_oper && !IsOper(target_p))
536     continue;
537    
538     if (!mask ||
539     match(mask, target_p->name) || match(mask, target_p->username) ||
540     match(mask, target_p->host) || match(mask, target_p->servptr->name) ||
541     match(mask, target_p->info) ||
542     (MyClient(target_p) && match(mask, target_p->sockhost)))
543     {
544     if (dlink_list_length(&target_p->channel))
545     {
546     struct Channel *chptr;
547     static char fl[5];
548    
549     chptr = ((struct Membership *)(target_p->channel.head->data))->chptr;
550     snprintf(fl, sizeof(fl), "%s",
551     get_member_status((struct Membership *)(target_p->channel.head->data), NO));
552    
553     do_who(source_p, target_p, chptr->chname, fl);
554     }
555     else
556     do_who(source_p, target_p, NULL, "");
557    
558     if (maxmatches > 0)
559     {
560     if (--maxmatches == 0)
561     return;
562     }
563     }
564     }
565     }
566    
567     static void
568     do_who_on_channel(struct Client *source_p, struct Channel *chptr,
569     char *chname)
570     {
571     dlink_node *ptr;
572     struct Membership *ms;
573    
574     DLINK_FOREACH(ptr, chptr->members.head)
575     {
576     ms = ptr->data;
577     do_who(source_p, ms->client_p, chname, get_member_status(ms, NO));
578     }
579     }
580    
581     #ifdef OPERSPY_LOG
582     static void
583     operspy_log(struct Client *source_p, const char *command, const char *target)
584     {
585     struct ConfItem *conf = NULL;
586     #ifdef OPERSPY_LOGFILE
587     size_t nbytes = 0;
588     FBFILE *operspy_fb;
589     dlink_node *cnode;
590     const char *opername = source_p->name;
591     char linebuf[IRCD_BUFSIZE], logfile[IRCD_BUFSIZE];
592     #endif
593    
594     assert(source_p != NULL);
595    
596     #ifdef OPERSPY_LOGFILE
597     if (IsOper(source_p) && MyClient(source_p))
598     {
599     DLINK_FOREACH(cnode, source_p->localClient->confs.head)
600     {
601     conf = cnode->data;
602    
603     if (conf->type == OPER_TYPE)
604     opername = conf->name;
605     }
606     }
607     else if (!MyClient(source_p))
608     opername = "remote";
609    
610     ircsprintf(logfile, "%s/operspy.%s.log", LOGPATH, opername);
611     if ((operspy_fb = fbopen(logfile, "a")) == NULL)
612     return;
613    
614     nbytes = ircsprintf(linebuf, "[%s] OPERSPY %s %s %s\n",
615     smalldate(CurrentTime),
616     get_oper_name(source_p),
617     command, target);
618     fbputs(linebuf, operspy_fb, nbytes);
619     fbclose(operspy_fb);
620     #endif
621    
622     #ifdef OPERSPY_NOTICE
623     sendto_realops_flags(UMODE_SPY, L_ALL, "OPERSPY %s %s %s",
624     get_oper_name(source_p), command, target);
625     #endif
626    
627     if (MyClient(source_p))
628     sendto_match_servs(source_p, "*", CAP_ENCAP, "ENCAP * OPERSPY %s :%s",
629     command, target);
630     }
631     #endif /* OPERSPY_LOG */

Properties

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