1 /* Copyright (C) 2009-2010, Martin Johansson <martin@fatbob.nu>
2 Copyright (C) 2005-2010, 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>
38 #include "messagehandler.h"
42 #include "voicetarget.h"
46 extern channel_t *defaultChan;
47 extern int iCodecAlpha, iCodecBeta;
48 extern bool_t bPreferAlpha;
50 static void sendServerReject(client_t *client, const char *reason, MumbleProto__Reject__RejectType type)
52 message_t *msg = Msg_create(Reject);
53 msg->payload.reject->reason = strdup(reason);
54 msg->payload.reject->type = type;
55 msg->payload.reject->has_type = true;
56 Client_send_message(client, msg);
58 Log_info_client(client, "Server reject reason: %s", reason);
61 static void sendPermissionDenied(client_t *client, const char *reason)
63 message_t *msg = Msg_create(PermissionDenied);
64 msg->payload.permissionDenied->has_type = true;
65 msg->payload.permissionDenied->type = MUMBLE_PROTO__PERMISSION_DENIED__DENY_TYPE__Text;
66 msg->payload.permissionDenied->reason = strdup(reason);
67 Client_send_message(client, msg);
70 void Mh_handle_message(client_t *client, message_t *msg)
72 message_t *sendmsg = NULL;
73 channel_t *ch_itr = NULL;
76 if (!client->authenticated && !(msg->messageType == Authenticate ||
77 msg->messageType == Version)) {
80 switch (msg->messageType) {
83 * 1. Check stuff, Serverreject if not ok
84 * 2. Setup UDP encryption -> MessageCryptSetup
86 * 4. MessageChannelAdd + MessageChannelDescUpdate for all channels
87 * 5. (MessageChannelLink)
88 * 6. MessageServerJoin
89 * 7. MessagePlayerMove
90 * 8. MessageServerJoin for all connected users
91 * 9. PlayerDeaf/PlayerMute/PlayerSelfMuteDeaf for all users it applies to
92 * 10. MessageServerSync
95 Log_debug("Authenticate message received");
96 Log_debug("Username: %s", msg->payload.authenticate->username);
98 client->authenticated = true;
101 while (Client_iterate(&client_itr) != NULL) {
102 if (!IS_AUTH(client_itr))
104 if (client_itr->playerName && strncmp(client_itr->playerName, msg->payload.authenticate->username, MAX_TEXT) == 0) {
106 sprintf(buf, "Username already in use");
107 Log_debug("Username already in use");
108 sendServerReject(client, buf, MUMBLE_PROTO__REJECT__REJECT_TYPE__UsernameInUse);
112 if (strlen(getStrConf(PASSPHRASE)) > 0) {
113 if (!msg->payload.authenticate->password || strncmp(getStrConf(PASSPHRASE), msg->payload.authenticate->password, MAX_TEXT) != 0) {
115 sprintf(buf, "Wrong server password");
116 sendServerReject(client, buf, MUMBLE_PROTO__REJECT__REJECT_TYPE__WrongServerPW);
117 Log_debug("Wrong server password: %s", msg->payload.authenticate->password);
121 if (strlen(msg->payload.authenticate->username) == 0 ||
122 strlen(msg->payload.authenticate->username) >= MAX_TEXT) { /* XXX - other invalid names? */
124 sprintf(buf, "Invalid username");
125 Log_debug("Invalid username");
126 sendServerReject(client, buf, MUMBLE_PROTO__REJECT__REJECT_TYPE__InvalidUsername);
130 if (Client_count() >= getIntConf(MAX_CLIENTS)) {
132 sprintf(buf, "Server is full (max %d users)", getIntConf(MAX_CLIENTS));
133 sendServerReject(client, buf, MUMBLE_PROTO__REJECT__REJECT_TYPE__ServerFull);
137 /* Name & password */
138 client->playerName = strdup(msg->payload.authenticate->username);
140 /* Setup UDP encryption */
141 CryptState_init(&client->cryptState);
142 CryptState_genKey(&client->cryptState);
143 sendmsg = Msg_create(CryptSetup);
144 sendmsg->payload.cryptSetup->has_key = true;
145 sendmsg->payload.cryptSetup->key.data = client->cryptState.raw_key;
146 sendmsg->payload.cryptSetup->key.len = AES_BLOCK_SIZE;
147 sendmsg->payload.cryptSetup->has_server_nonce = true;
148 sendmsg->payload.cryptSetup->server_nonce.data = client->cryptState.encrypt_iv;
149 sendmsg->payload.cryptSetup->server_nonce.len = AES_BLOCK_SIZE;
150 sendmsg->payload.cryptSetup->has_client_nonce = true;
151 sendmsg->payload.cryptSetup->client_nonce.data = client->cryptState.decrypt_iv;
152 sendmsg->payload.cryptSetup->client_nonce.len = AES_BLOCK_SIZE;
153 Client_send_message(client, sendmsg);
156 Chan_playerJoin(defaultChan, client); /* Join default channel */
159 if (msg->payload.authenticate->n_celt_versions > MAX_CODECS)
160 Log_warn("Client has more than %d CELT codecs. Ignoring %d codecs",
161 MAX_CODECS, msg->payload.authenticate->n_celt_versions - MAX_CODECS);
163 Log_debug("Client %d has %d CELT codecs", client->sessionId, msg->payload.authenticate->n_celt_versions);
164 if (msg->payload.authenticate->n_celt_versions > 0) {
166 client->codec_count = msg->payload.authenticate->n_celt_versions > MAX_CODECS ?
167 MAX_CODECS : msg->payload.authenticate->n_celt_versions;
168 for (i = 0; i < client->codec_count; i++) {
169 client->codecs[i] = msg->payload.authenticate->celt_versions[i];
170 Log_debug("Client %d CELT codec ver 0x%x", client->sessionId, client->codecs[i]);
173 client->codecs[0] = (int32_t)0x8000000a;
174 client->codec_count = 1;
177 recheckCodecVersions();
179 sendmsg = Msg_create(CodecVersion);
180 sendmsg->payload.codecVersion->alpha = iCodecAlpha;
181 sendmsg->payload.codecVersion->beta = iCodecBeta;
182 sendmsg->payload.codecVersion->prefer_alpha = bPreferAlpha;
183 Client_send_message(client, sendmsg);
185 /* Iterate channels and send channel info */
187 Chan_iterate(&ch_itr);
189 sendmsg = Msg_create(ChannelState);
190 sendmsg->payload.channelState->has_channel_id = true;
191 sendmsg->payload.channelState->channel_id = ch_itr->id;
192 if (ch_itr->id != 0) {
193 sendmsg->payload.channelState->has_parent = true;
194 sendmsg->payload.channelState->parent = ch_itr->parent->id;
196 sendmsg->payload.channelState->name = strdup(ch_itr->name);
198 sendmsg->payload.channelState->description = strdup(ch_itr->desc);
199 Log_debug("Send channel info: %s", sendmsg->payload.channelState->name);
200 Client_send_message(client, sendmsg);
202 Chan_iterate(&ch_itr);
203 } while (ch_itr != NULL);
205 /* Not supporting channel links yet */
207 /* Send user state for connecting user to other users */
208 sendmsg = Msg_create(UserState);
209 sendmsg->payload.userState->has_session = true;
210 sendmsg->payload.userState->session = client->sessionId;
211 sendmsg->payload.userState->has_user_id = true;
212 sendmsg->payload.userState->user_id = client->sessionId;
213 sendmsg->payload.userState->name = strdup(client->playerName);
214 sendmsg->payload.userState->has_channel_id = true;
215 sendmsg->payload.userState->channel_id = ((channel_t *)client->channel)->id;
217 Client_send_message_except(client, sendmsg);
220 while (Client_iterate(&client_itr) != NULL) {
221 if (!IS_AUTH(client_itr))
223 sendmsg = Msg_create(UserState);
224 sendmsg->payload.userState->has_session = true;
225 sendmsg->payload.userState->session = client_itr->sessionId;
226 sendmsg->payload.userState->name = strdup(client_itr->playerName);
227 sendmsg->payload.userState->has_channel_id = true;
228 sendmsg->payload.userState->channel_id = ((channel_t *)client_itr->channel)->id;
230 /* Only self_mute/deaf supported */
231 if (client_itr->deaf) {
232 sendmsg->payload.userState->has_self_deaf = true;
233 sendmsg->payload.userState->self_deaf = true;
235 if (client_itr->mute) {
236 sendmsg->payload.userState->has_self_mute = true;
237 sendmsg->payload.userState->self_mute = true;
239 Client_send_message(client, sendmsg);
243 sendmsg = Msg_create(ServerSync);
244 sendmsg->payload.serverSync->has_session = true;
245 sendmsg->payload.serverSync->session = client->sessionId;
246 sendmsg->payload.serverSync->welcome_text = strdup(getStrConf(WELCOMETEXT));
247 sendmsg->payload.serverSync->has_max_bandwidth = true;
248 sendmsg->payload.serverSync->max_bandwidth = getIntConf(MAX_BANDWIDTH);
249 sendmsg->payload.serverSync->has_allow_html = true;
250 sendmsg->payload.serverSync->allow_html = true; /* Support this? */
251 Client_send_message(client, sendmsg);
253 Log_info_client(client, "User %s authenticated", client->playerName);
257 if (msg->payload.ping->has_good)
258 client->cryptState.uiRemoteGood = msg->payload.ping->good;
259 if (msg->payload.ping->has_late)
260 client->cryptState.uiRemoteLate = msg->payload.ping->late;
261 if (msg->payload.ping->has_lost)
262 client->cryptState.uiRemoteLost = msg->payload.ping->lost;
263 if (msg->payload.ping->has_resync)
264 client->cryptState.uiRemoteResync = msg->payload.ping->resync;
266 Log_debug("Ping <-: %d %d %d %d",
267 client->cryptState.uiRemoteGood, client->cryptState.uiRemoteLate,
268 client->cryptState.uiRemoteLost, client->cryptState.uiRemoteResync
271 /* Ignoring the double values since they don't seem to be used */
273 sendmsg = Msg_create(Ping);
275 sendmsg->payload.ping->timestamp = msg->payload.ping->timestamp;
276 sendmsg->payload.ping->has_timestamp = true;
277 sendmsg->payload.ping->good = client->cryptState.uiGood;
278 sendmsg->payload.ping->has_good = true;
279 sendmsg->payload.ping->late = client->cryptState.uiLate;
280 sendmsg->payload.ping->has_late = true;
281 sendmsg->payload.ping->lost = client->cryptState.uiLost;
282 sendmsg->payload.ping->has_lost = true;
283 sendmsg->payload.ping->resync = client->cryptState.uiResync;
284 sendmsg->payload.ping->has_resync = true;
286 Client_send_message(client, sendmsg);
287 Log_debug("Ping ->: %d %d %d %d",
288 client->cryptState.uiGood, client->cryptState.uiLate,
289 client->cryptState.uiLost, client->cryptState.uiResync);
293 Log_debug("Voice channel crypt resync requested");
294 if (!msg->payload.cryptSetup->has_client_nonce) {
295 sendmsg = Msg_create(CryptSetup);
296 sendmsg->payload.cryptSetup->has_server_nonce = true;
297 sendmsg->payload.cryptSetup->server_nonce.data = client->cryptState.decrypt_iv;
298 sendmsg->payload.cryptSetup->server_nonce.len = AES_BLOCK_SIZE;
299 Client_send_message(client, sendmsg);
301 memcpy(client->cryptState.decrypt_iv, msg->payload.cryptSetup->client_nonce.data, AES_BLOCK_SIZE);
302 client->cryptState.uiResync++;
306 /* Only allow state changes for for the self user */
307 if (msg->payload.userState->has_session &&
308 msg->payload.userState->session != client->sessionId) {
309 sendPermissionDenied(client, "Permission denied");
312 if (msg->payload.userState->has_user_id || msg->payload.userState->has_mute ||
313 msg->payload.userState->has_deaf || msg->payload.userState->has_suppress ||
314 msg->payload.userState->has_texture) {
316 sendPermissionDenied(client, "Not supported by uMurmur");
319 if (msg->payload.userState->has_self_deaf) {
320 client->deaf = msg->payload.userState->self_deaf;
322 if (msg->payload.userState->has_self_mute) {
323 client->mute = msg->payload.userState->self_mute;
325 if (msg->payload.userState->has_channel_id) {
327 if (!Chan_playerJoin_id_test(msg->payload.userState->channel_id))
329 leave_id = Chan_playerJoin_id(msg->payload.userState->channel_id, client);
331 Log_debug("Removing channel ID %d", leave_id);
332 sendmsg = Msg_create(ChannelRemove);
333 sendmsg->payload.channelRemove->channel_id = leave_id;
336 if (msg->payload.userState->plugin_context != NULL) {
338 free(client->context);
339 client->context = strdup(msg->payload.userState->plugin_context);
340 if (client->context == NULL)
341 Log_fatal("Out of memory");
343 break; /* Don't inform other users about this state */
348 msg->payload.userState->has_actor = true;
349 msg->payload.userState->actor = client->sessionId;
350 Client_send_message_except(NULL, msg);
352 /* Need to send remove channel message _after_ UserState message */
354 Client_send_message_except(NULL, sendmsg);
358 msg->payload.textMessage->has_actor = true;
359 msg->payload.textMessage->actor = client->sessionId;
361 /* XXX - HTML is allowed and can't be turned off */
362 if (msg->payload.textMessage->n_tree_id > 0) {
363 sendPermissionDenied(client, "Tree message not supported");
367 if (msg->payload.textMessage->n_channel_id > 0) { /* To channel */
370 for (i = 0; i < msg->payload.textMessage->n_channel_id; i++) {
373 Chan_iterate(&ch_itr);
374 } while (ch_itr != NULL && ch_itr->id != msg->payload.textMessage->channel_id[i]);
375 if (ch_itr != NULL) {
377 list_iterate(itr, &ch_itr->clients) {
379 c = list_get_entry(itr, client_t, chan_node);
380 if (c != client && !c->deaf) {
382 Client_send_message(c, msg);
383 Log_debug("Text message to session ID %d", c->sessionId);
389 if (msg->payload.textMessage->n_session > 0) { /* To user */
392 for (i = 0; i < msg->payload.textMessage->n_session; i++) {
394 while (Client_iterate(&itr) != NULL) {
397 if (itr->sessionId == msg->payload.textMessage->session[i]) {
400 Client_send_message(itr, msg);
401 Log_debug("Text message to session ID %d", itr->sessionId);
407 Log_warn("TextMessage: Session ID %d not found", msg->payload.textMessage->session[i]);
414 int i, j, count, targetId = msg->payload.voiceTarget->id;
415 struct _MumbleProto__VoiceTarget__Target *target;
417 if (!targetId || targetId >= 0x1f)
419 Voicetarget_add_id(client, targetId);
420 count = msg->payload.voiceTarget->n_targets;
423 for (i = 0; i < count; i++) {
424 target = msg->payload.voiceTarget->targets[i];
425 for (j = 0; j < target->n_session; j++)
426 Voicetarget_add_session(client, targetId, target->session[j]);
427 if (target->has_channel_id) {
428 if (target->has_links || target->has_children)
429 Log_warn("Whisper to children or linked channels not implemented. Ignoring.");
430 Voicetarget_add_channel(client, targetId, target->channel_id);
436 Log_debug("Version message received");
437 if (msg->payload.version->has_version) {
438 client->version = msg->payload.version->version;
439 Log_debug("Client version 0x%x", client->version);
441 if (msg->payload.version->release) {
442 if (client->release) free(client->release);
443 client->release = strdup(msg->payload.version->release);
444 Log_debug("Client release %s", client->release);
446 if (msg->payload.version->os) {
447 if (client->os) free(client->os);
448 client->os = strdup(msg->payload.version->os);
449 Log_debug("Client OS %s", client->os);
452 case PermissionQuery:
453 Msg_inc_ref(msg); /* Re-use message */
454 msg->payload.permissionQuery->has_permissions = true;
455 msg->payload.permissionQuery->permissions = PERM_DEFAULT;
457 Client_send_message(client, msg);
460 Client_voiceMsg(client, msg->payload.UDPTunnel->packet.data, msg->payload.UDPTunnel->packet.len);
464 channel_t *ch_itr, *parent, *newchan;
466 /* Don't allow any changes to existing channels */
467 if (msg->payload.channelState->has_channel_id) {
468 sendPermissionDenied(client, "Not supported by uMurmur");
471 /* Must have parent */
472 if (!msg->payload.channelState->has_parent) {
473 sendPermissionDenied(client, "Not supported by uMurmur");
477 if (msg->payload.channelState->name == NULL) {
478 sendPermissionDenied(client, "Not supported by uMurmur");
481 /* Must be temporary channel */
482 if (msg->payload.channelState->temporary != true) {
483 sendPermissionDenied(client, "Only temporary channels are supported by uMurmur");
486 /* Check channel name is OK */
487 if (strlen(msg->payload.channelState->name) > MAX_TEXT) {
488 sendPermissionDenied(client, "Channel name too long");
492 parent = Chan_fromId(msg->payload.channelState->parent);
496 while (Chan_iterate_siblings(parent, &ch_itr) != NULL) {
497 if (strcmp(ch_itr->name, msg->payload.channelState->name) == 0) {
498 sendPermissionDenied(client, "Channel already exists");
505 /* Disallow temporary channels as siblings to temporary channels */
506 if (parent->temporary) {
507 sendPermissionDenied(client, "Parent channel is temporary channel");
511 /* XXX - Murmur looks for "\\w" and sends perm denied if not found.
512 * I don't know why so I don't do that here...
515 /* Create the channel */
516 newchan = Chan_createChannel(msg->payload.channelState->name,
517 msg->payload.channelState->description);
518 newchan->temporary = true;
519 Chan_addChannel(parent, newchan);
520 msg->payload.channelState->has_channel_id = true;
521 msg->payload.channelState->channel_id = newchan->id;
523 Client_send_message_except(NULL, msg);
525 /* Join the creating user */
526 sendmsg = Msg_create(UserState);
527 sendmsg->payload.userState->has_session = true;
528 sendmsg->payload.userState->session = client->sessionId;
529 sendmsg->payload.userState->has_channel_id = true;
530 sendmsg->payload.userState->channel_id = newchan->id;
531 Client_send_message_except(NULL, sendmsg);
533 leave_id = Chan_playerJoin(newchan, client);
535 Log_debug("Removing channel ID %d", leave_id);
536 sendmsg = Msg_create(ChannelRemove);
537 sendmsg->payload.channelRemove->channel_id = leave_id;
538 Client_send_message_except(NULL, sendmsg);
543 /* Permission denied for all these messages. Not implemented. */
546 case ContextActionAdd:
551 sendPermissionDenied(client, "Not supported by uMurmur");
555 Log_warn("Message %d not handled", msg->messageType);
564 Client_close(client);