]>
Commit | Line | Data |
---|---|---|
0a17908b | 1 | sethost patch: minor overhaul of sethost system |
2 | ||
3 | this patch replaces a number of other patches: | |
4 | autosethost.patch invalidatebanssethost.patch issethost.patch | |
5 | sethostnewhostmask.patch sethostoldcode.patch sethostprotocolviolation.patch | |
6 | showumodehtoclients.patch ulined.patch | |
7 | ||
8 | makes usermode +h visible to clients | |
9 | ||
10 | removes HasSetHost() macro (was same as IsSetHost()) | |
11 | ||
12 | removed 'Using S-line privilege' message on connect | |
13 | client is informed of spoofhost by 396 RPL_HOSTHIDDEN (host :is now your hidden host) | |
14 | ||
15 | change syntax to "SETHOST [<user>@]<host> [<password>]" | |
16 | ||
17 | disallow client to use MODE +h [<user>@]<host> [<pass>] (bug: mode +h took 2 parameters, even from remote users!) | |
18 | ||
19 | sethost can only be unset with "MODE <nick> -h" | |
20 | ||
21 | sethost #N no longer supported (N being the Nth configured spoof block) | |
22 | ||
23 | remote sethost can now be undone by using 0 as username and host, | |
24 | but only when the user has an account set and is allowed by server settings to set mode +x, | |
25 | to avoid revealing the real host out of the blue | |
26 | ||
27 | SETHOST now same as OPER | |
28 | modes h and o can only be set with SETHOST and OPER | |
29 | modes h and o are visible to clients | |
30 | modes h and o can only be unset with MODE <nick> -ho | |
31 | ||
32 | user sethosts are now also checked against their user@host/ip (and not just the password) | |
33 | ||
34 | applying the sethost and syncing of clients (quit user, rejoin user, restore modes on user) is now done in one place | |
35 | ||
36 | remote sethost can come from any server, does not need to have a Uworld block or be a service (ACCOUNT doesnt require that either) | |
37 | ||
38 | STATS s | |
39 | show if spoofhost is valid or not (S = valid, s = invalid) | |
40 | removed numbering (not required anymore?) | |
41 | merged showing of user@host | |
42 | ||
43 | diff -r c6f3803ee169 include/client.h | |
44 | --- a/include/client.h | |
45 | +++ b/include/client.h | |
46 | @@ -90,7 +90,7 @@ | |
47 | #define FlagClr(set,flag) ((set)->bits[FLAGSET_INDEX(flag)] &= ~FLAGSET_MASK(flag)) | |
48 | ||
49 | /** String containing valid user modes, in no particular order. */ | |
50 | -#define infousermodes "dioOswkgxRXInP" | |
51 | +#define infousermodes "dioOswkghxRXInP" | |
52 | ||
53 | /** Character to indicate no oper name available */ | |
54 | #define NOOPERNAMECHARACTER '-' | |
55 | @@ -627,7 +627,6 @@ | |
56 | #define HasHiddenHost(x) (IsHiddenHost(x) && IsAccount(x)) | |
57 | /** Return non-zero if the client is using a spoofhost */ | |
58 | #define IsSetHost(x) HasFlag(x, FLAG_SETHOST) | |
59 | -#define HasSetHost(x) (IsSetHost(x)) | |
60 | ||
61 | /** Mark a client as having an in-progress net.burst. */ | |
62 | #define SetBurst(x) SetFlag(x, FLAG_BURST) | |
63 | diff -r c6f3803ee169 include/numeric.h | |
64 | --- a/include/numeric.h | |
65 | +++ b/include/numeric.h | |
66 | @@ -314,7 +314,7 @@ | |
67 | /* RPL_NOUSERS 395 Dalnet/EFnet/IRCnet */ | |
68 | #define RPL_HOSTHIDDEN 396 /* UMODE +x completed succesfuly */ | |
69 | #define RPL_STATSSLINE 398 /* QuakeNet extension -froo */ | |
70 | -#define RPL_USINGSLINE 399 /* QuakeNet extension -froo */ | |
71 | +/* RPL_USINGSLINE 399 QuakeNet extension -froo */ | |
72 | ||
73 | /* | |
74 | * Errors are in the range from 400-599 currently and are grouped by what | |
75 | diff -r c6f3803ee169 include/s_conf.h | |
76 | --- a/include/s_conf.h | |
77 | +++ b/include/s_conf.h | |
78 | @@ -205,7 +205,8 @@ | |
79 | ||
80 | extern void conf_add_sline(const char* const* fields, int count); | |
81 | extern void clear_slines(void); | |
82 | -extern int conf_check_slines(struct Client *cptr); | |
83 | +extern struct sline *find_spoofblock(struct Client *cptr, char *spoofhost, char *password); | |
84 | +extern int apply_spoofblock(struct Client *cptr); | |
85 | extern void free_spoofhost(struct sline *spoof); | |
86 | ||
87 | extern void yyerror(const char *msg); | |
88 | diff -r c6f3803ee169 include/s_user.h | |
89 | --- a/include/s_user.h | |
90 | +++ b/include/s_user.h | |
91 | @@ -79,15 +79,15 @@ | |
92 | extern int set_nick_name(struct Client* cptr, struct Client* sptr, | |
93 | const char* nick, int parc, char* parv[]); | |
94 | extern void send_umode_out(struct Client* cptr, struct Client* sptr, | |
95 | - struct Flags* old, int prop); | |
96 | + struct Flags* old, int prop, int alreadyh); | |
97 | extern int whisper(struct Client* source, const char* nick, | |
98 | const char* channel, const char* text, int is_notice); | |
99 | extern void send_user_info(struct Client* to, char* names, int rpl, | |
100 | InfoFormatter fmt); | |
101 | ||
102 | extern int hide_hostmask(struct Client *cptr, unsigned int flags); | |
103 | -extern int set_hostmask(struct Client *cptr, char *hostmask, char *password); | |
104 | -extern int is_hostmask(char *word); | |
105 | +extern int set_hostmask(struct Client *sptr, char *user, char *host); | |
106 | +extern int is_validsethost(char *mask, int maxlen); | |
107 | extern int set_user_mode(struct Client *cptr, struct Client *sptr, | |
108 | int parc, char *parv[], int allow_modes); | |
109 | extern int is_silenced(struct Client *sptr, struct Client *acptr); | |
110 | @@ -102,7 +102,7 @@ | |
111 | extern struct Client* next_client(struct Client* next, const char* ch); | |
112 | extern char *umode_str(struct Client *cptr, int type); | |
113 | extern void send_umode(struct Client *cptr, struct Client *sptr, | |
114 | - struct Flags *old, int sendset, int opernames); | |
115 | + struct Flags *old, int sendset, int opernames, int alreadyh); | |
116 | extern void set_snomask(struct Client *, unsigned int, int); | |
117 | extern int is_snomask(char *); | |
118 | extern int check_target_limit(struct Client *sptr, void *target, const char *name, | |
119 | diff -r c6f3803ee169 ircd/channel.c | |
120 | --- a/ircd/channel.c | |
121 | +++ b/ircd/channel.c | |
122 | @@ -384,12 +384,12 @@ | |
123 | ircd_ntoa_r(iphost, &cli_ip(cptr)); | |
124 | ||
125 | /* sr is real host if +h */ | |
126 | - if (HasSetHost(cptr)) | |
127 | + if (IsSetHost(cptr)) | |
128 | sr = cli_user(cptr)->realhost; | |
129 | ||
130 | /* if +x and not +h sa is real host, if -x or +h sa is the account host */ | |
131 | if (IsAccount(cptr)) { | |
132 | - if (HasHiddenHost(cptr) && !HasSetHost(cptr)) { | |
133 | + if (HasHiddenHost(cptr) && !IsSetHost(cptr)) { | |
134 | sa = cli_user(cptr)->realhost; | |
135 | } else { | |
136 | ircd_snprintf(0, tmphost, HOSTLEN, "%s.%s", | |
137 | diff -r c6f3803ee169 ircd/m_oper.c | |
138 | --- a/ircd/m_oper.c | |
139 | +++ b/ircd/m_oper.c | |
140 | @@ -189,7 +189,7 @@ | |
141 | ||
142 | set_snomask(sptr, SNO_OPERDEFAULT, SNO_ADD); | |
143 | cli_max_sendq(sptr) = 0; /* Get the sendq from the oper's class */ | |
144 | - send_umode_out(cptr, sptr, &old_mode, HasPriv(sptr, PRIV_PROPAGATE)); | |
145 | + send_umode_out(cptr, sptr, &old_mode, HasPriv(sptr, PRIV_PROPAGATE), 0); | |
146 | send_reply(sptr, RPL_YOUREOPER); | |
147 | ||
148 | sendto_opmask_butone(0, SNO_OLDSNO, "%s (%s@%s) is now operator (%c) as %s", | |
149 | diff -r c6f3803ee169 ircd/m_sethost.c | |
150 | --- a/ircd/m_sethost.c | |
151 | +++ b/ircd/m_sethost.c | |
152 | @@ -82,174 +82,222 @@ | |
153 | #include "config.h" | |
154 | ||
155 | #include "client.h" | |
156 | +#include "ircd_features.h" | |
157 | +#include "ircd_log.h" | |
158 | #include "ircd_reply.h" | |
159 | #include "ircd_string.h" | |
160 | #include "ircd_snprintf.h" | |
161 | -#include "ircd_features.h" | |
162 | +#include "msg.h" | |
163 | #include "msgq.h" | |
164 | #include "numeric.h" | |
165 | #include "s_conf.h" | |
166 | +#include "s_debug.h" | |
167 | #include "s_user.h" | |
168 | -#include "s_debug.h" | |
169 | #include "send.h" | |
170 | #include "struct.h" | |
171 | #include "numnicks.h" | |
172 | ||
173 | -#include "channel.h" | |
174 | -#include "msg.h" | |
175 | - | |
176 | -#include <assert.h> | |
177 | #include <stdlib.h> | |
178 | ||
179 | -/* | |
180 | +/** | |
181 | * m_sethost - generic message handler | |
182 | * | |
183 | - * mimic old lain syntax: | |
184 | + * SETHOST [<user>@]<host> [<password>] | |
185 | * | |
186 | - * (Oper) /SETHOST ident host.cc [quit-message] | |
187 | - * (User) /SETHOST host.cc password | |
188 | - * (Both) /SETHOST undo | |
189 | + * parv[0] = sender prefix | |
190 | + * parv[1] = [user@]host | |
191 | + * parv[2] = password | |
192 | * | |
193 | - * check for undo, prepend parv w. <nick> -h or +h | |
194 | + * "MODE <nick> -h" to remove sethost | |
195 | + * | |
196 | */ | |
197 | int m_sethost(struct Client* cptr, struct Client* sptr, int parc, char* parv[]) | |
198 | { | |
199 | - char hostmask[USERLEN + HOSTLEN + 2]; | |
200 | - char curhostmask[USERLEN + HOSTLEN + 2]; | |
201 | + int alreadyh = 0; | |
202 | + int freeform = 0; | |
203 | + char *hostmask; | |
204 | + char *user = NULL; | |
205 | + char *host; | |
206 | + char *password = NULL; | |
207 | + struct Flags setflags; | |
208 | + struct sline *sconf; | |
209 | ||
210 | - struct Flags setflags; | |
211 | + /* disabled */ | |
212 | + if (!feature_bool(FEAT_SETHOST)) | |
213 | + return send_reply(sptr, ERR_DISABLED, "SETHOST"); | |
214 | ||
215 | - /* Back up the flags first */ | |
216 | + /* disabled for ordinary users */ | |
217 | + if (!IsAnOper(sptr) && !feature_bool(FEAT_SETHOST_USER)) | |
218 | + return send_reply(sptr, ERR_NOPRIVILEGES); | |
219 | + | |
220 | + /* need hostmask parameter | |
221 | + * and need password parameter from an ordinary user | |
222 | + */ | |
223 | + if (parc < 2 || EmptyString(parv[1]) || (parc < 3 && !IsAnOper(sptr))) | |
224 | + return need_more_params(sptr, "SETHOST"); | |
225 | + | |
226 | + hostmask = parv[1]; | |
227 | + | |
228 | + /* get user and host */ | |
229 | + if ((host = strrchr(hostmask, '@'))) { | |
230 | + *host++ = '\0'; | |
231 | + user = hostmask; | |
232 | + } | |
233 | + else | |
234 | + host = hostmask; | |
235 | + | |
236 | + /* got a pasword */ | |
237 | + if (parc > 2 && !EmptyString(parv[2])) | |
238 | + password = parv[2]; | |
239 | + | |
240 | + /* freeform - do not bother with password */ | |
241 | + if (IsAnOper(sptr) && HasPriv(sptr, PRIV_FREEFORM)) { | |
242 | + freeform = 1; | |
243 | + password = NULL; | |
244 | + } | |
245 | + | |
246 | + /* check if user and host are valid */ | |
247 | + if ((user && !is_validsethost(user, USERLEN)) || | |
248 | + !is_validsethost(host, HOSTLEN)) | |
249 | + return send_reply(sptr, ERR_BADHOSTMASK, user ? user : "", user ? "@" : "", host); | |
250 | + | |
251 | + /* not freeform */ | |
252 | + if (!freeform) { | |
253 | + | |
254 | + /* find the spoof block */ | |
255 | + if (!(sconf = find_spoofblock(sptr, host, password))) | |
256 | + return send_reply(sptr, ERR_HOSTUNAVAIL, user ? user : "", user ? "@" : "", host); | |
257 | + else | |
258 | + host = (char *)sconf->spoofhost; | |
259 | + | |
260 | + /* only freeform allowed to specify user */ | |
261 | + user = NULL; | |
262 | + } | |
263 | + | |
264 | + /* backup flags */ | |
265 | setflags = cli_flags(sptr); | |
266 | ||
267 | - if (parc < 2) | |
268 | - return need_more_params(sptr, "SETHOST"); | |
269 | + /* already +h, clear flag to force mode +h to be sent out again */ | |
270 | + if (IsSetHost(sptr)) { | |
271 | + FlagClr(&setflags, FLAG_SETHOST); | |
272 | + alreadyh = 1; | |
273 | + } | |
274 | ||
275 | - if (0 == ircd_strcmp("undo", parv[1])) { | |
276 | - set_hostmask(sptr, NULL, NULL); | |
277 | - } else { | |
278 | - if (parc<3) | |
279 | - return need_more_params(sptr, "SETHOST"); | |
280 | - if (IsAnOper(sptr)) { | |
281 | - ircd_snprintf(0, hostmask, USERLEN + HOSTLEN + 2, "%s@%s", parv[1], parv[2]); | |
282 | - if (!is_hostmask(hostmask)) { | |
283 | - send_reply(sptr, ERR_BADHOSTMASK, hostmask); | |
284 | - return 0; | |
285 | - } | |
286 | - if (IsSetHost(sptr) || IsAccount(sptr)) { | |
287 | - ircd_snprintf(0, curhostmask, USERLEN + HOSTLEN + 2, "%s@%s", sptr->cli_user->username, sptr->cli_user->host); | |
288 | - if (0 == strcmp(hostmask, curhostmask)) { | |
289 | - send_reply(sptr, RPL_HOSTHIDDEN, curhostmask); | |
290 | - return 0; | |
291 | - } | |
292 | - } | |
293 | - if (set_hostmask(sptr, hostmask, NULL)) | |
294 | - FlagClr(&setflags, FLAG_SETHOST); | |
295 | - } else { | |
296 | - if (!is_hostmask(parv[1])) { | |
297 | - send_reply(sptr, ERR_BADHOSTMASK, parv[1]); | |
298 | - return 0; | |
299 | - } | |
300 | - if (IsSetHost(sptr) || IsAccount(sptr)) { | |
301 | - if (0 == strcmp(parv[1], sptr->cli_user->host)) { | |
302 | - send_reply(sptr, RPL_HOSTHIDDEN, parv[1]); | |
303 | - return 0; | |
304 | - } | |
305 | - } | |
306 | - if (set_hostmask(sptr, parv[1], parv[2])) | |
307 | - FlagClr(&setflags, FLAG_SETHOST); | |
308 | - } | |
309 | - } | |
310 | + /* check if new sethost is different from before */ | |
311 | + if (IsSetHost(sptr) && | |
312 | + (!user || strcmp(cli_user(sptr)->username, user) == 0) && | |
313 | + strcmp(cli_user(sptr)->host, host) == 0) | |
314 | + return send_reply(sptr, RPL_HOSTHIDDEN, user ? user : "", user ? "@" : "", host); | |
315 | ||
316 | - send_umode_out(cptr, sptr, &setflags, 0); | |
317 | + /* do it */ | |
318 | + set_hostmask(sptr, user, host); | |
319 | + | |
320 | + /* log freeform */ | |
321 | + if (freeform) | |
322 | + log_write(LS_SETHOST, L_NOTICE, 0, | |
323 | + "SETHOST (%s@%s) by (%#R) using freeform", | |
324 | + cli_user(cptr)->username, cli_user(cptr)->host, cptr); | |
325 | + | |
326 | + /* send the mode out */ | |
327 | + send_umode_out(cptr, sptr, &setflags, 0, alreadyh); | |
328 | + | |
329 | return 0; | |
330 | } | |
331 | ||
332 | ||
333 | -/* | |
334 | + | |
335 | +/** | |
336 | * ms_sethost - sethost server message handler | |
337 | * | |
338 | * parv[0] = sender prefix | |
339 | * parv[1] = target user numeric | |
340 | - * parv[2] = target user's new ident | |
341 | - * parv[3] = target user's new host | |
342 | + * parv[2] = spoof username | |
343 | + * parv[3] = spoof host | |
344 | + * | |
345 | + * undo sethost when spoof username and host are 0 | |
346 | + * | |
347 | */ | |
348 | + /* TODO: IsRemoteSetHost() */ | |
349 | int ms_sethost(struct Client* cptr, struct Client* sptr, int parc, char* parv[]) | |
350 | { | |
351 | - struct Client *target; | |
352 | - char hostmask[USERLEN + HOSTLEN + 2]; | |
353 | - struct Membership *chan; | |
354 | + int alreadyh = 0; | |
355 | + char *target; | |
356 | + char *user; | |
357 | + char *host; | |
358 | + struct Client *acptr; | |
359 | struct Flags setflags; | |
360 | ||
361 | + /* check paramaters */ | |
362 | if (parc < 4) | |
363 | return need_more_params(sptr, "SETHOST"); | |
364 | ||
365 | + target = parv[1]; | |
366 | + user = parv[2]; | |
367 | + host = parv[3]; | |
368 | + | |
369 | + /* not from a server */ | |
370 | if (!IsServer(sptr)) | |
371 | - return protocol_violation(cptr, "SETHOST from non-server %s", | |
372 | - cli_name(sptr)); | |
373 | + return protocol_violation(cptr, "SETHOST from non-server %s", cli_name(sptr)); | |
374 | ||
375 | - /* Locate our target user; ignore the message if we can't */ | |
376 | - if(!(target = findNUser(parv[1]))) | |
377 | + /* find user */ | |
378 | + if(!(acptr = findNUser(target))) | |
379 | return 0; | |
380 | ||
381 | - /* Fake host assignments must be from services */ | |
382 | - if (!find_conf_byhost(cli_confs(sptr), cli_name(sptr), CONF_UWORLD)) | |
383 | - return protocol_violation(cptr, "Non-U:lined server %s set fake host on user %s", cli_name(sptr), cli_name(target)); | |
384 | - | |
385 | - if (!MyConnect(target)) { | |
386 | - sendcmdto_one(sptr, CMD_SETHOST, cli_user(target)->server, "%C %s %s", target, | |
387 | - parv[2], parv[3]); | |
388 | + /* not for my user, pass it along */ | |
389 | + if (!MyConnect(acptr)) { | |
390 | + sendcmdto_one(sptr, CMD_SETHOST, acptr, "%C %s %s", acptr, user, host); | |
391 | return 0; | |
392 | } | |
393 | ||
394 | - /* Back up the flags first */ | |
395 | - setflags = cli_flags(target); | |
396 | - FlagClr(&setflags, FLAG_SETHOST); | |
397 | + /* backup flags */ | |
398 | + setflags = cli_flags(acptr); | |
399 | ||
400 | - if (IsSetHost(target) || IsAccount(target)) { | |
401 | - if ((0 == strcmp(parv[2], target->cli_user->username)) && (0 == strcmp(parv[3], target->cli_user->host))) | |
402 | + /* check user and host are valid */ | |
403 | + if (!is_validsethost(user, USERLEN) || !is_validsethost(host, HOSTLEN)) | |
404 | + return protocol_violation(cptr, | |
405 | + "Server %C tried to SETHOST user %C with a badmask: %s@%s", | |
406 | + sptr, acptr, user, host); | |
407 | + | |
408 | + /* 'user host' is '0 0' - undo sethost */ | |
409 | + if (user[0] == '0' && user[1] == '\0' && | |
410 | + host[0] == '0' && host[1] == '\0') { | |
411 | + | |
412 | + /* user has no sethost or has no account | |
413 | + * | |
414 | + * user has +h their host is hidden, do not remove it | |
415 | + * unless the user has an account set | |
416 | + * we should not out of the blue expose the real host | |
417 | + */ | |
418 | + if (!IsSetHost(acptr) || !IsAccount(acptr)) | |
419 | return 0; | |
420 | + | |
421 | + /* user not +x and not allowed to set it */ | |
422 | + if (!IsHiddenHost(acptr) && !feature_bool(FEAT_HOST_HIDING)) | |
423 | + return 0; | |
424 | + | |
425 | + /* set +x */ | |
426 | + SetHiddenHost(acptr); | |
427 | + user = NULL; | |
428 | + host = NULL; | |
429 | } | |
430 | ||
431 | - ircd_snprintf(0, hostmask, USERLEN + HOSTLEN + 2, "%s@%s", parv[2], parv[3]); | |
432 | - if (!is_hostmask(hostmask)) | |
433 | - return protocol_violation(cptr, "Bad Host mask %s for user %s", hostmask, cli_name(target)); | |
434 | + /* check if new sethost is different from before */ | |
435 | + else if (IsSetHost(acptr) && | |
436 | + strcmp(cli_user(acptr)->username, user) == 0 && | |
437 | + strcmp(cli_user(acptr)->host, host) == 0) | |
438 | + return 0; | |
439 | ||
440 | - sendcmdto_common_channels_butone(target, CMD_QUIT, target, ":Host change"); | |
441 | - | |
442 | - /* Assign and propagate the fakehost */ | |
443 | - SetSetHost(target); | |
444 | - ircd_strncpy(cli_user(target)->username, parv[2], USERLEN); | |
445 | - ircd_strncpy(cli_user(target)->host, parv[3], HOSTLEN); | |
446 | - | |
447 | - send_reply(target, RPL_HOSTHIDDEN, hostmask); | |
448 | - | |
449 | - /* | |
450 | - * Go through all channels the client was on, rejoin him | |
451 | - * and set the modes, if any | |
452 | - */ | |
453 | - for (chan = cli_user(target)->channel; chan; chan = chan->next_channel) { | |
454 | - if (IsZombie(chan)) | |
455 | - continue; | |
456 | - /* If this channel has delayed joins and the user has no modes, just set | |
457 | - * the delayed join flag rather than showing the join, even if the user | |
458 | - * was visible before */ | |
459 | - if (!IsChanOp(chan) && !HasVoice(chan) | |
460 | - && (chan->channel->mode.mode & MODE_DELJOINS)) { | |
461 | - SetDelayedJoin(chan); | |
462 | - } else { | |
463 | - sendcmdto_channel_butserv_butone(target, CMD_JOIN, chan->channel, target, 0, | |
464 | - "%H", chan->channel); | |
465 | - } | |
466 | - if (IsChanOp(chan) && HasVoice(chan)) { | |
467 | - sendcmdto_channel_butserv_butone(&his, CMD_MODE, chan->channel, target, 0, | |
468 | - "%H +ov %C %C", chan->channel, target, target); | |
469 | - } else if (IsChanOp(chan) || HasVoice(chan)) { | |
470 | - sendcmdto_channel_butserv_butone(&his, CMD_MODE, chan->channel, target, 0, | |
471 | - "%H +%c %C", chan->channel, IsChanOp(chan) ? 'o' : 'v', target); | |
472 | - } | |
473 | + /* already +h, clear flag to force mode +h to be sent out again */ | |
474 | + else if (IsSetHost(acptr)) { | |
475 | + FlagClr(&setflags, FLAG_SETHOST); | |
476 | + alreadyh = 1; | |
477 | } | |
478 | ||
479 | - send_umode_out(target, target, &setflags, 0); | |
480 | + /* do it */ | |
481 | + set_hostmask(acptr, user, host); | |
482 | + | |
483 | + /* send out the mode */ | |
484 | + send_umode_out(acptr, acptr, &setflags, 0, alreadyh); | |
485 | + | |
486 | return 0; | |
487 | } | |
488 | diff -r c6f3803ee169 ircd/m_userhost.c | |
489 | --- a/ircd/m_userhost.c | |
490 | +++ b/ircd/m_userhost.c | |
491 | @@ -104,7 +104,7 @@ | |
492 | * of +x. If an oper wants the real host, he should go to | |
493 | * /whois to get it. | |
494 | */ | |
495 | - (HasHiddenHost(cptr) || HasSetHost(cptr)) && (sptr != cptr) ? | |
496 | + (HasHiddenHost(cptr) || IsSetHost(cptr)) && (sptr != cptr) ? | |
497 | cli_user(cptr)->host : cli_user(cptr)->realhost); | |
498 | } | |
499 | ||
500 | diff -r c6f3803ee169 ircd/m_userip.c | |
501 | --- a/ircd/m_userip.c | |
502 | +++ b/ircd/m_userip.c | |
503 | @@ -106,7 +106,7 @@ | |
504 | * of +x. If an oper wants the real IP, he should go to | |
505 | * /whois to get it. | |
506 | */ | |
507 | - ((HasHiddenHost(cptr) || HasSetHost(cptr) || feature_bool(FEAT_HIS_USERIP)) && (sptr != cptr)) ? | |
508 | + ((HasHiddenHost(cptr) || IsSetHost(cptr) || feature_bool(FEAT_HIS_USERIP)) && (sptr != cptr)) ? | |
509 | feature_str(FEAT_HIDDEN_IP) : | |
510 | ircd_ntoa(&cli_ip(cptr))); | |
511 | } | |
512 | diff -r c6f3803ee169 ircd/m_who.c | |
513 | --- a/ircd/m_who.c | |
514 | +++ b/ircd/m_who.c | |
515 | @@ -394,14 +394,14 @@ | |
516 | && ((!(matchsel & WHO_FIELD_HOS)) | |
517 | || matchexec(cli_user(acptr)->host, mymask, minlen)) | |
518 | && ((!(matchsel & WHO_FIELD_HOS)) | |
519 | - || !HasSetHost(acptr) | |
520 | + || !IsSetHost(acptr) | |
521 | || !HasHiddenHost(acptr) | |
522 | || !IsAnOper(sptr) | |
523 | || matchexec(cli_user(acptr)->realhost, mymask, minlen)) | |
524 | && ((!(matchsel & WHO_FIELD_REN)) | |
525 | || matchexec(cli_info(acptr), mymask, minlen)) | |
526 | && ((!(matchsel & WHO_FIELD_NIP)) | |
527 | - || ((HasHiddenHost(acptr) || HasSetHost(acptr)) && !IsAnOper(sptr)) | |
528 | + || ((HasHiddenHost(acptr) || IsSetHost(acptr)) && !IsAnOper(sptr)) | |
529 | || !ipmask_check(&cli_ip(acptr), &imask, ibits)) | |
530 | && ((!(matchsel & WHO_FIELD_ACC)) | |
531 | || matchexec(cli_user(acptr)->account, mymask, minlen))) | |
532 | @@ -433,14 +433,14 @@ | |
533 | && ((!(matchsel & WHO_FIELD_HOS)) | |
534 | || matchexec(cli_user(acptr)->host, mymask, minlen)) | |
535 | && ((!(matchsel & WHO_FIELD_HOS)) | |
536 | - || !HasSetHost(acptr) | |
537 | + || !IsSetHost(acptr) | |
538 | || !HasHiddenHost(acptr) | |
539 | || !IsAnOper(sptr) | |
540 | || matchexec(cli_user(acptr)->realhost, mymask, minlen)) | |
541 | && ((!(matchsel & WHO_FIELD_REN)) | |
542 | || matchexec(cli_info(acptr), mymask, minlen)) | |
543 | && ((!(matchsel & WHO_FIELD_NIP)) | |
544 | - || ((HasHiddenHost(acptr) || HasSetHost(acptr)) && !IsAnOper(sptr)) | |
545 | + || ((HasHiddenHost(acptr) || IsSetHost(acptr)) && !IsAnOper(sptr)) | |
546 | || !ipmask_check(&cli_ip(acptr), &imask, ibits)) | |
547 | && ((!(matchsel & WHO_FIELD_ACC)) | |
548 | || matchexec(cli_user(acptr)->account, mymask, minlen))) | |
549 | diff -r c6f3803ee169 ircd/m_whois.c | |
550 | --- a/ircd/m_whois.c | |
551 | +++ b/ircd/m_whois.c | |
552 | @@ -214,7 +214,7 @@ | |
553 | if (IsAccount(acptr)) | |
554 | send_reply(sptr, RPL_WHOISACCOUNT, name, user->account); | |
555 | ||
556 | - if ((HasHiddenHost(acptr) || HasSetHost(acptr)) && ((IsAnOper(sptr) && HasPriv(sptr, PRIV_USER_PRIVACY)) || acptr == sptr)) | |
557 | + if ((HasHiddenHost(acptr) || IsSetHost(acptr)) && ((IsAnOper(sptr) && HasPriv(sptr, PRIV_USER_PRIVACY)) || acptr == sptr)) | |
558 | send_reply(sptr, RPL_WHOISACTUALLY, name, user->realusername, | |
559 | user->realhost, ircd_ntoa(&cli_ip(acptr))); | |
560 | ||
561 | diff -r c6f3803ee169 ircd/s_conf.c | |
562 | --- a/ircd/s_conf.c | |
563 | +++ b/ircd/s_conf.c | |
564 | @@ -52,6 +52,7 @@ | |
565 | #include "s_bsd.h" | |
566 | #include "s_debug.h" | |
567 | #include "s_misc.h" | |
568 | +#include "s_user.h" | |
569 | #include "send.h" | |
570 | #include "struct.h" | |
571 | #include "sys.h" | |
572 | @@ -1239,44 +1240,162 @@ | |
573 | * -froo 1/2003 | |
574 | * | |
575 | */ | |
576 | +/** | |
577 | + * find_spoofblock | |
578 | + * | |
579 | + * Find matching spoof block for a user for the given spoofhost and password | |
580 | + * | |
581 | + * @param cptr User wanting to get a spoof host. | |
582 | + * @param spoofhost Spoof host to look for. | |
583 | + * @param password Password given by user (can be NULL). | |
584 | + * | |
585 | + * @return pointer to the matching spoofblock is found, else NULL | |
586 | + * | |
587 | + */ | |
588 | +struct sline *find_spoofblock(struct Client *cptr, char *spoofhost, char *password) { | |
589 | + struct sline *sconf; | |
590 | + int result = 0; | |
591 | + int r = 0; | |
592 | ||
593 | + Debug((DEBUG_INFO, "find_spoofblock() cptr=%C spoofhost=%s password=%s", | |
594 | + cptr, spoofhost, password)); | |
595 | + | |
596 | + for (sconf = GlobalSList; sconf; sconf = sconf->next) { | |
597 | + | |
598 | + /* check result of previous loop */ | |
599 | + if (r > result) | |
600 | + result = r; | |
601 | + | |
602 | + /* check spoofhost */ | |
603 | + if (strcasecmp(sconf->spoofhost, spoofhost) != 0) | |
604 | + continue; | |
605 | + r = 1; | |
606 | + | |
607 | + /* check cptr's host */ | |
608 | + /* cidr mask */ | |
609 | + if (sconf->flags == SLINE_FLAGS_IP) { | |
610 | + if (!ipmask_check(&(cli_ip(cptr)), &(sconf->address), sconf->bits)) | |
611 | + continue; | |
612 | + } | |
613 | + | |
614 | + /* hostname */ | |
615 | + else if (sconf->flags == SLINE_FLAGS_HOSTNAME) { | |
616 | + if ((match(sconf->realhost, cli_sockhost(cptr)) != 0) && | |
617 | + (match(sconf->realhost, cli_sock_ip(cptr)) != 0)) /* wildcarded IP address */ | |
618 | + continue; | |
619 | + } | |
620 | + | |
621 | + /* not cidr or hostname.. */ | |
622 | + else | |
623 | + continue; | |
624 | + r = 2; | |
625 | + | |
626 | + /* check cptr's username */ | |
627 | + if (!EmptyString(sconf->username) && match(sconf->username, cli_user(cptr)->realusername) != 0) | |
628 | + continue; | |
629 | + r = 3; | |
630 | + | |
631 | + /* check password */ | |
632 | + if (password) { | |
633 | + if (EmptyString(sconf->passwd) || strcmp(sconf->passwd, password) != 0) | |
634 | + continue; | |
635 | + } | |
636 | + | |
637 | + /* no password, but need one for this spoofblock */ | |
638 | + else if (!EmptyString(sconf->passwd)) | |
639 | + continue; | |
640 | + | |
641 | + /* got one */ | |
642 | + log_write(LS_SETHOST, L_INFO, 0, | |
643 | + "SETHOST (%s) by (%#R): ", sconf->spoofhost, cptr); | |
644 | + return sconf; | |
645 | + } | |
646 | + | |
647 | + /* TODO: lookup LOG stuff */ | |
648 | + /* TODO: L_INFO LOG_NOSNOTICE */ | |
649 | + /* log of best result we got */ | |
650 | + if (result == 0) | |
651 | + log_write(LS_SETHOST, L_INFO, 0, | |
652 | + "SETHOST (%s) by (%#R): no such Spoof block", spoofhost, cptr); | |
653 | + if (result == 1) | |
654 | + log_write(LS_SETHOST, L_INFO, 0, | |
655 | + "SETHOST (%s) by (%#R): IP / host mismatch", spoofhost, cptr); | |
656 | + if (result == 2) | |
657 | + log_write(LS_SETHOST, L_INFO, 0, | |
658 | + "SETHOST (%s) by (%#R): username mismatch", spoofhost, cptr); | |
659 | + if (result == 3) | |
660 | + log_write(LS_SETHOST, L_INFO, 0, | |
661 | + "SETHOST (%s) by (%#R): %s", spoofhost, cptr, | |
662 | + password ? "password mismatch" : "password required"); | |
663 | + return NULL; | |
664 | +} | |
665 | + | |
666 | + | |
667 | + | |
668 | +/** | |
669 | + * apply_spoofblock | |
670 | + * | |
671 | + * @param cptr User to apply Spoof block to on connect | |
672 | + * | |
673 | + * @return 1 for success, else 0 | |
674 | + * | |
675 | + */ | |
676 | int | |
677 | -conf_check_slines(struct Client *cptr) | |
678 | +apply_spoofblock(struct Client *cptr) | |
679 | { | |
680 | struct sline *sconf; | |
681 | char *hostonly; | |
682 | ||
683 | + /* disabled */ | |
684 | + if(!feature_bool(FEAT_SETHOST_AUTO)) | |
685 | + return 0; | |
686 | + | |
687 | + /* go over spoof blocks */ | |
688 | for (sconf = GlobalSList; sconf; sconf = sconf->next) { | |
689 | + | |
690 | + /* check IP */ | |
691 | if (sconf->flags == SLINE_FLAGS_IP) { | |
692 | if (!ipmask_check(&(cli_ip(cptr)), &(sconf->address), sconf->bits)) | |
693 | continue; | |
694 | + | |
695 | + /* check host */ | |
696 | } else if (sconf->flags == SLINE_FLAGS_HOSTNAME) { | |
697 | if ((match(sconf->realhost, cli_sockhost(cptr)) != 0) && | |
698 | - (match(sconf->realhost, cli_sock_ip(cptr)) != 0)) /* wildcarded IP address */ | |
699 | + (match(sconf->realhost, cli_sock_ip(cptr)) != 0)) /* wildcarded IP address */ | |
700 | continue; | |
701 | - } else { | |
702 | - continue; | |
703 | - } | |
704 | + } else | |
705 | + continue; | |
706 | ||
707 | - if (match(sconf->username, cli_user(cptr)->username) == 0) { | |
708 | - /* Ignore user part if u@h. */ | |
709 | - if ((hostonly = strchr(sconf->spoofhost, '@'))) | |
710 | - hostonly++; | |
711 | - else | |
712 | - hostonly = sconf->spoofhost; | |
713 | + /* check username */ | |
714 | + if (match(sconf->username, cli_user(cptr)->username) != 0) | |
715 | + continue; | |
716 | ||
717 | - if(!*hostonly) | |
718 | - continue; | |
719 | + /* Ignore user part if u@h. */ | |
720 | + if ((hostonly = strchr(sconf->spoofhost, '@'))) | |
721 | + hostonly++; | |
722 | + else | |
723 | + hostonly = sconf->spoofhost; | |
724 | ||
725 | - ircd_strncpy(cli_user(cptr)->host, hostonly, HOSTLEN); | |
726 | - log_write(LS_USER, L_INFO, LOG_NOSNOTICE, "S-Line (%s@%s) by (%#R)", | |
727 | - cli_user(cptr)->username, hostonly, cptr); | |
728 | - return 1; | |
729 | - } | |
730 | + /* invalid */ | |
731 | + if (!is_validsethost(hostonly, HOSTLEN)) | |
732 | + continue; | |
733 | + | |
734 | + /* do it and log */ | |
735 | + set_hostmask(cptr, NULL, hostonly); | |
736 | + /* LOG_NOSNOTICE */ | |
737 | + log_write(LS_USER, L_INFO, 0, "AUTO SETHOST %s on %s", | |
738 | + hostonly, get_client_name(cptr, SHOW_IP)); | |
739 | + return 1; | |
740 | } | |
741 | return 0; | |
742 | } | |
743 | ||
744 | + | |
745 | + | |
746 | +/** | |
747 | + * | |
748 | + * | |
749 | + */ | |
750 | void free_spoofhost(struct sline *spoof) { | |
751 | MyFree(spoof->spoofhost); | |
752 | MyFree(spoof->passwd); | |
753 | diff -r c6f3803ee169 ircd/s_err.c | |
754 | --- a/ircd/s_err.c | |
755 | +++ b/ircd/s_err.c | |
756 | @@ -824,13 +824,13 @@ | |
757 | /* 395 */ | |
758 | { 0 }, | |
759 | /* 396 */ | |
760 | - { RPL_HOSTHIDDEN, "%s :is now your hidden host", "396" }, | |
761 | + { RPL_HOSTHIDDEN, "%s%s%s :is now your hidden host", "396" }, | |
762 | /* 397 */ | |
763 | { 0 }, | |
764 | /* 398 */ | |
765 | - { RPL_STATSSLINE, "%d %s %s %s %s", "398" }, | |
766 | + { RPL_STATSSLINE, "%c %s %s %s%s%s", "398" }, | |
767 | /* 399 */ | |
768 | - { RPL_USINGSLINE, ":Using S-line privilege", "399" }, | |
769 | + { 0 }, | |
770 | /* 400 */ | |
771 | { 0 }, | |
772 | /* 401 */ | |
773 | @@ -1092,9 +1092,9 @@ | |
774 | /* 529 */ | |
775 | { 0 }, | |
776 | /* 530 */ | |
777 | - { ERR_BADHOSTMASK, "%s :Invalid username/hostmask", "530" }, | |
778 | + { ERR_BADHOSTMASK, "%s%s%s :Invalid username/hostmask", "530" }, | |
779 | /* 531 */ | |
780 | - { ERR_HOSTUNAVAIL, "%s :sethost not found", "531" }, | |
781 | + { ERR_HOSTUNAVAIL, "%s%s%s :Sethost not found", "531" }, | |
782 | /* 532 */ | |
783 | { 0 }, | |
784 | /* 533 */ | |
785 | diff -r c6f3803ee169 ircd/s_stats.c | |
786 | --- a/ircd/s_stats.c | |
787 | +++ b/ircd/s_stats.c | |
788 | @@ -400,41 +400,37 @@ | |
789 | } | |
790 | } | |
791 | ||
792 | +/* TODO: */ | |
793 | +/** List spoof blocks. | |
794 | + * @param[in] to Client requesting statistics. | |
795 | + * @param[in] sd Stats descriptor for request (ignored). | |
796 | + * @param[in] param Filter for spoofhost names. | |
797 | + */ | |
798 | static void | |
799 | stats_sline(struct Client* to, const struct StatDesc* sd, char* param) | |
800 | { | |
801 | - int y = 1, i = 1; | |
802 | struct sline *sline; | |
803 | ||
804 | if (IsAnOper(to)) | |
805 | - send_reply(to, SND_EXPLICIT | RPL_TEXT, "# Type Spoofhost Realhost Ident"); | |
806 | + send_reply(to, SND_EXPLICIT | RPL_TEXT, "S Type Spoofhost Hostmask"); | |
807 | else | |
808 | - send_reply(to, SND_EXPLICIT | RPL_TEXT, "# Type Spoofhost"); | |
809 | + send_reply(to, SND_EXPLICIT | RPL_TEXT, "S Type Spoofhost"); | |
810 | ||
811 | for (sline = GlobalSList; sline; sline = sline->next) { | |
812 | - if (param && match(param, sline->spoofhost)) { /* narrow search */ | |
813 | - if (IsAnOper(to)) | |
814 | - y++; | |
815 | - else | |
816 | - if (!EmptyString(sline->passwd)) | |
817 | - y++; | |
818 | + | |
819 | + if (param && match(param, sline->spoofhost)) | |
820 | continue; | |
821 | - } | |
822 | ||
823 | - if (IsAnOper(to)) { | |
824 | - send_reply(to, RPL_STATSSLINE, (param) ? y : i, | |
825 | - (EmptyString(sline->passwd)) ? "oper" : "user", | |
826 | - sline->spoofhost, | |
827 | - (EmptyString(sline->realhost)) ? "" : sline->realhost, | |
828 | - (EmptyString(sline->username)) ? "" : sline->username); | |
829 | - i++; | |
830 | - } else { | |
831 | - if (!EmptyString(sline->passwd)) { | |
832 | - send_reply(to, RPL_STATSSLINE, (param) ? y : i, "user", sline->spoofhost, | |
833 | - "", "", ""); | |
834 | - i++; | |
835 | - } | |
836 | - } | |
837 | + if (IsAnOper(to)) | |
838 | + send_reply(to, RPL_STATSSLINE, | |
839 | + is_validsethost(sline->spoofhost, HOSTLEN) ? 'S' : 's', /* valid show S else s */ | |
840 | + (EmptyString(sline->passwd)) ? "Oper" : "User", | |
841 | + sline->spoofhost, | |
842 | + (EmptyString(sline->username)) ? "" : sline->username, | |
843 | + (!EmptyString(sline->username)) ? "@" : "", /* always place a @ after the username */ | |
844 | + (EmptyString(sline->realhost)) ? "" : sline->realhost); | |
845 | + else if (!EmptyString(sline->passwd) && is_validsethost(sline->spoofhost, HOSTLEN)) | |
846 | + send_reply(to, RPL_STATSSLINE, 'S', "User", sline->spoofhost, "", "", ""); | |
847 | } | |
848 | } | |
849 | ||
850 | diff -r c6f3803ee169 ircd/s_user.c | |
851 | --- a/ircd/s_user.c | |
852 | +++ b/ircd/s_user.c | |
853 | @@ -73,9 +73,6 @@ | |
854 | #include <string.h> | |
855 | #include <sys/stat.h> | |
856 | ||
857 | -static char *IsVhost(char *hostmask, int oper); | |
858 | -static char *IsVhostPass(char *hostmask); | |
859 | - | |
860 | /** Count of allocated User structures. */ | |
861 | static int userCount = 0; | |
862 | ||
863 | @@ -373,13 +370,6 @@ | |
864 | ||
865 | if (feature_bool(FEAT_AUTOINVISIBLE)) | |
866 | SetInvisible(sptr); | |
867 | - | |
868 | - if(feature_bool(FEAT_SETHOST_AUTO)) { | |
869 | - if (conf_check_slines(sptr)) { | |
870 | - send_reply(sptr, RPL_USINGSLINE); | |
871 | - SetSetHost(sptr); | |
872 | - } | |
873 | - } | |
874 | ||
875 | SetUser(sptr); | |
876 | cli_handler(sptr) = CLIENT_HANDLER; | |
877 | @@ -411,6 +401,10 @@ | |
878 | cli_info(sptr), NumNick(cptr) /* two %s's */); | |
879 | ||
880 | IPcheck_connect_succeeded(sptr); | |
881 | + | |
882 | + /* TODO: */ | |
883 | + /* apply auto sethost if needed */ | |
884 | + apply_spoofblock(sptr); | |
885 | } | |
886 | else { | |
887 | struct Client *acptr = user->server; | |
888 | @@ -519,7 +513,7 @@ | |
889 | else | |
890 | FlagClr(&flags, FLAG_ACCOUNT); | |
891 | client_set_privs(sptr, NULL); | |
892 | - send_umode(cptr, sptr, &flags, ALL_UMODES, 0); | |
893 | + send_umode(cptr, sptr, &flags, ALL_UMODES, 0, 0); | |
894 | if ((cli_snomask(sptr) != SNO_DEFAULT) && HasFlag(sptr, FLAG_SERVNOTICE)) | |
895 | send_reply(sptr, RPL_SNOMASK, cli_snomask(sptr), cli_snomask(sptr)); | |
896 | } | |
897 | @@ -874,14 +868,15 @@ | |
898 | * @param[in] sptr Client who sent us the mode change message. | |
899 | * @param[in] old Prior set of user flags. | |
900 | * @param[in] prop If non-zero, also include FLAG_OPER. | |
901 | + * @param[in] alreadyh Client is already +h, do not show +h change | |
902 | */ | |
903 | void send_umode_out(struct Client *cptr, struct Client *sptr, | |
904 | - struct Flags *old, int prop) | |
905 | + struct Flags *old, int prop, int alreadyh) | |
906 | { | |
907 | int i; | |
908 | struct Client *acptr; | |
909 | ||
910 | - send_umode(NULL, sptr, old, prop ? SEND_UMODES : SEND_UMODES_BUT_OPER, 0); | |
911 | + send_umode(NULL, sptr, old, prop ? SEND_UMODES : SEND_UMODES_BUT_OPER, 0, 0); | |
912 | ||
913 | for (i = HighestFd; i >= 0; i--) | |
914 | { | |
915 | @@ -890,7 +885,7 @@ | |
916 | sendcmdto_one(sptr, CMD_MODE, acptr, "%s %s", cli_name(sptr), umodeBuf); | |
917 | } | |
918 | ||
919 | - send_umode(NULL, sptr, old, prop ? SEND_UMODES : SEND_UMODES_BUT_OPER, 1); | |
920 | + send_umode(NULL, sptr, old, prop ? SEND_UMODES : SEND_UMODES_BUT_OPER, 1, 0); | |
921 | ||
922 | for (i = HighestFd; i >= 0; i--) | |
923 | { | |
924 | @@ -900,7 +895,7 @@ | |
925 | } | |
926 | ||
927 | if (cptr && MyUser(cptr)) | |
928 | - send_umode(cptr, sptr, old, ALL_UMODES, 0); | |
929 | + send_umode(cptr, sptr, old, ALL_UMODES, 0, alreadyh); | |
930 | } | |
931 | ||
932 | ||
933 | @@ -965,7 +960,7 @@ | |
934 | } | |
935 | ||
936 | SetFlag(cptr, flag); | |
937 | - if (!HasFlag(cptr, FLAG_HIDDENHOST) || !HasFlag(cptr, FLAG_ACCOUNT) || HasSetHost(cptr)) | |
938 | + if (!HasFlag(cptr, FLAG_HIDDENHOST) || !HasFlag(cptr, FLAG_ACCOUNT) || IsSetHost(cptr)) | |
939 | return 0; | |
940 | ||
941 | sendcmdto_common_channels_butone(cptr, CMD_QUIT, cptr, ":Registered"); | |
942 | @@ -974,7 +969,7 @@ | |
943 | ||
944 | /* ok, the client is now fully hidden, so let them know -- hikari */ | |
945 | if (MyConnect(cptr)) | |
946 | - send_reply(cptr, RPL_HOSTHIDDEN, cli_user(cptr)->host); | |
947 | + send_reply(cptr, RPL_HOSTHIDDEN, "", "", cli_user(cptr)->host); | |
948 | ||
949 | /* | |
950 | * Go through all channels the client was on, rejoin him | |
951 | @@ -999,201 +994,104 @@ | |
952 | return 0; | |
953 | } | |
954 | ||
955 | +/* TODO: */ | |
956 | /* | |
957 | * set_hostmask() - derived from hide_hostmask() | |
958 | * | |
959 | */ | |
960 | -int set_hostmask(struct Client *cptr, char *hostmask, char *password) | |
961 | +int set_hostmask(struct Client *cptr, char *user, char *host) | |
962 | { | |
963 | - int restore = 0; | |
964 | - int freeform = 0; | |
965 | - char *host, *new_vhost, *vhost_pass; | |
966 | - char hiddenhost[USERLEN + HOSTLEN + 2]; | |
967 | + | |
968 | + int userchange = 0; | |
969 | + char hiddenhost[USERLEN + 1 + HOSTLEN + 1]; | |
970 | + char *msg = "Host change"; | |
971 | struct Membership *chan; | |
972 | ||
973 | - Debug((DEBUG_INFO, "set_hostmask() %C, %s, %s", cptr, hostmask, password)); | |
974 | + assert(0 != cptr); | |
975 | ||
976 | - /* sethost enabled? */ | |
977 | - if (MyConnect(cptr) && !feature_bool(FEAT_SETHOST)) { | |
978 | - send_reply(cptr, ERR_DISABLED, "SETHOST"); | |
979 | + Debug((DEBUG_INFO, "set_hostmask() cptr=%C user=%s host=%s", | |
980 | + cptr, user ? user : "<null>", host ? host : "<null>")); | |
981 | + | |
982 | + /* remove sethost, but user has none */ | |
983 | + if (!host && !IsSetHost(cptr)) | |
984 | return 0; | |
985 | + | |
986 | + /* remove sethost, user has +x host, realusername and username are the same | |
987 | + * pretend the user just set +x | |
988 | + */ | |
989 | + if (!host && HasHiddenHost(cptr) && | |
990 | + strcmp(cli_user(cptr)->username, cli_user(cptr)->realusername) == 0) | |
991 | + msg = "Registered"; | |
992 | + | |
993 | + /* quit user */ | |
994 | + sendcmdto_common_channels_butone(cptr, CMD_QUIT, cptr, ":%s", msg); | |
995 | + | |
996 | + /* remove sethost */ | |
997 | + if (!host) { | |
998 | + | |
999 | + /* clear flag */ | |
1000 | + ClearSetHost(cptr); | |
1001 | + | |
1002 | + /* restore user and host */ | |
1003 | + if (HasHiddenHost(cptr)) | |
1004 | + ircd_snprintf(0, cli_user(cptr)->host, HOSTLEN, "%s.%s", | |
1005 | + cli_user(cptr)->account, feature_str(FEAT_HIDDEN_HOST)); | |
1006 | + else | |
1007 | + strncpy(cli_user(cptr)->host, cli_user(cptr)->realhost, HOSTLEN); | |
1008 | + if (MyConnect(cptr) && strcmp(cli_user(cptr)->username, cli_user(cptr)->realusername) != 0) | |
1009 | + userchange = 1; | |
1010 | + strncpy(cli_user(cptr)->username, cli_user(cptr)->realusername, USERLEN); | |
1011 | } | |
1012 | ||
1013 | - /* sethost enabled for users? */ | |
1014 | - if (MyConnect(cptr) && !IsAnOper(cptr) && !feature_bool(FEAT_SETHOST_USER)) { | |
1015 | - send_reply(cptr, ERR_NOPRIVILEGES); | |
1016 | - return 0; | |
1017 | - } | |
1018 | - | |
1019 | - /* MODE_DEL: restore original hostmask */ | |
1020 | - if (EmptyString(hostmask)) { | |
1021 | - /* is already sethost'ed? and only opers can remove a sethost */ | |
1022 | - if (IsSetHost(cptr) && IsAnOper(cptr)) { | |
1023 | - restore = 1; | |
1024 | - sendcmdto_common_channels_butone(cptr, CMD_QUIT, cptr, ":Host change"); | |
1025 | - /* If they are +rx, we need to return to their +x host, not their "real" host */ | |
1026 | - if (HasHiddenHost(cptr)) | |
1027 | - ircd_snprintf(0, cli_user(cptr)->host, HOSTLEN, "%s.%s", | |
1028 | - cli_user(cptr)->account, feature_str(FEAT_HIDDEN_HOST)); | |
1029 | - else | |
1030 | - strncpy(cli_user(cptr)->host, cli_user(cptr)->realhost, HOSTLEN); | |
1031 | - strncpy(cli_user(cptr)->username, cli_user(cptr)->realusername, USERLEN); | |
1032 | - /* log it */ | |
1033 | - if (MyConnect(cptr)) | |
1034 | - log_write(LS_SETHOST, L_INFO, LOG_NOSNOTICE, | |
1035 | - "SETHOST (%s@%s) by (%#R): restoring real hostmask", | |
1036 | - cli_user(cptr)->username, cli_user(cptr)->host, cptr); | |
1037 | - } else | |
1038 | - return 0; | |
1039 | - /* MODE_ADD: set a new hostmask */ | |
1040 | - } else { | |
1041 | - /* chop up ident and host.cc */ | |
1042 | - if ((host = strrchr(hostmask, '@'))) { /* oper can specifiy ident@host.cc */ | |
1043 | - *host++ = '\0'; | |
1044 | - if ( MyConnect(cptr) && (0 == strcmp(host, cli_user(cptr)->host)) && (0 == strcmp(hostmask, cli_user(cptr)->username))) { | |
1045 | - ircd_snprintf(0, hiddenhost, HOSTLEN + USERLEN + 2, "%s@%s", | |
1046 | - cli_user(cptr)->username, cli_user(cptr)->host); | |
1047 | - send_reply(cptr, RPL_HOSTHIDDEN, hiddenhost); | |
1048 | - return 0; | |
1049 | - } | |
1050 | - } else { /* user can only specifiy host.cc [password] */ | |
1051 | - host = hostmask; | |
1052 | - if ( MyConnect(cptr) && (0 == strcmp(host, cli_user(cptr)->host))) { | |
1053 | - ircd_snprintf(0, hiddenhost, HOSTLEN + USERLEN + 2, "%s@%s", | |
1054 | - cli_user(cptr)->username, cli_user(cptr)->host); | |
1055 | - send_reply(cptr, RPL_HOSTHIDDEN, hiddenhost); | |
1056 | - return 0; | |
1057 | - } | |
1058 | - } | |
1059 | - /* | |
1060 | - * Oper sethost | |
1061 | - */ | |
1062 | - if (MyConnect(cptr)) { | |
1063 | - if (IsAnOper(cptr)) { | |
1064 | - if ((new_vhost = IsVhost(host, 1)) == NULL) { | |
1065 | - if (!HasPriv(cptr, PRIV_FREEFORM)) { | |
1066 | - send_reply(cptr, ERR_HOSTUNAVAIL, hostmask); | |
1067 | - log_write(LS_SETHOST, L_INFO, LOG_NOSNOTICE, | |
1068 | - "SETHOST (%s@%s) by (%#R): no such s-line", | |
1069 | - (host != hostmask) ? hostmask : cli_user(cptr)->username, host, cptr); | |
1070 | - return 0; | |
1071 | - } else /* freeform active, log and go */ | |
1072 | - freeform = 1; | |
1073 | - } | |
1074 | - sendcmdto_common_channels_butone(cptr, CMD_QUIT, cptr, ":Host change"); | |
1075 | - /* set the new ident and host */ | |
1076 | - if (host != hostmask) /* oper only specified host.cc */ | |
1077 | - strncpy(cli_user(cptr)->username, hostmask, USERLEN); | |
1078 | - strncpy(cli_user(cptr)->host, host, HOSTLEN); | |
1079 | - /* log it */ | |
1080 | - log_write(LS_SETHOST, (freeform) ? L_NOTICE : L_INFO, | |
1081 | - (freeform) ? 0 : LOG_NOSNOTICE, "SETHOST (%s@%s) by (%#R)%s", | |
1082 | - cli_user(cptr)->username, cli_user(cptr)->host, cptr, | |
1083 | - (freeform) ? ": using freeform" : ""); | |
1084 | - /* | |
1085 | - * plain user sethost, handled here | |
1086 | - */ | |
1087 | - } else { | |
1088 | - /* empty password? */ | |
1089 | - if (EmptyString(password)) { | |
1090 | - send_reply(cptr, ERR_NEEDMOREPARAMS, "MODE"); | |
1091 | - return 0; | |
1092 | - } | |
1093 | - /* no such s-line */ | |
1094 | - if ((new_vhost = IsVhost(host, 0)) == NULL) { | |
1095 | - send_reply(cptr, ERR_HOSTUNAVAIL, hostmask); | |
1096 | - log_write(LS_SETHOST, L_INFO, LOG_NOSNOTICE, "SETHOST (%s@%s %s) by (%#R): no such s-line", | |
1097 | - cli_user(cptr)->username, host, password, cptr); | |
1098 | - return 0; | |
1099 | - } | |
1100 | - /* no password */ | |
1101 | - if ((vhost_pass = IsVhostPass(new_vhost)) == NULL) { | |
1102 | - send_reply(cptr, ERR_PASSWDMISMATCH); | |
1103 | - log_write(LS_SETHOST, L_INFO, 0, "SETHOST (%s@%s %s) by (%#R): trying to use an oper s-line", | |
1104 | - cli_user(cptr)->username, host, password, cptr); | |
1105 | - return 0; | |
1106 | - } | |
1107 | - /* incorrect password */ | |
1108 | - if (strCasediff(vhost_pass, password)) { | |
1109 | - send_reply(cptr, ERR_PASSWDMISMATCH); | |
1110 | - log_write(LS_SETHOST, L_NOTICE, 0, "SETHOST (%s@%s %s) by (%#R): incorrect password", | |
1111 | - cli_user(cptr)->username, host, password, cptr); | |
1112 | - return 0; | |
1113 | - } | |
1114 | - sendcmdto_common_channels_butone(cptr, CMD_QUIT, cptr, ":Host change"); | |
1115 | - /* set the new host */ | |
1116 | - strncpy(cli_user(cptr)->host, new_vhost, HOSTLEN); | |
1117 | - /* log it */ | |
1118 | - log_write(LS_SETHOST, L_INFO, LOG_NOSNOTICE, "SETHOST (%s@%s) by (%#R)", | |
1119 | - cli_user(cptr)->username, cli_user(cptr)->host, cptr); | |
1120 | - } | |
1121 | - } else { /* remote user */ | |
1122 | - sendcmdto_common_channels_butone(cptr, CMD_QUIT, cptr, ":Host change"); | |
1123 | - if (host != hostmask) /* oper only specified host.cc */ | |
1124 | - strncpy(cli_user(cptr)->username, hostmask, USERLEN); | |
1125 | - strncpy(cli_user(cptr)->host, host, HOSTLEN); | |
1126 | - } | |
1127 | + /* apply sethost */ | |
1128 | + else { | |
1129 | + | |
1130 | + /* set flag */ | |
1131 | + SetSetHost(cptr); | |
1132 | + | |
1133 | + /* update user and host */ | |
1134 | + if (user) | |
1135 | + strncpy(cli_user(cptr)->username, user, USERLEN); | |
1136 | + strncpy(cli_user(cptr)->host, host, HOSTLEN); | |
1137 | } | |
1138 | ||
1139 | - if (restore) | |
1140 | - ClearSetHost(cptr); | |
1141 | - else | |
1142 | - SetSetHost(cptr); | |
1143 | + /* tell user */ | |
1144 | + if (MyConnect(cptr)) { | |
1145 | ||
1146 | - if (MyConnect(cptr)) { | |
1147 | - ircd_snprintf(0, hiddenhost, HOSTLEN + USERLEN + 2, "%s@%s", | |
1148 | - cli_user(cptr)->username, cli_user(cptr)->host); | |
1149 | - send_reply(cptr, RPL_HOSTHIDDEN, hiddenhost); | |
1150 | + /* user and host changed */ | |
1151 | + if (userchange || strcmp(cli_user(cptr)->username, cli_user(cptr)->realusername) != 0) | |
1152 | + send_reply(cptr, RPL_HOSTHIDDEN, cli_user(cptr)->username, "@", cli_user(cptr)->host); | |
1153 | + | |
1154 | + /* just host changed */ | |
1155 | + else | |
1156 | + send_reply(cptr, RPL_HOSTHIDDEN, "", "", cli_user(cptr)->host); | |
1157 | } | |
1158 | ||
1159 | -#if 0 | |
1160 | - /* Code copied from hide_hostmask(). This is the old (pre-delayedjoin) | |
1161 | - * version. Switch this in if you're not using the delayed join patch. */ | |
1162 | - /* | |
1163 | - * Go through all channels the client was on, rejoin him | |
1164 | - * and set the modes, if any | |
1165 | - */ | |
1166 | + /* go over the channels */ | |
1167 | for (chan = cli_user(cptr)->channel; chan; chan = chan->next_channel) { | |
1168 | + | |
1169 | + /* invalidate bans so they are rechecked */ | |
1170 | + ClearBanValid(chan); | |
1171 | + | |
1172 | + /* zombie */ | |
1173 | if (IsZombie(chan)) | |
1174 | continue; | |
1175 | - sendcmdto_channel_butserv_butone(cptr, CMD_JOIN, chan->channel, cptr, | |
1176 | - "%H", chan->channel); | |
1177 | - if (IsChanOp(chan) && HasVoice(chan)) { | |
1178 | - sendcmdto_channel_butserv_butone(&me, CMD_MODE, chan->channel, cptr, | |
1179 | - "%H +ov %C %C", chan->channel, cptr, cptr); | |
1180 | - } else if (IsChanOp(chan) || HasVoice(chan)) { | |
1181 | - sendcmdto_channel_butserv_butone(&me, CMD_MODE, chan->channel, cptr, | |
1182 | - "%H +%c %C", chan->channel, IsChanOp(chan) ? 'o' : 'v', cptr); | |
1183 | - } | |
1184 | - } | |
1185 | -#endif | |
1186 | ||
1187 | - /* | |
1188 | - * Go through all channels the client was on, rejoin him | |
1189 | - * and set the modes, if any | |
1190 | - */ | |
1191 | - for (chan = cli_user(cptr)->channel; chan; chan = chan->next_channel) { | |
1192 | - if (IsZombie(chan)) | |
1193 | - continue; | |
1194 | - /* If this channel has delayed joins and the user has no modes, just set | |
1195 | - * the delayed join flag rather than showing the join, even if the user | |
1196 | - * was visible before */ | |
1197 | - if (!IsChanOp(chan) && !HasVoice(chan) | |
1198 | - && (chan->channel->mode.mode & MODE_DELJOINS)) { | |
1199 | - SetDelayedJoin(chan); | |
1200 | - } else { | |
1201 | + /* not delayed join, rejoin user to chan */ | |
1202 | + if (!IsDelayedJoin(chan)) | |
1203 | sendcmdto_channel_butserv_butone(cptr, CMD_JOIN, chan->channel, cptr, 0, | |
1204 | "%H", chan->channel); | |
1205 | - } | |
1206 | - if (IsChanOp(chan) && HasVoice(chan)) { | |
1207 | + | |
1208 | + /* restore modes */ | |
1209 | + if (IsChanOp(chan) && HasVoice(chan)) | |
1210 | sendcmdto_channel_butserv_butone(&his, CMD_MODE, chan->channel, cptr, 0, | |
1211 | "%H +ov %C %C", chan->channel, cptr, cptr); | |
1212 | - } else if (IsChanOp(chan) || HasVoice(chan)) { | |
1213 | + else if (IsChanOp(chan) || HasVoice(chan)) | |
1214 | sendcmdto_channel_butserv_butone(&his, CMD_MODE, chan->channel, cptr, 0, | |
1215 | "%H +%c %C", chan->channel, IsChanOp(chan) ? 'o' : 'v', cptr); | |
1216 | - } | |
1217 | } | |
1218 | - return 1; | |
1219 | + | |
1220 | + return 0; | |
1221 | } | |
1222 | ||
1223 | /** Set a user's mode. This function checks that \a cptr is trying to | |
1224 | @@ -1220,15 +1118,17 @@ | |
1225 | unsigned int tmpmask = 0; | |
1226 | int snomask_given = 0; | |
1227 | char buf[BUFSIZE]; | |
1228 | - char *hostmask, *password; | |
1229 | + char *hostmask = NULL; | |
1230 | int prop = 0; | |
1231 | int do_host_hiding = 0; | |
1232 | int do_set_host = 0; | |
1233 | + int alreadyh = 0; | |
1234 | size_t opernamelen; | |
1235 | char *opername = 0; | |
1236 | char* account = NULL; | |
1237 | + char *user = NULL; | |
1238 | + char *host = NULL; | |
1239 | ||
1240 | - hostmask = password = NULL; | |
1241 | what = MODE_ADD; | |
1242 | ||
1243 | if (parc < 3) | |
1244 | @@ -1238,8 +1138,7 @@ | |
1245 | for (i = 0; i < USERMODELIST_SIZE; i++) | |
1246 | { | |
1247 | if (HasFlag(sptr, userModeList[i].flag) && | |
1248 | - ((userModeList[i].flag != FLAG_ACCOUNT) && | |
1249 | - (userModeList[i].flag != FLAG_SETHOST))) | |
1250 | + userModeList[i].flag != FLAG_ACCOUNT) | |
1251 | *m++ = userModeList[i].c; | |
1252 | } | |
1253 | *m = '\0'; | |
1254 | @@ -1251,6 +1150,9 @@ | |
1255 | return 0; | |
1256 | } | |
1257 | ||
1258 | + if (IsSetHost(sptr)) | |
1259 | + alreadyh = 1; | |
1260 | + | |
1261 | /* | |
1262 | * find flags already set for user | |
1263 | * why not just copy them? | |
1264 | @@ -1394,26 +1296,18 @@ | |
1265 | break; | |
1266 | case 'h': | |
1267 | if (what == MODE_ADD) { | |
1268 | - if (*(p + 1) && is_hostmask(*(p + 1))) { | |
1269 | - do_set_host = 1; | |
1270 | - hostmask = *++p; | |
1271 | - /* DON'T step p onto the trailing NULL in the parameter array! - splidge */ | |
1272 | - if (*(p+1)) | |
1273 | - password = *++p; | |
1274 | - else | |
1275 | - password = NULL; | |
1276 | - } else { | |
1277 | - if (!*(p+1)) | |
1278 | - send_reply(sptr, ERR_NEEDMOREPARAMS, "SETHOST"); | |
1279 | + /* TODO: */ | |
1280 | + if (IsServer(cptr)) { | |
1281 | + if (!*(p + 1)) | |
1282 | + protocol_violation(cptr, "Received mode +h for user %C without sethost parameter", sptr); | |
1283 | else { | |
1284 | - send_reply(sptr, ERR_BADHOSTMASK, *(p+1)); | |
1285 | - p++; /* Swallow the arg anyway */ | |
1286 | + hostmask = *++p; | |
1287 | + do_set_host = 1; | |
1288 | } | |
1289 | } | |
1290 | } else { /* MODE_DEL */ | |
1291 | + hostmask = NULL; | |
1292 | do_set_host = 1; | |
1293 | - hostmask = NULL; | |
1294 | - password = NULL; | |
1295 | } | |
1296 | break; | |
1297 | case 'R': | |
1298 | @@ -1468,6 +1362,11 @@ | |
1299 | if (!FlagHas(&setflags, FLAG_PARANOID) && !(IsOper(sptr) && HasPriv(sptr, PRIV_PARANOID))) | |
1300 | ClearParanoid(sptr); | |
1301 | ||
1302 | + /* TODO: */ | |
1303 | + /* only opers can remove a sethost */ | |
1304 | + if (do_set_host && !hostmask && !FlagHas(&setflags, FLAG_LOCOP) && !FlagHas(&setflags, FLAG_OPER)) | |
1305 | + do_set_host = 0; | |
1306 | + | |
1307 | /* | |
1308 | * only send wallops to opers | |
1309 | */ | |
1310 | @@ -1521,11 +1420,35 @@ | |
1311 | } | |
1312 | if (!FlagHas(&setflags, FLAG_HIDDENHOST) && do_host_hiding && allow_modes != ALLOWMODES_DEFAULT) | |
1313 | hide_hostmask(sptr, FLAG_HIDDENHOST); | |
1314 | + | |
1315 | + /* TODO: */ | |
1316 | if (do_set_host) { | |
1317 | - /* We clear the flag in the old mask, so that the +h will be sent */ | |
1318 | - /* Only do this if we're SETTING +h and it succeeded */ | |
1319 | - if (set_hostmask(sptr, hostmask, password) && hostmask) | |
1320 | - FlagClr(&setflags, FLAG_SETHOST); | |
1321 | + | |
1322 | + /* mode -h */ | |
1323 | + if (!hostmask) | |
1324 | + set_hostmask(sptr, NULL, NULL); | |
1325 | + | |
1326 | + /* mode +h */ | |
1327 | + else { | |
1328 | + if ((host = strrchr(hostmask, '@'))) { | |
1329 | + *host++ = '\0'; | |
1330 | + user = hostmask; | |
1331 | + } | |
1332 | + else | |
1333 | + host = hostmask; | |
1334 | + | |
1335 | + /* invalid */ | |
1336 | + if (!user || !is_validsethost(user, USERLEN) || !is_validsethost(host, HOSTLEN)) | |
1337 | + protocol_violation(cptr, "Received mode +h for user %C with an invalid sethost parameter '%s@%s'", | |
1338 | + sptr, user ? user : "", host); | |
1339 | + | |
1340 | + /* apply it */ | |
1341 | + else { | |
1342 | + /* clear flag in old mask so that +h will be sent again */ | |
1343 | + FlagClr(&setflags, FLAG_SETHOST); | |
1344 | + set_hostmask(sptr, user, host); | |
1345 | + } | |
1346 | + } | |
1347 | } | |
1348 | ||
1349 | if (IsRegistered(sptr)) { | |
1350 | @@ -1577,7 +1500,7 @@ | |
1351 | } | |
1352 | assert(UserStats.opers <= UserStats.clients + UserStats.unknowns); | |
1353 | assert(UserStats.inv_clients <= UserStats.clients + UserStats.unknowns); | |
1354 | - send_umode_out(cptr, sptr, &setflags, prop); | |
1355 | + send_umode_out(cptr, sptr, &setflags, prop, alreadyh); | |
1356 | } | |
1357 | ||
1358 | return 0; | |
1359 | @@ -1652,9 +1575,11 @@ | |
1360 | * @param[in] old Pre-change set of modes for \a sptr. | |
1361 | * @param[in] sendset One of ALL_UMODES, SEND_UMODES_BUT_OPER, | |
1362 | * SEND_UMODES, to select which changed user modes to send. | |
1363 | + * @param[in] opernames Include opername parameter. | |
1364 | + * @param[in] alreadyh Client already has +h set, do not show +h change. | |
1365 | */ | |
1366 | void send_umode(struct Client *cptr, struct Client *sptr, struct Flags *old, | |
1367 | - int sendset, int opernames) | |
1368 | + int sendset, int opernames, int alreadyh) | |
1369 | { | |
1370 | int i; | |
1371 | int flag; | |
1372 | @@ -1697,12 +1622,15 @@ | |
1373 | } | |
1374 | /* Special case for SETHOST.. */ | |
1375 | if (flag == FLAG_SETHOST) { | |
1376 | - /* Don't send to users */ | |
1377 | - if (cptr && MyUser(cptr)) | |
1378 | - continue; | |
1379 | - | |
1380 | - /* If we're setting +h, add the parameter later */ | |
1381 | - if (!FlagHas(old, flag)) | |
1382 | + | |
1383 | + /* do not show +h if client already had it */ | |
1384 | + if (cptr && MyUser(cptr) && IsSetHost(cptr) && alreadyh) | |
1385 | + continue; | |
1386 | + | |
1387 | + /* If we're setting +h, add the parameter later, | |
1388 | + * but not when showing to the user | |
1389 | + */ | |
1390 | + if (!FlagHas(old, flag) && (!cptr || !MyUser(cptr))) | |
1391 | needhost++; | |
1392 | } | |
1393 | if (FlagHas(old, flag)) | |
1394 | @@ -1769,108 +1697,30 @@ | |
1395 | return 0; | |
1396 | } | |
1397 | ||
1398 | - /* | |
1399 | - * Check to see if it resembles a valid hostmask. | |
1400 | - */ | |
1401 | -int is_hostmask(char *word) | |
1402 | +/** | |
1403 | + * Check to see if it resembles a valid sethost. | |
1404 | + * | |
1405 | + * @param[in] mask Mask to check (user or host part from a sethost) | |
1406 | + * @param[in] maxlen Max length for parameter mask (USERLEN or HOSTLEN) | |
1407 | + * @return Non-zero if \a mask looks like a valid sethost | |
1408 | + * | |
1409 | + */ | |
1410 | +int is_validsethost(char *mask, int maxlen) | |
1411 | { | |
1412 | - int i = 0; | |
1413 | - char *host; | |
1414 | + assert(mask != NULL); | |
1415 | + assert(maxlen > 0); | |
1416 | ||
1417 | - Debug((DEBUG_INFO, "is_hostmask() %s", word)); | |
1418 | - | |
1419 | - if (strlen(word) > (HOSTLEN + USERLEN + 1) || strlen(word) <= 0) | |
1420 | + /* too long or too short */ | |
1421 | + if (strlen(mask) > maxlen || strlen(mask) <= 0) | |
1422 | return 0; | |
1423 | ||
1424 | - /* if a host is specified, make sure it's valid */ | |
1425 | - host = strrchr(word, '@'); | |
1426 | - if (host) { | |
1427 | - if (strlen(++host) < 1) | |
1428 | - return 0; | |
1429 | - if (strlen(host) > HOSTLEN) | |
1430 | - return 0; | |
1431 | + /* check chars */ | |
1432 | + for (; *mask; mask++) { | |
1433 | + if (!IsHostChar(*mask)) | |
1434 | + return 0; | |
1435 | } | |
1436 | ||
1437 | - if (word) { | |
1438 | - if ('@' == *word) /* no leading @'s */ | |
1439 | - return 0; | |
1440 | - | |
1441 | - if ('#' == *word) { /* numeric index given? */ | |
1442 | - for (word++; *word; word++) { | |
1443 | - if (!IsDigit(*word)) | |
1444 | - return 0; | |
1445 | - } | |
1446 | - return 1; | |
1447 | - } | |
1448 | - | |
1449 | - /* normal hostmask, account for at most one '@' */ | |
1450 | - for (; *word; word++) { | |
1451 | - if ('@' == *word) { | |
1452 | - i++; | |
1453 | - continue; | |
1454 | - } | |
1455 | - if (!IsHostChar(*word)) | |
1456 | - return 0; | |
1457 | - } | |
1458 | - return (1 < i) ? 0 : 1; /* no more than on '@' */ | |
1459 | - } | |
1460 | - return 0; | |
1461 | -} | |
1462 | - | |
1463 | - /* | |
1464 | - * IsVhost() - Check if given host is a valid spoofhost | |
1465 | - * (ie: configured thru a S:line) | |
1466 | - */ | |
1467 | -static char *IsVhost(char *hostmask, int oper) | |
1468 | -{ | |
1469 | - unsigned int i = 0, y = 0; | |
1470 | - struct sline *sconf; | |
1471 | - | |
1472 | - Debug((DEBUG_INFO, "IsVhost() %s", hostmask)); | |
1473 | - | |
1474 | - if (EmptyString(hostmask)) | |
1475 | - return NULL; | |
1476 | - | |
1477 | - /* spoofhost specified as index, ie: #27 */ | |
1478 | - if ('#' == hostmask[0]) { | |
1479 | - y = atoi(hostmask + 1); | |
1480 | - for (i = 0, sconf = GlobalSList; sconf; sconf = sconf->next) { | |
1481 | - if (!oper && EmptyString(sconf->passwd)) | |
1482 | - continue; | |
1483 | - if (y == ++i) | |
1484 | - return sconf->spoofhost; | |
1485 | - } | |
1486 | - return NULL; | |
1487 | - } | |
1488 | - | |
1489 | - /* spoofhost specified as host, ie: host.cc */ | |
1490 | - for (sconf = GlobalSList; sconf; sconf = sconf->next) | |
1491 | - if (strCasediff(hostmask, sconf->spoofhost) == 0) | |
1492 | - return sconf->spoofhost; | |
1493 | - | |
1494 | - return NULL; | |
1495 | -} | |
1496 | - | |
1497 | - /* | |
1498 | - * IsVhostPass() - Check if given spoofhost has a password | |
1499 | - * associated with it, and if, return the password (cleartext) | |
1500 | - */ | |
1501 | -static char *IsVhostPass(char *hostmask) | |
1502 | -{ | |
1503 | - struct sline *sconf; | |
1504 | - | |
1505 | - Debug((DEBUG_INFO, "IsVhostPass() %s", hostmask)); | |
1506 | - | |
1507 | - if (EmptyString(hostmask)) | |
1508 | - return NULL; | |
1509 | - | |
1510 | - for (sconf = GlobalSList; sconf; sconf = sconf->next) | |
1511 | - if (strCasediff(hostmask, sconf->spoofhost) == 0) { | |
1512 | - Debug((DEBUG_INFO, "sconf->passwd %s", sconf->passwd)); | |
1513 | - return EmptyString(sconf->passwd) ? NULL : sconf->passwd; | |
1514 | - } | |
1515 | - | |
1516 | - return NULL; | |
1517 | + return 1; | |
1518 | } | |
1519 | ||
1520 | /** Update snomask \a oldmask according to \a arg and \a what. | |
1521 | diff -r c6f3803ee169 ircd/send.c | |
1522 | --- a/ircd/send.c | |
1523 | +++ b/ircd/send.c | |
1524 | @@ -281,7 +281,7 @@ | |
1525 | { | |
1526 | case MATCH_HOST: | |
1527 | return (match(mask, cli_user(one)->host) == 0 || | |
1528 | - ((HasHiddenHost(one) || HasSetHost(one)) && match(mask, cli_user(one)->realhost) == 0)); | |
1529 | + ((HasHiddenHost(one) || IsSetHost(one)) && match(mask, cli_user(one)->realhost) == 0)); | |
1530 | case MATCH_SERVER: | |
1531 | default: | |
1532 | return (match(mask, cli_name(cli_user(one)->server)) == 0); | |
1533 | diff -r c6f3803ee169 ircd/whocmds.c | |
1534 | --- a/ircd/whocmds.c | |
1535 | +++ b/ircd/whocmds.c | |
1536 | @@ -134,7 +134,7 @@ | |
1537 | ||
1538 | if (fields & WHO_FIELD_NIP) | |
1539 | { | |
1540 | - const char* p2 = (HasHiddenHost(acptr) || HasSetHost(acptr) || feature_bool(FEAT_HIS_USERIP)) && (!IsAnOper(sptr) || (IsAnOper(sptr) && !HasPriv(sptr, PRIV_USER_PRIVACY))) ? | |
1541 | + const char* p2 = (HasHiddenHost(acptr) || IsSetHost(acptr) || feature_bool(FEAT_HIS_USERIP)) && (!IsAnOper(sptr) || (IsAnOper(sptr) && !HasPriv(sptr, PRIV_USER_PRIVACY))) ? | |
1542 | feature_str(FEAT_HIDDEN_IP) : | |
1543 | ircd_ntoa(&cli_ip(acptr)); | |
1544 | *(p1++) = ' '; | |
1545 | @@ -210,7 +210,7 @@ | |
1546 | *(p1++) = 'w'; | |
1547 | if (SendDebug(acptr)) | |
1548 | *(p1++) = 'g'; | |
1549 | - if (HasSetHost(acptr)) | |
1550 | + if (IsSetHost(acptr)) | |
1551 | *(p1++) = 'h'; | |
1552 | } | |
1553 | if (HasHiddenHost(acptr)) |