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.
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) {
82 Log_debug("Authenticate message received");
84 if (IS_AUTH(client) || !msg->payload.authenticate->username) {
85 /* Authenticate message might be sent when a token is set by the user.*/
86 if (msg->payload.authenticate->n_tokens > 0) {
87 Log_debug("Tokens in auth message from %s", client->username);
92 client->authenticated = true;
95 while (Client_iterate(&client_itr) != NULL) {
96 if (!IS_AUTH(client_itr))
98 if (client_itr->username && strncmp(client_itr->username, msg->payload.authenticate->username, MAX_TEXT) == 0) {
100 sprintf(buf, "Username already in use");
101 Log_debug("Username already in use");
102 sendServerReject(client, buf, MUMBLE_PROTO__REJECT__REJECT_TYPE__UsernameInUse);
106 if (strlen(getStrConf(PASSPHRASE)) > 0) {
107 if (!msg->payload.authenticate->password || strncmp(getStrConf(PASSPHRASE), msg->payload.authenticate->password, MAX_TEXT) != 0) {
109 sprintf(buf, "Wrong server password");
110 sendServerReject(client, buf, MUMBLE_PROTO__REJECT__REJECT_TYPE__WrongServerPW);
111 Log_debug("Wrong server password: %s", msg->payload.authenticate->password);
115 if (strlen(msg->payload.authenticate->username) == 0 ||
116 strlen(msg->payload.authenticate->username) >= MAX_TEXT) { /* XXX - other invalid names? */
118 sprintf(buf, "Invalid username");
119 Log_debug("Invalid username");
120 sendServerReject(client, buf, MUMBLE_PROTO__REJECT__REJECT_TYPE__InvalidUsername);
124 if (Client_count() >= getIntConf(MAX_CLIENTS)) {
126 sprintf(buf, "Server is full (max %d users)", getIntConf(MAX_CLIENTS));
127 sendServerReject(client, buf, MUMBLE_PROTO__REJECT__REJECT_TYPE__ServerFull);
131 /* Name & password */
132 client->username = strdup(msg->payload.authenticate->username);
134 /* Setup UDP encryption */
135 CryptState_init(&client->cryptState);
136 CryptState_genKey(&client->cryptState);
137 sendmsg = Msg_create(CryptSetup);
138 sendmsg->payload.cryptSetup->has_key = true;
139 sendmsg->payload.cryptSetup->key.data = client->cryptState.raw_key;
140 sendmsg->payload.cryptSetup->key.len = AES_BLOCK_SIZE;
141 sendmsg->payload.cryptSetup->has_server_nonce = true;
142 sendmsg->payload.cryptSetup->server_nonce.data = client->cryptState.encrypt_iv;
143 sendmsg->payload.cryptSetup->server_nonce.len = AES_BLOCK_SIZE;
144 sendmsg->payload.cryptSetup->has_client_nonce = true;
145 sendmsg->payload.cryptSetup->client_nonce.data = client->cryptState.decrypt_iv;
146 sendmsg->payload.cryptSetup->client_nonce.len = AES_BLOCK_SIZE;
147 Client_send_message(client, sendmsg);
150 Chan_userJoin(defaultChan, client); /* Join default channel */
153 Log_debug("Client %d has %d CELT codecs", client->sessionId,
154 msg->payload.authenticate->n_celt_versions);
155 if (msg->payload.authenticate->n_celt_versions > 0) {
158 client->codec_count = msg->payload.authenticate->n_celt_versions;
160 for (i = 0; i < client->codec_count; i++)
161 Client_codec_add(client, msg->payload.authenticate->celt_versions[i]);
163 while (Client_codec_iterate(client, &codec_itr) != NULL)
164 Log_debug("Client %d CELT codec ver 0x%x", client->sessionId, codec_itr->codec);
167 Client_codec_add(client, (int32_t)0x8000000a);
168 client->codec_count = 1;
171 recheckCodecVersions();
173 sendmsg = Msg_create(CodecVersion);
174 sendmsg->payload.codecVersion->alpha = iCodecAlpha;
175 sendmsg->payload.codecVersion->beta = iCodecBeta;
176 sendmsg->payload.codecVersion->prefer_alpha = bPreferAlpha;
177 Client_send_message(client, sendmsg);
179 /* Iterate channels and send channel info */
181 while (Chan_iterate(&ch_itr) != NULL) {
182 sendmsg = Msg_create(ChannelState);
183 sendmsg->payload.channelState->has_channel_id = true;
184 sendmsg->payload.channelState->channel_id = ch_itr->id;
185 if (ch_itr->id != 0) {
186 sendmsg->payload.channelState->has_parent = true;
187 sendmsg->payload.channelState->parent = ch_itr->parent->id;
189 sendmsg->payload.channelState->name = strdup(ch_itr->name);
191 sendmsg->payload.channelState->description = strdup(ch_itr->desc);
192 Log_debug("Send channel info: %s", sendmsg->payload.channelState->name);
193 Client_send_message(client, sendmsg);
196 /* Iterate channels and send channel links info */
198 while (Chan_iterate(&ch_itr) != NULL) {
199 if (ch_itr->linkcount > 0) { /* Has links */
204 sendmsg = Msg_create(ChannelState);
205 sendmsg->payload.channelState->has_channel_id = true;
206 sendmsg->payload.channelState->channel_id = ch_itr->id;
207 sendmsg->payload.channelState->n_links = ch_itr->linkcount;
209 links = (uint32_t *)malloc(ch_itr->linkcount * sizeof(uint32_t));
210 list_iterate(itr, &ch_itr->channel_links) { /* Iterate links */
212 ch = list_get_entry(itr, channel_t, link_node);
215 sendmsg->payload.channelState->links = links;
216 Client_send_message(client, sendmsg);
220 /* Send user state for connecting user to other users */
221 sendmsg = Msg_create(UserState);
222 sendmsg->payload.userState->has_session = true;
223 sendmsg->payload.userState->session = client->sessionId;
224 sendmsg->payload.userState->has_user_id = true;
225 sendmsg->payload.userState->user_id = client->sessionId;
226 sendmsg->payload.userState->name = strdup(client->username);
227 sendmsg->payload.userState->has_channel_id = true;
228 sendmsg->payload.userState->channel_id = ((channel_t *)client->channel)->id;
230 Client_send_message_except(client, sendmsg);
233 while (Client_iterate(&client_itr) != NULL) {
234 if (!IS_AUTH(client_itr))
236 sendmsg = Msg_create(UserState);
237 sendmsg->payload.userState->has_session = true;
238 sendmsg->payload.userState->session = client_itr->sessionId;
239 sendmsg->payload.userState->name = strdup(client_itr->username);
240 sendmsg->payload.userState->has_channel_id = true;
241 sendmsg->payload.userState->channel_id = ((channel_t *)client_itr->channel)->id;
243 /* Only self_mute/deaf supported */
244 if (client_itr->deaf) {
245 sendmsg->payload.userState->has_self_deaf = true;
246 sendmsg->payload.userState->self_deaf = true;
248 if (client_itr->mute) {
249 sendmsg->payload.userState->has_self_mute = true;
250 sendmsg->payload.userState->self_mute = true;
252 Client_send_message(client, sendmsg);
256 sendmsg = Msg_create(ServerSync);
257 sendmsg->payload.serverSync->has_session = true;
258 sendmsg->payload.serverSync->session = client->sessionId;
259 sendmsg->payload.serverSync->welcome_text = strdup(getStrConf(WELCOMETEXT));
260 sendmsg->payload.serverSync->has_max_bandwidth = true;
261 sendmsg->payload.serverSync->max_bandwidth = getIntConf(MAX_BANDWIDTH);
262 sendmsg->payload.serverSync->has_allow_html = true;
263 sendmsg->payload.serverSync->allow_html = true; /* Support this? */
264 Client_send_message(client, sendmsg);
266 Log_info_client(client, "User %s authenticated", client->username);
270 if (msg->payload.ping->has_good)
271 client->cryptState.uiRemoteGood = msg->payload.ping->good;
272 if (msg->payload.ping->has_late)
273 client->cryptState.uiRemoteLate = msg->payload.ping->late;
274 if (msg->payload.ping->has_lost)
275 client->cryptState.uiRemoteLost = msg->payload.ping->lost;
276 if (msg->payload.ping->has_resync)
277 client->cryptState.uiRemoteResync = msg->payload.ping->resync;
279 Log_debug("Ping <-: %d %d %d %d",
280 client->cryptState.uiRemoteGood, client->cryptState.uiRemoteLate,
281 client->cryptState.uiRemoteLost, client->cryptState.uiRemoteResync
284 /* Ignoring the double values since they don't seem to be used */
286 sendmsg = Msg_create(Ping);
288 sendmsg->payload.ping->timestamp = msg->payload.ping->timestamp;
289 sendmsg->payload.ping->has_timestamp = true;
290 sendmsg->payload.ping->good = client->cryptState.uiGood;
291 sendmsg->payload.ping->has_good = true;
292 sendmsg->payload.ping->late = client->cryptState.uiLate;
293 sendmsg->payload.ping->has_late = true;
294 sendmsg->payload.ping->lost = client->cryptState.uiLost;
295 sendmsg->payload.ping->has_lost = true;
296 sendmsg->payload.ping->resync = client->cryptState.uiResync;
297 sendmsg->payload.ping->has_resync = true;
299 Client_send_message(client, sendmsg);
300 Log_debug("Ping ->: %d %d %d %d",
301 client->cryptState.uiGood, client->cryptState.uiLate,
302 client->cryptState.uiLost, client->cryptState.uiResync);
306 Log_debug("Voice channel crypt resync requested");
307 if (!msg->payload.cryptSetup->has_client_nonce) {
308 sendmsg = Msg_create(CryptSetup);
309 sendmsg->payload.cryptSetup->has_server_nonce = true;
310 sendmsg->payload.cryptSetup->server_nonce.data = client->cryptState.decrypt_iv;
311 sendmsg->payload.cryptSetup->server_nonce.len = AES_BLOCK_SIZE;
312 Client_send_message(client, sendmsg);
314 memcpy(client->cryptState.decrypt_iv, msg->payload.cryptSetup->client_nonce.data, AES_BLOCK_SIZE);
315 client->cryptState.uiResync++;
319 /* Only allow state changes for for the self user */
320 if (msg->payload.userState->has_session &&
321 msg->payload.userState->session != client->sessionId) {
322 sendPermissionDenied(client, "Permission denied");
325 if (msg->payload.userState->has_user_id || msg->payload.userState->has_mute ||
326 msg->payload.userState->has_deaf || msg->payload.userState->has_suppress ||
327 msg->payload.userState->has_texture) {
329 sendPermissionDenied(client, "Not supported by uMurmur");
332 if (msg->payload.userState->has_self_deaf) {
333 client->deaf = msg->payload.userState->self_deaf;
335 if (msg->payload.userState->has_self_mute) {
336 client->mute = msg->payload.userState->self_mute;
338 if (msg->payload.userState->has_channel_id) {
340 if (!Chan_userJoin_id_test(msg->payload.userState->channel_id))
342 leave_id = Chan_userJoin_id(msg->payload.userState->channel_id, client);
344 Log_debug("Removing channel ID %d", leave_id);
345 sendmsg = Msg_create(ChannelRemove);
346 sendmsg->payload.channelRemove->channel_id = leave_id;
349 if (msg->payload.userState->plugin_context != NULL) {
351 free(client->context);
352 client->context = strdup(msg->payload.userState->plugin_context);
353 if (client->context == NULL)
354 Log_fatal("Out of memory");
356 break; /* Don't inform other users about this state */
361 msg->payload.userState->has_actor = true;
362 msg->payload.userState->actor = client->sessionId;
363 Client_send_message_except(NULL, msg);
365 /* Need to send remove channel message _after_ UserState message */
367 Client_send_message_except(NULL, sendmsg);
371 msg->payload.textMessage->has_actor = true;
372 msg->payload.textMessage->actor = client->sessionId;
374 /* XXX - HTML is allowed and can't be turned off */
375 if (msg->payload.textMessage->n_tree_id > 0) {
376 sendPermissionDenied(client, "Tree message not supported");
380 if (msg->payload.textMessage->n_channel_id > 0) { /* To channel */
383 for (i = 0; i < msg->payload.textMessage->n_channel_id; i++) {
386 Chan_iterate(&ch_itr);
387 } while (ch_itr != NULL && ch_itr->id != msg->payload.textMessage->channel_id[i]);
388 if (ch_itr != NULL) {
390 list_iterate(itr, &ch_itr->clients) {
392 c = list_get_entry(itr, client_t, chan_node);
393 if (c != client && !c->deaf) {
395 Client_send_message(c, msg);
396 Log_debug("Text message to session ID %d", c->sessionId);
402 if (msg->payload.textMessage->n_session > 0) { /* To user */
405 for (i = 0; i < msg->payload.textMessage->n_session; i++) {
407 while (Client_iterate(&itr) != NULL) {
410 if (itr->sessionId == msg->payload.textMessage->session[i]) {
413 Client_send_message(itr, msg);
414 Log_debug("Text message to session ID %d", itr->sessionId);
420 Log_warn("TextMessage: Session ID %d not found", msg->payload.textMessage->session[i]);
427 int i, j, count, targetId = msg->payload.voiceTarget->id;
428 struct _MumbleProto__VoiceTarget__Target *target;
430 if (!targetId || targetId >= 0x1f)
432 Voicetarget_add_id(client, targetId);
433 count = msg->payload.voiceTarget->n_targets;
436 for (i = 0; i < count; i++) {
437 target = msg->payload.voiceTarget->targets[i];
438 for (j = 0; j < target->n_session; j++)
439 Voicetarget_add_session(client, targetId, target->session[j]);
440 if (target->has_channel_id) {
441 bool_t linked = false, children = false;
442 if (target->has_links)
443 linked = target->links;
444 if (target->has_children)
445 children = target->children;
446 Voicetarget_add_channel(client, targetId, target->channel_id, linked, children);
452 Log_debug("Version message received");
453 if (msg->payload.version->has_version) {
454 client->version = msg->payload.version->version;
455 Log_debug("Client version 0x%x", client->version);
457 if (msg->payload.version->release) {
458 if (client->release) free(client->release);
459 client->release = strdup(msg->payload.version->release);
460 Log_debug("Client release %s", client->release);
462 if (msg->payload.version->os) {
463 if (client->os) free(client->os);
464 client->os = strdup(msg->payload.version->os);
465 Log_debug("Client OS %s", client->os);
468 case PermissionQuery:
469 Msg_inc_ref(msg); /* Re-use message */
470 msg->payload.permissionQuery->has_permissions = true;
471 msg->payload.permissionQuery->permissions = PERM_DEFAULT;
473 Client_send_message(client, msg);
476 client->bUDP = false;
477 Client_voiceMsg(client, msg->payload.UDPTunnel->packet.data, msg->payload.UDPTunnel->packet.len);
481 channel_t *ch_itr, *parent, *newchan;
483 /* Don't allow any changes to existing channels */
484 if (msg->payload.channelState->has_channel_id) {
485 sendPermissionDenied(client, "Not supported by uMurmur");
488 /* Must have parent */
489 if (!msg->payload.channelState->has_parent) {
490 sendPermissionDenied(client, "Not supported by uMurmur");
494 if (msg->payload.channelState->name == NULL) {
495 sendPermissionDenied(client, "Not supported by uMurmur");
498 /* Must be temporary channel */
499 if (msg->payload.channelState->temporary != true) {
500 sendPermissionDenied(client, "Only temporary channels are supported by uMurmur");
503 /* Check channel name is OK */
504 if (strlen(msg->payload.channelState->name) > MAX_TEXT) {
505 sendPermissionDenied(client, "Channel name too long");
509 parent = Chan_fromId(msg->payload.channelState->parent);
513 while (Chan_iterate_siblings(parent, &ch_itr) != NULL) {
514 if (strcmp(ch_itr->name, msg->payload.channelState->name) == 0) {
515 sendPermissionDenied(client, "Channel already exists");
522 /* Disallow temporary channels as siblings to temporary channels */
523 if (parent->temporary) {
524 sendPermissionDenied(client, "Parent channel is temporary channel");
528 /* XXX - Murmur looks for "\\w" and sends perm denied if not found.
529 * I don't know why so I don't do that here...
532 /* Create the channel */
533 newchan = Chan_createChannel(msg->payload.channelState->name,
534 msg->payload.channelState->description);
535 newchan->temporary = true;
536 Chan_addChannel(parent, newchan);
537 msg->payload.channelState->has_channel_id = true;
538 msg->payload.channelState->channel_id = newchan->id;
540 Client_send_message_except(NULL, msg);
542 /* Join the creating user */
543 sendmsg = Msg_create(UserState);
544 sendmsg->payload.userState->has_session = true;
545 sendmsg->payload.userState->session = client->sessionId;
546 sendmsg->payload.userState->has_channel_id = true;
547 sendmsg->payload.userState->channel_id = newchan->id;
548 Client_send_message_except(NULL, sendmsg);
550 leave_id = Chan_userJoin(newchan, client);
552 Log_debug("Removing channel ID %d", leave_id);
553 sendmsg = Msg_create(ChannelRemove);
554 sendmsg->payload.channelRemove->channel_id = leave_id;
555 Client_send_message_except(NULL, sendmsg);
560 /* Permission denied for all these messages. Not implemented. */
563 case ContextActionAdd:
568 sendPermissionDenied(client, "Not supported by uMurmur");
572 Log_warn("Message %d not handled", msg->messageType);
581 Client_close(client);