ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid/trunk/modules/m_whois.c
Revision: 8214
Committed: Sun Apr 16 11:44:44 2017 UTC (9 years, 5 months ago) by michael
Content type: text/x-csrc
File size: 10486 byte(s)
Log Message:
- Store real host information in Client.realhost and extend the UID message to send the actual host.
  This allows operators to see the real host of a client in /whois and /whowas.

File Contents

# Content
1 /*
2 * ircd-hybrid: an advanced, lightweight Internet Relay Chat Daemon (ircd)
3 *
4 * Copyright (c) 1997-2017 ircd-hybrid development team
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
19 * USA
20 */
21
22 /*! \file m_whois.c
23 * \brief Includes required functions for processing the WHOIS command.
24 * \version $Id$
25 */
26
27 #include "stdinc.h"
28 #include "list.h"
29 #include "client.h"
30 #include "hash.h"
31 #include "channel.h"
32 #include "channel_mode.h"
33 #include "ircd.h"
34 #include "numeric.h"
35 #include "conf.h"
36 #include "misc.h"
37 #include "server.h"
38 #include "user.h"
39 #include "send.h"
40 #include "irc_string.h"
41 #include "parse.h"
42 #include "modules.h"
43
44
45 static int
46 whois_can_see_channels(struct Channel *chptr,
47 struct Client *source_p,
48 struct Client *target_p)
49 {
50 if (PubChannel(chptr) && !HasUMode(target_p, UMODE_HIDECHANS))
51 return 1;
52
53 if (source_p == target_p || IsMember(source_p, chptr))
54 return 1;
55
56 if (HasUMode(source_p, UMODE_OPER))
57 return 2;
58 return 0;
59 }
60
61 /* whois_person()
62 *
63 * inputs - source_p client to report to
64 * - target_p client to report on
65 * output - NONE
66 * side effects -
67 */
68 static void
69 whois_person(struct Client *source_p, struct Client *target_p)
70 {
71 char buf[IRCD_BUFSIZE] = "";
72 dlink_node *node;
73 const struct ServicesTag *svstag = NULL;
74 char *t = NULL;
75 int cur_len = 0;
76 int mlen = 0;
77 int tlen = 0;
78 int reply_to_send = 0;
79
80 sendto_one_numeric(source_p, &me, RPL_WHOISUSER, target_p->name,
81 target_p->username, target_p->host,
82 target_p->info);
83
84 cur_len = mlen = snprintf(buf, sizeof(buf), numeric_form(RPL_WHOISCHANNELS),
85 me.name, source_p->name, target_p->name, "");
86 t = buf + mlen;
87
88 DLINK_FOREACH(node, target_p->channel.head)
89 {
90 const struct Membership *member = node->data;
91 int show = whois_can_see_channels(member->chptr, source_p, target_p);
92
93 if (show)
94 {
95 if ((cur_len + 4 + member->chptr->name_len + 1) > (IRCD_BUFSIZE - 2))
96 {
97 *(t - 1) = '\0';
98 sendto_one(source_p, "%s", buf);
99 cur_len = mlen;
100 t = buf + mlen;
101 }
102
103 tlen = sprintf(t, "%s%s%s ", show == 2 ? "~" : "", get_member_status(member, 1),
104 member->chptr->name);
105 t += tlen;
106 cur_len += tlen;
107 reply_to_send = 1;
108 }
109 }
110
111 if (reply_to_send)
112 {
113 *(t - 1) = '\0';
114 sendto_one(source_p, "%s", buf);
115 }
116
117 if ((ConfigServerHide.hide_servers || IsHidden(target_p->servptr)) &&
118 !(HasUMode(source_p, UMODE_OPER) || source_p == target_p))
119 sendto_one_numeric(source_p, &me, RPL_WHOISSERVER, target_p->name,
120 ConfigServerHide.hidden_name,
121 ConfigServerInfo.network_desc);
122 else
123 sendto_one_numeric(source_p, &me, RPL_WHOISSERVER, target_p->name,
124 target_p->servptr->name, target_p->servptr->info);
125
126 if (HasUMode(target_p, UMODE_REGISTERED))
127 sendto_one_numeric(source_p, &me, RPL_WHOISREGNICK, target_p->name);
128
129 if (strcmp(target_p->account, "*"))
130 sendto_one_numeric(source_p, &me, RPL_WHOISACCOUNT, target_p->name,
131 target_p->account, "is");
132
133 if (target_p->away[0])
134 sendto_one_numeric(source_p, &me, RPL_AWAY, target_p->name,
135 target_p->away);
136
137 if (HasUMode(target_p, UMODE_CALLERID | UMODE_SOFTCALLERID))
138 {
139 const int callerid = !!HasUMode(target_p, UMODE_CALLERID);
140
141 sendto_one_numeric(source_p, &me, RPL_TARGUMODEG, target_p->name,
142 callerid ? "+g" : "+G",
143 callerid ? "server side ignore" :
144 "server side ignore with the exception of common channels");
145 }
146
147 if (target_p->svstags.head)
148 svstag = target_p->svstags.head->data;
149
150 if (HasUMode(target_p, UMODE_OPER))
151 if (!HasUMode(target_p, UMODE_HIDDEN) || HasUMode(source_p, UMODE_OPER))
152 if (!svstag || svstag->numeric != RPL_WHOISOPERATOR)
153 sendto_one_numeric(source_p, &me, RPL_WHOISOPERATOR, target_p->name,
154 HasUMode(target_p, UMODE_ADMIN) ? "is a Server Administrator" :
155 "is an IRC Operator");
156
157 DLINK_FOREACH(node, target_p->svstags.head)
158 {
159 svstag = node->data;
160
161 if (svstag->numeric == RPL_WHOISOPERATOR)
162 if (HasUMode(target_p, UMODE_HIDDEN) && !HasUMode(source_p, UMODE_OPER))
163 continue;
164
165 if (!svstag->umodes || HasUMode(source_p, svstag->umodes))
166 sendto_one_numeric(source_p, &me, svstag->numeric | SND_EXPLICIT, "%s :%s",
167 target_p->name, svstag->tag);
168 }
169
170 if (HasUMode(target_p, UMODE_WEBIRC))
171 sendto_one_numeric(source_p, &me, RPL_WHOISTEXT, target_p->name,
172 "User connected using a webirc gateway");
173
174 if (HasUMode(source_p, UMODE_OPER) || source_p == target_p)
175 {
176 char *m = buf;
177 *m++ = '+';
178
179 for (const struct user_modes *tab = umode_tab; tab->c; ++tab)
180 if (HasUMode(target_p, tab->flag))
181 *m++ = tab->c;
182 *m = '\0';
183
184 sendto_one_numeric(source_p, &me, RPL_WHOISMODES, target_p->name, buf);
185 }
186
187 if (HasUMode(source_p, UMODE_OPER) || source_p == target_p)
188 sendto_one_numeric(source_p, &me, RPL_WHOISACTUALLY, target_p->name,
189 target_p->username, target_p->realhost,
190 target_p->sockhost);
191
192 if (HasUMode(target_p, UMODE_SSL))
193 sendto_one_numeric(source_p, &me, RPL_WHOISSECURE, target_p->name);
194
195 if (!EmptyString(target_p->certfp))
196 if (target_p == source_p || HasUMode(source_p, UMODE_OPER))
197 sendto_one_numeric(source_p, &me, RPL_WHOISCERTFP, target_p->name, target_p->certfp);
198
199 if (MyConnect(target_p))
200 if (!HasUMode(target_p, UMODE_HIDEIDLE) || HasUMode(source_p, UMODE_OPER) ||
201 source_p == target_p)
202 sendto_one_numeric(source_p, &me, RPL_WHOISIDLE, target_p->name,
203 client_get_idle_time(source_p, target_p),
204 target_p->connection->firsttime);
205
206 if (HasUMode(target_p, UMODE_SPY) && source_p != target_p)
207 sendto_one_notice(target_p, &me, ":*** Notice -- %s (%s@%s) [%s] is doing a /whois on you",
208 source_p->name, source_p->username, source_p->host, source_p->servptr->name);
209 }
210
211 /* do_whois()
212 *
213 * inputs - pointer to /whois source
214 * - number of parameters
215 * - pointer to parameters array
216 * output - pointer to void
217 * side effects - Does whois
218 */
219 static void
220 do_whois(struct Client *source_p, const char *name)
221 {
222 struct Client *target_p = NULL;
223
224 if ((target_p = hash_find_client(name)) && IsClient(target_p))
225 whois_person(source_p, target_p);
226 else
227 sendto_one_numeric(source_p, &me, ERR_NOSUCHNICK, name);
228
229 sendto_one_numeric(source_p, &me, RPL_ENDOFWHOIS, name);
230 }
231
232 /*! \brief WHOIS command handler
233 *
234 * \param source_p Pointer to allocated Client struct from which the message
235 * originally comes from. This can be a local or remote client.
236 * \param parc Integer holding the number of supplied arguments.
237 * \param parv Argument vector where parv[0] .. parv[parc-1] are non-NULL
238 * pointers.
239 * \note Valid arguments for this command are:
240 * - parv[0] = command
241 * - parv[1] = nickname/servername
242 * - parv[2] = nickname
243 */
244 static int
245 m_whois(struct Client *source_p, int parc, char *parv[])
246 {
247 static uintmax_t last_used = 0;
248
249 if (parc < 2 || EmptyString(parv[1]))
250 {
251 sendto_one_numeric(source_p, &me, ERR_NONICKNAMEGIVEN);
252 return 0;
253 }
254
255 if (parc > 2 && !EmptyString(parv[2]))
256 {
257 /* seeing as this is going across servers, we should limit it */
258 if ((last_used + ConfigGeneral.pace_wait_simple) > CurrentTime)
259 {
260 sendto_one_numeric(source_p, &me, RPL_LOAD2HI, "WHOIS");
261 return 0;
262 }
263
264 last_used = CurrentTime;
265
266 /*
267 * if we have serverhide enabled, they can either ask the clients
268 * server, or our server.. I don't see why they would need to ask
269 * anything else for info about the client.. --fl_
270 */
271 if (ConfigServerHide.disable_remote_commands)
272 parv[1] = parv[2];
273
274 if (server_hunt(source_p, ":%s WHOIS %s :%s", 1, parc, parv)->ret != HUNTED_ISME)
275 return 0;
276
277 parv[1] = parv[2];
278 }
279
280 do_whois(source_p, parv[1]);
281 return 0;
282 }
283
284 /*! \brief WHOIS command handler
285 *
286 * \param source_p Pointer to allocated Client struct from which the message
287 * originally comes from. This can be a local or remote client.
288 * \param parc Integer holding the number of supplied arguments.
289 * \param parv Argument vector where parv[0] .. parv[parc-1] are non-NULL
290 * pointers.
291 * \note Valid arguments for this command are:
292 * - parv[0] = command
293 * - parv[1] = nickname/servername
294 * - parv[2] = nickname
295 */
296 static int
297 mo_whois(struct Client *source_p, int parc, char *parv[])
298 {
299 if (parc < 2 || EmptyString(parv[1]))
300 {
301 sendto_one_numeric(source_p, &me, ERR_NONICKNAMEGIVEN);
302 return 0;
303 }
304
305 if (parc > 2 && !EmptyString(parv[2]))
306 {
307 if (server_hunt(source_p, ":%s WHOIS %s :%s", 1, parc, parv)->ret != HUNTED_ISME)
308 return 0;
309
310 parv[1] = parv[2];
311 }
312
313 do_whois(source_p, parv[1]);
314 return 0;
315 }
316
317 static struct Message whois_msgtab =
318 {
319 .cmd = "WHOIS",
320 .args_max = MAXPARA,
321 .handlers[UNREGISTERED_HANDLER] = m_unregistered,
322 .handlers[CLIENT_HANDLER] = m_whois,
323 .handlers[SERVER_HANDLER] = mo_whois,
324 .handlers[ENCAP_HANDLER] = m_ignore,
325 .handlers[OPER_HANDLER] = mo_whois
326 };
327
328 static void
329 module_init(void)
330 {
331 mod_add_cmd(&whois_msgtab);
332 }
333
334 static void
335 module_exit(void)
336 {
337 mod_del_cmd(&whois_msgtab);
338 }
339
340 struct module module_entry =
341 {
342 .version = "$Revision$",
343 .modinit = module_init,
344 .modexit = module_exit,
345 };

Properties

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