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 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 Chan_iterate(&ch_itr);
177 sendmsg = Msg_create(ChannelState);
178 sendmsg->payload.channelState->has_channel_id = true;
179 sendmsg->payload.channelState->channel_id = ch_itr->id;
180 if (ch_itr->id != 0) {
181 sendmsg->payload.channelState->has_parent = true;
182 sendmsg->payload.channelState->parent = ch_itr->parent->id;
184 sendmsg->payload.channelState->name = strdup(ch_itr->name);
186 sendmsg->payload.channelState->description = strdup(ch_itr->desc);
187 Log_debug("Send channel info: %s", sendmsg->payload.channelState->name);
188 Client_send_message(client, sendmsg);
190 Chan_iterate(&ch_itr);
191 } while (ch_itr != NULL);
193 /* Not supporting channel links yet */
195 /* Send user state for connecting user to other users */
196 sendmsg = Msg_create(UserState);
197 sendmsg->payload.userState->has_session = true;
198 sendmsg->payload.userState->session = client->sessionId;
199 sendmsg->payload.userState->has_user_id = true;
200 sendmsg->payload.userState->user_id = client->sessionId;
201 sendmsg->payload.userState->name = strdup(client->username);
202 sendmsg->payload.userState->has_channel_id = true;
203 sendmsg->payload.userState->channel_id = ((channel_t *)client->channel)->id;
205 Client_send_message_except(client, sendmsg);
208 while (Client_iterate(&client_itr) != NULL) {
209 if (!IS_AUTH(client_itr))
211 sendmsg = Msg_create(UserState);
212 sendmsg->payload.userState->has_session = true;
213 sendmsg->payload.userState->session = client_itr->sessionId;
214 sendmsg->payload.userState->name = strdup(client_itr->username);
215 sendmsg->payload.userState->has_channel_id = true;
216 sendmsg->payload.userState->channel_id = ((channel_t *)client_itr->channel)->id;
218 /* Only self_mute/deaf supported */
219 if (client_itr->deaf) {
220 sendmsg->payload.userState->has_self_deaf = true;
221 sendmsg->payload.userState->self_deaf = true;
223 if (client_itr->mute) {
224 sendmsg->payload.userState->has_self_mute = true;
225 sendmsg->payload.userState->self_mute = true;
227 Client_send_message(client, sendmsg);
231 sendmsg = Msg_create(ServerSync);
232 sendmsg->payload.serverSync->has_session = true;
233 sendmsg->payload.serverSync->session = client->sessionId;
234 sendmsg->payload.serverSync->welcome_text = strdup(getStrConf(WELCOMETEXT));
235 sendmsg->payload.serverSync->has_max_bandwidth = true;
236 sendmsg->payload.serverSync->max_bandwidth = getIntConf(MAX_BANDWIDTH);
237 sendmsg->payload.serverSync->has_allow_html = true;
238 sendmsg->payload.serverSync->allow_html = true; /* Support this? */
239 Client_send_message(client, sendmsg);
241 Log_info_client(client, "User %s authenticated", client->username);
245 if (msg->payload.ping->has_good)
246 client->cryptState.uiRemoteGood = msg->payload.ping->good;
247 if (msg->payload.ping->has_late)
248 client->cryptState.uiRemoteLate = msg->payload.ping->late;
249 if (msg->payload.ping->has_lost)
250 client->cryptState.uiRemoteLost = msg->payload.ping->lost;
251 if (msg->payload.ping->has_resync)
252 client->cryptState.uiRemoteResync = msg->payload.ping->resync;
254 Log_debug("Ping <-: %d %d %d %d",
255 client->cryptState.uiRemoteGood, client->cryptState.uiRemoteLate,
256 client->cryptState.uiRemoteLost, client->cryptState.uiRemoteResync
259 /* Ignoring the double values since they don't seem to be used */
261 sendmsg = Msg_create(Ping);
263 sendmsg->payload.ping->timestamp = msg->payload.ping->timestamp;
264 sendmsg->payload.ping->has_timestamp = true;
265 sendmsg->payload.ping->good = client->cryptState.uiGood;
266 sendmsg->payload.ping->has_good = true;
267 sendmsg->payload.ping->late = client->cryptState.uiLate;
268 sendmsg->payload.ping->has_late = true;
269 sendmsg->payload.ping->lost = client->cryptState.uiLost;
270 sendmsg->payload.ping->has_lost = true;
271 sendmsg->payload.ping->resync = client->cryptState.uiResync;
272 sendmsg->payload.ping->has_resync = true;
274 Client_send_message(client, sendmsg);
275 Log_debug("Ping ->: %d %d %d %d",
276 client->cryptState.uiGood, client->cryptState.uiLate,
277 client->cryptState.uiLost, client->cryptState.uiResync);
281 Log_debug("Voice channel crypt resync requested");
282 if (!msg->payload.cryptSetup->has_client_nonce) {
283 sendmsg = Msg_create(CryptSetup);
284 sendmsg->payload.cryptSetup->has_server_nonce = true;
285 sendmsg->payload.cryptSetup->server_nonce.data = client->cryptState.decrypt_iv;
286 sendmsg->payload.cryptSetup->server_nonce.len = AES_BLOCK_SIZE;
287 Client_send_message(client, sendmsg);
289 memcpy(client->cryptState.decrypt_iv, msg->payload.cryptSetup->client_nonce.data, AES_BLOCK_SIZE);
290 client->cryptState.uiResync++;
294 /* Only allow state changes for for the self user */
295 if (msg->payload.userState->has_session &&
296 msg->payload.userState->session != client->sessionId) {
297 sendPermissionDenied(client, "Permission denied");
300 if (msg->payload.userState->has_user_id || msg->payload.userState->has_mute ||
301 msg->payload.userState->has_deaf || msg->payload.userState->has_suppress ||
302 msg->payload.userState->has_texture) {
304 sendPermissionDenied(client, "Not supported by uMurmur");
307 if (msg->payload.userState->has_self_deaf) {
308 client->deaf = msg->payload.userState->self_deaf;
310 if (msg->payload.userState->has_self_mute) {
311 client->mute = msg->payload.userState->self_mute;
313 if (msg->payload.userState->has_channel_id) {
315 if (!Chan_userJoin_id_test(msg->payload.userState->channel_id))
317 leave_id = Chan_userJoin_id(msg->payload.userState->channel_id, client);
319 Log_debug("Removing channel ID %d", leave_id);
320 sendmsg = Msg_create(ChannelRemove);
321 sendmsg->payload.channelRemove->channel_id = leave_id;
324 if (msg->payload.userState->plugin_context != NULL) {
326 free(client->context);
327 client->context = strdup(msg->payload.userState->plugin_context);
328 if (client->context == NULL)
329 Log_fatal("Out of memory");
331 break; /* Don't inform other users about this state */
336 msg->payload.userState->has_actor = true;
337 msg->payload.userState->actor = client->sessionId;
338 Client_send_message_except(NULL, msg);
340 /* Need to send remove channel message _after_ UserState message */
342 Client_send_message_except(NULL, sendmsg);
346 msg->payload.textMessage->has_actor = true;
347 msg->payload.textMessage->actor = client->sessionId;
349 /* XXX - HTML is allowed and can't be turned off */
350 if (msg->payload.textMessage->n_tree_id > 0) {
351 sendPermissionDenied(client, "Tree message not supported");
355 if (msg->payload.textMessage->n_channel_id > 0) { /* To channel */
358 for (i = 0; i < msg->payload.textMessage->n_channel_id; i++) {
361 Chan_iterate(&ch_itr);
362 } while (ch_itr != NULL && ch_itr->id != msg->payload.textMessage->channel_id[i]);
363 if (ch_itr != NULL) {
365 list_iterate(itr, &ch_itr->clients) {
367 c = list_get_entry(itr, client_t, chan_node);
368 if (c != client && !c->deaf) {
370 Client_send_message(c, msg);
371 Log_debug("Text message to session ID %d", c->sessionId);
377 if (msg->payload.textMessage->n_session > 0) { /* To user */
380 for (i = 0; i < msg->payload.textMessage->n_session; i++) {
382 while (Client_iterate(&itr) != NULL) {
385 if (itr->sessionId == msg->payload.textMessage->session[i]) {
388 Client_send_message(itr, msg);
389 Log_debug("Text message to session ID %d", itr->sessionId);
395 Log_warn("TextMessage: Session ID %d not found", msg->payload.textMessage->session[i]);
402 int i, j, count, targetId = msg->payload.voiceTarget->id;
403 struct _MumbleProto__VoiceTarget__Target *target;
405 if (!targetId || targetId >= 0x1f)
407 Voicetarget_add_id(client, targetId);
408 count = msg->payload.voiceTarget->n_targets;
411 for (i = 0; i < count; i++) {
412 target = msg->payload.voiceTarget->targets[i];
413 for (j = 0; j < target->n_session; j++)
414 Voicetarget_add_session(client, targetId, target->session[j]);
415 if (target->has_channel_id) {
416 bool_t linked = false, children = false;
417 if (target->has_links)
418 linked = target->links;
419 if (target->has_children)
420 children = target->children;
421 Voicetarget_add_channel(client, targetId, target->channel_id, linked, children);
427 Log_debug("Version message received");
428 if (msg->payload.version->has_version) {
429 client->version = msg->payload.version->version;
430 Log_debug("Client version 0x%x", client->version);
432 if (msg->payload.version->release) {
433 if (client->release) free(client->release);
434 client->release = strdup(msg->payload.version->release);
435 Log_debug("Client release %s", client->release);
437 if (msg->payload.version->os) {
438 if (client->os) free(client->os);
439 client->os = strdup(msg->payload.version->os);
440 Log_debug("Client OS %s", client->os);
443 case PermissionQuery:
444 Msg_inc_ref(msg); /* Re-use message */
445 msg->payload.permissionQuery->has_permissions = true;
446 msg->payload.permissionQuery->permissions = PERM_DEFAULT;
448 Client_send_message(client, msg);
451 client->bUDP = false;
452 Client_voiceMsg(client, msg->payload.UDPTunnel->packet.data, msg->payload.UDPTunnel->packet.len);
456 channel_t *ch_itr, *parent, *newchan;
458 /* Don't allow any changes to existing channels */
459 if (msg->payload.channelState->has_channel_id) {
460 sendPermissionDenied(client, "Not supported by uMurmur");
463 /* Must have parent */
464 if (!msg->payload.channelState->has_parent) {
465 sendPermissionDenied(client, "Not supported by uMurmur");
469 if (msg->payload.channelState->name == NULL) {
470 sendPermissionDenied(client, "Not supported by uMurmur");
473 /* Must be temporary channel */
474 if (msg->payload.channelState->temporary != true) {
475 sendPermissionDenied(client, "Only temporary channels are supported by uMurmur");
478 /* Check channel name is OK */
479 if (strlen(msg->payload.channelState->name) > MAX_TEXT) {
480 sendPermissionDenied(client, "Channel name too long");
484 parent = Chan_fromId(msg->payload.channelState->parent);
488 while (Chan_iterate_siblings(parent, &ch_itr) != NULL) {
489 if (strcmp(ch_itr->name, msg->payload.channelState->name) == 0) {
490 sendPermissionDenied(client, "Channel already exists");
497 /* Disallow temporary channels as siblings to temporary channels */
498 if (parent->temporary) {
499 sendPermissionDenied(client, "Parent channel is temporary channel");
503 /* XXX - Murmur looks for "\\w" and sends perm denied if not found.
504 * I don't know why so I don't do that here...
507 /* Create the channel */
508 newchan = Chan_createChannel(msg->payload.channelState->name,
509 msg->payload.channelState->description);
510 newchan->temporary = true;
511 Chan_addChannel(parent, newchan);
512 msg->payload.channelState->has_channel_id = true;
513 msg->payload.channelState->channel_id = newchan->id;
515 Client_send_message_except(NULL, msg);
517 /* Join the creating user */
518 sendmsg = Msg_create(UserState);
519 sendmsg->payload.userState->has_session = true;
520 sendmsg->payload.userState->session = client->sessionId;
521 sendmsg->payload.userState->has_channel_id = true;
522 sendmsg->payload.userState->channel_id = newchan->id;
523 Client_send_message_except(NULL, sendmsg);
525 leave_id = Chan_userJoin(newchan, client);
527 Log_debug("Removing channel ID %d", leave_id);
528 sendmsg = Msg_create(ChannelRemove);
529 sendmsg->payload.channelRemove->channel_id = leave_id;
530 Client_send_message_except(NULL, sendmsg);
535 /* Permission denied for all these messages. Not implemented. */
538 case ContextActionAdd:
543 sendPermissionDenied(client, "Not supported by uMurmur");
547 Log_warn("Message %d not handled", msg->messageType);
556 Client_close(client);