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) {
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 (client_itr->username && strncmp(client_itr->username, 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 (strlen(getStrConf(PASSPHRASE)) > 0) {
101 if (!msg->payload.authenticate->password || strncmp(getStrConf(PASSPHRASE), msg->payload.authenticate->password, MAX_TEXT) != 0) {
103 sprintf(buf, "Wrong server password");
104 sendServerReject(client, buf, MUMBLE_PROTO__REJECT__REJECT_TYPE__WrongServerPW);
105 Log_debug("Wrong server password: %s", msg->payload.authenticate->password);
109 if (strlen(msg->payload.authenticate->username) == 0 ||
110 strlen(msg->payload.authenticate->username) >= MAX_TEXT) { /* XXX - other invalid names? */
112 sprintf(buf, "Invalid username");
113 Log_debug("Invalid username");
114 sendServerReject(client, buf, MUMBLE_PROTO__REJECT__REJECT_TYPE__InvalidUsername);
118 if (Client_count() >= getIntConf(MAX_CLIENTS)) {
120 sprintf(buf, "Server is full (max %d users)", getIntConf(MAX_CLIENTS));
121 sendServerReject(client, buf, MUMBLE_PROTO__REJECT__REJECT_TYPE__ServerFull);
125 /* Name & password */
126 client->username = strdup(msg->payload.authenticate->username);
128 /* Setup UDP encryption */
129 CryptState_init(&client->cryptState);
130 CryptState_genKey(&client->cryptState);
131 sendmsg = Msg_create(CryptSetup);
132 sendmsg->payload.cryptSetup->has_key = true;
133 sendmsg->payload.cryptSetup->key.data = client->cryptState.raw_key;
134 sendmsg->payload.cryptSetup->key.len = AES_BLOCK_SIZE;
135 sendmsg->payload.cryptSetup->has_server_nonce = true;
136 sendmsg->payload.cryptSetup->server_nonce.data = client->cryptState.encrypt_iv;
137 sendmsg->payload.cryptSetup->server_nonce.len = AES_BLOCK_SIZE;
138 sendmsg->payload.cryptSetup->has_client_nonce = true;
139 sendmsg->payload.cryptSetup->client_nonce.data = client->cryptState.decrypt_iv;
140 sendmsg->payload.cryptSetup->client_nonce.len = AES_BLOCK_SIZE;
141 Client_send_message(client, sendmsg);
144 Chan_userJoin(defaultChan, client); /* Join default channel */
147 Log_debug("Client %d has %d CELT codecs", client->sessionId,
148 msg->payload.authenticate->n_celt_versions);
149 if (msg->payload.authenticate->n_celt_versions > 0) {
152 client->codec_count = msg->payload.authenticate->n_celt_versions;
154 for (i = 0; i < client->codec_count; i++)
155 Client_codec_add(client, msg->payload.authenticate->celt_versions[i]);
157 while (Client_codec_iterate(client, &codec_itr) != NULL)
158 Log_debug("Client %d CELT codec ver 0x%x", client->sessionId, codec_itr->codec);
161 Client_codec_add(client, (int32_t)0x8000000a);
162 client->codec_count = 1;
165 recheckCodecVersions();
167 sendmsg = Msg_create(CodecVersion);
168 sendmsg->payload.codecVersion->alpha = iCodecAlpha;
169 sendmsg->payload.codecVersion->beta = iCodecBeta;
170 sendmsg->payload.codecVersion->prefer_alpha = bPreferAlpha;
171 Client_send_message(client, sendmsg);
173 /* Iterate channels and send channel info */
175 while (Chan_iterate(&ch_itr) != NULL) {
176 sendmsg = Msg_create(ChannelState);
177 sendmsg->payload.channelState->has_channel_id = true;
178 sendmsg->payload.channelState->channel_id = ch_itr->id;
179 if (ch_itr->id != 0) {
180 sendmsg->payload.channelState->has_parent = true;
181 sendmsg->payload.channelState->parent = ch_itr->parent->id;
183 sendmsg->payload.channelState->name = strdup(ch_itr->name);
185 sendmsg->payload.channelState->description = strdup(ch_itr->desc);
186 Log_debug("Send channel info: %s", sendmsg->payload.channelState->name);
187 Client_send_message(client, sendmsg);
190 /* Iterate channels and send channel links info */
192 while (Chan_iterate(&ch_itr) != NULL) {
193 if (ch_itr->linkcount > 0) { /* Has links */
198 sendmsg = Msg_create(ChannelState);
199 sendmsg->payload.channelState->has_channel_id = true;
200 sendmsg->payload.channelState->channel_id = ch_itr->id;
201 sendmsg->payload.channelState->n_links = ch_itr->linkcount;
203 links = (uint32_t *)malloc(ch_itr->linkcount * sizeof(uint32_t));
204 list_iterate(itr, &ch_itr->channel_links) { /* Iterate links */
206 ch = list_get_entry(itr, channel_t, link_node);
209 sendmsg->payload.channelState->links = links;
210 Client_send_message(client, sendmsg);
214 /* Send user state for connecting user to other users */
215 sendmsg = Msg_create(UserState);
216 sendmsg->payload.userState->has_session = true;
217 sendmsg->payload.userState->session = client->sessionId;
218 sendmsg->payload.userState->has_user_id = true;
219 sendmsg->payload.userState->user_id = client->sessionId;
220 sendmsg->payload.userState->name = strdup(client->username);
221 sendmsg->payload.userState->has_channel_id = true;
222 sendmsg->payload.userState->channel_id = ((channel_t *)client->channel)->id;
224 Client_send_message_except(client, sendmsg);
227 while (Client_iterate(&client_itr) != NULL) {
228 if (!IS_AUTH(client_itr))
230 sendmsg = Msg_create(UserState);
231 sendmsg->payload.userState->has_session = true;
232 sendmsg->payload.userState->session = client_itr->sessionId;
233 sendmsg->payload.userState->name = strdup(client_itr->username);
234 sendmsg->payload.userState->has_channel_id = true;
235 sendmsg->payload.userState->channel_id = ((channel_t *)client_itr->channel)->id;
237 /* Only self_mute/deaf supported */
238 if (client_itr->deaf) {
239 sendmsg->payload.userState->has_self_deaf = true;
240 sendmsg->payload.userState->self_deaf = true;
242 if (client_itr->mute) {
243 sendmsg->payload.userState->has_self_mute = true;
244 sendmsg->payload.userState->self_mute = true;
246 Client_send_message(client, sendmsg);
250 sendmsg = Msg_create(ServerSync);
251 sendmsg->payload.serverSync->has_session = true;
252 sendmsg->payload.serverSync->session = client->sessionId;
253 sendmsg->payload.serverSync->welcome_text = strdup(getStrConf(WELCOMETEXT));
254 sendmsg->payload.serverSync->has_max_bandwidth = true;
255 sendmsg->payload.serverSync->max_bandwidth = getIntConf(MAX_BANDWIDTH);
256 sendmsg->payload.serverSync->has_allow_html = true;
257 sendmsg->payload.serverSync->allow_html = true; /* Support this? */
258 Client_send_message(client, sendmsg);
260 Log_info_client(client, "User %s authenticated", client->username);
264 if (msg->payload.ping->has_good)
265 client->cryptState.uiRemoteGood = msg->payload.ping->good;
266 if (msg->payload.ping->has_late)
267 client->cryptState.uiRemoteLate = msg->payload.ping->late;
268 if (msg->payload.ping->has_lost)
269 client->cryptState.uiRemoteLost = msg->payload.ping->lost;
270 if (msg->payload.ping->has_resync)
271 client->cryptState.uiRemoteResync = msg->payload.ping->resync;
273 Log_debug("Ping <-: %d %d %d %d",
274 client->cryptState.uiRemoteGood, client->cryptState.uiRemoteLate,
275 client->cryptState.uiRemoteLost, client->cryptState.uiRemoteResync
278 /* Ignoring the double values since they don't seem to be used */
280 sendmsg = Msg_create(Ping);
282 sendmsg->payload.ping->timestamp = msg->payload.ping->timestamp;
283 sendmsg->payload.ping->has_timestamp = true;
284 sendmsg->payload.ping->good = client->cryptState.uiGood;
285 sendmsg->payload.ping->has_good = true;
286 sendmsg->payload.ping->late = client->cryptState.uiLate;
287 sendmsg->payload.ping->has_late = true;
288 sendmsg->payload.ping->lost = client->cryptState.uiLost;
289 sendmsg->payload.ping->has_lost = true;
290 sendmsg->payload.ping->resync = client->cryptState.uiResync;
291 sendmsg->payload.ping->has_resync = true;
293 Client_send_message(client, sendmsg);
294 Log_debug("Ping ->: %d %d %d %d",
295 client->cryptState.uiGood, client->cryptState.uiLate,
296 client->cryptState.uiLost, client->cryptState.uiResync);
300 Log_debug("Voice channel crypt resync requested");
301 if (!msg->payload.cryptSetup->has_client_nonce) {
302 sendmsg = Msg_create(CryptSetup);
303 sendmsg->payload.cryptSetup->has_server_nonce = true;
304 sendmsg->payload.cryptSetup->server_nonce.data = client->cryptState.decrypt_iv;
305 sendmsg->payload.cryptSetup->server_nonce.len = AES_BLOCK_SIZE;
306 Client_send_message(client, sendmsg);
308 memcpy(client->cryptState.decrypt_iv, msg->payload.cryptSetup->client_nonce.data, AES_BLOCK_SIZE);
309 client->cryptState.uiResync++;
313 /* Only allow state changes for for the self user */
314 if (msg->payload.userState->has_session &&
315 msg->payload.userState->session != client->sessionId) {
316 sendPermissionDenied(client, "Permission denied");
319 if (msg->payload.userState->has_user_id || msg->payload.userState->has_mute ||
320 msg->payload.userState->has_deaf || msg->payload.userState->has_suppress ||
321 msg->payload.userState->has_texture) {
323 sendPermissionDenied(client, "Not supported by uMurmur");
326 if (msg->payload.userState->has_self_deaf) {
327 client->deaf = msg->payload.userState->self_deaf;
329 if (msg->payload.userState->has_self_mute) {
330 client->mute = msg->payload.userState->self_mute;
332 if (msg->payload.userState->has_channel_id) {
334 if (!Chan_userJoin_id_test(msg->payload.userState->channel_id))
336 leave_id = Chan_userJoin_id(msg->payload.userState->channel_id, client);
338 Log_debug("Removing channel ID %d", leave_id);
339 sendmsg = Msg_create(ChannelRemove);
340 sendmsg->payload.channelRemove->channel_id = leave_id;
343 if (msg->payload.userState->plugin_context != NULL) {
345 free(client->context);
346 client->context = strdup(msg->payload.userState->plugin_context);
347 if (client->context == NULL)
348 Log_fatal("Out of memory");
350 break; /* Don't inform other users about this state */
355 msg->payload.userState->has_actor = true;
356 msg->payload.userState->actor = client->sessionId;
357 Client_send_message_except(NULL, msg);
359 /* Need to send remove channel message _after_ UserState message */
361 Client_send_message_except(NULL, sendmsg);
365 msg->payload.textMessage->has_actor = true;
366 msg->payload.textMessage->actor = client->sessionId;
368 /* XXX - HTML is allowed and can't be turned off */
369 if (msg->payload.textMessage->n_tree_id > 0) {
370 sendPermissionDenied(client, "Tree message not supported");
374 if (msg->payload.textMessage->n_channel_id > 0) { /* To channel */
377 for (i = 0; i < msg->payload.textMessage->n_channel_id; i++) {
380 Chan_iterate(&ch_itr);
381 } while (ch_itr != NULL && ch_itr->id != msg->payload.textMessage->channel_id[i]);
382 if (ch_itr != NULL) {
384 list_iterate(itr, &ch_itr->clients) {
386 c = list_get_entry(itr, client_t, chan_node);
387 if (c != client && !c->deaf) {
389 Client_send_message(c, msg);
390 Log_debug("Text message to session ID %d", c->sessionId);
396 if (msg->payload.textMessage->n_session > 0) { /* To user */
399 for (i = 0; i < msg->payload.textMessage->n_session; i++) {
401 while (Client_iterate(&itr) != NULL) {
404 if (itr->sessionId == msg->payload.textMessage->session[i]) {
407 Client_send_message(itr, msg);
408 Log_debug("Text message to session ID %d", itr->sessionId);
414 Log_warn("TextMessage: Session ID %d not found", msg->payload.textMessage->session[i]);
421 int i, j, count, targetId = msg->payload.voiceTarget->id;
422 struct _MumbleProto__VoiceTarget__Target *target;
424 if (!targetId || targetId >= 0x1f)
426 Voicetarget_add_id(client, targetId);
427 count = msg->payload.voiceTarget->n_targets;
430 for (i = 0; i < count; i++) {
431 target = msg->payload.voiceTarget->targets[i];
432 for (j = 0; j < target->n_session; j++)
433 Voicetarget_add_session(client, targetId, target->session[j]);
434 if (target->has_channel_id) {
435 bool_t linked = false, children = false;
436 if (target->has_links)
437 linked = target->links;
438 if (target->has_children)
439 children = target->children;
440 Voicetarget_add_channel(client, targetId, target->channel_id, linked, children);
446 Log_debug("Version message received");
447 if (msg->payload.version->has_version) {
448 client->version = msg->payload.version->version;
449 Log_debug("Client version 0x%x", client->version);
451 if (msg->payload.version->release) {
452 if (client->release) free(client->release);
453 client->release = strdup(msg->payload.version->release);
454 Log_debug("Client release %s", client->release);
456 if (msg->payload.version->os) {
457 if (client->os) free(client->os);
458 client->os = strdup(msg->payload.version->os);
459 Log_debug("Client OS %s", client->os);
462 case PermissionQuery:
463 Msg_inc_ref(msg); /* Re-use message */
464 msg->payload.permissionQuery->has_permissions = true;
465 msg->payload.permissionQuery->permissions = PERM_DEFAULT;
467 Client_send_message(client, msg);
470 client->bUDP = false;
471 Client_voiceMsg(client, msg->payload.UDPTunnel->packet.data, msg->payload.UDPTunnel->packet.len);
475 channel_t *ch_itr, *parent, *newchan;
477 /* Don't allow any changes to existing channels */
478 if (msg->payload.channelState->has_channel_id) {
479 sendPermissionDenied(client, "Not supported by uMurmur");
482 /* Must have parent */
483 if (!msg->payload.channelState->has_parent) {
484 sendPermissionDenied(client, "Not supported by uMurmur");
488 if (msg->payload.channelState->name == NULL) {
489 sendPermissionDenied(client, "Not supported by uMurmur");
492 /* Must be temporary channel */
493 if (msg->payload.channelState->temporary != true) {
494 sendPermissionDenied(client, "Only temporary channels are supported by uMurmur");
497 /* Check channel name is OK */
498 if (strlen(msg->payload.channelState->name) > MAX_TEXT) {
499 sendPermissionDenied(client, "Channel name too long");
503 parent = Chan_fromId(msg->payload.channelState->parent);
507 while (Chan_iterate_siblings(parent, &ch_itr) != NULL) {
508 if (strcmp(ch_itr->name, msg->payload.channelState->name) == 0) {
509 sendPermissionDenied(client, "Channel already exists");
516 /* Disallow temporary channels as siblings to temporary channels */
517 if (parent->temporary) {
518 sendPermissionDenied(client, "Parent channel is temporary channel");
522 /* XXX - Murmur looks for "\\w" and sends perm denied if not found.
523 * I don't know why so I don't do that here...
526 /* Create the channel */
527 newchan = Chan_createChannel(msg->payload.channelState->name,
528 msg->payload.channelState->description);
529 newchan->temporary = true;
530 Chan_addChannel(parent, newchan);
531 msg->payload.channelState->has_channel_id = true;
532 msg->payload.channelState->channel_id = newchan->id;
534 Client_send_message_except(NULL, msg);
536 /* Join the creating user */
537 sendmsg = Msg_create(UserState);
538 sendmsg->payload.userState->has_session = true;
539 sendmsg->payload.userState->session = client->sessionId;
540 sendmsg->payload.userState->has_channel_id = true;
541 sendmsg->payload.userState->channel_id = newchan->id;
542 Client_send_message_except(NULL, sendmsg);
544 leave_id = Chan_userJoin(newchan, client);
546 Log_debug("Removing channel ID %d", leave_id);
547 sendmsg = Msg_create(ChannelRemove);
548 sendmsg->payload.channelRemove->channel_id = leave_id;
549 Client_send_message_except(NULL, sendmsg);
554 /* Permission denied for all these messages. Not implemented. */
557 case ContextActionAdd:
562 sendPermissionDenied(client, "Not supported by uMurmur");
566 Log_warn("Message %d not handled", msg->messageType);
575 Client_close(client);