1 /* Copyright (C) 2009-2012, Martin Johansson <martin@fatbob.nu>
2 Copyright (C) 2005-2012, 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 #define MAX_USERNAME 128
48 #define NO_CELT_MESSAGE "<strong>WARNING:</strong> Your client doesn't support the CELT codec, you won't be able to talk to or hear most clients. Please make sure your client was built with CELT support."
51 extern channel_t *defaultChan;
52 extern int iCodecAlpha, iCodecBeta;
53 extern bool_t bPreferAlpha, bOpus;
55 static bool_t fake_celt_support;
57 static void sendServerReject(client_t *client, const char *reason, MumbleProto__Reject__RejectType type)
59 message_t *msg = Msg_create(Reject);
60 msg->payload.reject->reason = strdup(reason);
61 msg->payload.reject->type = type;
62 msg->payload.reject->has_type = true;
63 Client_send_message(client, msg);
65 Log_info_client(client, "Server reject reason: %s", reason);
68 static void sendPermissionDenied(client_t *client, const char *reason)
70 message_t *msg = Msg_create(PermissionDenied);
71 msg->payload.permissionDenied->has_type = true;
72 msg->payload.permissionDenied->type = MUMBLE_PROTO__PERMISSION_DENIED__DENY_TYPE__Text;
73 msg->payload.permissionDenied->reason = strdup(reason);
74 Client_send_message(client, msg);
77 static void addTokens(client_t *client, message_t *msg)
80 if (client->tokencount + msg->payload.authenticate->n_tokens < MAX_TOKENS) {
81 /* Check lengths first */
82 for (i = 0; i < msg->payload.authenticate->n_tokens; i++) {
83 if (strlen(msg->payload.authenticate->tokens[i]) > MAX_TOKENSIZE - 1) {
84 sendPermissionDenied(client, "Too long token");
89 for (i = 0; i < msg->payload.authenticate->n_tokens; i++) {
90 Log_debug("Adding token '%s' to client '%s'", msg->payload.authenticate->tokens[i], client->username);
91 Client_token_add(client, msg->payload.authenticate->tokens[i]);
95 sendPermissionDenied(client, "Too many tokens");
98 void Mh_handle_message(client_t *client, message_t *msg)
100 message_t *sendmsg = NULL;
101 channel_t *ch_itr = NULL;
102 client_t *client_itr, *target;
104 if (!client->authenticated && !(msg->messageType == Authenticate ||
105 msg->messageType == Version)) {
109 switch (msg->messageType) {
115 case PermissionQuery:
118 Timer_restart(&client->idleTime);
121 switch (msg->messageType) {
123 Log_debug("Authenticate message received");
125 if (IS_AUTH(client) || !msg->payload.authenticate->username) {
126 /* Authenticate message might be sent when a tokens are changed by the user.*/
127 Client_token_free(client); /* Clear the token list */
128 if (msg->payload.authenticate->n_tokens > 0) {
129 Log_debug("Tokens in auth message from '%s'. n_tokens = %d", client->username,
130 msg->payload.authenticate->n_tokens);
131 addTokens(client, msg);
136 if (SSLi_getSHA1Hash(client->ssl, client->hash) && Ban_isBanned(client)) {
138 SSLi_hash2hex(client->hash, hexhash);
139 Log_info("Client with hash '%s' is banned. Disconnecting", hexhash);
143 client->authenticated = true;
146 while (Client_iterate(&client_itr) != NULL) {
147 if (!IS_AUTH(client_itr))
149 if (client_itr->username && strncmp(client_itr->username, msg->payload.authenticate->username, MAX_USERNAME) == 0) {
151 sprintf(buf, "Username already in use");
152 Log_debug("Username already in use");
153 sendServerReject(client, buf, MUMBLE_PROTO__REJECT__REJECT_TYPE__UsernameInUse);
157 if (strlen(getStrConf(PASSPHRASE)) > 0) {
158 if (!msg->payload.authenticate->password ||
159 (msg->payload.authenticate->password &&
160 strncmp(getStrConf(PASSPHRASE), msg->payload.authenticate->password, MAX_TEXT) != 0)) {
162 sprintf(buf, "Wrong server password");
163 sendServerReject(client, buf, MUMBLE_PROTO__REJECT__REJECT_TYPE__WrongServerPW);
164 Log_debug("Wrong server password: '%s'", msg->payload.authenticate->password != NULL ?
165 msg->payload.authenticate->password : "(null)");
169 if (strlen(msg->payload.authenticate->username) == 0 ||
170 strlen(msg->payload.authenticate->username) >= MAX_USERNAME) { /* XXX - other invalid names? */
172 sprintf(buf, "Invalid username");
173 Log_debug("Invalid username");
174 sendServerReject(client, buf, MUMBLE_PROTO__REJECT__REJECT_TYPE__InvalidUsername);
178 if (Client_count() >= getIntConf(MAX_CLIENTS)) {
180 snprintf(buf, 64, "Server is full (max %d users)", getIntConf(MAX_CLIENTS));
181 sendServerReject(client, buf, MUMBLE_PROTO__REJECT__REJECT_TYPE__ServerFull);
186 client->username = strdup(msg->payload.authenticate->username);
189 if (msg->payload.authenticate->n_tokens > 0)
190 addTokens(client, msg);
192 /* Check if admin PW among tokens */
193 if (strlen(getStrConf(ADMIN_PASSPHRASE)) > 0 &&
194 Client_token_match(client, getStrConf(ADMIN_PASSPHRASE))) {
195 client->isAdmin = true;
196 Log_info_client(client, "User provided admin password");
199 /* Setup UDP encryption */
200 CryptState_init(&client->cryptState);
201 CryptState_genKey(&client->cryptState);
202 sendmsg = Msg_create(CryptSetup);
203 sendmsg->payload.cryptSetup->has_key = true;
204 sendmsg->payload.cryptSetup->key.data = client->cryptState.raw_key;
205 sendmsg->payload.cryptSetup->key.len = AES_BLOCK_SIZE;
206 sendmsg->payload.cryptSetup->has_server_nonce = true;
207 sendmsg->payload.cryptSetup->server_nonce.data = client->cryptState.encrypt_iv;
208 sendmsg->payload.cryptSetup->server_nonce.len = AES_BLOCK_SIZE;
209 sendmsg->payload.cryptSetup->has_client_nonce = true;
210 sendmsg->payload.cryptSetup->client_nonce.data = client->cryptState.decrypt_iv;
211 sendmsg->payload.cryptSetup->client_nonce.len = AES_BLOCK_SIZE;
212 Client_send_message(client, sendmsg);
215 Chan_userJoin(defaultChan, client); /* Join default channel */
218 Log_debug("Client %d has %d CELT codecs", client->sessionId,
219 msg->payload.authenticate->n_celt_versions);
220 if (msg->payload.authenticate->n_celt_versions > 0) {
223 client->codec_count = msg->payload.authenticate->n_celt_versions;
225 for (i = 0; i < client->codec_count; i++)
226 Client_codec_add(client, msg->payload.authenticate->celt_versions[i]);
228 while (Client_codec_iterate(client, &codec_itr) != NULL)
229 Log_debug("Client %d CELT codec ver 0x%x", client->sessionId, codec_itr->codec);
232 Client_codec_add(client, (int32_t)0x8000000b);
233 client->codec_count = 1;
234 fake_celt_support = true;
236 if (msg->payload.authenticate->opus)
237 client->bOpus = true;
239 recheckCodecVersions(client);
241 sendmsg = Msg_create(CodecVersion);
242 sendmsg->payload.codecVersion->alpha = iCodecAlpha;
243 sendmsg->payload.codecVersion->beta = iCodecBeta;
244 sendmsg->payload.codecVersion->prefer_alpha = bPreferAlpha;
245 sendmsg->payload.codecVersion->has_opus = true;
246 sendmsg->payload.codecVersion->opus = bOpus;
247 Client_send_message(client, sendmsg);
249 if (!bOpus && client->bOpus && fake_celt_support) {
252 message_t *sendmsg = NULL;
254 message = malloc(strlen(NO_CELT_MESSAGE) + 1);
256 Log_fatal("Out of memory");
257 tree_id = malloc(sizeof(uint32_t));
259 Log_fatal("Out of memory");
261 sendmsg = Msg_create(TextMessage);
262 sendmsg->payload.textMessage->message = message;
263 sendmsg->payload.textMessage->n_tree_id = 1;
264 sendmsg->payload.textMessage->tree_id = tree_id;
265 sprintf(message, NO_CELT_MESSAGE);
266 Client_send_message(client, sendmsg);
270 /* Iterate channels and send channel info */
272 while (Chan_iterate(&ch_itr) != NULL) {
273 sendmsg = Msg_create(ChannelState);
274 sendmsg->payload.channelState->has_channel_id = true;
275 sendmsg->payload.channelState->channel_id = ch_itr->id;
276 if (ch_itr->id != 0) {
277 sendmsg->payload.channelState->has_parent = true;
278 sendmsg->payload.channelState->parent = ch_itr->parent->id;
280 sendmsg->payload.channelState->name = strdup(ch_itr->name);
282 sendmsg->payload.channelState->description = strdup(ch_itr->desc);
283 Log_debug("Send channel info: %s", sendmsg->payload.channelState->name);
284 Client_send_message(client, sendmsg);
287 /* Iterate channels and send channel links info */
289 while (Chan_iterate(&ch_itr) != NULL) {
290 if (ch_itr->linkcount > 0) { /* Has links */
295 sendmsg = Msg_create(ChannelState);
296 sendmsg->payload.channelState->has_channel_id = true;
297 sendmsg->payload.channelState->channel_id = ch_itr->id;
298 sendmsg->payload.channelState->n_links = ch_itr->linkcount;
300 links = (uint32_t *)malloc(ch_itr->linkcount * sizeof(uint32_t));
301 list_iterate(itr, &ch_itr->channel_links) { /* Iterate links */
303 ch = list_get_entry(itr, channel_t, link_node);
306 sendmsg->payload.channelState->links = links;
307 Client_send_message(client, sendmsg);
311 /* Send user state for connecting user to other users */
312 sendmsg = Msg_create(UserState);
313 sendmsg->payload.userState->has_session = true;
314 sendmsg->payload.userState->session = client->sessionId;
315 sendmsg->payload.userState->name = strdup(client->username);
316 sendmsg->payload.userState->has_channel_id = true;
317 sendmsg->payload.userState->channel_id = ((channel_t *)client->channel)->id;
319 Client_send_message_except(client, sendmsg);
322 while (Client_iterate(&client_itr) != NULL) {
323 if (!IS_AUTH(client_itr))
325 sendmsg = Msg_create(UserState);
326 sendmsg->payload.userState->has_session = true;
327 sendmsg->payload.userState->session = client_itr->sessionId;
328 sendmsg->payload.userState->name = strdup(client_itr->username);
329 sendmsg->payload.userState->has_channel_id = true;
330 sendmsg->payload.userState->channel_id = ((channel_t *)client_itr->channel)->id;
332 if (client_itr->self_deaf) {
333 sendmsg->payload.userState->has_self_deaf = true;
334 sendmsg->payload.userState->self_deaf = true;
336 if (client_itr->self_mute) {
337 sendmsg->payload.userState->has_self_mute = true;
338 sendmsg->payload.userState->self_mute = true;
340 if (client_itr->deaf) {
341 sendmsg->payload.userState->has_deaf = true;
342 sendmsg->payload.userState->deaf = true;
344 if (client_itr->mute) {
345 sendmsg->payload.userState->has_mute = true;
346 sendmsg->payload.userState->mute = true;
348 if (client_itr->recording) {
349 sendmsg->payload.userState->has_recording = true;
350 sendmsg->payload.userState->recording = true;
352 Client_send_message(client, sendmsg);
356 sendmsg = Msg_create(ServerSync);
357 sendmsg->payload.serverSync->has_session = true;
358 sendmsg->payload.serverSync->session = client->sessionId;
359 sendmsg->payload.serverSync->welcome_text = strdup(getStrConf(WELCOMETEXT));
360 sendmsg->payload.serverSync->has_max_bandwidth = true;
361 sendmsg->payload.serverSync->max_bandwidth = getIntConf(MAX_BANDWIDTH);
362 Client_send_message(client, sendmsg);
364 /* Server config message */
365 sendmsg = Msg_create(ServerConfig);
366 sendmsg->payload.serverConfig->has_allow_html = true;
367 sendmsg->payload.serverConfig->allow_html = true; /* Support this? */
368 sendmsg->payload.serverConfig->has_message_length = true;
369 sendmsg->payload.serverConfig->message_length = MAX_TEXT; /* Hardcoded */
370 sendmsg->payload.serverConfig->has_image_message_length = true;
371 sendmsg->payload.serverConfig->image_message_length = 0; /* XXX */
372 Client_send_message(client, sendmsg);
374 Log_info_client(client, "User %s authenticated", client->username);
378 if (msg->payload.ping->has_good)
379 client->cryptState.uiRemoteGood = msg->payload.ping->good;
380 if (msg->payload.ping->has_late)
381 client->cryptState.uiRemoteLate = msg->payload.ping->late;
382 if (msg->payload.ping->has_lost)
383 client->cryptState.uiRemoteLost = msg->payload.ping->lost;
384 if (msg->payload.ping->has_resync)
385 client->cryptState.uiRemoteResync = msg->payload.ping->resync;
387 Log_debug("Ping <-: %d %d %d %d",
388 client->cryptState.uiRemoteGood, client->cryptState.uiRemoteLate,
389 client->cryptState.uiRemoteLost, client->cryptState.uiRemoteResync
392 client->UDPPingAvg = msg->payload.ping->udp_ping_avg;
393 client->UDPPingVar = msg->payload.ping->udp_ping_var;
394 client->TCPPingAvg = msg->payload.ping->tcp_ping_avg;
395 client->TCPPingVar = msg->payload.ping->tcp_ping_var;
396 client->UDPPackets = msg->payload.ping->udp_packets;
397 client->TCPPackets = msg->payload.ping->tcp_packets;
399 sendmsg = Msg_create(Ping);
401 sendmsg->payload.ping->timestamp = msg->payload.ping->timestamp;
402 sendmsg->payload.ping->has_timestamp = true;
403 sendmsg->payload.ping->good = client->cryptState.uiGood;
404 sendmsg->payload.ping->has_good = true;
405 sendmsg->payload.ping->late = client->cryptState.uiLate;
406 sendmsg->payload.ping->has_late = true;
407 sendmsg->payload.ping->lost = client->cryptState.uiLost;
408 sendmsg->payload.ping->has_lost = true;
409 sendmsg->payload.ping->resync = client->cryptState.uiResync;
410 sendmsg->payload.ping->has_resync = true;
412 Client_send_message(client, sendmsg);
413 Log_debug("Ping ->: %d %d %d %d",
414 client->cryptState.uiGood, client->cryptState.uiLate,
415 client->cryptState.uiLost, client->cryptState.uiResync);
419 Log_debug("Voice channel crypt resync requested");
420 if (!msg->payload.cryptSetup->has_client_nonce) {
421 sendmsg = Msg_create(CryptSetup);
422 sendmsg->payload.cryptSetup->has_server_nonce = true;
423 sendmsg->payload.cryptSetup->server_nonce.data = client->cryptState.decrypt_iv;
424 sendmsg->payload.cryptSetup->server_nonce.len = AES_BLOCK_SIZE;
425 Client_send_message(client, sendmsg);
427 memcpy(client->cryptState.decrypt_iv, msg->payload.cryptSetup->client_nonce.data, AES_BLOCK_SIZE);
428 client->cryptState.uiResync++;
433 /* Only allow state changes for for the self user unless an admin is issuing */
434 if (msg->payload.userState->has_session &&
435 msg->payload.userState->session != client->sessionId && !client->isAdmin) {
436 sendPermissionDenied(client, "Permission denied");
439 if (msg->payload.userState->has_session && msg->payload.userState->session != client->sessionId) {
440 while (Client_iterate(&target) != NULL) {
441 if (target->sessionId == msg->payload.userState->session)
444 if (target == NULL) {
445 Log_warn("Client with sessionID %d not found", msg->payload.userState->session);
450 if (msg->payload.userState->has_user_id || msg->payload.userState->has_suppress ||
451 msg->payload.userState->has_priority_speaker || msg->payload.userState->has_texture) {
452 sendPermissionDenied(client, "Not supported by uMurmur");
459 msg->payload.userState->has_session = true;
460 msg->payload.userState->session = target->sessionId;
461 msg->payload.userState->has_actor = true;
462 msg->payload.userState->actor = client->sessionId;
464 if (msg->payload.userState->has_deaf) {
465 target->deaf = msg->payload.userState->deaf;
467 msg->payload.userState->has_mute = true;
468 msg->payload.userState->mute = true;
471 if (msg->payload.userState->has_mute) {
472 target->mute = msg->payload.userState->mute;
474 msg->payload.userState->has_deaf = true;
475 msg->payload.userState->deaf = false;
476 target->deaf = false;
479 if (msg->payload.userState->has_self_deaf) {
480 client->self_deaf = msg->payload.userState->self_deaf;
481 if (client->self_deaf) {
482 msg->payload.userState->has_self_mute = true;
483 msg->payload.userState->self_mute = true;
486 if (msg->payload.userState->has_self_mute) {
487 client->self_mute = msg->payload.userState->self_mute;
488 if (!client->self_mute) {
489 msg->payload.userState->has_self_deaf = true;
490 msg->payload.userState->self_deaf = false;
491 client->self_deaf = false;
494 if (msg->payload.userState->has_recording &&
495 msg->payload.userState->recording != client->recording) {
496 client->recording = msg->payload.userState->recording;
500 message = malloc(strlen(client->username) + 32);
502 Log_fatal("Out of memory");
503 tree_id = malloc(sizeof(uint32_t));
505 Log_fatal("Out of memory");
507 sendmsg = Msg_create(TextMessage);
508 sendmsg->payload.textMessage->message = message;
509 sendmsg->payload.textMessage->n_tree_id = 1;
510 sendmsg->payload.textMessage->tree_id = tree_id;
511 if (client->recording)
512 sprintf(message, "User %s started recording", client->username);
514 sprintf(message, "User %s stopped recording", client->username);
515 Client_send_message_except_ver(NULL, sendmsg, ~0x010203);
518 if (msg->payload.userState->has_channel_id) {
520 channelJoinResult_t chjoin_rc = Chan_userJoin_id_test(msg->payload.userState->channel_id, target);
522 if (chjoin_rc != CHJOIN_OK) {
523 if (chjoin_rc == CHJOIN_WRONGPW) {
524 if (target == client && !client->isAdmin) {
525 sendPermissionDenied(client, "Wrong channel password");
528 /* Tricky one: if user hasn't the password, but is moved to the channel by admin then let
529 * the user in. Also let admin user in regardless of channel password.
530 * Take no action on other errors.
532 else if (!client->isAdmin)
538 leave_id = Chan_userJoin_id(msg->payload.userState->channel_id, target);
540 Log_debug("Removing channel ID %d", leave_id);
541 sendmsg = Msg_create(ChannelRemove);
542 sendmsg->payload.channelRemove->channel_id = leave_id;
545 if (msg->payload.userState->has_plugin_context) {
547 free(client->context);
548 client->context = malloc(msg->payload.userState->plugin_context.len);
549 if (client->context == NULL)
550 Log_fatal("Out of memory");
551 memcpy(client->context, msg->payload.userState->plugin_context.data,
552 msg->payload.userState->plugin_context.len);
554 break; /* Don't inform other users about this state */
559 Client_send_message_except(NULL, msg);
561 /* Need to send remove channel message _after_ UserState message */
563 Client_send_message_except(NULL, sendmsg);
567 if (!getBoolConf(ALLOW_TEXTMESSAGE))
569 msg->payload.textMessage->has_actor = true;
570 msg->payload.textMessage->actor = client->sessionId;
572 /* XXX - HTML is allowed and can't be turned off */
573 if (msg->payload.textMessage->n_tree_id > 0) {
574 sendPermissionDenied(client, "Tree message not supported");
578 if (msg->payload.textMessage->n_channel_id > 0) { /* To channel */
581 for (i = 0; i < msg->payload.textMessage->n_channel_id; i++) {
584 Chan_iterate(&ch_itr);
585 } while (ch_itr != NULL && ch_itr->id != msg->payload.textMessage->channel_id[i]);
586 if (ch_itr != NULL) {
588 list_iterate(itr, &ch_itr->clients) {
590 c = list_get_entry(itr, client_t, chan_node);
591 if (c != client && !c->deaf && !c->self_deaf) {
593 Client_send_message(c, msg);
594 Log_debug("Text message to session ID %d", c->sessionId);
600 if (msg->payload.textMessage->n_session > 0) { /* To user */
603 for (i = 0; i < msg->payload.textMessage->n_session; i++) {
605 while (Client_iterate(&itr) != NULL) {
608 if (itr->sessionId == msg->payload.textMessage->session[i]) {
609 if (!itr->deaf && !itr->self_deaf) {
611 Client_send_message(itr, msg);
612 Log_debug("Text message to session ID %d", itr->sessionId);
618 Log_warn("TextMessage: Session ID %d not found", msg->payload.textMessage->session[i]);
625 int i, j, count, targetId = msg->payload.voiceTarget->id;
626 struct _MumbleProto__VoiceTarget__Target *target;
628 if (!targetId || targetId >= 0x1f)
630 Voicetarget_add_id(client, targetId);
631 count = msg->payload.voiceTarget->n_targets;
634 for (i = 0; i < count; i++) {
635 target = msg->payload.voiceTarget->targets[i];
636 for (j = 0; j < target->n_session; j++)
637 Voicetarget_add_session(client, targetId, target->session[j]);
638 if (target->has_channel_id) {
639 bool_t linked = false, children = false;
640 if (target->has_links)
641 linked = target->links;
642 if (target->has_children)
643 children = target->children;
644 Voicetarget_add_channel(client, targetId, target->channel_id, linked, children);
650 Log_debug("Version message received");
651 if (msg->payload.version->has_version) {
652 client->version = msg->payload.version->version;
653 Log_debug("Client version 0x%x", client->version);
655 if (msg->payload.version->release) {
656 if (client->release) free(client->release);
657 client->release = strdup(msg->payload.version->release);
658 Log_debug("Client release %s", client->release);
660 if (msg->payload.version->os) {
661 if (client->os) free(client->os);
662 client->os = strdup(msg->payload.version->os);
663 Log_debug("Client OS %s", client->os);
665 if (msg->payload.version->os_version) {
666 if (client->os_version) free(client->os_version);
667 client->os_version = strdup(msg->payload.version->os_version);
668 Log_debug("Client OS version %s", client->os_version);
671 case PermissionQuery:
672 Msg_inc_ref(msg); /* Re-use message */
673 msg->payload.permissionQuery->has_permissions = true;
676 msg->payload.permissionQuery->permissions = PERM_ADMIN;
678 msg->payload.permissionQuery->permissions = PERM_DEFAULT;
680 if (!getBoolConf(ALLOW_TEXTMESSAGE))
681 msg->payload.permissionQuery->permissions &= ~PERM_TEXTMESSAGE;
682 if (!getBoolConf(ENABLE_BAN))
683 msg->payload.permissionQuery->permissions &= ~PERM_BAN;
685 Client_send_message(client, msg);
688 client->bUDP = false;
689 Client_voiceMsg(client, msg->payload.UDPTunnel->packet.data, msg->payload.UDPTunnel->packet.len);
693 channel_t *ch_itr, *parent, *newchan;
695 /* Don't allow any changes to existing channels */
696 if (msg->payload.channelState->has_channel_id) {
697 sendPermissionDenied(client, "Not supported by uMurmur");
700 /* Must have parent */
701 if (!msg->payload.channelState->has_parent) {
702 sendPermissionDenied(client, "Not supported by uMurmur");
706 if (msg->payload.channelState->name == NULL) {
707 sendPermissionDenied(client, "Not supported by uMurmur");
710 /* Must be temporary channel */
711 if (msg->payload.channelState->temporary != true) {
712 sendPermissionDenied(client, "Only temporary channels are supported by uMurmur");
715 /* Check channel name is OK */
716 if (strlen(msg->payload.channelState->name) > MAX_TEXT) {
717 sendPermissionDenied(client, "Channel name too long");
721 parent = Chan_fromId(msg->payload.channelState->parent);
725 while (Chan_iterate_siblings(parent, &ch_itr) != NULL) {
726 if (strcmp(ch_itr->name, msg->payload.channelState->name) == 0) {
727 sendPermissionDenied(client, "Channel already exists");
734 /* Disallow temporary channels as siblings to temporary channels */
735 if (parent->temporary) {
736 sendPermissionDenied(client, "Parent channel is temporary channel");
740 /* XXX - Murmur looks for "\\w" and sends perm denied if not found.
741 * I don't know why so I don't do that here...
744 /* Create the channel */
745 newchan = Chan_createChannel(msg->payload.channelState->name,
746 msg->payload.channelState->description);
747 newchan->temporary = true;
748 Chan_addChannel(parent, newchan);
749 msg->payload.channelState->has_channel_id = true;
750 msg->payload.channelState->channel_id = newchan->id;
752 Client_send_message_except(NULL, msg);
754 /* Join the creating user */
755 sendmsg = Msg_create(UserState);
756 sendmsg->payload.userState->has_session = true;
757 sendmsg->payload.userState->session = client->sessionId;
758 sendmsg->payload.userState->has_channel_id = true;
759 sendmsg->payload.userState->channel_id = newchan->id;
760 Client_send_message_except(NULL, sendmsg);
762 leave_id = Chan_userJoin(newchan, client);
764 Log_debug("Removing channel ID %d", leave_id);
765 sendmsg = Msg_create(ChannelRemove);
766 sendmsg->payload.channelRemove->channel_id = leave_id;
767 Client_send_message_except(NULL, sendmsg);
774 client_t *target = NULL;
775 codec_t *codec_itr = NULL;
777 bool_t details = true;
779 if (msg->payload.userStats->has_stats_only)
780 details = !msg->payload.userStats->stats_only;
782 if (!msg->payload.userStats->has_session)
783 sendPermissionDenied(client, "Not supported by uMurmur");
784 while (Client_iterate(&target) != NULL) {
785 if (!IS_AUTH(target))
787 if (target->sessionId == msg->payload.userStats->session)
790 if (!target) /* Not found */
794 * Differences from Murmur:
795 * o Ignoring certificates intentionally
796 * o Ignoring channel local determining
799 sendmsg = Msg_create(UserStats);
800 sendmsg->payload.userStats->session = msg->payload.userStats->session;
801 sendmsg->payload.userStats->from_client->has_good = true;
802 sendmsg->payload.userStats->from_client->good = target->cryptState.uiGood;
803 sendmsg->payload.userStats->from_client->has_late = true;
804 sendmsg->payload.userStats->from_client->late = target->cryptState.uiLate;
805 sendmsg->payload.userStats->from_client->has_lost = true;
806 sendmsg->payload.userStats->from_client->lost = target->cryptState.uiLost;
807 sendmsg->payload.userStats->from_client->has_resync = true;
808 sendmsg->payload.userStats->from_client->resync = target->cryptState.uiResync;
810 sendmsg->payload.userStats->from_server->has_good = true;
811 sendmsg->payload.userStats->from_server->good = target->cryptState.uiRemoteGood;
812 sendmsg->payload.userStats->from_server->has_late = true;
813 sendmsg->payload.userStats->from_server->late = target->cryptState.uiRemoteLate;
814 sendmsg->payload.userStats->from_server->has_lost = true;
815 sendmsg->payload.userStats->from_server->lost = target->cryptState.uiRemoteLost;
816 sendmsg->payload.userStats->from_server->has_resync = true;
817 sendmsg->payload.userStats->from_server->resync = target->cryptState.uiRemoteResync;
819 sendmsg->payload.userStats->has_udp_packets = true;
820 sendmsg->payload.userStats->udp_packets = target->UDPPackets;
821 sendmsg->payload.userStats->has_udp_ping_avg = true;
822 sendmsg->payload.userStats->udp_ping_avg = target->UDPPingAvg;
823 sendmsg->payload.userStats->has_udp_ping_var = true;
824 sendmsg->payload.userStats->udp_ping_var = target->UDPPingVar;
826 sendmsg->payload.userStats->has_tcp_ping_avg = true;
827 sendmsg->payload.userStats->tcp_ping_avg = target->TCPPingAvg;
828 sendmsg->payload.userStats->has_tcp_ping_var = true;
829 sendmsg->payload.userStats->tcp_ping_var = target->TCPPingVar;
830 sendmsg->payload.userStats->has_tcp_packets = true;
831 sendmsg->payload.userStats->tcp_packets = target->TCPPackets;
835 sendmsg->payload.userStats->version->has_version = true;
836 sendmsg->payload.userStats->version->version = target->version;
837 sendmsg->payload.userStats->version->release = strdup(target->release);
838 sendmsg->payload.userStats->version->os = strdup(target->os);
839 sendmsg->payload.userStats->version->os_version = strdup(target->os_version);
841 sendmsg->payload.userStats->n_celt_versions = target->codec_count;
842 sendmsg->payload.userStats->celt_versions = malloc(sizeof(int32_t) * target->codec_count);
843 if (!sendmsg->payload.userStats->celt_versions)
844 Log_fatal("Out of memory");
846 while (Client_codec_iterate(target, &codec_itr) != NULL)
847 sendmsg->payload.userStats->celt_versions[i++] = codec_itr->codec;
849 sendmsg->payload.userStats->opus = target->bOpus;
852 sendmsg->payload.userStats->has_address = true;
853 sendmsg->payload.userStats->address.data = malloc(sizeof(uint8_t) * 16);
854 if (!sendmsg->payload.userStats->address.data)
855 Log_fatal("Out of memory");
856 memset(sendmsg->payload.userStats->address.data, 0, 16);
857 /* ipv4 representation as ipv6 address. Supposedly correct. */
858 memcpy(&sendmsg->payload.userStats->address.data[12], &target->remote_tcp.sin_addr, 4);
859 memset(&sendmsg->payload.userStats->address.data[10], 0xff, 2); /* IPv4 */
860 sendmsg->payload.userStats->address.len = 16;
863 sendmsg->payload.userStats->has_bandwidth = true;
864 sendmsg->payload.userStats->bandwidth = target->availableBandwidth;
867 sendmsg->payload.userStats->has_onlinesecs = true;
868 sendmsg->payload.userStats->onlinesecs = Timer_elapsed(&target->connectTime) / 1000000LL;
870 sendmsg->payload.userStats->has_idlesecs = true;
871 sendmsg->payload.userStats->idlesecs = Timer_elapsed(&target->idleTime) / 1000000LL;
872 Client_send_message(client, sendmsg);
877 /* Only admin can issue this */
878 if (!client->isAdmin) {
879 sendPermissionDenied(client, "Permission denied");
882 while (Client_iterate(&target) != NULL) {
883 if (target->sessionId == msg->payload.userRemove->session)
886 if (target == NULL) {
887 Log_warn("Client with sessionId %d not found", msg->payload.userRemove->session);
890 msg->payload.userRemove->session = target->sessionId;
891 msg->payload.userRemove->has_actor = true;
892 msg->payload.userRemove->actor = client->sessionId;
894 if (msg->payload.userRemove->has_ban && msg->payload.userRemove->ban) {
895 if (!getBoolConf(ENABLE_BAN))
896 sendPermissionDenied(client, "Permission denied");
898 Ban_UserBan(target, msg->payload.userRemove->reason);
900 Log_info_client(target, "User kicked. Reason: '%s'",
901 strlen(msg->payload.userRemove->reason) == 0 ? "N/A" : msg->payload.userRemove->reason);
906 Client_send_message_except(NULL, msg);
907 Client_close(target);
910 /* Only admin can issue this */
911 if (!client->isAdmin) {
912 sendPermissionDenied(client, "Permission denied");
915 if (!getBoolConf(ENABLE_BAN)) {
916 sendPermissionDenied(client, "Permission denied");
919 if (msg->payload.banList->has_query && msg->payload.banList->query) {
920 /* Create banlist message and add banentrys */
921 sendmsg = Ban_getBanList();
922 Client_send_message(client, sendmsg);
924 /* Clear banlist and set the new one */
926 Ban_putBanList(msg, msg->payload.banList->n_bans);
930 /* Permission denied for all these messages. Not implemented. */
933 case ContextActionAdd:
937 sendPermissionDenied(client, "Not supported by uMurmur");
941 Log_warn("Message %d not handled", msg->messageType);
950 Client_close(client);