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 if (target->has_links || target->has_children)
417 Log_warn("Whisper to children or linked channels not implemented. Ignoring.");
418 Voicetarget_add_channel(client, targetId, target->channel_id);
424 Log_debug("Version message received");
425 if (msg->payload.version->has_version) {
426 client->version = msg->payload.version->version;
427 Log_debug("Client version 0x%x", client->version);
429 if (msg->payload.version->release) {
430 if (client->release) free(client->release);
431 client->release = strdup(msg->payload.version->release);
432 Log_debug("Client release %s", client->release);
434 if (msg->payload.version->os) {
435 if (client->os) free(client->os);
436 client->os = strdup(msg->payload.version->os);
437 Log_debug("Client OS %s", client->os);
440 case PermissionQuery:
441 Msg_inc_ref(msg); /* Re-use message */
442 msg->payload.permissionQuery->has_permissions = true;
443 msg->payload.permissionQuery->permissions = PERM_DEFAULT;
445 Client_send_message(client, msg);
448 Client_voiceMsg(client, msg->payload.UDPTunnel->packet.data, msg->payload.UDPTunnel->packet.len);
452 channel_t *ch_itr, *parent, *newchan;
454 /* Don't allow any changes to existing channels */
455 if (msg->payload.channelState->has_channel_id) {
456 sendPermissionDenied(client, "Not supported by uMurmur");
459 /* Must have parent */
460 if (!msg->payload.channelState->has_parent) {
461 sendPermissionDenied(client, "Not supported by uMurmur");
465 if (msg->payload.channelState->name == NULL) {
466 sendPermissionDenied(client, "Not supported by uMurmur");
469 /* Must be temporary channel */
470 if (msg->payload.channelState->temporary != true) {
471 sendPermissionDenied(client, "Only temporary channels are supported by uMurmur");
474 /* Check channel name is OK */
475 if (strlen(msg->payload.channelState->name) > MAX_TEXT) {
476 sendPermissionDenied(client, "Channel name too long");
480 parent = Chan_fromId(msg->payload.channelState->parent);
484 while (Chan_iterate_siblings(parent, &ch_itr) != NULL) {
485 if (strcmp(ch_itr->name, msg->payload.channelState->name) == 0) {
486 sendPermissionDenied(client, "Channel already exists");
493 /* Disallow temporary channels as siblings to temporary channels */
494 if (parent->temporary) {
495 sendPermissionDenied(client, "Parent channel is temporary channel");
499 /* XXX - Murmur looks for "\\w" and sends perm denied if not found.
500 * I don't know why so I don't do that here...
503 /* Create the channel */
504 newchan = Chan_createChannel(msg->payload.channelState->name,
505 msg->payload.channelState->description);
506 newchan->temporary = true;
507 Chan_addChannel(parent, newchan);
508 msg->payload.channelState->has_channel_id = true;
509 msg->payload.channelState->channel_id = newchan->id;
511 Client_send_message_except(NULL, msg);
513 /* Join the creating user */
514 sendmsg = Msg_create(UserState);
515 sendmsg->payload.userState->has_session = true;
516 sendmsg->payload.userState->session = client->sessionId;
517 sendmsg->payload.userState->has_channel_id = true;
518 sendmsg->payload.userState->channel_id = newchan->id;
519 Client_send_message_except(NULL, sendmsg);
521 leave_id = Chan_userJoin(newchan, client);
523 Log_debug("Removing channel ID %d", leave_id);
524 sendmsg = Msg_create(ChannelRemove);
525 sendmsg->payload.channelRemove->channel_id = leave_id;
526 Client_send_message_except(NULL, sendmsg);
531 /* Permission denied for all these messages. Not implemented. */
534 case ContextActionAdd:
539 sendPermissionDenied(client, "Not supported by uMurmur");
543 Log_warn("Message %d not handled", msg->messageType);
552 Client_close(client);