]>
Commit | Line | Data |
---|---|---|
1d4df40c | 1 | /* |
2 | * IRC - Internet Relay Chat, ircd/m_sethost.c | |
3 | * Copyright (C) 1990 Jarkko Oikarinen and | |
4 | * University of Oulu, Computing Center | |
5 | * | |
6 | * See file AUTHORS in IRC package for additional names of | |
7 | * the programmers. | |
8 | * | |
9 | * This program is free software; you can redistribute it and/or modify | |
10 | * it under the terms of the GNU General Public License as published by | |
11 | * the Free Software Foundation; either version 1, or (at your option) | |
12 | * any later version. | |
13 | * | |
14 | * This program is distributed in the hope that it will be useful, | |
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
17 | * GNU General Public License for more details. | |
18 | * | |
19 | * You should have received a copy of the GNU General Public License | |
20 | * along with this program; if not, write to the Free Software | |
21 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |
22 | * | |
23 | * $Id: asuka-sethost.patch,v 1.27 2005/02/13 17:28:11 froo Exp $ | |
24 | */ | |
25 | ||
26 | /* | |
27 | * m_functions execute protocol messages on this server: | |
28 | * | |
29 | * cptr is always NON-NULL, pointing to a *LOCAL* client | |
30 | * structure (with an open socket connected!). This | |
31 | * identifies the physical socket where the message | |
32 | * originated (or which caused the m_function to be | |
33 | * executed--some m_functions may call others...). | |
34 | * | |
35 | * sptr is the source of the message, defined by the | |
36 | * prefix part of the message if present. If not | |
37 | * or prefix not found, then sptr==cptr. | |
38 | * | |
39 | * (!IsServer(cptr)) => (cptr == sptr), because | |
40 | * prefixes are taken *only* from servers... | |
41 | * | |
42 | * (IsServer(cptr)) | |
43 | * (sptr == cptr) => the message didn't | |
44 | * have the prefix. | |
45 | * | |
46 | * (sptr != cptr && IsServer(sptr) means | |
47 | * the prefix specified servername. (?) | |
48 | * | |
49 | * (sptr != cptr && !IsServer(sptr) means | |
50 | * that message originated from a remote | |
51 | * user (not local). | |
52 | * | |
53 | * combining | |
54 | * | |
55 | * (!IsServer(sptr)) means that, sptr can safely | |
56 | * taken as defining the target structure of the | |
57 | * message in this server. | |
58 | * | |
59 | * *Always* true (if 'parse' and others are working correct): | |
60 | * | |
61 | * 1) sptr->from == cptr (note: cptr->from == cptr) | |
62 | * | |
63 | * 2) MyConnect(sptr) <=> sptr == cptr (e.g. sptr | |
64 | * *cannot* be a local connection, unless it's | |
65 | * actually cptr!). [MyConnect(x) should probably | |
66 | * be defined as (x == x->from) --msa ] | |
67 | * | |
68 | * parc number of variable parameter strings (if zero, | |
69 | * parv is allowed to be NULL) | |
70 | * | |
71 | * parv a NULL terminated list of parameter pointers, | |
72 | * | |
73 | * parv[0], sender (prefix string), if not present | |
74 | * this points to an empty string. | |
75 | * parv[1]...parv[parc-1] | |
76 | * pointers to additional parameters | |
77 | * parv[parc] == NULL, *always* | |
78 | * | |
79 | * note: it is guaranteed that parv[0]..parv[parc-1] are all | |
80 | * non-NULL pointers. | |
81 | */ | |
82 | #include "config.h" | |
83 | ||
84 | #include "client.h" | |
85 | #include "ircd_reply.h" | |
86 | #include "ircd_string.h" | |
caa12862 | 87 | #include "ircd_snprintf.h" |
1d4df40c | 88 | #include "ircd_features.h" |
89 | #include "msgq.h" | |
90 | #include "numeric.h" | |
5a8c3006 | 91 | #include "s_conf.h" |
1d4df40c | 92 | #include "s_user.h" |
93 | #include "s_debug.h" | |
5a8c3006 | 94 | #include "send.h" |
1d4df40c | 95 | #include "struct.h" |
5a8c3006 | 96 | #include "numnicks.h" |
97 | ||
98 | #include "channel.h" | |
99 | #include "msg.h" | |
1d4df40c | 100 | |
101 | #include <assert.h> | |
102 | #include <stdlib.h> | |
103 | ||
104 | /* | |
105 | * m_sethost - generic message handler | |
106 | * | |
107 | * mimic old lain syntax: | |
108 | * | |
109 | * (Oper) /SETHOST ident host.cc [quit-message] | |
110 | * (User) /SETHOST host.cc password | |
111 | * (Both) /SETHOST undo | |
112 | * | |
113 | * check for undo, prepend parv w. <nick> -h or +h | |
114 | */ | |
115 | int m_sethost(struct Client* cptr, struct Client* sptr, int parc, char* parv[]) | |
116 | { | |
839fb76e | 117 | char hostmask[USERLEN + HOSTLEN + 2]; |
118 | char curhostmask[USERLEN + HOSTLEN + 2]; | |
119 | ||
1d4df40c | 120 | struct Flags setflags; |
121 | ||
122 | /* Back up the flags first */ | |
123 | setflags = cli_flags(sptr); | |
124 | ||
125 | if (parc < 2) | |
126 | return need_more_params(sptr, "SETHOST"); | |
127 | ||
128 | if (0 == ircd_strcmp("undo", parv[1])) { | |
129 | set_hostmask(sptr, NULL, NULL); | |
130 | } else { | |
131 | if (parc<3) | |
132 | return need_more_params(sptr, "SETHOST"); | |
133 | if (IsAnOper(sptr)) { | |
5a8c3006 | 134 | ircd_snprintf(0, hostmask, USERLEN + HOSTLEN + 2, "%s@%s", parv[1], parv[2]); |
1d4df40c | 135 | if (!is_hostmask(hostmask)) { |
136 | send_reply(sptr, ERR_BADHOSTMASK, hostmask); | |
137 | return 0; | |
138 | } | |
839fb76e | 139 | if (IsSetHost(sptr) || IsAccount(sptr)) { |
5a8c3006 | 140 | ircd_snprintf(0, curhostmask, USERLEN + HOSTLEN + 2, "%s@%s", sptr->cli_user->username, sptr->cli_user->host); |
839fb76e | 141 | if (0 == strcmp(hostmask, curhostmask)) { |
36cc44fe | 142 | send_reply(sptr, RPL_HOSTHIDDEN, curhostmask); |
839fb76e | 143 | return 0; |
144 | } | |
145 | } | |
1d4df40c | 146 | if (set_hostmask(sptr, hostmask, NULL)) |
147 | FlagClr(&setflags, FLAG_SETHOST); | |
148 | } else { | |
149 | if (!is_hostmask(parv[1])) { | |
150 | send_reply(sptr, ERR_BADHOSTMASK, parv[1]); | |
151 | return 0; | |
152 | } | |
839fb76e | 153 | if (IsSetHost(sptr) || IsAccount(sptr)) { |
154 | if (0 == strcmp(parv[1], sptr->cli_user->host)) { | |
36cc44fe | 155 | send_reply(sptr, RPL_HOSTHIDDEN, parv[1]); |
839fb76e | 156 | return 0; |
157 | } | |
158 | } | |
1d4df40c | 159 | if (set_hostmask(sptr, parv[1], parv[2])) |
160 | FlagClr(&setflags, FLAG_SETHOST); | |
161 | } | |
162 | } | |
163 | ||
164 | send_umode_out(cptr, sptr, &setflags, 0); | |
caa12862 | 165 | return 0; |
1d4df40c | 166 | } |
5a8c3006 | 167 | |
168 | ||
169 | /* | |
170 | * ms_sethost - sethost server message handler | |
171 | * | |
172 | * parv[0] = sender prefix | |
173 | * parv[1] = target user numeric | |
174 | * parv[2] = target user's new ident | |
175 | * parv[3] = target user's new host | |
176 | */ | |
177 | int ms_sethost(struct Client* cptr, struct Client* sptr, int parc, char* parv[]) | |
178 | { | |
179 | struct Client *target; | |
180 | char hostmask[USERLEN + HOSTLEN + 2]; | |
181 | struct Membership *chan; | |
36cc44fe | 182 | struct Flags setflags; |
5a8c3006 | 183 | |
184 | if (parc < 4) | |
185 | return need_more_params(sptr, "SETHOST"); | |
186 | ||
187 | if (!IsServer(sptr)) | |
188 | return protocol_violation(cptr, "SETHOST from non-server %s", | |
189 | cli_name(sptr)); | |
190 | ||
191 | /* Locate our target user; ignore the message if we can't */ | |
192 | if(!(target = findNUser(parv[1]))) | |
193 | return 0; | |
194 | ||
195 | /* Fake host assignments must be from services */ | |
196 | if (!find_conf_byhost(cli_confs(sptr), cli_name(sptr), CONF_UWORLD)) | |
197 | return protocol_violation(cptr, "Non-U:lined server %s set fake host on user %s", cli_name(sptr), cli_name(target)); | |
198 | ||
36cc44fe | 199 | if (!MyConnect(target)) { |
200 | sendcmdto_one(sptr, CMD_SETHOST, cli_user(target)->server, "%C %s %s", target, | |
201 | parv[2], parv[3]); | |
202 | return 0; | |
203 | } | |
204 | ||
205 | /* Back up the flags first */ | |
206 | setflags = cli_flags(target); | |
207 | FlagClr(&setflags, FLAG_SETHOST); | |
208 | ||
5a8c3006 | 209 | if (IsSetHost(target) || IsAccount(target)) { |
210 | if ((0 == strcmp(parv[2], target->cli_user->username)) && (0 == strcmp(parv[3], target->cli_user->host))) | |
211 | return 0; | |
212 | } | |
213 | ||
214 | ircd_snprintf(0, hostmask, USERLEN + HOSTLEN + 2, "%s@%s", parv[2], parv[3]); | |
215 | if (!is_hostmask(hostmask)) | |
216 | return protocol_violation(cptr, "Bad Host mask %s for user %s", hostmask, cli_name(target)); | |
217 | ||
9e602a3d | 218 | sendcmdto_common_channels_butone(target, CMD_QUIT, target, ":Host change"); |
219 | ||
5a8c3006 | 220 | /* Assign and propagate the fakehost */ |
221 | SetSetHost(target); | |
222 | ircd_strncpy(cli_user(target)->username, parv[2], USERLEN); | |
223 | ircd_strncpy(cli_user(target)->host, parv[3], HOSTLEN); | |
224 | ||
36cc44fe | 225 | send_reply(target, RPL_HOSTHIDDEN, hostmask); |
5a8c3006 | 226 | |
227 | /* | |
228 | * Go through all channels the client was on, rejoin him | |
229 | * and set the modes, if any | |
230 | */ | |
231 | for (chan = cli_user(target)->channel; chan; chan = chan->next_channel) { | |
232 | if (IsZombie(chan)) | |
233 | continue; | |
234 | /* If this channel has delayed joins and the user has no modes, just set | |
235 | * the delayed join flag rather than showing the join, even if the user | |
236 | * was visible before */ | |
237 | if (!IsChanOp(chan) && !HasVoice(chan) | |
238 | && (chan->channel->mode.mode & MODE_DELJOINS)) { | |
239 | SetDelayedJoin(chan); | |
240 | } else { | |
241 | sendcmdto_channel_butserv_butone(target, CMD_JOIN, chan->channel, target, 0, | |
242 | "%H", chan->channel); | |
243 | } | |
244 | if (IsChanOp(chan) && HasVoice(chan)) { | |
245 | sendcmdto_channel_butserv_butone(&his, CMD_MODE, chan->channel, target, 0, | |
246 | "%H +ov %C %C", chan->channel, target, target); | |
247 | } else if (IsChanOp(chan) || HasVoice(chan)) { | |
248 | sendcmdto_channel_butserv_butone(&his, CMD_MODE, chan->channel, target, 0, | |
249 | "%H +%c %C", chan->channel, IsChanOp(chan) ? 'o' : 'v', target); | |
250 | } | |
251 | } | |
252 | ||
36cc44fe | 253 | send_umode_out(target, target, &setflags, 0); |
254 | return 0; | |
5a8c3006 | 255 | } |