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->name = strdup(client->username);
225 sendmsg->payload.userState->has_channel_id = true;
226 sendmsg->payload.userState->channel_id = ((channel_t *)client->channel)->id;
228 Client_send_message_except(client, sendmsg);
231 while (Client_iterate(&client_itr) != NULL) {
232 if (!IS_AUTH(client_itr))
234 sendmsg = Msg_create(UserState);
235 sendmsg->payload.userState->has_session = true;
236 sendmsg->payload.userState->session = client_itr->sessionId;
237 sendmsg->payload.userState->name = strdup(client_itr->username);
238 sendmsg->payload.userState->has_channel_id = true;
239 sendmsg->payload.userState->channel_id = ((channel_t *)client_itr->channel)->id;
241 /* Only self_mute/deaf supported */
242 if (client_itr->deaf) {
243 sendmsg->payload.userState->has_self_deaf = true;
244 sendmsg->payload.userState->self_deaf = true;
246 if (client_itr->mute) {
247 sendmsg->payload.userState->has_self_mute = true;
248 sendmsg->payload.userState->self_mute = true;
250 Client_send_message(client, sendmsg);
254 sendmsg = Msg_create(ServerSync);
255 sendmsg->payload.serverSync->has_session = true;
256 sendmsg->payload.serverSync->session = client->sessionId;
257 sendmsg->payload.serverSync->welcome_text = strdup(getStrConf(WELCOMETEXT));
258 sendmsg->payload.serverSync->has_max_bandwidth = true;
259 sendmsg->payload.serverSync->max_bandwidth = getIntConf(MAX_BANDWIDTH);
260 sendmsg->payload.serverSync->has_allow_html = true;
261 sendmsg->payload.serverSync->allow_html = true; /* Support this? */
262 Client_send_message(client, sendmsg);
264 Log_info_client(client, "User %s authenticated", client->username);
268 if (msg->payload.ping->has_good)
269 client->cryptState.uiRemoteGood = msg->payload.ping->good;
270 if (msg->payload.ping->has_late)
271 client->cryptState.uiRemoteLate = msg->payload.ping->late;
272 if (msg->payload.ping->has_lost)
273 client->cryptState.uiRemoteLost = msg->payload.ping->lost;
274 if (msg->payload.ping->has_resync)
275 client->cryptState.uiRemoteResync = msg->payload.ping->resync;
277 Log_debug("Ping <-: %d %d %d %d",
278 client->cryptState.uiRemoteGood, client->cryptState.uiRemoteLate,
279 client->cryptState.uiRemoteLost, client->cryptState.uiRemoteResync
282 /* Ignoring the double values since they don't seem to be used */
284 sendmsg = Msg_create(Ping);
286 sendmsg->payload.ping->timestamp = msg->payload.ping->timestamp;
287 sendmsg->payload.ping->has_timestamp = true;
288 sendmsg->payload.ping->good = client->cryptState.uiGood;
289 sendmsg->payload.ping->has_good = true;
290 sendmsg->payload.ping->late = client->cryptState.uiLate;
291 sendmsg->payload.ping->has_late = true;
292 sendmsg->payload.ping->lost = client->cryptState.uiLost;
293 sendmsg->payload.ping->has_lost = true;
294 sendmsg->payload.ping->resync = client->cryptState.uiResync;
295 sendmsg->payload.ping->has_resync = true;
297 Client_send_message(client, sendmsg);
298 Log_debug("Ping ->: %d %d %d %d",
299 client->cryptState.uiGood, client->cryptState.uiLate,
300 client->cryptState.uiLost, client->cryptState.uiResync);
304 Log_debug("Voice channel crypt resync requested");
305 if (!msg->payload.cryptSetup->has_client_nonce) {
306 sendmsg = Msg_create(CryptSetup);
307 sendmsg->payload.cryptSetup->has_server_nonce = true;
308 sendmsg->payload.cryptSetup->server_nonce.data = client->cryptState.decrypt_iv;
309 sendmsg->payload.cryptSetup->server_nonce.len = AES_BLOCK_SIZE;
310 Client_send_message(client, sendmsg);
312 memcpy(client->cryptState.decrypt_iv, msg->payload.cryptSetup->client_nonce.data, AES_BLOCK_SIZE);
313 client->cryptState.uiResync++;
317 /* Only allow state changes for for the self user */
318 if (msg->payload.userState->has_session &&
319 msg->payload.userState->session != client->sessionId) {
320 sendPermissionDenied(client, "Permission denied");
323 if (msg->payload.userState->has_user_id || msg->payload.userState->has_mute ||
324 msg->payload.userState->has_deaf || msg->payload.userState->has_suppress ||
325 msg->payload.userState->has_texture) {
327 sendPermissionDenied(client, "Not supported by uMurmur");
331 msg->payload.userState->has_session = true;
332 msg->payload.userState->session = client->sessionId;
333 msg->payload.userState->has_actor = true;
334 msg->payload.userState->actor = client->sessionId;
336 if (msg->payload.userState->has_self_deaf) {
337 client->deaf = msg->payload.userState->self_deaf;
339 if (msg->payload.userState->has_self_mute) {
340 client->mute = msg->payload.userState->self_mute;
342 msg->payload.userState->has_self_deaf = true;
343 msg->payload.userState->self_deaf = false;
344 client->deaf = false;
347 if (msg->payload.userState->has_channel_id) {
349 if (!Chan_userJoin_id_test(msg->payload.userState->channel_id))
351 leave_id = Chan_userJoin_id(msg->payload.userState->channel_id, client);
353 Log_debug("Removing channel ID %d", leave_id);
354 sendmsg = Msg_create(ChannelRemove);
355 sendmsg->payload.channelRemove->channel_id = leave_id;
358 if (msg->payload.userState->plugin_context != NULL) {
360 free(client->context);
361 client->context = strdup(msg->payload.userState->plugin_context);
362 if (client->context == NULL)
363 Log_fatal("Out of memory");
365 break; /* Don't inform other users about this state */
371 Client_send_message_except(NULL, msg);
373 /* Need to send remove channel message _after_ UserState message */
375 Client_send_message_except(NULL, sendmsg);
379 msg->payload.textMessage->has_actor = true;
380 msg->payload.textMessage->actor = client->sessionId;
382 /* XXX - HTML is allowed and can't be turned off */
383 if (msg->payload.textMessage->n_tree_id > 0) {
384 sendPermissionDenied(client, "Tree message not supported");
388 if (msg->payload.textMessage->n_channel_id > 0) { /* To channel */
391 for (i = 0; i < msg->payload.textMessage->n_channel_id; i++) {
394 Chan_iterate(&ch_itr);
395 } while (ch_itr != NULL && ch_itr->id != msg->payload.textMessage->channel_id[i]);
396 if (ch_itr != NULL) {
398 list_iterate(itr, &ch_itr->clients) {
400 c = list_get_entry(itr, client_t, chan_node);
401 if (c != client && !c->deaf) {
403 Client_send_message(c, msg);
404 Log_debug("Text message to session ID %d", c->sessionId);
410 if (msg->payload.textMessage->n_session > 0) { /* To user */
413 for (i = 0; i < msg->payload.textMessage->n_session; i++) {
415 while (Client_iterate(&itr) != NULL) {
418 if (itr->sessionId == msg->payload.textMessage->session[i]) {
421 Client_send_message(itr, msg);
422 Log_debug("Text message to session ID %d", itr->sessionId);
428 Log_warn("TextMessage: Session ID %d not found", msg->payload.textMessage->session[i]);
435 int i, j, count, targetId = msg->payload.voiceTarget->id;
436 struct _MumbleProto__VoiceTarget__Target *target;
438 if (!targetId || targetId >= 0x1f)
440 Voicetarget_add_id(client, targetId);
441 count = msg->payload.voiceTarget->n_targets;
444 for (i = 0; i < count; i++) {
445 target = msg->payload.voiceTarget->targets[i];
446 for (j = 0; j < target->n_session; j++)
447 Voicetarget_add_session(client, targetId, target->session[j]);
448 if (target->has_channel_id) {
449 bool_t linked = false, children = false;
450 if (target->has_links)
451 linked = target->links;
452 if (target->has_children)
453 children = target->children;
454 Voicetarget_add_channel(client, targetId, target->channel_id, linked, children);
460 Log_debug("Version message received");
461 if (msg->payload.version->has_version) {
462 client->version = msg->payload.version->version;
463 Log_debug("Client version 0x%x", client->version);
465 if (msg->payload.version->release) {
466 if (client->release) free(client->release);
467 client->release = strdup(msg->payload.version->release);
468 Log_debug("Client release %s", client->release);
470 if (msg->payload.version->os) {
471 if (client->os) free(client->os);
472 client->os = strdup(msg->payload.version->os);
473 Log_debug("Client OS %s", client->os);
476 case PermissionQuery:
477 Msg_inc_ref(msg); /* Re-use message */
478 msg->payload.permissionQuery->has_permissions = true;
479 msg->payload.permissionQuery->permissions = PERM_DEFAULT;
481 Client_send_message(client, msg);
484 client->bUDP = false;
485 Client_voiceMsg(client, msg->payload.UDPTunnel->packet.data, msg->payload.UDPTunnel->packet.len);
489 channel_t *ch_itr, *parent, *newchan;
491 /* Don't allow any changes to existing channels */
492 if (msg->payload.channelState->has_channel_id) {
493 sendPermissionDenied(client, "Not supported by uMurmur");
496 /* Must have parent */
497 if (!msg->payload.channelState->has_parent) {
498 sendPermissionDenied(client, "Not supported by uMurmur");
502 if (msg->payload.channelState->name == NULL) {
503 sendPermissionDenied(client, "Not supported by uMurmur");
506 /* Must be temporary channel */
507 if (msg->payload.channelState->temporary != true) {
508 sendPermissionDenied(client, "Only temporary channels are supported by uMurmur");
511 /* Check channel name is OK */
512 if (strlen(msg->payload.channelState->name) > MAX_TEXT) {
513 sendPermissionDenied(client, "Channel name too long");
517 parent = Chan_fromId(msg->payload.channelState->parent);
521 while (Chan_iterate_siblings(parent, &ch_itr) != NULL) {
522 if (strcmp(ch_itr->name, msg->payload.channelState->name) == 0) {
523 sendPermissionDenied(client, "Channel already exists");
530 /* Disallow temporary channels as siblings to temporary channels */
531 if (parent->temporary) {
532 sendPermissionDenied(client, "Parent channel is temporary channel");
536 /* XXX - Murmur looks for "\\w" and sends perm denied if not found.
537 * I don't know why so I don't do that here...
540 /* Create the channel */
541 newchan = Chan_createChannel(msg->payload.channelState->name,
542 msg->payload.channelState->description);
543 newchan->temporary = true;
544 Chan_addChannel(parent, newchan);
545 msg->payload.channelState->has_channel_id = true;
546 msg->payload.channelState->channel_id = newchan->id;
548 Client_send_message_except(NULL, msg);
550 /* Join the creating user */
551 sendmsg = Msg_create(UserState);
552 sendmsg->payload.userState->has_session = true;
553 sendmsg->payload.userState->session = client->sessionId;
554 sendmsg->payload.userState->has_channel_id = true;
555 sendmsg->payload.userState->channel_id = newchan->id;
556 Client_send_message_except(NULL, sendmsg);
558 leave_id = Chan_userJoin(newchan, client);
560 Log_debug("Removing channel ID %d", leave_id);
561 sendmsg = Msg_create(ChannelRemove);
562 sendmsg->payload.channelRemove->channel_id = leave_id;
563 Client_send_message_except(NULL, sendmsg);
568 /* Permission denied for all these messages. Not implemented. */
571 case ContextActionAdd:
576 sendPermissionDenied(client, "Not supported by uMurmur");
580 Log_warn("Message %d not handled", msg->messageType);
589 Client_close(client);