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("Server reject reason: %s. Disconnecting session %d - %s@%s:%d",
62 inet_ntoa(client->remote_tcp.sin_addr),
63 ntohs(client->remote_tcp.sin_port));
67 static void sendPermissionDenied(client_t *client, const char *reason)
69 message_t *msg = Msg_create(PermissionDenied);
70 msg->payload.permissionDenied->has_type = true;
71 msg->payload.permissionDenied->type = MUMBLE_PROTO__PERMISSION_DENIED__DENY_TYPE__Text;
72 msg->payload.permissionDenied->reason = strdup(reason);
73 Client_send_message(client, msg);
76 void Mh_handle_message(client_t *client, message_t *msg)
78 message_t *sendmsg = NULL;
79 channel_t *ch_itr = NULL;
82 if (!client->authenticated && !(msg->messageType == Authenticate ||
83 msg->messageType == Version)) {
86 switch (msg->messageType) {
89 * 1. Check stuff, Serverreject if not ok
90 * 2. Setup UDP encryption -> MessageCryptSetup
92 * 4. MessageChannelAdd + MessageChannelDescUpdate for all channels
93 * 5. (MessageChannelLink)
94 * 6. MessageServerJoin
95 * 7. MessagePlayerMove
96 * 8. MessageServerJoin for all connected users
97 * 9. PlayerDeaf/PlayerMute/PlayerSelfMuteDeaf for all users it applies to
98 * 10. MessageServerSync
101 Log_debug("Authenticate message received");
102 Log_debug("Username: %s", msg->payload.authenticate->username);
104 client->authenticated = true;
107 while (Client_iterate(&client_itr) != NULL) {
108 if (!IS_AUTH(client_itr))
110 if (client_itr->playerName && strncmp(client_itr->playerName, msg->payload.authenticate->username, MAX_TEXT) == 0) {
112 sprintf(buf, "Username already in use");
113 Log_debug("Username already in use");
114 sendServerReject(client, buf, MUMBLE_PROTO__REJECT__REJECT_TYPE__UsernameInUse);
118 if (strlen(getStrConf(PASSPHRASE)) > 0) {
119 if (!msg->payload.authenticate->password || strncmp(getStrConf(PASSPHRASE), msg->payload.authenticate->password, MAX_TEXT) != 0) {
121 sprintf(buf, "Wrong server password");
122 sendServerReject(client, buf, MUMBLE_PROTO__REJECT__REJECT_TYPE__WrongServerPW);
123 Log_debug("Wrong server password: %s", msg->payload.authenticate->password);
127 if (strlen(msg->payload.authenticate->username) == 0 ||
128 strlen(msg->payload.authenticate->username) >= MAX_TEXT) { /* XXX - other invalid names? */
130 sprintf(buf, "Invalid username");
131 Log_debug("Invalid username");
132 sendServerReject(client, buf, MUMBLE_PROTO__REJECT__REJECT_TYPE__InvalidUsername);
136 if (Client_count() >= getIntConf(MAX_CLIENTS)) {
138 sprintf(buf, "Server is full (max %d users)", getIntConf(MAX_CLIENTS));
139 sendServerReject(client, buf, MUMBLE_PROTO__REJECT__REJECT_TYPE__ServerFull);
143 /* Name & password */
144 client->playerName = strdup(msg->payload.authenticate->username);
146 /* Setup UDP encryption */
147 CryptState_init(&client->cryptState);
148 CryptState_genKey(&client->cryptState);
149 sendmsg = Msg_create(CryptSetup);
150 sendmsg->payload.cryptSetup->has_key = true;
151 sendmsg->payload.cryptSetup->key.data = client->cryptState.raw_key;
152 sendmsg->payload.cryptSetup->key.len = AES_BLOCK_SIZE;
153 sendmsg->payload.cryptSetup->has_server_nonce = true;
154 sendmsg->payload.cryptSetup->server_nonce.data = client->cryptState.encrypt_iv;
155 sendmsg->payload.cryptSetup->server_nonce.len = AES_BLOCK_SIZE;
156 sendmsg->payload.cryptSetup->has_client_nonce = true;
157 sendmsg->payload.cryptSetup->client_nonce.data = client->cryptState.decrypt_iv;
158 sendmsg->payload.cryptSetup->client_nonce.len = AES_BLOCK_SIZE;
159 Client_send_message(client, sendmsg);
162 Chan_playerJoin(defaultChan, client); /* Join default channel */
165 if (msg->payload.authenticate->n_celt_versions > MAX_CODECS)
166 Log_warn("Client has more than %d CELT codecs. Ignoring %d codecs",
167 MAX_CODECS, msg->payload.authenticate->n_celt_versions - MAX_CODECS);
169 Log_debug("Client %d has %d CELT codecs", client->sessionId, msg->payload.authenticate->n_celt_versions);
170 if (msg->payload.authenticate->n_celt_versions > 0) {
172 client->codec_count = msg->payload.authenticate->n_celt_versions > MAX_CODECS ?
173 MAX_CODECS : msg->payload.authenticate->n_celt_versions;
174 for (i = 0; i < client->codec_count; i++) {
175 client->codecs[i] = msg->payload.authenticate->celt_versions[i];
176 Log_debug("Client %d CELT codec ver 0x%x", client->sessionId, client->codecs[i]);
179 client->codecs[0] = (int32_t)0x8000000a;
180 client->codec_count = 1;
183 recheckCodecVersions();
185 sendmsg = Msg_create(CodecVersion);
186 sendmsg->payload.codecVersion->alpha = iCodecAlpha;
187 sendmsg->payload.codecVersion->beta = iCodecBeta;
188 sendmsg->payload.codecVersion->prefer_alpha = bPreferAlpha;
189 Client_send_message(client, sendmsg);
191 /* Iterate channels and send channel info */
193 Chan_iterate(&ch_itr);
195 sendmsg = Msg_create(ChannelState);
196 sendmsg->payload.channelState->has_channel_id = true;
197 sendmsg->payload.channelState->channel_id = ch_itr->id;
198 if (ch_itr->id != 0) {
199 sendmsg->payload.channelState->has_parent = true;
200 sendmsg->payload.channelState->parent = ch_itr->parent->id;
202 sendmsg->payload.channelState->name = strdup(ch_itr->name);
204 sendmsg->payload.channelState->description = strdup(ch_itr->desc);
205 Log_debug("Send channel info: %s", sendmsg->payload.channelState->name);
206 Client_send_message(client, sendmsg);
208 Chan_iterate(&ch_itr);
209 } while (ch_itr != NULL);
211 /* Not supporting channel links yet */
213 /* Send user state for connecting user to other users */
214 sendmsg = Msg_create(UserState);
215 sendmsg->payload.userState->has_session = true;
216 sendmsg->payload.userState->session = client->sessionId;
217 sendmsg->payload.userState->has_user_id = true;
218 sendmsg->payload.userState->user_id = client->sessionId;
219 sendmsg->payload.userState->name = strdup(client->playerName);
220 sendmsg->payload.userState->has_channel_id = true;
221 sendmsg->payload.userState->channel_id = ((channel_t *)client->channel)->id;
223 Client_send_message_except(client, sendmsg);
226 while (Client_iterate(&client_itr) != NULL) {
227 if (!IS_AUTH(client_itr))
229 sendmsg = Msg_create(UserState);
230 sendmsg->payload.userState->has_session = true;
231 sendmsg->payload.userState->session = client_itr->sessionId;
232 sendmsg->payload.userState->name = strdup(client_itr->playerName);
233 sendmsg->payload.userState->has_channel_id = true;
234 sendmsg->payload.userState->channel_id = ((channel_t *)client_itr->channel)->id;
236 /* Only self_mute/deaf supported */
237 if (client_itr->deaf) {
238 sendmsg->payload.userState->has_self_deaf = true;
239 sendmsg->payload.userState->self_deaf = true;
241 if (client_itr->mute) {
242 sendmsg->payload.userState->has_self_mute = true;
243 sendmsg->payload.userState->self_mute = true;
245 Client_send_message(client, sendmsg);
249 sendmsg = Msg_create(ServerSync);
250 sendmsg->payload.serverSync->has_session = true;
251 sendmsg->payload.serverSync->session = client->sessionId;
252 sendmsg->payload.serverSync->welcome_text = strdup(getStrConf(WELCOMETEXT));
253 sendmsg->payload.serverSync->has_max_bandwidth = true;
254 sendmsg->payload.serverSync->max_bandwidth = getIntConf(MAX_BANDWIDTH);
255 sendmsg->payload.serverSync->has_allow_html = true;
256 sendmsg->payload.serverSync->allow_html = true; /* Support this? */
257 Client_send_message(client, sendmsg);
259 Log_info("User %s authenticated", client->playerName);
263 if (msg->payload.ping->has_good)
264 client->cryptState.uiRemoteGood = msg->payload.ping->good;
265 if (msg->payload.ping->has_late)
266 client->cryptState.uiRemoteLate = msg->payload.ping->late;
267 if (msg->payload.ping->has_lost)
268 client->cryptState.uiRemoteLost = msg->payload.ping->lost;
269 if (msg->payload.ping->has_resync)
270 client->cryptState.uiRemoteResync = msg->payload.ping->resync;
272 Log_debug("Ping <-: %d %d %d %d",
273 client->cryptState.uiRemoteGood, client->cryptState.uiRemoteLate,
274 client->cryptState.uiRemoteLost, client->cryptState.uiRemoteResync
277 /* Ignoring the double values since they don't seem to be used */
279 sendmsg = Msg_create(Ping);
281 sendmsg->payload.ping->timestamp = msg->payload.ping->timestamp;
282 sendmsg->payload.ping->has_timestamp = true;
283 sendmsg->payload.ping->good = client->cryptState.uiGood;
284 sendmsg->payload.ping->has_good = true;
285 sendmsg->payload.ping->late = client->cryptState.uiLate;
286 sendmsg->payload.ping->has_late = true;
287 sendmsg->payload.ping->lost = client->cryptState.uiLost;
288 sendmsg->payload.ping->has_lost = true;
289 sendmsg->payload.ping->resync = client->cryptState.uiResync;
290 sendmsg->payload.ping->has_resync = true;
292 Client_send_message(client, sendmsg);
293 Log_debug("Ping ->: %d %d %d %d",
294 client->cryptState.uiGood, client->cryptState.uiLate,
295 client->cryptState.uiLost, client->cryptState.uiResync);
299 Log_debug("Voice channel crypt resync requested");
300 if (!msg->payload.cryptSetup->has_client_nonce) {
301 sendmsg = Msg_create(CryptSetup);
302 sendmsg->payload.cryptSetup->has_server_nonce = true;
303 sendmsg->payload.cryptSetup->server_nonce.data = client->cryptState.decrypt_iv;
304 sendmsg->payload.cryptSetup->server_nonce.len = AES_BLOCK_SIZE;
305 Client_send_message(client, sendmsg);
307 memcpy(client->cryptState.decrypt_iv, msg->payload.cryptSetup->client_nonce.data, AES_BLOCK_SIZE);
308 client->cryptState.uiResync++;
312 /* Only allow state changes for for the self user */
313 if (msg->payload.userState->has_session &&
314 msg->payload.userState->session != client->sessionId) {
315 sendPermissionDenied(client, "Permission denied");
318 if (msg->payload.userState->has_user_id || msg->payload.userState->has_mute ||
319 msg->payload.userState->has_deaf || msg->payload.userState->has_suppress ||
320 msg->payload.userState->has_texture) {
322 sendPermissionDenied(client, "Not supported by uMurmur");
325 if (msg->payload.userState->has_self_deaf) {
326 client->deaf = msg->payload.userState->self_deaf;
328 if (msg->payload.userState->has_self_mute) {
329 client->mute = msg->payload.userState->self_mute;
331 if (msg->payload.userState->has_channel_id) {
333 if (!Chan_playerJoin_id_test(msg->payload.userState->channel_id))
335 leave_id = Chan_playerJoin_id(msg->payload.userState->channel_id, client);
337 Log_debug("Removing channel ID %d", leave_id);
338 sendmsg = Msg_create(ChannelRemove);
339 sendmsg->payload.channelRemove->channel_id = leave_id;
342 if (msg->payload.userState->plugin_context != NULL) {
344 free(client->context);
345 client->context = strdup(msg->payload.userState->plugin_context);
346 if (client->context == NULL)
347 Log_fatal("Out of memory");
349 break; /* Don't inform other users about this state */
354 msg->payload.userState->has_actor = true;
355 msg->payload.userState->actor = client->sessionId;
356 Client_send_message_except(NULL, msg);
358 /* Need to send remove channel message _after_ UserState message */
360 Client_send_message_except(NULL, sendmsg);
364 msg->payload.textMessage->has_actor = true;
365 msg->payload.textMessage->actor = client->sessionId;
367 /* XXX - HTML is allowed and can't be turned off */
368 if (msg->payload.textMessage->n_tree_id > 0) {
369 sendPermissionDenied(client, "Tree message not supported");
373 if (msg->payload.textMessage->n_channel_id > 0) { /* To channel */
376 for (i = 0; i < msg->payload.textMessage->n_channel_id; i++) {
379 Chan_iterate(&ch_itr);
380 } while (ch_itr != NULL && ch_itr->id != msg->payload.textMessage->channel_id[i]);
382 Log_warn("Channel id %d not found - ignoring.", msg->payload.textMessage->channel_id[i]);
385 list_iterate(itr, &ch_itr->clients) {
387 c = list_get_entry(itr, client_t, chan_node);
388 if (c != client && !c->deaf) {
390 Client_send_message(c, msg);
391 Log_debug("Text message to session ID %d", c->sessionId);
397 if (msg->payload.textMessage->n_session > 0) { /* To user */
400 for (i = 0; i < msg->payload.textMessage->n_session; i++) {
402 while (Client_iterate(&itr) != NULL) {
405 if (itr->sessionId == msg->payload.textMessage->session[i]) {
408 Client_send_message(itr, msg);
409 Log_debug("Text message to session ID %d", itr->sessionId);
415 Log_warn("TextMessage: Session ID %d not found", msg->payload.textMessage->session[i]);
422 int i, j, count, targetId = msg->payload.voiceTarget->id;
423 struct _MumbleProto__VoiceTarget__Target *target;
425 if (!targetId || targetId >= 0x1f)
427 Voicetarget_add_id(client, targetId);
428 count = msg->payload.voiceTarget->n_targets;
431 for (i = 0; i < count; i++) {
432 target = msg->payload.voiceTarget->targets[i];
433 for (j = 0; j < target->n_session; j++)
434 Voicetarget_add_session(client, targetId, target->session[j]);
435 if (target->has_channel_id) {
436 if (target->has_links || target->has_children)
437 Log_warn("Whisper to children or linked channels not implemented. Ignoring.");
438 Voicetarget_add_channel(client, targetId, target->channel_id);
444 Log_debug("Version message received");
445 if (msg->payload.version->has_version) {
446 client->version = msg->payload.version->version;
447 Log_debug("Client version 0x%x", client->version);
449 if (msg->payload.version->release) {
450 if (client->release) free(client->release);
451 client->release = strdup(msg->payload.version->release);
452 Log_debug("Client release %s", client->release);
454 if (msg->payload.version->os) {
455 if (client->os) free(client->os);
456 client->os = strdup(msg->payload.version->os);
457 Log_debug("Client OS %s", client->os);
460 case PermissionQuery:
461 Msg_inc_ref(msg); /* Re-use message */
462 msg->payload.permissionQuery->has_permissions = true;
463 msg->payload.permissionQuery->permissions = PERM_DEFAULT;
465 Client_send_message(client, msg);
468 Client_voiceMsg(client, msg->payload.UDPTunnel->packet.data, msg->payload.UDPTunnel->packet.len);
472 channel_t *ch_itr, *parent, *newchan;
474 /* Don't allow any changes to existing channels */
475 if (msg->payload.channelState->has_channel_id) {
476 sendPermissionDenied(client, "Not supported by uMurmur");
479 /* Must have parent */
480 if (!msg->payload.channelState->has_parent) {
481 sendPermissionDenied(client, "Not supported by uMurmur");
485 if (msg->payload.channelState->name == NULL) {
486 sendPermissionDenied(client, "Not supported by uMurmur");
489 /* Must be temporary channel */
490 if (msg->payload.channelState->temporary != true) {
491 sendPermissionDenied(client, "Only temporary channels are supported by uMurmur");
494 /* Check channel name is OK */
495 if (strlen(msg->payload.channelState->name) > MAX_TEXT) {
496 sendPermissionDenied(client, "Channel name too long");
500 parent = Chan_fromId(msg->payload.channelState->parent);
504 while (Chan_iterate_siblings(parent, &ch_itr) != NULL) {
505 if (strcmp(ch_itr->name, msg->payload.channelState->name) == 0) {
506 sendPermissionDenied(client, "Channel already exists");
513 /* Disallow temporary channels as siblings to temporary channels */
514 if (parent->temporary) {
515 sendPermissionDenied(client, "Parent channel is temporary channel");
519 /* XXX - Murmur looks for "\\w" and sends perm denied if not found.
520 * I don't know why so I don't do that here...
523 /* Create the channel */
524 newchan = Chan_createChannel(msg->payload.channelState->name,
525 msg->payload.channelState->description);
526 newchan->temporary = true;
527 Chan_addChannel(parent, newchan);
528 msg->payload.channelState->has_channel_id = true;
529 msg->payload.channelState->channel_id = newchan->id;
531 Client_send_message_except(NULL, msg);
533 /* Join the creating user */
534 sendmsg = Msg_create(UserState);
535 sendmsg->payload.userState->has_session = true;
536 sendmsg->payload.userState->session = client->sessionId;
537 sendmsg->payload.userState->has_channel_id = true;
538 sendmsg->payload.userState->channel_id = newchan->id;
539 Client_send_message_except(NULL, sendmsg);
541 leave_id = Chan_playerJoin(newchan, client);
543 Log_debug("Removing channel ID %d", leave_id);
544 sendmsg = Msg_create(ChannelRemove);
545 sendmsg->payload.channelRemove->channel_id = leave_id;
546 Client_send_message_except(NULL, sendmsg);
551 /* Permission denied for all these messages. Not implemented. */
554 case ContextActionAdd:
559 sendPermissionDenied(client, "Not supported by uMurmur");
563 Log_warn("Message %d not handled", msg->messageType);
572 Client_close(client);