]>
Commit | Line | Data |
---|---|---|
edb26b39 P |
1 | # HG changeset patch |
2 | # Parent 6fd814ecf94bb1713ebf96bffcab63d6c3bdd72b | |
3 | ||
4 | diff -r 6fd814ecf94b include/client.h | |
5 | --- a/include/client.h Fri Jul 19 21:53:51 2013 +0100 | |
6 | +++ b/include/client.h Fri Jul 19 22:26:20 2013 +0100 | |
7 | @@ -168,6 +168,7 @@ | |
8 | FLAG_ACCOUNTONLY, /**< ASUKA_R: hide privmsgs/notices if | |
9 | user is not authed or opered */ | |
10 | FLAG_HIDDENHOST, /**< user's host is hidden */ | |
11 | + FLAG_SETHOST, /**< ASUKA_h: oper's host is changed */ | |
12 | FLAG_NOCHAN, /**< user's channels are hidden */ | |
13 | FLAG_NOIDLE, /**< user's idletime is hidden */ | |
14 | FLAG_XTRAOP, /**< oper has special powers */ | |
15 | @@ -601,6 +602,9 @@ | |
16 | #define IsPrivileged(x) (IsAnOper(x) || IsServer(x)) | |
17 | /** Return non-zero if the client's host is hidden. */ | |
18 | #define HasHiddenHost(x) (IsHiddenHost(x) && IsAccount(x)) | |
19 | +/** Return non-zero if the client is using a spoofhost */ | |
20 | +#define IsSetHost(x) HasFlag(x, FLAG_SETHOST) | |
21 | +#define HasSetHost(x) (IsSetHost(x)) | |
22 | ||
23 | /** Mark a client as having an in-progress net.burst. */ | |
24 | #define SetBurst(x) SetFlag(x, FLAG_BURST) | |
25 | @@ -640,6 +644,8 @@ | |
26 | #define SetAccount(x) SetFlag(x, FLAG_ACCOUNT) | |
27 | /** Mark a client as having mode +x (hidden host). */ | |
28 | #define SetHiddenHost(x) SetFlag(x, FLAG_HIDDENHOST) | |
29 | +/** Mark a client as having mode +h (spoofhost). */ | |
30 | +#define SetSetHost(x) SetFlag(x, FLAG_SETHOST) | |
31 | /** Mark a client as having mode +X (xtraop). */ | |
32 | #define SetXtraOp(x) SetFlag(x, FLAG_XTRAOP) | |
33 | /** Mark a client as having mode +n (hide channels). */ | |
34 | @@ -681,6 +687,8 @@ | |
35 | #define ClearServNotice(x) ClrFlag(x, FLAG_SERVNOTICE) | |
36 | /** Remove mode +x (hidden host) from the client. */ | |
37 | #define ClearHiddenHost(x) ClrFlag(x, FLAG_HIDDENHOST) | |
38 | +/** Remove mode +h (spoofhost) from a client. */ | |
39 | +#define ClearSetHost(x) ClrFlag(x, FLAG_SETHOST) | |
40 | /** Remove mode +X (xtraop) from a client. */ | |
41 | #define ClearXtraOp(x) ClrFlag(x, FLAG_XTRAOP) | |
42 | /** Remove mode +n (hide channels) from a client. */ | |
43 | diff -r 6fd814ecf94b include/handlers.h | |
44 | --- a/include/handlers.h Fri Jul 19 21:53:51 2013 +0100 | |
45 | +++ b/include/handlers.h Fri Jul 19 22:26:20 2013 +0100 | |
46 | @@ -124,6 +124,7 @@ | |
47 | extern int m_pseudo(struct Client*, struct Client*, int, char*[]); | |
48 | extern int m_quit(struct Client*, struct Client*, int, char*[]); | |
49 | extern int m_registered(struct Client*, struct Client*, int, char*[]); | |
50 | +extern int m_sethost(struct Client*, struct Client*, int, char*[]); | |
51 | extern int m_silence(struct Client*, struct Client*, int, char*[]); | |
52 | extern int m_stats(struct Client*, struct Client*, int, char*[]); | |
53 | extern int m_time(struct Client*, struct Client*, int, char*[]); | |
54 | @@ -213,6 +214,7 @@ | |
55 | extern int ms_rping(struct Client*, struct Client*, int, char*[]); | |
56 | extern int ms_rpong(struct Client*, struct Client*, int, char*[]); | |
57 | extern int ms_server(struct Client*, struct Client*, int, char*[]); | |
58 | +extern int ms_sethost(struct Client*, struct Client*, int, char*[]); | |
59 | extern int ms_settime(struct Client*, struct Client*, int, char*[]); | |
60 | extern int ms_silence(struct Client*, struct Client*, int, char*[]); | |
61 | extern int ms_squit(struct Client*, struct Client*, int, char*[]); | |
62 | diff -r 6fd814ecf94b include/ircd_features.h | |
63 | --- a/include/ircd_features.h Fri Jul 19 21:53:51 2013 +0100 | |
64 | +++ b/include/ircd_features.h Fri Jul 19 22:26:20 2013 +0100 | |
65 | @@ -103,6 +103,9 @@ | |
66 | ||
67 | /* features that affect all operators */ | |
68 | FEAT_CONFIG_OPERCMDS, | |
69 | + FEAT_SETHOST, | |
70 | + FEAT_SETHOST_USER, | |
71 | + FEAT_SETHOST_AUTO, | |
72 | ||
73 | /* HEAD_IN_SAND Features */ | |
74 | FEAT_HIS_SNOTICES, | |
75 | @@ -131,6 +134,7 @@ | |
76 | FEAT_HIS_STATS_q, | |
77 | FEAT_HIS_STATS_R, | |
78 | FEAT_HIS_STATS_r, | |
79 | + FEAT_HIS_STATS_s, | |
80 | FEAT_HIS_STATS_t, | |
81 | FEAT_HIS_STATS_T, | |
82 | FEAT_HIS_STATS_u, | |
83 | diff -r 6fd814ecf94b include/ircd_log.h | |
84 | --- a/include/ircd_log.h Fri Jul 19 21:53:51 2013 +0100 | |
85 | +++ b/include/ircd_log.h Fri Jul 19 22:26:20 2013 +0100 | |
86 | @@ -65,6 +65,7 @@ | |
87 | LS_SOCKET, /**< Unexpected socket operation errors. */ | |
88 | LS_IAUTH, /**< IAuth status. */ | |
89 | LS_DEBUG, /**< Debug messages. */ | |
90 | + LS_SETHOST, /**< Usage of the sethost command. */ | |
91 | LS_LAST_SYSTEM /**< Count of valid LogSys values. */ | |
92 | }; | |
93 | ||
94 | diff -r 6fd814ecf94b include/msg.h | |
95 | --- a/include/msg.h Fri Jul 19 21:53:51 2013 +0100 | |
96 | +++ b/include/msg.h Fri Jul 19 22:26:20 2013 +0100 | |
97 | @@ -356,6 +356,10 @@ | |
98 | #define TOK_PRIVS "PR" | |
99 | #define CMD_PRIVS MSG_PRIVS, TOK_PRIVS | |
100 | ||
101 | +#define MSG_SETHOST "SETHOST" /* SETHOST */ | |
102 | +#define TOK_SETHOST "SH" | |
103 | +#define CMD_SETHOST MSG_SETHOST, TOK_SETHOST | |
104 | + | |
105 | #define MSG_CAP "CAP" | |
106 | #define TOK_CAP "CAP" | |
107 | #define CMD_CAP MSG_CAP, TOK_CAP | |
108 | diff -r 6fd814ecf94b include/numeric.h | |
109 | --- a/include/numeric.h Fri Jul 19 21:53:51 2013 +0100 | |
110 | +++ b/include/numeric.h Fri Jul 19 22:26:20 2013 +0100 | |
111 | @@ -207,7 +207,7 @@ | |
112 | #define RPL_AWAY 301 | |
113 | #define RPL_USERHOST 302 | |
114 | #define RPL_ISON 303 | |
115 | -/* RPL_TEXT 304 unused */ | |
116 | +#define RPL_TEXT 304 /* unused */ | |
117 | #define RPL_UNAWAY 305 | |
118 | #define RPL_NOWAWAY 306 | |
119 | /* NotAway, aircd */ | |
120 | @@ -312,6 +312,8 @@ | |
121 | /* RPL_END_USERS 394 Dalnet/EFnet/IRCnet */ | |
122 | /* RPL_NOUSERS 395 Dalnet/EFnet/IRCnet */ | |
123 | #define RPL_HOSTHIDDEN 396 /* UMODE +x completed succesfuly */ | |
124 | +#define RPL_STATSSLINE 398 /* QuakeNet extension -froo */ | |
125 | +#define RPL_USINGSLINE 399 /* QuakeNet extension -froo */ | |
126 | ||
127 | /* | |
128 | * Errors are in the range from 400-599 currently and are grouped by what | |
129 | @@ -461,6 +463,9 @@ | |
130 | #define ERR_QUARANTINED 524 /* Undernet extension -Vampire */ | |
131 | #define ERR_INVALIDKEY 525 /* Undernet extension */ | |
132 | ||
133 | +#define ERR_BADHOSTMASK 530 /* QuakeNet extension -froo */ | |
134 | +#define ERR_HOSTUNAVAIL 531 /* QuakeNet extension -froo */ | |
135 | + | |
136 | #define ERR_NOTLOWEROPLEVEL 560 /* Undernet extension */ | |
137 | #define ERR_NOTMANAGER 561 /* Undernet extension */ | |
138 | #define ERR_CHANSECURED 562 /* Undernet extension */ | |
139 | diff -r 6fd814ecf94b include/s_conf.h | |
140 | --- a/include/s_conf.h Fri Jul 19 21:53:51 2013 +0100 | |
141 | +++ b/include/s_conf.h Fri Jul 19 22:26:20 2013 +0100 | |
142 | @@ -80,6 +80,20 @@ | |
143 | char *reason; /**< Reason for quarantine. */ | |
144 | }; | |
145 | ||
146 | +struct sline { | |
147 | + struct sline *next; | |
148 | + char *spoofhost; | |
149 | + char *passwd; | |
150 | + char *realhost; | |
151 | + char *username; | |
152 | + struct irc_in_addr address; | |
153 | + unsigned int flags; | |
154 | + char bits; /* Number of bits for CIDR match on realhost */ | |
155 | +}; | |
156 | + | |
157 | +#define SLINE_FLAGS_HOSTNAME 0x0001 /* S-line by hostname */ | |
158 | +#define SLINE_FLAGS_IP 0x0002 /* S-line by IP address/CIDR */ | |
159 | + | |
160 | /** Local K-line structure. */ | |
161 | struct DenyConf { | |
162 | struct DenyConf* next; /**< Next DenyConf in #denyConfList. */ | |
163 | @@ -157,6 +171,7 @@ | |
164 | extern int GlobalConfCount; | |
165 | extern struct s_map* GlobalServiceMapList; | |
166 | extern struct qline* GlobalQuarantineList; | |
167 | +extern struct sline* GlobalSList; | |
168 | ||
169 | /* | |
170 | * Proto types | |
171 | @@ -188,6 +203,11 @@ | |
172 | extern struct ConfItem *conf_debug_iline(const char *client); | |
173 | extern void free_mapping(struct s_map *smap); | |
174 | ||
175 | +extern void conf_add_sline(const char* const* fields, int count); | |
176 | +extern void clear_slines(void); | |
177 | +extern int conf_check_slines(struct Client *cptr); | |
178 | +extern void free_spoofhost(struct sline *spoof); | |
179 | + | |
180 | extern void yyerror(const char *msg); | |
181 | ||
182 | #endif /* INCLUDED_s_conf_h */ | |
183 | diff -r 6fd814ecf94b include/s_user.h | |
184 | --- a/include/s_user.h Fri Jul 19 21:53:51 2013 +0100 | |
185 | +++ b/include/s_user.h Fri Jul 19 22:26:20 2013 +0100 | |
186 | @@ -80,6 +80,8 @@ | |
187 | InfoFormatter fmt); | |
188 | ||
189 | extern int hide_hostmask(struct Client *cptr, unsigned int flags); | |
190 | +extern int set_hostmask(struct Client *cptr, char *hostmask, char *password); | |
191 | +extern int is_hostmask(char *word); | |
192 | extern int set_user_mode(struct Client *cptr, struct Client *sptr, | |
193 | int parc, char *parv[], int allow_modes); | |
194 | extern int is_silenced(struct Client *sptr, struct Client *acptr); | |
195 | diff -r 6fd814ecf94b include/struct.h | |
196 | --- a/include/struct.h Fri Jul 19 21:53:51 2013 +0100 | |
197 | +++ b/include/struct.h Fri Jul 19 22:26:20 2013 +0100 | |
198 | @@ -80,10 +80,11 @@ | |
199 | * overwritten with the ident response. | |
200 | */ | |
201 | char username[USERLEN + 1]; | |
202 | - char host[HOSTLEN + 1]; /**< displayed hostname */ | |
203 | - char realhost[HOSTLEN + 1]; /**< actual hostname */ | |
204 | - char account[ACCOUNTLEN + 1]; /**< IRC account name */ | |
205 | - time_t acc_create; /**< IRC account timestamp */ | |
206 | + char host[HOSTLEN + 1]; /**< displayed hostname */ | |
207 | + char realusername[USERLEN + 1]; /**< actual username */ | |
208 | + char realhost[HOSTLEN + 1]; /**< actual hostname */ | |
209 | + char account[ACCOUNTLEN + 1]; /**< IRC account name */ | |
210 | + time_t acc_create; /**< IRC account timestamp */ | |
211 | }; | |
212 | ||
213 | #endif /* INCLUDED_struct_h */ | |
214 | diff -r 6fd814ecf94b ircd/Makefile.in | |
215 | --- a/ircd/Makefile.in Fri Jul 19 21:53:51 2013 +0100 | |
216 | +++ b/ircd/Makefile.in Fri Jul 19 22:26:20 2013 +0100 | |
217 | @@ -167,6 +167,7 @@ | |
218 | m_rpong.c \ | |
219 | m_server.c \ | |
220 | m_set.c \ | |
221 | + m_sethost.c \ | |
222 | m_settime.c \ | |
223 | m_silence.c \ | |
224 | m_squit.c \ | |
225 | diff -r 6fd814ecf94b ircd/channel.c | |
226 | --- a/ircd/channel.c Fri Jul 19 21:53:51 2013 +0100 | |
227 | +++ b/ircd/channel.c Fri Jul 19 22:26:20 2013 +0100 | |
228 | @@ -374,22 +374,28 @@ | |
229 | char tmphost[HOSTLEN + 1]; | |
230 | char iphost[SOCKIPLEN + 1]; | |
231 | char *hostmask; | |
232 | - char *sr; | |
233 | + char *sr = NULL; | |
234 | + char *sa = NULL; | |
235 | struct Ban *found; | |
236 | ||
237 | /* Build nick!user and alternate host names. */ | |
238 | ircd_snprintf(0, nu, sizeof(nu), "%s!%s", | |
239 | cli_name(cptr), cli_user(cptr)->username); | |
240 | ircd_ntoa_r(iphost, &cli_ip(cptr)); | |
241 | - if (!IsAccount(cptr)) | |
242 | - sr = NULL; | |
243 | - else if (HasHiddenHost(cptr)) | |
244 | + | |
245 | + /* sr is real host if +h */ | |
246 | + if (HasSetHost(cptr)) | |
247 | sr = cli_user(cptr)->realhost; | |
248 | - else | |
249 | - { | |
250 | - ircd_snprintf(0, tmphost, HOSTLEN, "%s.%s", | |
251 | - cli_user(cptr)->account, feature_str(FEAT_HIDDEN_HOST)); | |
252 | - sr = tmphost; | |
253 | + | |
254 | + /* if +x and not +h sa is real host, if -x or +h sa is the account host */ | |
255 | + if (IsAccount(cptr)) { | |
256 | + if (HasHiddenHost(cptr) && !HasSetHost(cptr)) { | |
257 | + sa = cli_user(cptr)->realhost; | |
258 | + } else { | |
259 | + ircd_snprintf(0, tmphost, HOSTLEN, "%s.%s", | |
260 | + cli_user(cptr)->account, feature_str(FEAT_HIDDEN_HOST)); | |
261 | + sa = tmphost; | |
262 | + } | |
263 | } | |
264 | ||
265 | /* Walk through ban list. */ | |
266 | @@ -409,7 +415,8 @@ | |
267 | if (!((banlist->flags & BAN_IPMASK) | |
268 | && ipmask_check(&cli_ip(cptr), &banlist->address, banlist->addrbits)) | |
269 | && match(hostmask, cli_user(cptr)->host) | |
270 | - && !(sr && !match(hostmask, sr))) | |
271 | + && !(sr && !match(hostmask, sr)) | |
272 | + && !(sa && !match(hostmask, sa))) | |
273 | continue; | |
274 | /* If an exception matches, no ban can match. */ | |
275 | if (banlist->flags & BAN_EXCEPTION) | |
276 | diff -r 6fd814ecf94b ircd/gline.c | |
277 | --- a/ircd/gline.c Fri Jul 19 21:53:51 2013 +0100 | |
278 | +++ b/ircd/gline.c Fri Jul 19 22:26:20 2013 +0100 | |
279 | @@ -221,7 +221,7 @@ | |
280 | Debug((DEBUG_DEBUG,"Matched!")); | |
281 | } else { /* Host/IP gline */ | |
282 | if (cli_user(acptr)->username && | |
283 | - match(gline->gl_user, (cli_user(acptr))->username) != 0) | |
284 | + match(gline->gl_user, (cli_user(acptr))->realusername) != 0) | |
285 | continue; | |
286 | ||
287 | if (GlineIsIpMask(gline)) { | |
288 | diff -r 6fd814ecf94b ircd/ircd_features.c | |
289 | --- a/ircd/ircd_features.c Fri Jul 19 21:53:51 2013 +0100 | |
290 | +++ b/ircd/ircd_features.c Fri Jul 19 22:26:20 2013 +0100 | |
291 | @@ -368,6 +368,9 @@ | |
292 | ||
293 | /* features that affect all operators */ | |
294 | F_B(CONFIG_OPERCMDS, 0, 0, 0), | |
295 | + F_B(SETHOST, 0, 0, 0), | |
296 | + F_B(SETHOST_USER, 0, 0, 0), | |
297 | + F_B(SETHOST_AUTO, 0, 0, 0), | |
298 | ||
299 | /* HEAD_IN_SAND Features */ | |
300 | F_B(HIS_SNOTICES, 0, 1, 0), | |
301 | @@ -396,6 +399,7 @@ | |
302 | F_B(HIS_STATS_q, 0, 1, 0), | |
303 | F_B(HIS_STATS_R, 0, 1, 0), | |
304 | F_B(HIS_STATS_r, 0, 1, 0), | |
305 | + F_B(HIS_STATS_s, 0, 1, 0), | |
306 | F_B(HIS_STATS_t, 0, 1, 0), | |
307 | F_B(HIS_STATS_T, 0, 1, 0), | |
308 | F_B(HIS_STATS_u, 0, 0, 0), | |
309 | diff -r 6fd814ecf94b ircd/ircd_lexer.l | |
310 | --- a/ircd/ircd_lexer.l Fri Jul 19 21:53:51 2013 +0100 | |
311 | +++ b/ircd/ircd_lexer.l Fri Jul 19 22:26:20 2013 +0100 | |
312 | @@ -103,6 +103,7 @@ | |
313 | TOKEN(USERMODE), | |
314 | TOKEN(FAST), | |
315 | TOKEN(AUTOCONNECT), | |
316 | + TOKEN(SPOOFHOST), | |
317 | TOKEN(PROGRAM), | |
318 | TOKEN(DNS), | |
319 | #undef TOKEN | |
320 | diff -r 6fd814ecf94b ircd/ircd_log.c | |
321 | --- a/ircd/ircd_log.c Fri Jul 19 21:53:51 2013 +0100 | |
322 | +++ b/ircd/ircd_log.c Fri Jul 19 22:26:20 2013 +0100 | |
323 | @@ -164,6 +164,7 @@ | |
324 | S(SOCKET, -1, 0), | |
325 | S(IAUTH, -1, SNO_NETWORK), | |
326 | S(DEBUG, -1, SNO_DEBUG), | |
327 | + S(SETHOST, -1, SNO_OLDSNO), | |
328 | #undef S | |
329 | { LS_LAST_SYSTEM, 0, 0, -1, 0, -1, 0 } | |
330 | }; | |
331 | diff -r 6fd814ecf94b ircd/ircd_parser.y | |
332 | --- a/ircd/ircd_parser.y Fri Jul 19 21:53:51 2013 +0100 | |
333 | +++ b/ircd/ircd_parser.y Fri Jul 19 22:26:20 2013 +0100 | |
334 | @@ -69,6 +69,7 @@ | |
335 | extern struct ServerConf* serverConfList; | |
336 | extern struct s_map* GlobalServiceMapList; | |
337 | extern struct qline* GlobalQuarantineList; | |
338 | + extern struct sline* GlobalSList; | |
339 | ||
340 | int yylex(void); | |
341 | /* Now all the globals we need :/... */ | |
342 | @@ -81,6 +82,7 @@ | |
343 | struct DenyConf *dconf; | |
344 | struct ServerConf *sconf; | |
345 | struct s_map *smap; | |
346 | + struct sline *spoof; | |
347 | struct Privs privs; | |
348 | struct Privs privs_dirty; | |
349 | ||
350 | @@ -173,6 +175,7 @@ | |
351 | %token FAST | |
352 | %token AUTOCONNECT | |
353 | %token PROGRAM | |
354 | +%token SPOOFHOST | |
355 | %token TOK_IPV4 TOK_IPV6 | |
356 | %token DNS | |
357 | /* and now a lot of privileges... */ | |
358 | @@ -202,7 +205,7 @@ | |
359 | block: adminblock | generalblock | classblock | connectblock | | |
360 | uworldblock | operblock | portblock | jupeblock | clientblock | | |
361 | killblock | cruleblock | motdblock | featuresblock | quarantineblock | | |
362 | - pseudoblock | iauthblock | error ';'; | |
363 | + pseudoblock | iauthblock | spoofblock | error ';'; | |
364 | ||
365 | /* The timespec, sizespec and expr was ripped straight from | |
366 | * ircd-hybrid-7. */ | |
367 | @@ -1160,3 +1163,71 @@ | |
368 | MyFree(stringlist[stringno]); | |
369 | } | |
370 | } stringlist ';'; | |
371 | + | |
372 | +spoofblock: SPOOFHOST QSTRING '{' | |
373 | +{ | |
374 | + spoof = MyCalloc(1, sizeof(struct sline)); | |
375 | + spoof->spoofhost = $2; | |
376 | + spoof->passwd = NULL; | |
377 | + spoof->realhost = NULL; | |
378 | + spoof->username = NULL; | |
379 | +} | |
380 | +spoofitems '}' ';' | |
381 | +{ | |
382 | + struct irc_in_addr ip; | |
383 | + char bits; | |
384 | + int valid = 0; | |
385 | + | |
386 | + if (spoof->username == NULL && spoof->realhost) { | |
387 | + parse_error("Username missing in spoofhost."); | |
388 | + } else if (spoof->realhost == NULL && spoof->username) { | |
389 | + parse_error("Realhost missing in spoofhost."); | |
390 | + } else | |
391 | + valid = 1; | |
392 | + | |
393 | + if (valid) { | |
394 | + if (spoof->realhost) { | |
395 | + if (!string_has_wildcards(spoof->realhost)) { | |
396 | + if (ipmask_parse(spoof->realhost, &ip, &bits) != 0) { | |
397 | + spoof->address = ip; | |
398 | + spoof->bits = bits; | |
399 | + spoof->flags = SLINE_FLAGS_IP; | |
400 | + } else { | |
401 | + Debug((DEBUG_DEBUG, "S-Line: \"%s\" appears not to be a valid IP address, might be wildcarded.", spoof->realhost)); | |
402 | + spoof->flags = SLINE_FLAGS_HOSTNAME; | |
403 | + } | |
404 | + } else | |
405 | + spoof->flags = SLINE_FLAGS_HOSTNAME; | |
406 | + } else | |
407 | + spoof->flags = 0; | |
408 | + | |
409 | + spoof->next = GlobalSList; | |
410 | + GlobalSList = spoof; | |
411 | + } else { | |
412 | + MyFree(spoof->spoofhost); | |
413 | + MyFree(spoof->passwd); | |
414 | + MyFree(spoof->realhost); | |
415 | + MyFree(spoof->username); | |
416 | + MyFree(spoof); | |
417 | + } | |
418 | + spoof = NULL; | |
419 | +}; | |
420 | + | |
421 | +spoofitems: spoofitem spoofitems | spoofitem; | |
422 | +spoofitem: spoofpassword | spoofrealhost | spoofrealident; | |
423 | +spoofpassword: PASS '=' QSTRING ';' | |
424 | +{ | |
425 | + MyFree(spoof->passwd); | |
426 | + spoof->passwd = $3; | |
427 | +}; | |
428 | +spoofrealhost: HOST '=' QSTRING ';' | |
429 | +{ | |
430 | + MyFree(spoof->realhost); | |
431 | + spoof->realhost = $3; | |
432 | +}; | |
433 | +spoofrealident: USERNAME '=' QSTRING ';' | |
434 | +{ | |
435 | + MyFree(spoof->username); | |
436 | + spoof->username = $3; | |
437 | +}; | |
438 | + | |
439 | diff -r 6fd814ecf94b ircd/ircd_snprintf.c | |
440 | --- a/ircd/ircd_snprintf.c Fri Jul 19 21:53:51 2013 +0100 | |
441 | +++ b/ircd/ircd_snprintf.c Fri Jul 19 22:26:20 2013 +0100 | |
442 | @@ -180,8 +180,8 @@ | |
443 | #define CONV_VARARGS 0x05000000 /**< convert a %v */ | |
444 | #define CONV_CLIENT 0x06000000 /**< convert a struct Client */ | |
445 | #define CONV_CHANNEL 0x07000000 /**< convert a struct Channel */ | |
446 | +#define CONV_REAL 0x08000000 /**< convert a struct Client and show realhost */ | |
447 | ||
448 | -#define CONV_RESERVED7 0x08000000 /**< reserved for future expansion */ | |
449 | #define CONV_RESERVED6 0x09000000 /**< reserved for future expansion */ | |
450 | #define CONV_RESERVED5 0x0a000000 /**< reserved for future expansion */ | |
451 | #define CONV_RESERVED4 0x0b000000 /**< reserved for future expansion */ | |
452 | @@ -1778,6 +1778,11 @@ | |
453 | fld_s.flags |= ARG_PTR | CONV_CLIENT; | |
454 | break; | |
455 | ||
456 | + case 'R': /* convert a client name... */ | |
457 | + fld_s.flags &= ~(FLAG_PLUS | FLAG_SPACE | FLAG_ZERO | TYPE_MASK); | |
458 | + fld_s.flags |= ARG_PTR | CONV_REAL; | |
459 | + break; | |
460 | + | |
461 | case 'H': /* convert a channel name... */ | |
462 | fld_s.flags &= ~(FLAG_PLUS | FLAG_SPACE | FLAG_ALT | FLAG_ZERO | | |
463 | FLAG_COLON | TYPE_MASK); | |
464 | @@ -2038,7 +2043,8 @@ | |
465 | ||
466 | vdata->vd_chars = buf_s.buf_loc; /* return relevant data */ | |
467 | vdata->vd_overflow = SNP_MAX(buf_s.buf_overflow, buf_s.overflow); | |
468 | - } else if ((fld_s.flags & CONV_MASK) == CONV_CLIENT) { | |
469 | + } else if (((fld_s.flags & CONV_MASK) == CONV_CLIENT) || | |
470 | + ((fld_s.flags & CONV_MASK) == CONV_REAL)) { | |
471 | struct Client *cptr = (struct Client*) fld_s.value.v_ptr; | |
472 | const char *str1 = 0, *str2 = 0, *str3 = 0; | |
473 | int slen1 = 0, slen2 = 0, slen3 = 0, elen = 0, plen = 0; | |
474 | @@ -2057,8 +2063,13 @@ | |
475 | if (!IsServer(cptr) && !IsMe(cptr) && fld_s.flags & FLAG_ALT) { | |
476 | assert(0 != cli_user(cptr)); | |
477 | assert(0 != *(cli_name(cptr))); | |
478 | - str2 = cli_user(cptr)->username; | |
479 | - str3 = cli_user(cptr)->host; | |
480 | + if ((fld_s.flags & CONV_MASK) == CONV_REAL) { | |
481 | + str2 = cli_user(cptr)->realusername; | |
482 | + str3 = cli_user(cptr)->realhost; | |
483 | + } else { | |
484 | + str2 = cli_user(cptr)->username; | |
485 | + str3 = cli_user(cptr)->host; | |
486 | + } | |
487 | } else | |
488 | fld_s.flags &= ~FLAG_ALT; | |
489 | } | |
490 | diff -r 6fd814ecf94b ircd/m_oper.c | |
491 | --- a/ircd/m_oper.c Fri Jul 19 21:53:51 2013 +0100 | |
492 | +++ b/ircd/m_oper.c Fri Jul 19 22:26:20 2013 +0100 | |
493 | @@ -151,7 +151,7 @@ | |
494 | { | |
495 | send_reply(sptr, ERR_NOOPERHOST); | |
496 | sendto_opmask_butone(0, SNO_OLDREALOP, "Failed OPER attempt by %s (%s@%s)", | |
497 | - parv[0], cli_user(sptr)->username, cli_sockhost(sptr)); | |
498 | + parv[0], cli_user(sptr)->realusername, cli_sockhost(sptr)); | |
499 | return 0; | |
500 | } | |
501 | assert(0 != (aconf->status & CONF_OPERATOR)); | |
502 | @@ -163,7 +163,7 @@ | |
503 | if (ACR_OK != attach_conf(sptr, aconf)) { | |
504 | send_reply(sptr, ERR_NOOPERHOST); | |
505 | sendto_opmask_butone(0, SNO_OLDREALOP, "Failed OPER attempt by %s " | |
506 | - "(%s@%s)", parv[0], cli_user(sptr)->username, | |
507 | + "(%s@%s)", parv[0], cli_user(sptr)->realusername, | |
508 | cli_sockhost(sptr)); | |
509 | return 0; | |
510 | } | |
511 | @@ -187,16 +187,16 @@ | |
512 | send_reply(sptr, RPL_YOUREOPER); | |
513 | ||
514 | sendto_opmask_butone(0, SNO_OLDSNO, "%s (%s@%s) is now operator (%c)", | |
515 | - parv[0], cli_user(sptr)->username, cli_sockhost(sptr), | |
516 | + parv[0], cli_user(sptr)->realusername, cli_sockhost(sptr), | |
517 | IsOper(sptr) ? 'O' : 'o'); | |
518 | ||
519 | - log_write(LS_OPER, L_INFO, 0, "OPER (%s) by (%#C)", name, sptr); | |
520 | + log_write(LS_OPER, L_INFO, 0, "OPER (%s) by (%#R)", name, sptr); | |
521 | } | |
522 | else | |
523 | { | |
524 | send_reply(sptr, ERR_PASSWDMISMATCH); | |
525 | sendto_opmask_butone(0, SNO_OLDREALOP, "Failed OPER attempt by %s (%s@%s)", | |
526 | - parv[0], cli_user(sptr)->username, cli_sockhost(sptr)); | |
527 | + parv[0], cli_user(sptr)->realusername, cli_sockhost(sptr)); | |
528 | } | |
529 | return 0; | |
530 | } | |
531 | diff -r 6fd814ecf94b ircd/m_sethost.c | |
532 | --- /dev/null Thu Jan 01 00:00:00 1970 +0000 | |
533 | +++ b/ircd/m_sethost.c Fri Jul 19 22:26:20 2013 +0100 | |
534 | @@ -0,0 +1,256 @@ | |
535 | +/* | |
536 | + * IRC - Internet Relay Chat, ircd/m_sethost.c | |
537 | + * Copyright (C) 1990 Jarkko Oikarinen and | |
538 | + * University of Oulu, Computing Center | |
539 | + * | |
540 | + * See file AUTHORS in IRC package for additional names of | |
541 | + * the programmers. | |
542 | + * | |
543 | + * This program is free software; you can redistribute it and/or modify | |
544 | + * it under the terms of the GNU General Public License as published by | |
545 | + * the Free Software Foundation; either version 1, or (at your option) | |
546 | + * any later version. | |
547 | + * | |
548 | + * This program is distributed in the hope that it will be useful, | |
549 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
550 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
551 | + * GNU General Public License for more details. | |
552 | + * | |
553 | + * You should have received a copy of the GNU General Public License | |
554 | + * along with this program; if not, write to the Free Software | |
555 | + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |
556 | + * | |
557 | + * $Id: asuka-sethost.patch,v 1.27 2005/02/13 17:28:11 froo Exp $ | |
558 | + */ | |
559 | + | |
560 | +/* | |
561 | + * m_functions execute protocol messages on this server: | |
562 | + * | |
563 | + * cptr is always NON-NULL, pointing to a *LOCAL* client | |
564 | + * structure (with an open socket connected!). This | |
565 | + * identifies the physical socket where the message | |
566 | + * originated (or which caused the m_function to be | |
567 | + * executed--some m_functions may call others...). | |
568 | + * | |
569 | + * sptr is the source of the message, defined by the | |
570 | + * prefix part of the message if present. If not | |
571 | + * or prefix not found, then sptr==cptr. | |
572 | + * | |
573 | + * (!IsServer(cptr)) => (cptr == sptr), because | |
574 | + * prefixes are taken *only* from servers... | |
575 | + * | |
576 | + * (IsServer(cptr)) | |
577 | + * (sptr == cptr) => the message didn't | |
578 | + * have the prefix. | |
579 | + * | |
580 | + * (sptr != cptr && IsServer(sptr) means | |
581 | + * the prefix specified servername. (?) | |
582 | + * | |
583 | + * (sptr != cptr && !IsServer(sptr) means | |
584 | + * that message originated from a remote | |
585 | + * user (not local). | |
586 | + * | |
587 | + * combining | |
588 | + * | |
589 | + * (!IsServer(sptr)) means that, sptr can safely | |
590 | + * taken as defining the target structure of the | |
591 | + * message in this server. | |
592 | + * | |
593 | + * *Always* true (if 'parse' and others are working correct): | |
594 | + * | |
595 | + * 1) sptr->from == cptr (note: cptr->from == cptr) | |
596 | + * | |
597 | + * 2) MyConnect(sptr) <=> sptr == cptr (e.g. sptr | |
598 | + * *cannot* be a local connection, unless it's | |
599 | + * actually cptr!). [MyConnect(x) should probably | |
600 | + * be defined as (x == x->from) --msa ] | |
601 | + * | |
602 | + * parc number of variable parameter strings (if zero, | |
603 | + * parv is allowed to be NULL) | |
604 | + * | |
605 | + * parv a NULL terminated list of parameter pointers, | |
606 | + * | |
607 | + * parv[0], sender (prefix string), if not present | |
608 | + * this points to an empty string. | |
609 | + * parv[1]...parv[parc-1] | |
610 | + * pointers to additional parameters | |
611 | + * parv[parc] == NULL, *always* | |
612 | + * | |
613 | + * note: it is guaranteed that parv[0]..parv[parc-1] are all | |
614 | + * non-NULL pointers. | |
615 | + */ | |
616 | +#include "config.h" | |
617 | + | |
618 | +#include "client.h" | |
619 | +#include "ircd_reply.h" | |
620 | +#include "ircd_string.h" | |
621 | +#include "ircd_snprintf.h" | |
622 | +#include "ircd_features.h" | |
623 | +#include "msgq.h" | |
624 | +#include "numeric.h" | |
625 | +#include "s_conf.h" | |
626 | +#include "s_user.h" | |
627 | +#include "s_debug.h" | |
628 | +#include "send.h" | |
629 | +#include "struct.h" | |
630 | +#include "numnicks.h" | |
631 | + | |
632 | +#include "channel.h" | |
633 | +#include "msg.h" | |
634 | + | |
635 | +#include <assert.h> | |
636 | +#include <stdlib.h> | |
637 | + | |
638 | +/* | |
639 | + * m_sethost - generic message handler | |
640 | + * | |
641 | + * mimic old lain syntax: | |
642 | + * | |
643 | + * (Oper) /SETHOST ident host.cc [quit-message] | |
644 | + * (User) /SETHOST host.cc password | |
645 | + * (Both) /SETHOST undo | |
646 | + * | |
647 | + * check for undo, prepend parv w. <nick> -h or +h | |
648 | + */ | |
649 | +int m_sethost(struct Client* cptr, struct Client* sptr, int parc, char* parv[]) | |
650 | +{ | |
651 | + char hostmask[USERLEN + HOSTLEN + 2]; | |
652 | + char curhostmask[USERLEN + HOSTLEN + 2]; | |
653 | + | |
654 | + struct Flags setflags; | |
655 | + | |
656 | + /* Back up the flags first */ | |
657 | + setflags = cli_flags(sptr); | |
658 | + | |
659 | + if (parc < 2) | |
660 | + return need_more_params(sptr, "SETHOST"); | |
661 | + | |
662 | + if (0 == ircd_strcmp("undo", parv[1])) { | |
663 | + set_hostmask(sptr, NULL, NULL); | |
664 | + } else { | |
665 | + if (parc<3) | |
666 | + return need_more_params(sptr, "SETHOST"); | |
667 | + if (IsAnOper(sptr)) { | |
668 | + ircd_snprintf(0, hostmask, USERLEN + HOSTLEN + 2, "%s@%s", parv[1], parv[2]); | |
669 | + if (!is_hostmask(hostmask)) { | |
670 | + send_reply(sptr, ERR_BADHOSTMASK, hostmask); | |
671 | + return 0; | |
672 | + } | |
673 | + if (IsSetHost(sptr) || IsAccount(sptr)) { | |
674 | + ircd_snprintf(0, curhostmask, USERLEN + HOSTLEN + 2, "%s@%s", sptr->cli_user->username, sptr->cli_user->host); | |
675 | + if (0 == strcmp(hostmask, curhostmask)) { | |
676 | + send_reply(sptr, RPL_HOSTHIDDEN, curhostmask); | |
677 | + return 0; | |
678 | + } | |
679 | + } | |
680 | + if (set_hostmask(sptr, hostmask, NULL)) | |
681 | + FlagClr(&setflags, FLAG_SETHOST); | |
682 | + } else { | |
683 | + if (!is_hostmask(parv[1])) { | |
684 | + send_reply(sptr, ERR_BADHOSTMASK, parv[1]); | |
685 | + return 0; | |
686 | + } | |
687 | + if (IsSetHost(sptr) || IsAccount(sptr)) { | |
688 | + if (0 == strcmp(parv[1], sptr->cli_user->host)) { | |
689 | + send_reply(sptr, RPL_HOSTHIDDEN, parv[1]); | |
690 | + return 0; | |
691 | + } | |
692 | + } | |
693 | + if (set_hostmask(sptr, parv[1], parv[2])) | |
694 | + FlagClr(&setflags, FLAG_SETHOST); | |
695 | + } | |
696 | + } | |
697 | + | |
698 | + send_umode_out(cptr, sptr, &setflags, 0); | |
699 | + return 0; | |
700 | +} | |
701 | + | |
702 | + | |
703 | +/* | |
704 | + * ms_sethost - sethost server message handler | |
705 | + * | |
706 | + * parv[0] = sender prefix | |
707 | + * parv[1] = target user numeric | |
708 | + * parv[2] = target user's new ident | |
709 | + * parv[3] = target user's new host | |
710 | + */ | |
711 | +int ms_sethost(struct Client* cptr, struct Client* sptr, int parc, char* parv[]) | |
712 | +{ | |
713 | + struct Client *target; | |
714 | + char hostmask[USERLEN + HOSTLEN + 2]; | |
715 | + struct Membership *chan; | |
716 | + struct Flags setflags; | |
717 | + | |
718 | + if (parc < 4) | |
719 | + return need_more_params(sptr, "SETHOST"); | |
720 | + | |
721 | + if (!IsServer(sptr)) | |
722 | + return protocol_violation(cptr, "SETHOST from non-server %s", | |
723 | + cli_name(sptr)); | |
724 | + | |
725 | + /* Locate our target user; ignore the message if we can't */ | |
726 | + if(!(target = findNUser(parv[1]))) | |
727 | + return 0; | |
728 | + | |
729 | + /* Fake host assignments must be from services */ | |
730 | + if (!find_conf_byhost(cli_confs(sptr), cli_name(sptr), CONF_UWORLD)) | |
731 | + return protocol_violation(cptr, "Non-U:lined server %s set fake host on user %s", cli_name(sptr), cli_name(target)); | |
732 | + | |
733 | + if (!MyConnect(target)) { | |
734 | + sendcmdto_one(sptr, CMD_SETHOST, cli_user(target)->server, "%C %s %s", target, | |
735 | + parv[2], parv[3]); | |
736 | + return 0; | |
737 | + } | |
738 | + | |
739 | + /* Back up the flags first */ | |
740 | + setflags = cli_flags(target); | |
741 | + FlagClr(&setflags, FLAG_SETHOST); | |
742 | + | |
743 | + if (IsSetHost(target) || IsAccount(target)) { | |
744 | + if ((0 == strcmp(parv[2], target->cli_user->username)) && (0 == strcmp(parv[3], target->cli_user->host))) | |
745 | + return 0; | |
746 | + } | |
747 | + | |
748 | + ircd_snprintf(0, hostmask, USERLEN + HOSTLEN + 2, "%s@%s", parv[2], parv[3]); | |
749 | + if (!is_hostmask(hostmask)) | |
750 | + return protocol_violation(cptr, "Bad Host mask %s for user %s", hostmask, cli_name(target)); | |
751 | + | |
752 | + sendcmdto_common_channels_butone(target, CMD_QUIT, target, ":Host change"); | |
753 | + | |
754 | + /* Assign and propagate the fakehost */ | |
755 | + SetSetHost(target); | |
756 | + ircd_strncpy(cli_user(target)->username, parv[2], USERLEN); | |
757 | + ircd_strncpy(cli_user(target)->host, parv[3], HOSTLEN); | |
758 | + | |
759 | + send_reply(target, RPL_HOSTHIDDEN, hostmask); | |
760 | + | |
761 | + /* | |
762 | + * Go through all channels the client was on, rejoin him | |
763 | + * and set the modes, if any | |
764 | + */ | |
765 | + for (chan = cli_user(target)->channel; chan; chan = chan->next_channel) { | |
766 | + if (IsZombie(chan)) | |
767 | + continue; | |
768 | + /* If this channel has delayed joins and the user has no modes, just set | |
769 | + * the delayed join flag rather than showing the join, even if the user | |
770 | + * was visible before */ | |
771 | + if (!IsChanOp(chan) && !HasVoice(chan) | |
772 | + && (chan->channel->mode.mode & MODE_DELJOINS)) { | |
773 | + SetDelayedJoin(chan); | |
774 | + } else { | |
775 | + sendcmdto_channel_butserv_butone(target, CMD_JOIN, chan->channel, target, 0, | |
776 | + "%H", chan->channel); | |
777 | + } | |
778 | + if (IsChanOp(chan) && HasVoice(chan)) { | |
779 | + sendcmdto_channel_butserv_butone(&his, CMD_MODE, chan->channel, target, 0, | |
780 | + "%H +ov %C %C", chan->channel, target, target); | |
781 | + } else if (IsChanOp(chan) || HasVoice(chan)) { | |
782 | + sendcmdto_channel_butserv_butone(&his, CMD_MODE, chan->channel, target, 0, | |
783 | + "%H +%c %C", chan->channel, IsChanOp(chan) ? 'o' : 'v', target); | |
784 | + } | |
785 | + } | |
786 | + | |
787 | + send_umode_out(target, target, &setflags, 0); | |
788 | + return 0; | |
789 | +} | |
790 | + | |
791 | diff -r 6fd814ecf94b ircd/m_userhost.c | |
792 | --- a/ircd/m_userhost.c Fri Jul 19 21:53:51 2013 +0100 | |
793 | +++ b/ircd/m_userhost.c Fri Jul 19 22:26:20 2013 +0100 | |
794 | @@ -104,7 +104,7 @@ | |
795 | * of +x. If an oper wants the real host, he should go to | |
796 | * /whois to get it. | |
797 | */ | |
798 | - HasHiddenHost(cptr) && (sptr != cptr) ? | |
799 | + !IsAnOper(sptr) ? | |
800 | cli_user(cptr)->host : cli_user(cptr)->realhost); | |
801 | } | |
802 | ||
803 | diff -r 6fd814ecf94b ircd/m_userip.c | |
804 | --- a/ircd/m_userip.c Fri Jul 19 21:53:51 2013 +0100 | |
805 | +++ b/ircd/m_userip.c Fri Jul 19 22:26:20 2013 +0100 | |
806 | @@ -95,6 +95,7 @@ | |
807 | ||
808 | static void userip_formatter(struct Client* cptr, struct Client *sptr, struct MsgBuf* mb) | |
809 | { | |
810 | + /* !!FIXME!! */ | |
811 | assert(IsUser(cptr)); | |
812 | msgq_append(0, mb, "%s%s=%c%s@%s", cli_name(cptr), | |
813 | SeeOper(sptr,cptr) ? "*" : "", | |
814 | @@ -105,7 +106,7 @@ | |
815 | * of +x. If an oper wants the real IP, he should go to | |
816 | * /whois to get it. | |
817 | */ | |
818 | - HasHiddenHost(cptr) && (sptr != cptr) ? | |
819 | + (HasHiddenHost(cptr) || HasSetHost(cptr)) && !IsAnOper(sptr) ? | |
820 | feature_str(FEAT_HIDDEN_IP) : | |
821 | ircd_ntoa(&cli_ip(cptr))); | |
822 | } | |
823 | diff -r 6fd814ecf94b ircd/m_who.c | |
824 | --- a/ircd/m_who.c Fri Jul 19 21:53:51 2013 +0100 | |
825 | +++ b/ircd/m_who.c Fri Jul 19 22:26:20 2013 +0100 | |
826 | @@ -408,13 +408,14 @@ | |
827 | && ((!(matchsel & WHO_FIELD_HOS)) | |
828 | || matchexec(cli_user(acptr)->host, mymask, minlen)) | |
829 | && ((!(matchsel & WHO_FIELD_HOS)) | |
830 | + || !HasSetHost(acptr) | |
831 | || !HasHiddenHost(acptr) | |
832 | || !IsAnOper(sptr) | |
833 | || matchexec(cli_user(acptr)->realhost, mymask, minlen)) | |
834 | && ((!(matchsel & WHO_FIELD_REN)) | |
835 | || matchexec(cli_info(acptr), mymask, minlen)) | |
836 | && ((!(matchsel & WHO_FIELD_NIP)) | |
837 | - || (HasHiddenHost(acptr) && !IsAnOper(sptr)) | |
838 | + || ((HasHiddenHost(acptr) || HasSetHost(acptr)) && !IsAnOper(sptr)) | |
839 | || !ipmask_check(&cli_ip(acptr), &imask, ibits)) | |
840 | && ((!(matchsel & WHO_FIELD_ACC)) | |
841 | || matchexec(cli_user(acptr)->account, mymask, minlen))) | |
842 | @@ -446,13 +447,14 @@ | |
843 | && ((!(matchsel & WHO_FIELD_HOS)) | |
844 | || matchexec(cli_user(acptr)->host, mymask, minlen)) | |
845 | && ((!(matchsel & WHO_FIELD_HOS)) | |
846 | + || !HasSetHost(acptr) | |
847 | || !HasHiddenHost(acptr) | |
848 | || !IsAnOper(sptr) | |
849 | || matchexec(cli_user(acptr)->realhost, mymask, minlen)) | |
850 | && ((!(matchsel & WHO_FIELD_REN)) | |
851 | || matchexec(cli_info(acptr), mymask, minlen)) | |
852 | && ((!(matchsel & WHO_FIELD_NIP)) | |
853 | - || (HasHiddenHost(acptr) && !IsAnOper(sptr)) | |
854 | + || ((HasHiddenHost(acptr) || HasSetHost(acptr)) && !IsAnOper(sptr)) | |
855 | || !ipmask_check(&cli_ip(acptr), &imask, ibits)) | |
856 | && ((!(matchsel & WHO_FIELD_ACC)) | |
857 | || matchexec(cli_user(acptr)->account, mymask, minlen))) | |
858 | diff -r 6fd814ecf94b ircd/m_whois.c | |
859 | --- a/ircd/m_whois.c Fri Jul 19 21:53:51 2013 +0100 | |
860 | +++ b/ircd/m_whois.c Fri Jul 19 22:26:20 2013 +0100 | |
861 | @@ -211,8 +211,8 @@ | |
862 | if (IsAccount(acptr)) | |
863 | send_reply(sptr, RPL_WHOISACCOUNT, name, user->account); | |
864 | ||
865 | - if (HasHiddenHost(acptr) && (IsAnOper(sptr) || acptr == sptr)) | |
866 | - send_reply(sptr, RPL_WHOISACTUALLY, name, user->username, | |
867 | + if ((HasHiddenHost(acptr) || HasSetHost(acptr)) && (IsAnOper(sptr) || acptr == sptr)) | |
868 | + send_reply(sptr, RPL_WHOISACTUALLY, name, user->realusername, | |
869 | user->realhost, ircd_ntoa(&cli_ip(acptr))); | |
870 | ||
871 | /* Hint: if your looking to add more flags to a user, eg +h, here's | |
872 | diff -r 6fd814ecf94b ircd/parse.c | |
873 | --- a/ircd/parse.c Fri Jul 19 21:53:51 2013 +0100 | |
874 | +++ b/ircd/parse.c Fri Jul 19 22:26:20 2013 +0100 | |
875 | @@ -618,6 +618,13 @@ | |
876 | { m_ignore, m_not_oper, ms_asll, mo_asll, m_ignore } | |
877 | }, | |
878 | { | |
879 | + MSG_SETHOST, | |
880 | + TOK_SETHOST, | |
881 | + 0, MAXPARA, MFLG_SLOW, 0, NULL, | |
882 | + /* UNREG, CLIENT, SERVER, OPER, SERVICE */ | |
883 | + { m_unregistered, m_sethost, ms_sethost, m_sethost, m_ignore } | |
884 | + }, | |
885 | + { | |
886 | MSG_XQUERY, | |
887 | TOK_XQUERY, | |
888 | 0, MAXPARA, MFLG_SLOW, 0, NULL, | |
889 | diff -r 6fd814ecf94b ircd/s_conf.c | |
890 | --- a/ircd/s_conf.c Fri Jul 19 21:53:51 2013 +0100 | |
891 | +++ b/ircd/s_conf.c Fri Jul 19 22:26:20 2013 +0100 | |
892 | @@ -74,6 +74,8 @@ | |
893 | struct s_map *GlobalServiceMapList; | |
894 | /** Global list of channel quarantines. */ | |
895 | struct qline *GlobalQuarantineList; | |
896 | +/** Global list of spoofhosts. */ | |
897 | +struct sline *GlobalSList = 0; | |
898 | ||
899 | /** Current line number in scanner input. */ | |
900 | int lineno; | |
901 | @@ -943,6 +945,7 @@ | |
902 | clearNickJupes(); | |
903 | ||
904 | clear_quarantines(); | |
905 | + clear_slines(); | |
906 | ||
907 | class_mark_delete(); | |
908 | mark_listeners_closing(); | |
909 | @@ -1193,3 +1196,81 @@ | |
910 | return 0; | |
911 | } | |
912 | ||
913 | +void clear_slines(void) | |
914 | +{ | |
915 | + struct sline *sline; | |
916 | + while ((sline = GlobalSList)) { | |
917 | + GlobalSList = sline->next; | |
918 | + MyFree(sline->spoofhost); | |
919 | + if (!EmptyString(sline->passwd)) | |
920 | + MyFree(sline->passwd); | |
921 | + if (!EmptyString(sline->realhost)) | |
922 | + MyFree(sline->realhost); | |
923 | + if (!EmptyString(sline->username)) | |
924 | + MyFree(sline->username); | |
925 | + MyFree(sline); | |
926 | + } | |
927 | +} | |
928 | + | |
929 | +/* | |
930 | + * conf_check_slines() | |
931 | + * | |
932 | + * Check S lines for the specified client, passed in cptr struct. | |
933 | + * If the client's IP is S-lined, process the substitution here. | |
934 | + * | |
935 | + * Precondition | |
936 | + * cptr != NULL | |
937 | + * | |
938 | + * Returns | |
939 | + * 0 = No S-line found | |
940 | + * 1 = S-line found and substitution done. | |
941 | + * | |
942 | + * -mbuna 9/2001 | |
943 | + * -froo 1/2003 | |
944 | + * | |
945 | + */ | |
946 | + | |
947 | +int | |
948 | +conf_check_slines(struct Client *cptr) | |
949 | +{ | |
950 | + struct sline *sconf; | |
951 | + char *hostonly; | |
952 | + | |
953 | + for (sconf = GlobalSList; sconf; sconf = sconf->next) { | |
954 | + if (sconf->flags == SLINE_FLAGS_IP) { | |
955 | + if (!ipmask_check(&(cli_ip(cptr)), &(sconf->address), sconf->bits)) | |
956 | + continue; | |
957 | + } else if (sconf->flags == SLINE_FLAGS_HOSTNAME) { | |
958 | + if ((match(sconf->realhost, cli_sockhost(cptr)) != 0) && | |
959 | + (match(sconf->realhost, cli_sock_ip(cptr)) != 0)) /* wildcarded IP address */ | |
960 | + continue; | |
961 | + } else { | |
962 | + continue; | |
963 | + } | |
964 | + | |
965 | + if (match(sconf->username, cli_user(cptr)->username) == 0) { | |
966 | + /* Ignore user part if u@h. */ | |
967 | + if ((hostonly = strchr(sconf->spoofhost, '@'))) | |
968 | + hostonly++; | |
969 | + else | |
970 | + hostonly = sconf->spoofhost; | |
971 | + | |
972 | + if(!*hostonly) | |
973 | + continue; | |
974 | + | |
975 | + ircd_strncpy(cli_user(cptr)->host, hostonly, HOSTLEN); | |
976 | + log_write(LS_USER, L_INFO, LOG_NOSNOTICE, "S-Line (%s@%s) by (%#R)", | |
977 | + cli_user(cptr)->username, hostonly, cptr); | |
978 | + return 1; | |
979 | + } | |
980 | + } | |
981 | + return 0; | |
982 | +} | |
983 | + | |
984 | +void free_spoofhost(struct sline *spoof) { | |
985 | + MyFree(spoof->spoofhost); | |
986 | + MyFree(spoof->passwd); | |
987 | + MyFree(spoof->realhost); | |
988 | + MyFree(spoof->username); | |
989 | + MyFree(spoof); | |
990 | +} | |
991 | diff -r 6fd814ecf94b ircd/s_err.c | |
992 | --- a/ircd/s_err.c Fri Jul 19 21:53:51 2013 +0100 | |
993 | +++ b/ircd/s_err.c Fri Jul 19 22:26:20 2013 +0100 | |
994 | @@ -640,7 +640,7 @@ | |
995 | /* 303 */ | |
996 | { RPL_ISON, ":", "303" }, | |
997 | /* 304 */ | |
998 | - { 0 }, | |
999 | + { RPL_TEXT, "%s", "304" }, | |
1000 | /* 305 */ | |
1001 | { RPL_UNAWAY, ":You are no longer marked as being away", "305" }, | |
1002 | /* 306 */ | |
1003 | @@ -828,9 +828,9 @@ | |
1004 | /* 397 */ | |
1005 | { 0 }, | |
1006 | /* 398 */ | |
1007 | - { 0 }, | |
1008 | + { RPL_STATSSLINE, "%d %s %s %s %s", "398" }, | |
1009 | /* 399 */ | |
1010 | - { 0 }, | |
1011 | + { RPL_USINGSLINE, ":Using S-line privilege", "399" }, | |
1012 | /* 400 */ | |
1013 | { 0 }, | |
1014 | /* 401 */ | |
1015 | @@ -1092,9 +1092,9 @@ | |
1016 | /* 529 */ | |
1017 | { 0 }, | |
1018 | /* 530 */ | |
1019 | - { 0 }, | |
1020 | + { ERR_BADHOSTMASK, "%s :Invalid username/hostmask", "530" }, | |
1021 | /* 531 */ | |
1022 | - { 0 }, | |
1023 | + { ERR_HOSTUNAVAIL, "%s :sethost not found", "531" }, | |
1024 | /* 532 */ | |
1025 | { 0 }, | |
1026 | /* 533 */ | |
1027 | diff -r 6fd814ecf94b ircd/s_serv.c | |
1028 | --- a/ircd/s_serv.c Fri Jul 19 21:53:51 2013 +0100 | |
1029 | +++ b/ircd/s_serv.c Fri Jul 19 22:26:20 2013 +0100 | |
1030 | @@ -247,7 +247,7 @@ | |
1031 | sendcmdto_one(cli_user(acptr)->server, CMD_NICK, cptr, | |
1032 | "%s %d %Tu %s %s %s%s%s%s %s%s :%s", | |
1033 | cli_name(acptr), cli_hopcount(acptr) + 1, cli_lastnick(acptr), | |
1034 | - cli_user(acptr)->username, cli_user(acptr)->realhost, | |
1035 | + cli_user(acptr)->realusername, cli_user(acptr)->realhost, | |
1036 | *s ? "+" : "", s, *s ? " " : "", | |
1037 | iptobase64(xxx_buf, &cli_ip(acptr), sizeof(xxx_buf), IsIPv6(cptr)), | |
1038 | NumNick(acptr), cli_info(acptr)); | |
1039 | diff -r 6fd814ecf94b ircd/s_stats.c | |
1040 | --- a/ircd/s_stats.c Fri Jul 19 21:53:51 2013 +0100 | |
1041 | +++ b/ircd/s_stats.c Fri Jul 19 22:26:20 2013 +0100 | |
1042 | @@ -400,6 +400,44 @@ | |
1043 | } | |
1044 | } | |
1045 | ||
1046 | +static void | |
1047 | +stats_sline(struct Client* to, const struct StatDesc* sd, char* param) | |
1048 | +{ | |
1049 | + int y = 1, i = 1; | |
1050 | + struct sline *sline; | |
1051 | + | |
1052 | + if (IsAnOper(to)) | |
1053 | + send_reply(to, SND_EXPLICIT | RPL_TEXT, "# Type Spoofhost Realhost Ident"); | |
1054 | + else | |
1055 | + send_reply(to, SND_EXPLICIT | RPL_TEXT, "# Type Spoofhost"); | |
1056 | + | |
1057 | + for (sline = GlobalSList; sline; sline = sline->next) { | |
1058 | + if (param && match(param, sline->spoofhost)) { /* narrow search */ | |
1059 | + if (IsAnOper(to)) | |
1060 | + y++; | |
1061 | + else | |
1062 | + if (!EmptyString(sline->passwd)) | |
1063 | + y++; | |
1064 | + continue; | |
1065 | + } | |
1066 | + | |
1067 | + if (IsAnOper(to)) { | |
1068 | + send_reply(to, RPL_STATSSLINE, (param) ? y : i, | |
1069 | + (EmptyString(sline->passwd)) ? "oper" : "user", | |
1070 | + sline->spoofhost, | |
1071 | + (EmptyString(sline->realhost)) ? "" : sline->realhost, | |
1072 | + (EmptyString(sline->username)) ? "" : sline->username); | |
1073 | + i++; | |
1074 | + } else { | |
1075 | + if (!EmptyString(sline->passwd)) { | |
1076 | + send_reply(to, RPL_STATSSLINE, (param) ? y : i, "user", sline->spoofhost, | |
1077 | + "", "", ""); | |
1078 | + i++; | |
1079 | + } | |
1080 | + } | |
1081 | + } | |
1082 | +} | |
1083 | + | |
1084 | /** List service pseudo-command mappings. | |
1085 | * @param[in] to Client requesting statistics. | |
1086 | * @param[in] sd Stats descriptor for request (ignored). | |
1087 | @@ -593,6 +631,9 @@ | |
1088 | send_usage, 0, | |
1089 | "System resource usage (Debug only)." }, | |
1090 | #endif | |
1091 | + { 's', "spoofhosts", (STAT_FLAG_OPERFEAT | STAT_FLAG_VARPARAM), FEAT_HIS_STATS_s, | |
1092 | + stats_sline, 0, | |
1093 | + "Spoofed hosts information." }, | |
1094 | { 'T', "motds", (STAT_FLAG_OPERFEAT | STAT_FLAG_CASESENS), FEAT_HIS_STATS_T, | |
1095 | motd_report, 0, | |
1096 | "Configured Message Of The Day files." }, | |
1097 | diff -r 6fd814ecf94b ircd/s_user.c | |
1098 | --- a/ircd/s_user.c Fri Jul 19 21:53:51 2013 +0100 | |
1099 | +++ b/ircd/s_user.c Fri Jul 19 22:26:20 2013 +0100 | |
1100 | @@ -73,6 +73,9 @@ | |
1101 | #include <string.h> | |
1102 | #include <sys/stat.h> | |
1103 | ||
1104 | +static char *IsVhost(char *hostmask, int oper); | |
1105 | +static char *IsVhostPass(char *hostmask); | |
1106 | + | |
1107 | /** Count of allocated User structures. */ | |
1108 | static int userCount = 0; | |
1109 | ||
1110 | @@ -368,6 +371,13 @@ | |
1111 | if (feature_bool(FEAT_AUTOINVISIBLE)) | |
1112 | SetInvisible(sptr); | |
1113 | ||
1114 | + if(feature_bool(FEAT_SETHOST_AUTO)) { | |
1115 | + if (conf_check_slines(sptr)) { | |
1116 | + send_reply(sptr, RPL_USINGSLINE); | |
1117 | + SetSetHost(sptr); | |
1118 | + } | |
1119 | + } | |
1120 | + | |
1121 | SetUser(sptr); | |
1122 | cli_handler(sptr) = CLIENT_HANDLER; | |
1123 | SetLocalNumNick(sptr); | |
1124 | @@ -433,6 +443,7 @@ | |
1125 | sptr, cli_name(&me)); | |
1126 | return exit_client(cptr, sptr, &me,"Too many connections from your host -- throttled"); | |
1127 | } | |
1128 | + | |
1129 | SetUser(sptr); | |
1130 | } | |
1131 | ||
1132 | @@ -454,7 +465,7 @@ | |
1133 | "%s %d %Tu %s %s %s%s%s%s %s%s :%s", | |
1134 | cli_name(sptr), cli_hopcount(sptr) + 1, | |
1135 | cli_lastnick(sptr), | |
1136 | - user->username, user->realhost, | |
1137 | + user->realusername, user->realhost, | |
1138 | *tmpstr ? "+" : "", tmpstr, *tmpstr ? " " : "", | |
1139 | iptobase64(ip_base64, &cli_ip(sptr), sizeof(ip_base64), 1), | |
1140 | NumNick(sptr), cli_info(sptr)); | |
1141 | @@ -464,7 +475,7 @@ | |
1142 | "%s %d %Tu %s %s %s%s%s%s %s%s :%s", | |
1143 | cli_name(sptr), cli_hopcount(sptr) + 1, | |
1144 | cli_lastnick(sptr), | |
1145 | - user->username, user->realhost, | |
1146 | + user->realusername, user->realhost, | |
1147 | *tmpstr ? "+" : "", tmpstr, *tmpstr ? " " : "", | |
1148 | iptobase64(ip_base64, &cli_ip(sptr), sizeof(ip_base64), 0), | |
1149 | NumNick(sptr), cli_info(sptr)); | |
1150 | @@ -506,7 +517,8 @@ | |
1151 | { FLAG_ACCOUNTONLY, 'R' }, | |
1152 | { FLAG_XTRAOP, 'X' }, | |
1153 | { FLAG_NOCHAN, 'n' }, | |
1154 | - { FLAG_NOIDLE, 'I' } | |
1155 | + { FLAG_NOIDLE, 'I' }, | |
1156 | + { FLAG_SETHOST, 'h' } | |
1157 | }; | |
1158 | ||
1159 | /** Length of #userModeList. */ | |
1160 | @@ -559,6 +571,7 @@ | |
1161 | cli_serv(sptr)->ghost = 0; /* :server NICK means end of net.burst */ | |
1162 | ircd_strncpy(cli_username(new_client), parv[4], USERLEN); | |
1163 | ircd_strncpy(cli_user(new_client)->username, parv[4], USERLEN); | |
1164 | + ircd_strncpy(cli_user(new_client)->realusername, parv[4], USERLEN); | |
1165 | ircd_strncpy(cli_user(new_client)->host, parv[5], HOSTLEN); | |
1166 | ircd_strncpy(cli_user(new_client)->realhost, parv[5], HOSTLEN); | |
1167 | ircd_strncpy(cli_info(new_client), parv[parc - 1], REALLEN); | |
1168 | @@ -837,7 +850,7 @@ | |
1169 | { | |
1170 | if ((acptr = LocalClientArray[i]) && IsServer(acptr) && | |
1171 | (acptr != cptr) && (acptr != sptr) && *umodeBuf) | |
1172 | - sendcmdto_one(sptr, CMD_MODE, acptr, "%s :%s", cli_name(sptr), umodeBuf); | |
1173 | + sendcmdto_one(sptr, CMD_MODE, acptr, "%s %s", cli_name(sptr), umodeBuf); | |
1174 | } | |
1175 | if (cptr && MyUser(cptr)) | |
1176 | send_umode(cptr, sptr, old, ALL_UMODES); | |
1177 | @@ -905,7 +918,7 @@ | |
1178 | } | |
1179 | ||
1180 | SetFlag(cptr, flag); | |
1181 | - if (!HasFlag(cptr, FLAG_HIDDENHOST) || !HasFlag(cptr, FLAG_ACCOUNT)) | |
1182 | + if (!HasFlag(cptr, FLAG_HIDDENHOST) || !HasFlag(cptr, FLAG_ACCOUNT) || HasSetHost(cptr)) | |
1183 | return 0; | |
1184 | ||
1185 | sendcmdto_common_channels_butone(cptr, CMD_QUIT, cptr, ":Registered"); | |
1186 | @@ -939,6 +952,190 @@ | |
1187 | return 0; | |
1188 | } | |
1189 | ||
1190 | +/* | |
1191 | + * set_hostmask() - derived from hide_hostmask() | |
1192 | + * | |
1193 | + */ | |
1194 | +int set_hostmask(struct Client *cptr, char *hostmask, char *password) | |
1195 | +{ | |
1196 | + int restore = 0; | |
1197 | + int freeform = 0; | |
1198 | + char *host, *new_vhost, *vhost_pass; | |
1199 | + char hiddenhost[USERLEN + HOSTLEN + 2]; | |
1200 | + struct Membership *chan; | |
1201 | + | |
1202 | + Debug((DEBUG_INFO, "set_hostmask() %C, %s, %s", cptr, hostmask, password)); | |
1203 | + | |
1204 | + /* sethost enabled? */ | |
1205 | + if (MyConnect(cptr) && !feature_bool(FEAT_SETHOST)) { | |
1206 | + send_reply(cptr, ERR_DISABLED, "SETHOST"); | |
1207 | + return 0; | |
1208 | + } | |
1209 | + | |
1210 | + /* sethost enabled for users? */ | |
1211 | + if (MyConnect(cptr) && !IsAnOper(cptr) && !feature_bool(FEAT_SETHOST_USER)) { | |
1212 | + send_reply(cptr, ERR_NOPRIVILEGES); | |
1213 | + return 0; | |
1214 | + } | |
1215 | + | |
1216 | + /* MODE_DEL: restore original hostmask */ | |
1217 | + if (EmptyString(hostmask)) { | |
1218 | + /* is already sethost'ed? and only opers can remove a sethost */ | |
1219 | + if (IsSetHost(cptr) && IsAnOper(cptr)) { | |
1220 | + restore = 1; | |
1221 | + sendcmdto_common_channels_butone(cptr, CMD_QUIT, cptr, ":Host change"); | |
1222 | + /* If they are +rx, we need to return to their +x host, not their "real" host */ | |
1223 | + if (HasHiddenHost(cptr)) | |
1224 | + ircd_snprintf(0, cli_user(cptr)->host, HOSTLEN, "%s.%s", | |
1225 | + cli_user(cptr)->account, feature_str(FEAT_HIDDEN_HOST)); | |
1226 | + else | |
1227 | + strncpy(cli_user(cptr)->host, cli_user(cptr)->realhost, HOSTLEN); | |
1228 | + strncpy(cli_user(cptr)->username, cli_user(cptr)->realusername, USERLEN); | |
1229 | + /* log it */ | |
1230 | + if (MyConnect(cptr)) | |
1231 | + log_write(LS_SETHOST, L_INFO, LOG_NOSNOTICE, | |
1232 | + "SETHOST (%s@%s) by (%#R): restoring real hostmask", | |
1233 | + cli_user(cptr)->username, cli_user(cptr)->host, cptr); | |
1234 | + } else | |
1235 | + return 0; | |
1236 | + /* MODE_ADD: set a new hostmask */ | |
1237 | + } else { | |
1238 | + /* chop up ident and host.cc */ | |
1239 | + if ((host = strrchr(hostmask, '@'))) /* oper can specifiy ident@host.cc */ | |
1240 | + *host++ = '\0'; | |
1241 | + else /* user can only specifiy host.cc [password] */ | |
1242 | + host = hostmask; | |
1243 | + /* | |
1244 | + * Oper sethost | |
1245 | + */ | |
1246 | + if (MyConnect(cptr)) { | |
1247 | + if (IsAnOper(cptr)) { | |
1248 | + if ((new_vhost = IsVhost(host, 1)) == NULL) { | |
1249 | + if (!feature_bool(FEAT_SETHOST_FREEFORM)) { | |
1250 | + send_reply(cptr, ERR_HOSTUNAVAIL, hostmask); | |
1251 | + log_write(LS_SETHOST, L_INFO, LOG_NOSNOTICE, | |
1252 | + "SETHOST (%s@%s) by (%#R): no such s-line", | |
1253 | + (host != hostmask) ? hostmask : cli_user(cptr)->username, host, cptr); | |
1254 | + return 0; | |
1255 | + } else /* freeform active, log and go */ | |
1256 | + freeform = 1; | |
1257 | + } | |
1258 | + sendcmdto_common_channels_butone(cptr, CMD_QUIT, cptr, ":Host change"); | |
1259 | + /* set the new ident and host */ | |
1260 | + if (host != hostmask) /* oper only specified host.cc */ | |
1261 | + strncpy(cli_user(cptr)->username, hostmask, USERLEN); | |
1262 | + strncpy(cli_user(cptr)->host, host, HOSTLEN); | |
1263 | + /* log it */ | |
1264 | + log_write(LS_SETHOST, (freeform) ? L_NOTICE : L_INFO, | |
1265 | + (freeform) ? 0 : LOG_NOSNOTICE, "SETHOST (%s@%s) by (%#R)%s", | |
1266 | + cli_user(cptr)->username, cli_user(cptr)->host, cptr, | |
1267 | + (freeform) ? ": using freeform" : ""); | |
1268 | + /* | |
1269 | + * plain user sethost, handled here | |
1270 | + */ | |
1271 | + } else { | |
1272 | + /* empty password? */ | |
1273 | + if (EmptyString(password)) { | |
1274 | + send_reply(cptr, ERR_NEEDMOREPARAMS, "MODE"); | |
1275 | + return 0; | |
1276 | + } | |
1277 | + /* no such s-line */ | |
1278 | + if ((new_vhost = IsVhost(host, 0)) == NULL) { | |
1279 | + send_reply(cptr, ERR_HOSTUNAVAIL, hostmask); | |
1280 | + log_write(LS_SETHOST, L_INFO, LOG_NOSNOTICE, "SETHOST (%s@%s %s) by (%#R): no such s-line", | |
1281 | + cli_user(cptr)->username, host, password, cptr); | |
1282 | + return 0; | |
1283 | + } | |
1284 | + /* no password */ | |
1285 | + if ((vhost_pass = IsVhostPass(new_vhost)) == NULL) { | |
1286 | + send_reply(cptr, ERR_PASSWDMISMATCH); | |
1287 | + log_write(LS_SETHOST, L_INFO, 0, "SETHOST (%s@%s %s) by (%#R): trying to use an oper s-line", | |
1288 | + cli_user(cptr)->username, host, password, cptr); | |
1289 | + return 0; | |
1290 | + } | |
1291 | + /* incorrect password */ | |
1292 | + if (strCasediff(vhost_pass, password)) { | |
1293 | + send_reply(cptr, ERR_PASSWDMISMATCH); | |
1294 | + log_write(LS_SETHOST, L_NOTICE, 0, "SETHOST (%s@%s %s) by (%#R): incorrect password", | |
1295 | + cli_user(cptr)->username, host, password, cptr); | |
1296 | + return 0; | |
1297 | + } | |
1298 | + sendcmdto_common_channels_butone(cptr, CMD_QUIT, cptr, ":Host change"); | |
1299 | + /* set the new host */ | |
1300 | + strncpy(cli_user(cptr)->host, new_vhost, HOSTLEN); | |
1301 | + /* log it */ | |
1302 | + log_write(LS_SETHOST, L_INFO, LOG_NOSNOTICE, "SETHOST (%s@%s) by (%#R)", | |
1303 | + cli_user(cptr)->username, cli_user(cptr)->host, cptr); | |
1304 | + } | |
1305 | + } else { /* remote user */ | |
1306 | + sendcmdto_common_channels_butone(cptr, CMD_QUIT, cptr, ":Host change"); | |
1307 | + if (host != hostmask) /* oper only specified host.cc */ | |
1308 | + strncpy(cli_user(cptr)->username, hostmask, USERLEN); | |
1309 | + strncpy(cli_user(cptr)->host, host, HOSTLEN); | |
1310 | + } | |
1311 | + } | |
1312 | + | |
1313 | + if (restore) | |
1314 | + ClearSetHost(cptr); | |
1315 | + else | |
1316 | + SetSetHost(cptr); | |
1317 | + | |
1318 | + if (MyConnect(cptr)) { | |
1319 | + ircd_snprintf(0, hiddenhost, HOSTLEN + USERLEN + 2, "%s@%s", | |
1320 | + cli_user(cptr)->username, cli_user(cptr)->host); | |
1321 | + send_reply(cptr, RPL_HOSTHIDDEN, hiddenhost); | |
1322 | + } | |
1323 | + | |
1324 | +#if 0 | |
1325 | + /* Code copied from hide_hostmask(). This is the old (pre-delayedjoin) | |
1326 | + * version. Switch this in if you're not using the delayed join patch. */ | |
1327 | + /* | |
1328 | + * Go through all channels the client was on, rejoin him | |
1329 | + * and set the modes, if any | |
1330 | + */ | |
1331 | + for (chan = cli_user(cptr)->channel; chan; chan = chan->next_channel) { | |
1332 | + if (IsZombie(chan)) | |
1333 | + continue; | |
1334 | + sendcmdto_channel_butserv_butone(cptr, CMD_JOIN, chan->channel, cptr, | |
1335 | + "%H", chan->channel); | |
1336 | + if (IsChanOp(chan) && HasVoice(chan)) { | |
1337 | + sendcmdto_channel_butserv_butone(&me, CMD_MODE, chan->channel, cptr, | |
1338 | + "%H +ov %C %C", chan->channel, cptr, cptr); | |
1339 | + } else if (IsChanOp(chan) || HasVoice(chan)) { | |
1340 | + sendcmdto_channel_butserv_butone(&me, CMD_MODE, chan->channel, cptr, | |
1341 | + "%H +%c %C", chan->channel, IsChanOp(chan) ? 'o' : 'v', cptr); | |
1342 | + } | |
1343 | + } | |
1344 | +#endif | |
1345 | + | |
1346 | + /* | |
1347 | + * Go through all channels the client was on, rejoin him | |
1348 | + * and set the modes, if any | |
1349 | + */ | |
1350 | + for (chan = cli_user(cptr)->channel; chan; chan = chan->next_channel) { | |
1351 | + if (IsZombie(chan)) | |
1352 | + continue; | |
1353 | + /* If this channel has delayed joins and the user has no modes, just set | |
1354 | + * the delayed join flag rather than showing the join, even if the user | |
1355 | + * was visible before */ | |
1356 | + if (!IsChanOp(chan) && !HasVoice(chan) | |
1357 | + && (chan->channel->mode.mode & MODE_DELJOINS)) { | |
1358 | + SetDelayedJoin(chan); | |
1359 | + } else { | |
1360 | + sendcmdto_channel_butserv_butone(cptr, CMD_JOIN, chan->channel, cptr, 0, | |
1361 | + "%H", chan->channel); | |
1362 | + } | |
1363 | + if (IsChanOp(chan) && HasVoice(chan)) { | |
1364 | + sendcmdto_channel_butserv_butone(&me, CMD_MODE, chan->channel, cptr, 0, | |
1365 | + "%H +ov %C %C", chan->channel, cptr, cptr); | |
1366 | + } else if (IsChanOp(chan) || HasVoice(chan)) { | |
1367 | + sendcmdto_channel_butserv_butone(&me, CMD_MODE, chan->channel, cptr, 0, | |
1368 | + "%H +%c %C", chan->channel, IsChanOp(chan) ? 'o' : 'v', cptr); | |
1369 | + } | |
1370 | + } | |
1371 | + return 1; | |
1372 | +} | |
1373 | + | |
1374 | /** Set a user's mode. This function checks that \a cptr is trying to | |
1375 | * set his own mode, prevents local users from setting inappropriate | |
1376 | * modes through this function, and applies any other side effects of | |
1377 | @@ -965,6 +1162,7 @@ | |
1378 | char buf[BUFSIZE]; | |
1379 | int prop = 0; | |
1380 | int do_host_hiding = 0; | |
1381 | + int do_set_host = 0; | |
1382 | char* account = NULL; | |
1383 | ||
1384 | what = MODE_ADD; | |
1385 | @@ -976,7 +1174,8 @@ | |
1386 | for (i = 0; i < USERMODELIST_SIZE; i++) | |
1387 | { | |
1388 | if (HasFlag(sptr, userModeList[i].flag) && | |
1389 | - userModeList[i].flag != FLAG_ACCOUNT) | |
1390 | + ((userModeList[i].flag != FLAG_ACCOUNT) && | |
1391 | + (userModeList[i].flag != FLAG_SETHOST))) | |
1392 | *m++ = userModeList[i].c; | |
1393 | } | |
1394 | *m = '\0'; | |
1395 | @@ -1103,6 +1302,30 @@ | |
1396 | if (what == MODE_ADD) | |
1397 | do_host_hiding = 1; | |
1398 | break; | |
1399 | + case 'h': | |
1400 | + if (what == MODE_ADD) { | |
1401 | + if (*(p + 1) && is_hostmask(*(p + 1))) { | |
1402 | + do_set_host = 1; | |
1403 | + hostmask = *++p; | |
1404 | + /* DON'T step p onto the trailing NULL in the parameter array! - splidge */ | |
1405 | + if (*(p+1)) | |
1406 | + password = *++p; | |
1407 | + else | |
1408 | + password = NULL; | |
1409 | + } else { | |
1410 | + if (!*(p+1)) | |
1411 | + send_reply(sptr, ERR_NEEDMOREPARAMS, "SETHOST"); | |
1412 | + else { | |
1413 | + send_reply(sptr, ERR_BADHOSTMASK, *(p+1)); | |
1414 | + p++; /* Swallow the arg anyway */ | |
1415 | + } | |
1416 | + } | |
1417 | + } else { /* MODE_DEL */ | |
1418 | + do_set_host = 1; | |
1419 | + hostmask = NULL; | |
1420 | + password = NULL; | |
1421 | + } | |
1422 | + break; | |
1423 | case 'r': | |
1424 | if (*(p + 1) && (what == MODE_ADD)) { | |
1425 | account = *(++p); | |
1426 | @@ -1269,10 +1492,15 @@ | |
1427 | while ((*m++ = *t++)) | |
1428 | ; /* Empty loop */ | |
1429 | } | |
1430 | + m--; /* Step back over the '\0' */ | |
1431 | } | |
1432 | ||
1433 | - *m = '\0'; | |
1434 | - | |
1435 | + if (IsSetHost(cptr)) { | |
1436 | + *m++ = ' '; | |
1437 | + ircd_snprintf(0, m, USERLEN + HOSTLEN + 2, "%s@%s", cli_user(cptr)->username, | |
1438 | + cli_user(cptr)->host); | |
1439 | + } else | |
1440 | + *m = '\0'; | |
1441 | return umodeBuf; /* Note: static buffer, gets | |
1442 | overwritten by send_umode() */ | |
1443 | } | |
1444 | @@ -1289,6 +1517,7 @@ | |
1445 | { | |
1446 | int i; | |
1447 | int flag; | |
1448 | + int needhost = 0; | |
1449 | char *m; | |
1450 | int what = MODE_NULL; | |
1451 | ||
1452 | @@ -1318,6 +1547,16 @@ | |
1453 | continue; | |
1454 | break; | |
1455 | } | |
1456 | + /* Special case for SETHOST.. */ | |
1457 | + if (flag == FLAG_SETHOST) { | |
1458 | + /* Don't send to users */ | |
1459 | + if (cptr && MyUser(cptr)) | |
1460 | + continue; | |
1461 | + | |
1462 | + /* If we're setting +h, add the parameter later */ | |
1463 | + if (!FlagHas(old, flag)) | |
1464 | + needhost++; | |
1465 | + } | |
1466 | if (FlagHas(old, flag)) | |
1467 | { | |
1468 | if (what == MODE_DEL) | |
1469 | @@ -1341,9 +1580,14 @@ | |
1470 | } | |
1471 | } | |
1472 | } | |
1473 | - *m = '\0'; | |
1474 | + if (needhost) { | |
1475 | + *m++ = ' '; | |
1476 | + ircd_snprintf(0, m, USERLEN + HOSTLEN + 1, "%s@%s", cli_user(sptr)->username, | |
1477 | + cli_user(sptr)->host); | |
1478 | + } else | |
1479 | + *m = '\0'; | |
1480 | if (*umodeBuf && cptr) | |
1481 | - sendcmdto_one(sptr, CMD_MODE, cptr, "%s :%s", cli_name(sptr), umodeBuf); | |
1482 | + sendcmdto_one(sptr, CMD_MODE, cptr, "%s %s", cli_name(sptr), umodeBuf); | |
1483 | } | |
1484 | ||
1485 | /** | |
1486 | @@ -1366,6 +1610,110 @@ | |
1487 | return 0; | |
1488 | } | |
1489 | ||
1490 | + /* | |
1491 | + * Check to see if it resembles a valid hostmask. | |
1492 | + */ | |
1493 | +int is_hostmask(char *word) | |
1494 | +{ | |
1495 | + int i = 0; | |
1496 | + char *host; | |
1497 | + | |
1498 | + Debug((DEBUG_INFO, "is_hostmask() %s", word)); | |
1499 | + | |
1500 | + if (strlen(word) > (HOSTLEN + USERLEN + 1) || strlen(word) <= 0) | |
1501 | + return 0; | |
1502 | + | |
1503 | + /* if a host is specified, make sure it's valid */ | |
1504 | + host = strrchr(word, '@'); | |
1505 | + if (host) { | |
1506 | + if (strlen(++host) < 1) | |
1507 | + return 0; | |
1508 | + if (strlen(host) > HOSTLEN) | |
1509 | + return 0; | |
1510 | + } | |
1511 | + | |
1512 | + if (word) { | |
1513 | + if ('@' == *word) /* no leading @'s */ | |
1514 | + return 0; | |
1515 | + | |
1516 | + if ('#' == *word) { /* numeric index given? */ | |
1517 | + for (word++; *word; word++) { | |
1518 | + if (!IsDigit(*word)) | |
1519 | + return 0; | |
1520 | + } | |
1521 | + return 1; | |
1522 | + } | |
1523 | + | |
1524 | + /* normal hostmask, account for at most one '@' */ | |
1525 | + for (; *word; word++) { | |
1526 | + if ('@' == *word) { | |
1527 | + i++; | |
1528 | + continue; | |
1529 | + } | |
1530 | + if (!IsHostChar(*word)) | |
1531 | + return 0; | |
1532 | + } | |
1533 | + return (1 < i) ? 0 : 1; /* no more than on '@' */ | |
1534 | + } | |
1535 | + return 0; | |
1536 | +} | |
1537 | + | |
1538 | + /* | |
1539 | + * IsVhost() - Check if given host is a valid spoofhost | |
1540 | + * (ie: configured thru a S:line) | |
1541 | + */ | |
1542 | +static char *IsVhost(char *hostmask, int oper) | |
1543 | +{ | |
1544 | + unsigned int i = 0, y = 0; | |
1545 | + struct sline *sconf; | |
1546 | + | |
1547 | + Debug((DEBUG_INFO, "IsVhost() %s", hostmask)); | |
1548 | + | |
1549 | + if (EmptyString(hostmask)) | |
1550 | + return NULL; | |
1551 | + | |
1552 | + /* spoofhost specified as index, ie: #27 */ | |
1553 | + if ('#' == hostmask[0]) { | |
1554 | + y = atoi(hostmask + 1); | |
1555 | + for (i = 0, sconf = GlobalSList; sconf; sconf = sconf->next) { | |
1556 | + if (!oper && EmptyString(sconf->passwd)) | |
1557 | + continue; | |
1558 | + if (y == ++i) | |
1559 | + return sconf->spoofhost; | |
1560 | + } | |
1561 | + return NULL; | |
1562 | + } | |
1563 | + | |
1564 | + /* spoofhost specified as host, ie: host.cc */ | |
1565 | + for (sconf = GlobalSList; sconf; sconf = sconf->next) | |
1566 | + if (strCasediff(hostmask, sconf->spoofhost) == 0) | |
1567 | + return sconf->spoofhost; | |
1568 | + | |
1569 | + return NULL; | |
1570 | +} | |
1571 | + | |
1572 | + /* | |
1573 | + * IsVhostPass() - Check if given spoofhost has a password | |
1574 | + * associated with it, and if, return the password (cleartext) | |
1575 | + */ | |
1576 | +static char *IsVhostPass(char *hostmask) | |
1577 | +{ | |
1578 | + struct sline *sconf; | |
1579 | + | |
1580 | + Debug((DEBUG_INFO, "IsVhostPass() %s", hostmask)); | |
1581 | + | |
1582 | + if (EmptyString(hostmask)) | |
1583 | + return NULL; | |
1584 | + | |
1585 | + for (sconf = GlobalSList; sconf; sconf = sconf->next) | |
1586 | + if (strCasediff(hostmask, sconf->spoofhost) == 0) { | |
1587 | + Debug((DEBUG_INFO, "sconf->passwd %s", sconf->passwd)); | |
1588 | + return EmptyString(sconf->passwd) ? NULL : sconf->passwd; | |
1589 | + } | |
1590 | + | |
1591 | + return NULL; | |
1592 | +} | |
1593 | + | |
1594 | /** Update snomask \a oldmask according to \a arg and \a what. | |
1595 | * @param[in] oldmask Original user mask. | |
1596 | * @param[in] arg Update string (either a number or '+'/'-' followed by a number). | |
1597 | diff -r 6fd814ecf94b ircd/send.c | |
1598 | --- a/ircd/send.c Fri Jul 19 21:53:51 2013 +0100 | |
1599 | +++ b/ircd/send.c Fri Jul 19 22:26:20 2013 +0100 | |
1600 | @@ -281,7 +281,7 @@ | |
1601 | { | |
1602 | case MATCH_HOST: | |
1603 | return (match(mask, cli_user(one)->host) == 0 || | |
1604 | - (HasHiddenHost(one) && match(mask, cli_user(one)->realhost) == 0)); | |
1605 | + ((HasHiddenHost(one) || HasSetHost(one)) && match(mask, cli_user(one)->realhost) == 0)); | |
1606 | case MATCH_SERVER: | |
1607 | default: | |
1608 | return (match(mask, cli_name(cli_user(one)->server)) == 0); | |
1609 | diff -r 6fd814ecf94b ircd/whocmds.c | |
1610 | --- a/ircd/whocmds.c Fri Jul 19 21:53:51 2013 +0100 | |
1611 | +++ b/ircd/whocmds.c Fri Jul 19 22:26:20 2013 +0100 | |
1612 | @@ -129,7 +129,7 @@ | |
1613 | ||
1614 | if (fields & WHO_FIELD_NIP) | |
1615 | { | |
1616 | - const char* p2 = HasHiddenHost(acptr) && !IsAnOper(sptr) ? | |
1617 | + const char* p2 = (HasHiddenHost(acptr) || HasSetHost(acptr)) && !IsAnOper(sptr) ? | |
1618 | feature_str(FEAT_HIDDEN_IP) : | |
1619 | ircd_ntoa(&cli_ip(acptr)); | |
1620 | *(p1++) = ' '; | |
1621 | @@ -205,6 +205,8 @@ | |
1622 | *(p1++) = 'w'; | |
1623 | if (SendDebug(acptr)) | |
1624 | *(p1++) = 'g'; | |
1625 | + if (HasSetHost(acptr)) | |
1626 | + *(p1++) = 'h'; | |
1627 | } | |
1628 | if (HasHiddenHost(acptr)) | |
1629 | *(p1++) = 'x'; | |
1630 | diff -r 6fd814ecf94b tools/convert_slines.sh | |
1631 | --- /dev/null Thu Jan 01 00:00:00 1970 +0000 | |
1632 | +++ b/tools/convert_slines.sh Fri Jul 19 22:26:20 2013 +0100 | |
1633 | @@ -0,0 +1,50 @@ | |
1634 | +#!/bin/sh | |
1635 | +# | |
1636 | +# $Id: asuka-sethost.patch,v 1.29 2005/02/24 01:06:52 froo Exp $ | |
1637 | +# | |
1638 | +# aid in converting S: and F:lines from old lain configs | |
1639 | +# to the new "super S:line" format of asuka. | |
1640 | +# | |
1641 | +# When Who What | |
1642 | +# 2003-01-05 froo@quakenet.org Created. | |
1643 | + | |
1644 | +PATH=/bin:/usr/bin | |
1645 | +PROG=`basename $0` | |
1646 | +USAGE="Usage: $PROG </path/to/ircd.cfg>" | |
1647 | + | |
1648 | +if [ $# -lt 1 ]; then | |
1649 | + echo $USAGE | |
1650 | + exit | |
1651 | +fi | |
1652 | + | |
1653 | +CONFIG=$1 | |
1654 | + | |
1655 | +if [ ! -f $CONFIG ]; then | |
1656 | + echo "Can't open \"$CONFIG\", bailing out." | |
1657 | + exit | |
1658 | +fi | |
1659 | + | |
1660 | +{ | |
1661 | +for LINE in `grep -E "^F:" $CONFIG` | |
1662 | +do | |
1663 | + IDENT=`echo $LINE | cut -f2 -d:` | |
1664 | + REALHOST=`echo $LINE | cut -f3 -d:` | |
1665 | + SPOOFHOST=`echo $LINE | cut -f4 -d:` | |
1666 | + | |
1667 | + IDENT=`echo $IDENT | sed -e 's,^~,\*,'` | |
1668 | + | |
1669 | + echo "S:$SPOOFHOST::$REALHOST:$IDENT" | |
1670 | +done | |
1671 | + | |
1672 | +for LINE in `grep -E "^S:" $CONFIG` | |
1673 | +do | |
1674 | + SPOOFHOST=`echo $LINE | cut -f2 -d:` | |
1675 | + PASSWD=`echo $LINE | cut -f3 -d:` | |
1676 | + | |
1677 | + IDENT=`echo $IDENT | sed -e 's,^~,\*,'` | |
1678 | + | |
1679 | + echo "S:$SPOOFHOST:$PASSWD::" | |
1680 | +done | |
1681 | +} | sort | |
1682 | + | |
1683 | +exit 0 |