1 /* Copyright (C) 2009, Martin Johansson <martin@fatbob.nu>
2 Copyright (C) 2005-2009, Thorvald Natvig <thorvald@natvig.com>
6 Redistribution and use in source and binary forms, with or without
7 modification, are permitted provided that the following conditions
10 - Redistributions of source code must retain the above copyright notice,
11 this list of conditions and the following disclaimer.
12 - Redistributions in binary form must reproduce the above copyright notice,
13 this list of conditions and the following disclaimer in the documentation
14 and/or other materials provided with the distribution.
15 - Neither the name of the Developers nor the names of its contributors may
16 be used to endorse or promote products derived from this software without
17 specific prior written permission.
19 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22 A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR
23 CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
24 EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
25 PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
26 PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
27 LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
28 NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
29 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 #include <openssl/aes.h>
42 extern channel_t *defaultChan;
44 static void sendServerReject(client_t *client, const char *reason, MumbleProto__Reject__RejectType type)
46 message_t *msg = Msg_create(Reject);
47 msg->payload.reject->reason = strdup(reason);
48 msg->payload.reject->type = type;
49 msg->payload.reject->has_type = true;
50 Client_send_message(client, msg);
53 static void sendPermissionDenied(client_t *client, const char *reason)
55 message_t *msg = Msg_create(PermissionDenied);
56 msg->payload.permissionDenied->has_type = true;
57 msg->payload.permissionDenied->type = MUMBLE_PROTO__PERMISSION_DENIED__DENY_TYPE__Text;
58 msg->payload.permissionDenied->reason = strdup(reason);
59 Client_send_message(client, msg);
62 void Mh_handle_message(client_t *client, message_t *msg)
65 channel_t *ch_itr = NULL;
68 switch (msg->messageType) {
71 * 1. Check stuff, Serverreject if not ok
72 * 2. Setup UDP encryption -> MessageCryptSetup
74 * 4. MessageChannelAdd + MessageChannelDescUpdate for all channels
75 * 5. (MessageChannelLink)
76 * 6. MessageServerJoin
77 * 7. MessagePlayerMove
78 * 8. MessageServerJoin for all connected users
79 * 9. PlayerDeaf/PlayerMute/PlayerSelfMuteDeaf for all users it applies to
80 * 10. MessageServerSync
83 Log_debug("Authenticate message received");
84 Log_debug("Username: %s", msg->payload.authenticate->username);
86 client->authenticated = true;
89 while (Client_iterate(&client_itr) != NULL) {
90 if (!IS_AUTH(client_itr))
92 if (strncmp(client_itr->playerName, msg->payload.authenticate->username, MAX_TEXT) == 0) {
94 sprintf(buf, "Username already in use");
95 Log_debug("Username already in use");
96 sendServerReject(client, buf, MUMBLE_PROTO__REJECT__REJECT_TYPE__UsernameInUse);
100 if (msg->payload.authenticate->password && strncmp(getStrConf(PASSPHRASE), msg->payload.authenticate->password, MAX_TEXT) != 0) {
102 sprintf(buf, "Wrong server password");
103 Log_debug("Wrong server password: %s", msg->payload.authenticate->password);
104 sendServerReject(client, buf, MUMBLE_PROTO__REJECT__REJECT_TYPE__WrongServerPW);
107 if (strlen(msg->payload.authenticate->username) == 0 ||
108 strlen(msg->payload.authenticate->username) >= MAX_TEXT) { /* XXX - other invalid names? */
110 sprintf(buf, "Invalid username");
111 Log_debug("Invalid username");
112 sendServerReject(client, buf, MUMBLE_PROTO__REJECT__REJECT_TYPE__InvalidUsername);
116 if (Client_count() >= getIntConf(MAX_CLIENTS)) {
118 sprintf(buf, "Server is full (max %d users)", getIntConf(MAX_CLIENTS));
119 sendServerReject(client, buf, MUMBLE_PROTO__REJECT__REJECT_TYPE__ServerFull);
123 /* Name & password */
124 strncpy(client->playerName, msg->payload.authenticate->username, MAX_TEXT);
125 client->playerId = client->sessionId;
128 /* XXX - Kick ghost? */
130 /* Setup UDP encryption */
131 CryptState_init(&client->cryptState);
132 CryptState_genKey(&client->cryptState);
133 sendmsg = Msg_create(CryptSetup);
134 sendmsg->payload.cryptSetup->has_key = true;
135 sendmsg->payload.cryptSetup->key.data = client->cryptState.raw_key;
136 sendmsg->payload.cryptSetup->key.len = AES_BLOCK_SIZE;
137 sendmsg->payload.cryptSetup->has_server_nonce = true;
138 sendmsg->payload.cryptSetup->server_nonce.data = client->cryptState.encrypt_iv;
139 sendmsg->payload.cryptSetup->server_nonce.len = AES_BLOCK_SIZE;
140 sendmsg->payload.cryptSetup->has_client_nonce = true;
141 sendmsg->payload.cryptSetup->client_nonce.data = client->cryptState.decrypt_iv;
142 sendmsg->payload.cryptSetup->client_nonce.len = AES_BLOCK_SIZE;
143 Client_send_message(client, sendmsg);
146 Chan_playerJoin(defaultChan, client); /* Join default channel */
149 if (msg->payload.authenticate->n_celt_versions > MAX_CODECS)
150 Log_warn("Client has more than %d CELT codecs. Ignoring %d codecs",
151 MAX_CODECS, msg->payload.authenticate->n_celt_versions - MAX_CODECS);
152 if (msg->payload.authenticate->n_celt_versions > 0) {
154 client->codec_count = msg->payload.authenticate->n_celt_versions > MAX_CODECS ?
155 MAX_CODECS : msg->payload.authenticate->n_celt_versions;
156 for (i = 0; i < client->codec_count; i++)
157 client->codecs[i] = msg->payload.authenticate->celt_versions[i];
159 client->codecs[0] = (int32_t)0x8000000a;
160 client->codec_count = 1;
162 recheckCodecVersions();
164 /* Iterate channels and send channel info */
166 Chan_iterate(&ch_itr);
168 sendmsg = Msg_create(ChannelState);
169 sendmsg->payload.channelState->has_channel_id = true;
170 sendmsg->payload.channelState->channel_id = ch_itr->id;
171 if (ch_itr->id != 0) {
172 sendmsg->payload.channelState->has_parent = true;
173 sendmsg->payload.channelState->parent = ch_itr->parent->id;
175 sendmsg->payload.channelState->name = strdup(ch_itr->name);
176 if (strlen(ch_itr->desc) > 0) {
177 sendmsg->payload.channelState->description = strdup(ch_itr->desc);
179 Log_debug("Send channel info: %s", sendmsg->payload.channelState->name);
180 Client_send_message(client, sendmsg);
182 Chan_iterate(&ch_itr);
183 } while (ch_itr != NULL);
185 /* Not supporting channel links yet */
187 /* Send user state for connecting user to other users */
188 sendmsg = Msg_create(UserState);
189 sendmsg->payload.userState->has_session = true;
190 sendmsg->payload.userState->session = client->sessionId;
191 sendmsg->payload.userState->has_user_id = true;
192 sendmsg->payload.userState->user_id = client->playerId;
193 sendmsg->payload.userState->name = strdup(client->playerName);
194 sendmsg->payload.userState->has_channel_id = true;
195 sendmsg->payload.userState->channel_id = ((channel_t *)client->channel)->id;
197 Client_send_message_except(client, sendmsg);
200 while (Client_iterate(&client_itr) != NULL) {
201 if (!IS_AUTH(client_itr))
203 sendmsg = Msg_create(UserState);
204 sendmsg->payload.userState->has_session = true;
205 sendmsg->payload.userState->session = client_itr->sessionId;
206 sendmsg->payload.userState->name = strdup(client_itr->playerName);
207 sendmsg->payload.userState->has_channel_id = true;
208 sendmsg->payload.userState->channel_id = ((channel_t *)client_itr->channel)->id;
210 /* XXX - check if self_* is correct */
211 if (client_itr->deaf) {
212 sendmsg->payload.userState->has_self_deaf = true;
213 sendmsg->payload.userState->self_deaf = true;
215 if (client_itr->mute) {
216 sendmsg->payload.userState->has_self_mute = true;
217 sendmsg->payload.userState->self_mute = true;
219 Client_send_message(client, sendmsg);
223 sendmsg = Msg_create(ServerSync);
224 sendmsg->payload.serverSync->has_session = true;
225 sendmsg->payload.serverSync->session = client->sessionId;
226 sendmsg->payload.serverSync->welcome_text = strdup(getStrConf(WELCOMETEXT));
227 sendmsg->payload.serverSync->has_max_bandwidth = true;
228 sendmsg->payload.serverSync->max_bandwidth = getIntConf(MAX_BANDWIDTH);
229 sendmsg->payload.serverSync->has_allow_html = true;
230 sendmsg->payload.serverSync->allow_html = false; /* Support this? */
231 Client_send_message(client, sendmsg);
233 Log_info("User %s authenticated", client->playerName);
239 if (msg->payload.ping->has_good)
240 client->cryptState.uiRemoteGood = msg->payload.ping->good;
241 if (msg->payload.ping->has_late)
242 client->cryptState.uiRemoteLate = msg->payload.ping->late;
243 if (msg->payload.ping->has_lost)
244 client->cryptState.uiRemoteLost = msg->payload.ping->lost;
245 if (msg->payload.ping->has_resync)
246 client->cryptState.uiRemoteResync = msg->payload.ping->resync;
248 Log_debug("Ping <-: %d %d %d %d",
249 client->cryptState.uiRemoteGood, client->cryptState.uiRemoteLate,
250 client->cryptState.uiRemoteLost, client->cryptState.uiRemoteResync
253 /* Ignoring the double values since they don't seem to be used */
255 sendmsg = Msg_create(Ping);
256 timestamp = msg->payload.ping->timestamp;
258 sendmsg->payload.ping->timestamp = timestamp;
260 sendmsg->payload.ping->good = client->cryptState.uiGood;
261 sendmsg->payload.ping->has_good = true;
262 sendmsg->payload.ping->late = client->cryptState.uiLate;
263 sendmsg->payload.ping->has_late = true;
264 sendmsg->payload.ping->lost = client->cryptState.uiLost;
265 sendmsg->payload.ping->has_lost = true;
266 sendmsg->payload.ping->resync = client->cryptState.uiResync;
267 sendmsg->payload.ping->has_resync = true;
269 Client_send_message(client, sendmsg);
270 Log_debug("Ping ->: %d %d %d %d",
271 client->cryptState.uiGood, client->cryptState.uiLate,
272 client->cryptState.uiLost, client->cryptState.uiResync);
277 Log_debug("Voice channel crypt resync requested");
278 if (!msg->payload.cryptSetup->has_client_nonce) {
279 sendmsg = Msg_create(CryptSetup);
280 sendmsg->payload.cryptSetup->has_server_nonce = true;
281 sendmsg->payload.cryptSetup->server_nonce.data = client->cryptState.decrypt_iv;
282 sendmsg->payload.cryptSetup->server_nonce.len = AES_BLOCK_SIZE;
283 Client_send_message(client, sendmsg);
285 memcpy(client->cryptState.decrypt_iv, msg->payload.cryptSetup->client_nonce.data, AES_BLOCK_SIZE);
286 client->cryptState.uiResync++;
290 /* Only allow state changes for for the self user */
291 if (msg->payload.userState->has_session &&
292 msg->payload.userState->session != client->sessionId) {
293 sendPermissionDenied(client, "Permission denied");
296 if (msg->payload.userState->has_user_id || msg->payload.userState->has_mute ||
297 msg->payload.userState->has_deaf || msg->payload.userState->has_suppress ||
298 msg->payload.userState->has_texture) {
300 sendPermissionDenied(client, "Not supported by uMurmur");
303 if (msg->payload.userState->has_self_deaf) {
304 client->deaf = msg->payload.userState->self_deaf;
306 if (msg->payload.userState->has_self_mute) {
307 client->mute = msg->payload.userState->self_mute;
309 if (msg->payload.userState->has_channel_id) {
310 Chan_playerJoin_id(msg->payload.userState->channel_id, client);
314 msg->payload.userState->has_actor = true;
315 msg->payload.userState->actor = client->sessionId;
316 Client_send_message_except(NULL, msg);
321 if (msg->payload.textMessage.bTree)
322 sendPermissionDenied(client, "Tree message not supported");
323 else if (msg->payload.textMessage.channel != -1) { /* To channel */
324 channel_t *ch_itr = NULL;
326 Chan_iterate(&ch_itr);
327 } while (ch_itr != NULL && ch_itr->id != msg->payload.textMessage.channel);
329 Log_warn("Channel id %d not found - ignoring.", msg->payload.textMessage.channel);
332 list_iterate(itr, &ch_itr->clients) {
334 c = list_get_entry(itr, client_t, chan_node);
335 if (c != client && !c->deaf) {
337 Client_send_message(c, msg);
338 Log_debug("Text message to player ID %d", c->playerId);
342 } else { /* To player */
343 client_t *itr = NULL;
344 while (Client_iterate(&itr) != NULL) {
347 if (itr->playerId == msg->payload.textMessage.victim) {
350 Client_send_message(itr, msg);
356 Log_warn("TextMessage: Player ID %d not found", msg->payload.textMessage.victim);
366 Log_debug("Version message received");
367 if (msg->payload.version->has_version) {
368 client->version = msg->payload.version->version;
369 Log_debug("Client version 0x%x", client->version);
371 if (msg->payload.version->release) {
372 if (client->release) free(client->release);
373 client->release = strdup(msg->payload.version->release);
374 Log_debug("Client release %s", client->release);
376 if (msg->payload.version->os) {
377 if (client->os) free(client->os);
378 client->os = strdup(msg->payload.version->os);
379 Log_debug("Client OS %s", client->os);
383 Msg_inc_ref(msg); /* Re-use message */
385 /* XXX - fill in version */
387 Client_send_message(client, msg);
390 Client_voiceMsg(client, msg->payload.UDPTunnel->packet.data, msg->payload.UDPTunnel->packet.len);
392 /* Permission denied for all these messages. Not implemented. */
396 case ContextActionAdd:
399 sendPermissionDenied(client, "Not supported by uMurmur");
403 Log_warn("Message %d not handled", msg->messageType);
410 Client_close(client);