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 ||
108 (msg->payload.authenticate->password &&
109 strncmp(getStrConf(PASSPHRASE), msg->payload.authenticate->password, MAX_TEXT) != 0)) {
111 sprintf(buf, "Wrong server password");
112 sendServerReject(client, buf, MUMBLE_PROTO__REJECT__REJECT_TYPE__WrongServerPW);
113 Log_debug("Wrong server password: '%s'", msg->payload.authenticate->password != NULL ?
114 msg->payload.authenticate->password : "(null)");
118 if (strlen(msg->payload.authenticate->username) == 0 ||
119 strlen(msg->payload.authenticate->username) >= MAX_TEXT) { /* XXX - other invalid names? */
121 sprintf(buf, "Invalid username");
122 Log_debug("Invalid username");
123 sendServerReject(client, buf, MUMBLE_PROTO__REJECT__REJECT_TYPE__InvalidUsername);
127 if (Client_count() >= getIntConf(MAX_CLIENTS)) {
129 sprintf(buf, "Server is full (max %d users)", getIntConf(MAX_CLIENTS));
130 sendServerReject(client, buf, MUMBLE_PROTO__REJECT__REJECT_TYPE__ServerFull);
134 /* Name & password */
135 client->username = strdup(msg->payload.authenticate->username);
137 /* Setup UDP encryption */
138 CryptState_init(&client->cryptState);
139 CryptState_genKey(&client->cryptState);
140 sendmsg = Msg_create(CryptSetup);
141 sendmsg->payload.cryptSetup->has_key = true;
142 sendmsg->payload.cryptSetup->key.data = client->cryptState.raw_key;
143 sendmsg->payload.cryptSetup->key.len = AES_BLOCK_SIZE;
144 sendmsg->payload.cryptSetup->has_server_nonce = true;
145 sendmsg->payload.cryptSetup->server_nonce.data = client->cryptState.encrypt_iv;
146 sendmsg->payload.cryptSetup->server_nonce.len = AES_BLOCK_SIZE;
147 sendmsg->payload.cryptSetup->has_client_nonce = true;
148 sendmsg->payload.cryptSetup->client_nonce.data = client->cryptState.decrypt_iv;
149 sendmsg->payload.cryptSetup->client_nonce.len = AES_BLOCK_SIZE;
150 Client_send_message(client, sendmsg);
153 Chan_userJoin(defaultChan, client); /* Join default channel */
156 Log_debug("Client %d has %d CELT codecs", client->sessionId,
157 msg->payload.authenticate->n_celt_versions);
158 if (msg->payload.authenticate->n_celt_versions > 0) {
161 client->codec_count = msg->payload.authenticate->n_celt_versions;
163 for (i = 0; i < client->codec_count; i++)
164 Client_codec_add(client, msg->payload.authenticate->celt_versions[i]);
166 while (Client_codec_iterate(client, &codec_itr) != NULL)
167 Log_debug("Client %d CELT codec ver 0x%x", client->sessionId, codec_itr->codec);
170 Client_codec_add(client, (int32_t)0x8000000a);
171 client->codec_count = 1;
174 recheckCodecVersions();
176 sendmsg = Msg_create(CodecVersion);
177 sendmsg->payload.codecVersion->alpha = iCodecAlpha;
178 sendmsg->payload.codecVersion->beta = iCodecBeta;
179 sendmsg->payload.codecVersion->prefer_alpha = bPreferAlpha;
180 Client_send_message(client, sendmsg);
182 /* Iterate channels and send channel info */
184 while (Chan_iterate(&ch_itr) != NULL) {
185 sendmsg = Msg_create(ChannelState);
186 sendmsg->payload.channelState->has_channel_id = true;
187 sendmsg->payload.channelState->channel_id = ch_itr->id;
188 if (ch_itr->id != 0) {
189 sendmsg->payload.channelState->has_parent = true;
190 sendmsg->payload.channelState->parent = ch_itr->parent->id;
192 sendmsg->payload.channelState->name = strdup(ch_itr->name);
194 sendmsg->payload.channelState->description = strdup(ch_itr->desc);
195 Log_debug("Send channel info: %s", sendmsg->payload.channelState->name);
196 Client_send_message(client, sendmsg);
199 /* Iterate channels and send channel links info */
201 while (Chan_iterate(&ch_itr) != NULL) {
202 if (ch_itr->linkcount > 0) { /* Has links */
207 sendmsg = Msg_create(ChannelState);
208 sendmsg->payload.channelState->has_channel_id = true;
209 sendmsg->payload.channelState->channel_id = ch_itr->id;
210 sendmsg->payload.channelState->n_links = ch_itr->linkcount;
212 links = (uint32_t *)malloc(ch_itr->linkcount * sizeof(uint32_t));
213 list_iterate(itr, &ch_itr->channel_links) { /* Iterate links */
215 ch = list_get_entry(itr, channel_t, link_node);
218 sendmsg->payload.channelState->links = links;
219 Client_send_message(client, sendmsg);
223 /* Send user state for connecting user to other users */
224 sendmsg = Msg_create(UserState);
225 sendmsg->payload.userState->has_session = true;
226 sendmsg->payload.userState->session = client->sessionId;
227 sendmsg->payload.userState->name = strdup(client->username);
228 sendmsg->payload.userState->has_channel_id = true;
229 sendmsg->payload.userState->channel_id = ((channel_t *)client->channel)->id;
231 Client_send_message_except(client, sendmsg);
234 while (Client_iterate(&client_itr) != NULL) {
235 if (!IS_AUTH(client_itr))
237 sendmsg = Msg_create(UserState);
238 sendmsg->payload.userState->has_session = true;
239 sendmsg->payload.userState->session = client_itr->sessionId;
240 sendmsg->payload.userState->name = strdup(client_itr->username);
241 sendmsg->payload.userState->has_channel_id = true;
242 sendmsg->payload.userState->channel_id = ((channel_t *)client_itr->channel)->id;
244 /* Only self_mute/deaf supported */
245 if (client_itr->deaf) {
246 sendmsg->payload.userState->has_self_deaf = true;
247 sendmsg->payload.userState->self_deaf = true;
249 if (client_itr->mute) {
250 sendmsg->payload.userState->has_self_mute = true;
251 sendmsg->payload.userState->self_mute = true;
253 Client_send_message(client, sendmsg);
257 sendmsg = Msg_create(ServerSync);
258 sendmsg->payload.serverSync->has_session = true;
259 sendmsg->payload.serverSync->session = client->sessionId;
260 sendmsg->payload.serverSync->welcome_text = strdup(getStrConf(WELCOMETEXT));
261 sendmsg->payload.serverSync->has_max_bandwidth = true;
262 sendmsg->payload.serverSync->max_bandwidth = getIntConf(MAX_BANDWIDTH);
263 sendmsg->payload.serverSync->has_allow_html = true;
264 sendmsg->payload.serverSync->allow_html = true; /* Support this? */
265 Client_send_message(client, sendmsg);
267 Log_info_client(client, "User %s authenticated", client->username);
271 if (msg->payload.ping->has_good)
272 client->cryptState.uiRemoteGood = msg->payload.ping->good;
273 if (msg->payload.ping->has_late)
274 client->cryptState.uiRemoteLate = msg->payload.ping->late;
275 if (msg->payload.ping->has_lost)
276 client->cryptState.uiRemoteLost = msg->payload.ping->lost;
277 if (msg->payload.ping->has_resync)
278 client->cryptState.uiRemoteResync = msg->payload.ping->resync;
280 Log_debug("Ping <-: %d %d %d %d",
281 client->cryptState.uiRemoteGood, client->cryptState.uiRemoteLate,
282 client->cryptState.uiRemoteLost, client->cryptState.uiRemoteResync
285 /* Ignoring the double values since they don't seem to be used */
287 sendmsg = Msg_create(Ping);
289 sendmsg->payload.ping->timestamp = msg->payload.ping->timestamp;
290 sendmsg->payload.ping->has_timestamp = true;
291 sendmsg->payload.ping->good = client->cryptState.uiGood;
292 sendmsg->payload.ping->has_good = true;
293 sendmsg->payload.ping->late = client->cryptState.uiLate;
294 sendmsg->payload.ping->has_late = true;
295 sendmsg->payload.ping->lost = client->cryptState.uiLost;
296 sendmsg->payload.ping->has_lost = true;
297 sendmsg->payload.ping->resync = client->cryptState.uiResync;
298 sendmsg->payload.ping->has_resync = true;
300 Client_send_message(client, sendmsg);
301 Log_debug("Ping ->: %d %d %d %d",
302 client->cryptState.uiGood, client->cryptState.uiLate,
303 client->cryptState.uiLost, client->cryptState.uiResync);
307 Log_debug("Voice channel crypt resync requested");
308 if (!msg->payload.cryptSetup->has_client_nonce) {
309 sendmsg = Msg_create(CryptSetup);
310 sendmsg->payload.cryptSetup->has_server_nonce = true;
311 sendmsg->payload.cryptSetup->server_nonce.data = client->cryptState.decrypt_iv;
312 sendmsg->payload.cryptSetup->server_nonce.len = AES_BLOCK_SIZE;
313 Client_send_message(client, sendmsg);
315 memcpy(client->cryptState.decrypt_iv, msg->payload.cryptSetup->client_nonce.data, AES_BLOCK_SIZE);
316 client->cryptState.uiResync++;
320 /* Only allow state changes for for the self user */
321 if (msg->payload.userState->has_session &&
322 msg->payload.userState->session != client->sessionId) {
323 sendPermissionDenied(client, "Permission denied");
326 if (msg->payload.userState->has_user_id || msg->payload.userState->has_mute ||
327 msg->payload.userState->has_deaf || msg->payload.userState->has_suppress ||
328 msg->payload.userState->has_texture) {
330 sendPermissionDenied(client, "Not supported by uMurmur");
334 msg->payload.userState->has_session = true;
335 msg->payload.userState->session = client->sessionId;
336 msg->payload.userState->has_actor = true;
337 msg->payload.userState->actor = client->sessionId;
339 if (msg->payload.userState->has_self_deaf) {
340 client->deaf = msg->payload.userState->self_deaf;
342 if (msg->payload.userState->has_self_mute) {
343 client->mute = msg->payload.userState->self_mute;
345 msg->payload.userState->has_self_deaf = true;
346 msg->payload.userState->self_deaf = false;
347 client->deaf = false;
350 if (msg->payload.userState->has_channel_id) {
352 if (!Chan_userJoin_id_test(msg->payload.userState->channel_id))
354 leave_id = Chan_userJoin_id(msg->payload.userState->channel_id, client);
356 Log_debug("Removing channel ID %d", leave_id);
357 sendmsg = Msg_create(ChannelRemove);
358 sendmsg->payload.channelRemove->channel_id = leave_id;
361 if (msg->payload.userState->plugin_context != NULL) {
363 free(client->context);
364 client->context = strdup(msg->payload.userState->plugin_context);
365 if (client->context == NULL)
366 Log_fatal("Out of memory");
368 break; /* Don't inform other users about this state */
374 Client_send_message_except(NULL, msg);
376 /* Need to send remove channel message _after_ UserState message */
378 Client_send_message_except(NULL, sendmsg);
382 msg->payload.textMessage->has_actor = true;
383 msg->payload.textMessage->actor = client->sessionId;
385 /* XXX - HTML is allowed and can't be turned off */
386 if (msg->payload.textMessage->n_tree_id > 0) {
387 sendPermissionDenied(client, "Tree message not supported");
391 if (msg->payload.textMessage->n_channel_id > 0) { /* To channel */
394 for (i = 0; i < msg->payload.textMessage->n_channel_id; i++) {
397 Chan_iterate(&ch_itr);
398 } while (ch_itr != NULL && ch_itr->id != msg->payload.textMessage->channel_id[i]);
399 if (ch_itr != NULL) {
401 list_iterate(itr, &ch_itr->clients) {
403 c = list_get_entry(itr, client_t, chan_node);
404 if (c != client && !c->deaf) {
406 Client_send_message(c, msg);
407 Log_debug("Text message to session ID %d", c->sessionId);
413 if (msg->payload.textMessage->n_session > 0) { /* To user */
416 for (i = 0; i < msg->payload.textMessage->n_session; i++) {
418 while (Client_iterate(&itr) != NULL) {
421 if (itr->sessionId == msg->payload.textMessage->session[i]) {
424 Client_send_message(itr, msg);
425 Log_debug("Text message to session ID %d", itr->sessionId);
431 Log_warn("TextMessage: Session ID %d not found", msg->payload.textMessage->session[i]);
438 int i, j, count, targetId = msg->payload.voiceTarget->id;
439 struct _MumbleProto__VoiceTarget__Target *target;
441 if (!targetId || targetId >= 0x1f)
443 Voicetarget_add_id(client, targetId);
444 count = msg->payload.voiceTarget->n_targets;
447 for (i = 0; i < count; i++) {
448 target = msg->payload.voiceTarget->targets[i];
449 for (j = 0; j < target->n_session; j++)
450 Voicetarget_add_session(client, targetId, target->session[j]);
451 if (target->has_channel_id) {
452 bool_t linked = false, children = false;
453 if (target->has_links)
454 linked = target->links;
455 if (target->has_children)
456 children = target->children;
457 Voicetarget_add_channel(client, targetId, target->channel_id, linked, children);
463 Log_debug("Version message received");
464 if (msg->payload.version->has_version) {
465 client->version = msg->payload.version->version;
466 Log_debug("Client version 0x%x", client->version);
468 if (msg->payload.version->release) {
469 if (client->release) free(client->release);
470 client->release = strdup(msg->payload.version->release);
471 Log_debug("Client release %s", client->release);
473 if (msg->payload.version->os) {
474 if (client->os) free(client->os);
475 client->os = strdup(msg->payload.version->os);
476 Log_debug("Client OS %s", client->os);
479 case PermissionQuery:
480 Msg_inc_ref(msg); /* Re-use message */
481 msg->payload.permissionQuery->has_permissions = true;
482 msg->payload.permissionQuery->permissions = PERM_DEFAULT;
484 Client_send_message(client, msg);
487 client->bUDP = false;
488 Client_voiceMsg(client, msg->payload.UDPTunnel->packet.data, msg->payload.UDPTunnel->packet.len);
492 channel_t *ch_itr, *parent, *newchan;
494 /* Don't allow any changes to existing channels */
495 if (msg->payload.channelState->has_channel_id) {
496 sendPermissionDenied(client, "Not supported by uMurmur");
499 /* Must have parent */
500 if (!msg->payload.channelState->has_parent) {
501 sendPermissionDenied(client, "Not supported by uMurmur");
505 if (msg->payload.channelState->name == NULL) {
506 sendPermissionDenied(client, "Not supported by uMurmur");
509 /* Must be temporary channel */
510 if (msg->payload.channelState->temporary != true) {
511 sendPermissionDenied(client, "Only temporary channels are supported by uMurmur");
514 /* Check channel name is OK */
515 if (strlen(msg->payload.channelState->name) > MAX_TEXT) {
516 sendPermissionDenied(client, "Channel name too long");
520 parent = Chan_fromId(msg->payload.channelState->parent);
524 while (Chan_iterate_siblings(parent, &ch_itr) != NULL) {
525 if (strcmp(ch_itr->name, msg->payload.channelState->name) == 0) {
526 sendPermissionDenied(client, "Channel already exists");
533 /* Disallow temporary channels as siblings to temporary channels */
534 if (parent->temporary) {
535 sendPermissionDenied(client, "Parent channel is temporary channel");
539 /* XXX - Murmur looks for "\\w" and sends perm denied if not found.
540 * I don't know why so I don't do that here...
543 /* Create the channel */
544 newchan = Chan_createChannel(msg->payload.channelState->name,
545 msg->payload.channelState->description);
546 newchan->temporary = true;
547 Chan_addChannel(parent, newchan);
548 msg->payload.channelState->has_channel_id = true;
549 msg->payload.channelState->channel_id = newchan->id;
551 Client_send_message_except(NULL, msg);
553 /* Join the creating user */
554 sendmsg = Msg_create(UserState);
555 sendmsg->payload.userState->has_session = true;
556 sendmsg->payload.userState->session = client->sessionId;
557 sendmsg->payload.userState->has_channel_id = true;
558 sendmsg->payload.userState->channel_id = newchan->id;
559 Client_send_message_except(NULL, sendmsg);
561 leave_id = Chan_userJoin(newchan, client);
563 Log_debug("Removing channel ID %d", leave_id);
564 sendmsg = Msg_create(ChannelRemove);
565 sendmsg->payload.channelRemove->channel_id = leave_id;
566 Client_send_message_except(NULL, sendmsg);
571 /* Permission denied for all these messages. Not implemented. */
574 case ContextActionAdd:
579 sendPermissionDenied(client, "Not supported by uMurmur");
583 Log_warn("Message %d not handled", msg->messageType);
592 Client_close(client);