1 /* Copyright (C) 2009-2014, Martin Johansson <martin@fatbob.nu>
2 Copyright (C) 2005-2014, 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) {
250 Client_textmessage(client, NO_CELT_MESSAGE);
253 /* Iterate channels and send channel info */
255 while (Chan_iterate(&ch_itr) != NULL) {
256 sendmsg = Msg_create(ChannelState);
257 sendmsg->payload.channelState->has_channel_id = true;
258 sendmsg->payload.channelState->channel_id = ch_itr->id;
259 if (ch_itr->id != 0) {
260 sendmsg->payload.channelState->has_parent = true;
261 sendmsg->payload.channelState->parent = ch_itr->parent->id;
263 sendmsg->payload.channelState->name = strdup(ch_itr->name);
265 sendmsg->payload.channelState->description = strdup(ch_itr->desc);
266 if (ch_itr->position != 0) {
267 sendmsg->payload.channelState->has_position = true;
268 sendmsg->payload.channelState->position = ch_itr->position;
270 Log_debug("Send channel info: %s", sendmsg->payload.channelState->name);
271 Client_send_message(client, sendmsg);
274 /* Iterate channels and send channel links info */
276 while (Chan_iterate(&ch_itr) != NULL) {
277 if (ch_itr->linkcount > 0) { /* Has links */
282 sendmsg = Msg_create(ChannelState);
283 sendmsg->payload.channelState->has_channel_id = true;
284 sendmsg->payload.channelState->channel_id = ch_itr->id;
285 sendmsg->payload.channelState->n_links = ch_itr->linkcount;
287 links = (uint32_t *)malloc(ch_itr->linkcount * sizeof(uint32_t));
288 list_iterate(itr, &ch_itr->channel_links) { /* Iterate links */
290 ch = list_get_entry(itr, channel_t, link_node);
293 sendmsg->payload.channelState->links = links;
294 Client_send_message(client, sendmsg);
298 /* Send user state for connecting user to other users */
299 sendmsg = Msg_create(UserState);
300 sendmsg->payload.userState->has_session = true;
301 sendmsg->payload.userState->session = client->sessionId;
302 sendmsg->payload.userState->name = strdup(client->username);
303 sendmsg->payload.userState->has_channel_id = true;
304 sendmsg->payload.userState->channel_id = ((channel_t *)client->channel)->id;
306 if (defaultChan->silent) {
307 sendmsg->payload.userState->has_suppress = true;
308 sendmsg->payload.userState->suppress = true;
311 Client_send_message_except(client, sendmsg);
314 while (Client_iterate(&client_itr) != NULL) {
315 if (!IS_AUTH(client_itr))
317 sendmsg = Msg_create(UserState);
318 sendmsg->payload.userState->has_session = true;
319 sendmsg->payload.userState->session = client_itr->sessionId;
320 sendmsg->payload.userState->name = strdup(client_itr->username);
321 sendmsg->payload.userState->has_channel_id = true;
322 sendmsg->payload.userState->channel_id = ((channel_t *)client_itr->channel)->id;
323 sendmsg->payload.userState->has_suppress = ((channel_t *)client_itr->channel)->silent;
324 sendmsg->payload.userState->suppress = ((channel_t *)client_itr->channel)->silent;
326 client_itr->isSuppressed = ((channel_t *)client_itr->channel)->silent;
328 if (client_itr->self_deaf) {
329 sendmsg->payload.userState->has_self_deaf = true;
330 sendmsg->payload.userState->self_deaf = true;
332 if (client_itr->self_mute) {
333 sendmsg->payload.userState->has_self_mute = true;
334 sendmsg->payload.userState->self_mute = true;
336 if (client_itr->deaf) {
337 sendmsg->payload.userState->has_deaf = true;
338 sendmsg->payload.userState->deaf = true;
340 if (client_itr->mute) {
341 sendmsg->payload.userState->has_mute = true;
342 sendmsg->payload.userState->mute = true;
344 if (client_itr->recording) {
345 sendmsg->payload.userState->has_recording = true;
346 sendmsg->payload.userState->recording = true;
348 Client_send_message(client, sendmsg);
352 sendmsg = Msg_create(ServerSync);
353 sendmsg->payload.serverSync->has_session = true;
354 sendmsg->payload.serverSync->session = client->sessionId;
355 sendmsg->payload.serverSync->welcome_text = strdup(getStrConf(WELCOMETEXT));
356 sendmsg->payload.serverSync->has_max_bandwidth = true;
357 sendmsg->payload.serverSync->max_bandwidth = getIntConf(MAX_BANDWIDTH);
358 Client_send_message(client, sendmsg);
360 /* Server config message */
361 sendmsg = Msg_create(ServerConfig);
362 sendmsg->payload.serverConfig->has_allow_html = true;
363 sendmsg->payload.serverConfig->allow_html = true; /* Support this? */
364 sendmsg->payload.serverConfig->has_message_length = true;
365 sendmsg->payload.serverConfig->message_length = MAX_TEXT; /* Hardcoded */
366 sendmsg->payload.serverConfig->has_image_message_length = true;
367 sendmsg->payload.serverConfig->image_message_length = 0; /* XXX */
368 Client_send_message(client, sendmsg);
370 Log_info_client(client, "User %s authenticated", client->username);
374 if (msg->payload.ping->has_good)
375 client->cryptState.uiRemoteGood = msg->payload.ping->good;
376 if (msg->payload.ping->has_late)
377 client->cryptState.uiRemoteLate = msg->payload.ping->late;
378 if (msg->payload.ping->has_lost)
379 client->cryptState.uiRemoteLost = msg->payload.ping->lost;
380 if (msg->payload.ping->has_resync)
381 client->cryptState.uiRemoteResync = msg->payload.ping->resync;
383 Log_debug("Ping <-: %d %d %d %d",
384 client->cryptState.uiRemoteGood, client->cryptState.uiRemoteLate,
385 client->cryptState.uiRemoteLost, client->cryptState.uiRemoteResync
388 client->UDPPingAvg = msg->payload.ping->udp_ping_avg;
389 client->UDPPingVar = msg->payload.ping->udp_ping_var;
390 client->TCPPingAvg = msg->payload.ping->tcp_ping_avg;
391 client->TCPPingVar = msg->payload.ping->tcp_ping_var;
392 client->UDPPackets = msg->payload.ping->udp_packets;
393 client->TCPPackets = msg->payload.ping->tcp_packets;
395 sendmsg = Msg_create(Ping);
397 sendmsg->payload.ping->timestamp = msg->payload.ping->timestamp;
398 sendmsg->payload.ping->has_timestamp = true;
399 sendmsg->payload.ping->good = client->cryptState.uiGood;
400 sendmsg->payload.ping->has_good = true;
401 sendmsg->payload.ping->late = client->cryptState.uiLate;
402 sendmsg->payload.ping->has_late = true;
403 sendmsg->payload.ping->lost = client->cryptState.uiLost;
404 sendmsg->payload.ping->has_lost = true;
405 sendmsg->payload.ping->resync = client->cryptState.uiResync;
406 sendmsg->payload.ping->has_resync = true;
408 Client_send_message(client, sendmsg);
409 Log_debug("Ping ->: %d %d %d %d",
410 client->cryptState.uiGood, client->cryptState.uiLate,
411 client->cryptState.uiLost, client->cryptState.uiResync);
415 Log_debug("Voice channel crypt resync requested");
416 if (!msg->payload.cryptSetup->has_client_nonce) {
417 sendmsg = Msg_create(CryptSetup);
418 sendmsg->payload.cryptSetup->has_server_nonce = true;
419 sendmsg->payload.cryptSetup->server_nonce.data = client->cryptState.decrypt_iv;
420 sendmsg->payload.cryptSetup->server_nonce.len = AES_BLOCK_SIZE;
421 Client_send_message(client, sendmsg);
423 memcpy(client->cryptState.decrypt_iv, msg->payload.cryptSetup->client_nonce.data, AES_BLOCK_SIZE);
424 client->cryptState.uiResync++;
429 /* Only allow state changes for for the self user unless an admin is issuing */
430 if (msg->payload.userState->has_session &&
431 msg->payload.userState->session != client->sessionId && !client->isAdmin) {
432 sendPermissionDenied(client, "Permission denied");
435 if (msg->payload.userState->has_session && msg->payload.userState->session != client->sessionId) {
436 while (Client_iterate(&target) != NULL) {
437 if (target->sessionId == msg->payload.userState->session)
440 if (target == NULL) {
441 Log_warn("Client with sessionID %d not found", msg->payload.userState->session);
446 if (msg->payload.userState->has_user_id || msg->payload.userState->has_suppress ||
447 msg->payload.userState->has_priority_speaker || msg->payload.userState->has_texture) {
448 sendPermissionDenied(client, "Not supported by uMurmur");
455 msg->payload.userState->has_session = true;
456 msg->payload.userState->session = target->sessionId;
457 msg->payload.userState->has_actor = true;
458 msg->payload.userState->actor = client->sessionId;
460 if (msg->payload.userState->has_deaf) {
461 target->deaf = msg->payload.userState->deaf;
463 msg->payload.userState->has_mute = true;
464 msg->payload.userState->mute = true;
467 if (msg->payload.userState->has_mute) {
468 target->mute = msg->payload.userState->mute;
470 msg->payload.userState->has_deaf = true;
471 msg->payload.userState->deaf = false;
472 target->deaf = false;
475 if (msg->payload.userState->has_self_deaf) {
476 client->self_deaf = msg->payload.userState->self_deaf;
477 if (client->self_deaf) {
478 msg->payload.userState->has_self_mute = true;
479 msg->payload.userState->self_mute = true;
482 if (msg->payload.userState->has_self_mute) {
483 client->self_mute = msg->payload.userState->self_mute;
484 if (!client->self_mute) {
485 msg->payload.userState->has_self_deaf = true;
486 msg->payload.userState->self_deaf = false;
487 client->self_deaf = false;
490 if (msg->payload.userState->has_recording &&
491 msg->payload.userState->recording != client->recording) {
492 client->recording = msg->payload.userState->recording;
496 message = malloc(strlen(client->username) + 32);
498 Log_fatal("Out of memory");
499 tree_id = malloc(sizeof(uint32_t));
501 Log_fatal("Out of memory");
503 sendmsg = Msg_create(TextMessage);
504 sendmsg->payload.textMessage->message = message;
505 sendmsg->payload.textMessage->n_tree_id = 1;
506 sendmsg->payload.textMessage->tree_id = tree_id;
507 if (client->recording)
508 sprintf(message, "User %s started recording", client->username);
510 sprintf(message, "User %s stopped recording", client->username);
511 Client_send_message_except_ver(NULL, sendmsg, ~0x010203);
514 if (msg->payload.userState->has_channel_id) {
517 channelJoinResult_t result = Chan_userJoin_id_test(msg->payload.userState->channel_id, target);
519 if (result.CHJOIN_NOENTER || result.CHJOIN_NOTFOUND)
522 if (result.CHJOIN_WRONGPW) {
523 if (target == client && !client->isAdmin) {
524 sendPermissionDenied(client, "Wrong channel password");
527 /* Tricky one: if user hasn't the password, but is moved to the channel by admin then let
528 * the user in. Also let admin user in regardless of channel password.
529 * Take no action on other errors.
531 else if (!client->isAdmin)
535 leave_id = Chan_userJoin_id(msg->payload.userState->channel_id, target);
537 Log_debug("Removing channel ID %d", leave_id);
538 sendmsg = Msg_create(ChannelRemove);
539 sendmsg->payload.channelRemove->channel_id = leave_id;
542 if (result.CHJOIN_SILENT) {
543 if (!target->isSuppressed) {
544 msg->payload.userState->has_suppress = true;
545 msg->payload.userState->suppress = true;
546 target->isSuppressed = true;
549 else if (target->isSuppressed) {
550 msg->payload.userState->has_suppress = true;
551 msg->payload.userState->suppress = false;
552 target->isSuppressed = false;
555 if (msg->payload.userState->has_plugin_context) {
557 free(client->context);
558 client->context = malloc(msg->payload.userState->plugin_context.len);
559 if (client->context == NULL)
560 Log_fatal("Out of memory");
561 memcpy(client->context, msg->payload.userState->plugin_context.data,
562 msg->payload.userState->plugin_context.len);
564 break; /* Don't inform other users about this state */
569 Client_send_message_except(NULL, msg);
571 /* Need to send remove channel message _after_ UserState message */
573 Client_send_message_except(NULL, sendmsg);
577 if (!getBoolConf(ALLOW_TEXTMESSAGE))
579 msg->payload.textMessage->has_actor = true;
580 msg->payload.textMessage->actor = client->sessionId;
582 /* XXX - HTML is allowed and can't be turned off */
583 if (msg->payload.textMessage->n_tree_id > 0) {
584 sendPermissionDenied(client, "Tree message not supported");
588 if (msg->payload.textMessage->n_channel_id > 0) { /* To channel */
591 for (i = 0; i < msg->payload.textMessage->n_channel_id; i++) {
594 Chan_iterate(&ch_itr);
595 } while (ch_itr != NULL && ch_itr->id != msg->payload.textMessage->channel_id[i]);
596 if (ch_itr != NULL) {
598 list_iterate(itr, &ch_itr->clients) {
600 c = list_get_entry(itr, client_t, chan_node);
601 if (c != client && !c->deaf && !c->self_deaf) {
603 Client_send_message(c, msg);
604 Log_debug("Text message to session ID %d", c->sessionId);
610 if (msg->payload.textMessage->n_session > 0) { /* To user */
613 for (i = 0; i < msg->payload.textMessage->n_session; i++) {
615 while (Client_iterate(&itr) != NULL) {
618 if (itr->sessionId == msg->payload.textMessage->session[i]) {
619 if (!itr->deaf && !itr->self_deaf) {
621 Client_send_message(itr, msg);
622 Log_debug("Text message to session ID %d", itr->sessionId);
628 Log_warn("TextMessage: Session ID %d not found", msg->payload.textMessage->session[i]);
635 int i, j, count, targetId = msg->payload.voiceTarget->id;
636 struct _MumbleProto__VoiceTarget__Target *target;
638 if (!targetId || targetId >= 0x1f)
640 Voicetarget_add_id(client, targetId);
641 count = msg->payload.voiceTarget->n_targets;
644 for (i = 0; i < count; i++) {
645 target = msg->payload.voiceTarget->targets[i];
646 for (j = 0; j < target->n_session; j++)
647 Voicetarget_add_session(client, targetId, target->session[j]);
648 if (target->has_channel_id) {
649 bool_t linked = false, children = false;
650 if (target->has_links)
651 linked = target->links;
652 if (target->has_children)
653 children = target->children;
654 Voicetarget_add_channel(client, targetId, target->channel_id, linked, children);
660 Log_debug("Version message received");
661 if (msg->payload.version->has_version) {
662 client->version = msg->payload.version->version;
663 Log_debug("Client version 0x%x", client->version);
665 if (msg->payload.version->release) {
666 if (client->release) free(client->release);
667 client->release = strdup(msg->payload.version->release);
668 Log_debug("Client release %s", client->release);
670 if (msg->payload.version->os) {
671 if (client->os) free(client->os);
672 client->os = strdup(msg->payload.version->os);
673 Log_debug("Client OS %s", client->os);
675 if (msg->payload.version->os_version) {
676 if (client->os_version) free(client->os_version);
677 client->os_version = strdup(msg->payload.version->os_version);
678 Log_debug("Client OS version %s", client->os_version);
681 case PermissionQuery:
682 Msg_inc_ref(msg); /* Re-use message */
683 msg->payload.permissionQuery->has_permissions = true;
686 msg->payload.permissionQuery->permissions = PERM_ADMIN;
688 msg->payload.permissionQuery->permissions = PERM_DEFAULT;
690 if (!getBoolConf(ALLOW_TEXTMESSAGE))
691 msg->payload.permissionQuery->permissions &= ~PERM_TEXTMESSAGE;
692 if (!getBoolConf(ENABLE_BAN))
693 msg->payload.permissionQuery->permissions &= ~PERM_BAN;
695 Client_send_message(client, msg);
698 client->bUDP = false;
699 Client_voiceMsg(client, msg->payload.UDPTunnel->packet.data, msg->payload.UDPTunnel->packet.len);
703 channel_t *ch_itr, *parent, *newchan;
705 /* Don't allow any changes to existing channels */
706 if (msg->payload.channelState->has_channel_id) {
707 sendPermissionDenied(client, "Not supported by uMurmur");
710 /* Must have parent */
711 if (!msg->payload.channelState->has_parent) {
712 sendPermissionDenied(client, "Not supported by uMurmur");
716 if (msg->payload.channelState->name == NULL) {
717 sendPermissionDenied(client, "Not supported by uMurmur");
720 /* Must be temporary channel */
721 if (msg->payload.channelState->temporary != true) {
722 sendPermissionDenied(client, "Only temporary channels are supported by uMurmur");
725 /* Check channel name is OK */
726 if (strlen(msg->payload.channelState->name) > MAX_TEXT) {
727 sendPermissionDenied(client, "Channel name too long");
731 parent = Chan_fromId(msg->payload.channelState->parent);
735 while (Chan_iterate_siblings(parent, &ch_itr) != NULL) {
736 if (strcmp(ch_itr->name, msg->payload.channelState->name) == 0) {
737 sendPermissionDenied(client, "Channel already exists");
744 /* Disallow temporary channels as siblings to temporary channels */
745 if (parent->temporary) {
746 sendPermissionDenied(client, "Parent channel is temporary channel");
750 /* XXX - Murmur looks for "\\w" and sends perm denied if not found.
751 * I don't know why so I don't do that here...
754 /* Create the channel */
755 newchan = Chan_createChannel(msg->payload.channelState->name,
756 msg->payload.channelState->description);
757 newchan->temporary = true;
758 if (msg->payload.channelState->has_position)
759 newchan->position = msg->payload.channelState->position;
760 Chan_addChannel(parent, newchan);
761 msg->payload.channelState->has_channel_id = true;
762 msg->payload.channelState->channel_id = newchan->id;
764 Client_send_message_except(NULL, msg);
766 /* Join the creating user */
767 sendmsg = Msg_create(UserState);
768 sendmsg->payload.userState->has_session = true;
769 sendmsg->payload.userState->session = client->sessionId;
770 sendmsg->payload.userState->has_channel_id = true;
771 sendmsg->payload.userState->channel_id = newchan->id;
773 if (client->isSuppressed) {
774 sendmsg->payload.userState->has_suppress = true;
775 sendmsg->payload.userState->suppress = false;
776 client->isSuppressed = false;
779 Client_send_message_except(NULL, sendmsg);
781 leave_id = Chan_userJoin(newchan, client);
783 Log_debug("Removing channel ID %d", leave_id);
784 sendmsg = Msg_create(ChannelRemove);
785 sendmsg->payload.channelRemove->channel_id = leave_id;
786 Client_send_message_except(NULL, sendmsg);
793 client_t *target = NULL;
794 codec_t *codec_itr = NULL;
796 bool_t details = true;
798 if (msg->payload.userStats->has_stats_only)
799 details = !msg->payload.userStats->stats_only;
801 if (!msg->payload.userStats->has_session)
802 sendPermissionDenied(client, "Not supported by uMurmur");
803 while (Client_iterate(&target) != NULL) {
804 if (!IS_AUTH(target))
806 if (target->sessionId == msg->payload.userStats->session)
809 if (!target) /* Not found */
813 * Differences from Murmur:
814 * o Ignoring certificates intentionally
815 * o Ignoring channel local determining
818 sendmsg = Msg_create(UserStats);
819 sendmsg->payload.userStats->session = msg->payload.userStats->session;
820 sendmsg->payload.userStats->from_client->has_good = true;
821 sendmsg->payload.userStats->from_client->good = target->cryptState.uiGood;
822 sendmsg->payload.userStats->from_client->has_late = true;
823 sendmsg->payload.userStats->from_client->late = target->cryptState.uiLate;
824 sendmsg->payload.userStats->from_client->has_lost = true;
825 sendmsg->payload.userStats->from_client->lost = target->cryptState.uiLost;
826 sendmsg->payload.userStats->from_client->has_resync = true;
827 sendmsg->payload.userStats->from_client->resync = target->cryptState.uiResync;
829 sendmsg->payload.userStats->from_server->has_good = true;
830 sendmsg->payload.userStats->from_server->good = target->cryptState.uiRemoteGood;
831 sendmsg->payload.userStats->from_server->has_late = true;
832 sendmsg->payload.userStats->from_server->late = target->cryptState.uiRemoteLate;
833 sendmsg->payload.userStats->from_server->has_lost = true;
834 sendmsg->payload.userStats->from_server->lost = target->cryptState.uiRemoteLost;
835 sendmsg->payload.userStats->from_server->has_resync = true;
836 sendmsg->payload.userStats->from_server->resync = target->cryptState.uiRemoteResync;
838 sendmsg->payload.userStats->has_udp_packets = true;
839 sendmsg->payload.userStats->udp_packets = target->UDPPackets;
840 sendmsg->payload.userStats->has_udp_ping_avg = true;
841 sendmsg->payload.userStats->udp_ping_avg = target->UDPPingAvg;
842 sendmsg->payload.userStats->has_udp_ping_var = true;
843 sendmsg->payload.userStats->udp_ping_var = target->UDPPingVar;
845 sendmsg->payload.userStats->has_tcp_ping_avg = true;
846 sendmsg->payload.userStats->tcp_ping_avg = target->TCPPingAvg;
847 sendmsg->payload.userStats->has_tcp_ping_var = true;
848 sendmsg->payload.userStats->tcp_ping_var = target->TCPPingVar;
849 sendmsg->payload.userStats->has_tcp_packets = true;
850 sendmsg->payload.userStats->tcp_packets = target->TCPPackets;
854 sendmsg->payload.userStats->version->has_version = true;
855 sendmsg->payload.userStats->version->version = target->version;
857 sendmsg->payload.userStats->version->release = strdup(target->release);
859 sendmsg->payload.userStats->version->os = strdup(target->os);
860 if (target->os_version)
861 sendmsg->payload.userStats->version->os_version = strdup(target->os_version);
863 sendmsg->payload.userStats->n_celt_versions = target->codec_count;
864 sendmsg->payload.userStats->celt_versions = malloc(sizeof(int32_t) * target->codec_count);
865 if (!sendmsg->payload.userStats->celt_versions)
866 Log_fatal("Out of memory");
868 while (Client_codec_iterate(target, &codec_itr) != NULL)
869 sendmsg->payload.userStats->celt_versions[i++] = codec_itr->codec;
871 sendmsg->payload.userStats->has_opus = true;
872 sendmsg->payload.userStats->opus = target->bOpus;
875 sendmsg->payload.userStats->has_address = true;
876 sendmsg->payload.userStats->address.data = malloc(sizeof(uint8_t) * 16);
877 if (!sendmsg->payload.userStats->address.data)
878 Log_fatal("Out of memory");
879 memset(sendmsg->payload.userStats->address.data, 0, 16);
880 /* ipv4 representation as ipv6 address. Supposedly correct. */
881 memcpy(&sendmsg->payload.userStats->address.data[12], &target->remote_tcp.sin_addr, 4);
882 memset(&sendmsg->payload.userStats->address.data[10], 0xff, 2); /* IPv4 */
883 sendmsg->payload.userStats->address.len = 16;
886 sendmsg->payload.userStats->has_bandwidth = true;
887 sendmsg->payload.userStats->bandwidth = target->availableBandwidth;
890 sendmsg->payload.userStats->has_onlinesecs = true;
891 sendmsg->payload.userStats->onlinesecs = Timer_elapsed(&target->connectTime) / 1000000LL;
893 sendmsg->payload.userStats->has_idlesecs = true;
894 sendmsg->payload.userStats->idlesecs = Timer_elapsed(&target->idleTime) / 1000000LL;
895 Client_send_message(client, sendmsg);
900 /* Only admin can issue this */
901 if (!client->isAdmin) {
902 sendPermissionDenied(client, "Permission denied");
905 while (Client_iterate(&target) != NULL) {
906 if (target->sessionId == msg->payload.userRemove->session)
909 if (target == NULL) {
910 Log_warn("Client with sessionId %d not found", msg->payload.userRemove->session);
913 msg->payload.userRemove->session = target->sessionId;
914 msg->payload.userRemove->has_actor = true;
915 msg->payload.userRemove->actor = client->sessionId;
917 if (msg->payload.userRemove->has_ban && msg->payload.userRemove->ban) {
918 if (!getBoolConf(ENABLE_BAN))
919 sendPermissionDenied(client, "Permission denied");
921 Ban_UserBan(target, msg->payload.userRemove->reason);
923 Log_info_client(target, "User kicked. Reason: '%s'",
924 strlen(msg->payload.userRemove->reason) == 0 ? "N/A" : msg->payload.userRemove->reason);
929 Client_send_message_except(NULL, msg);
930 Client_close(target);
933 /* Only admin can issue this */
934 if (!client->isAdmin) {
935 sendPermissionDenied(client, "Permission denied");
938 if (!getBoolConf(ENABLE_BAN)) {
939 sendPermissionDenied(client, "Permission denied");
942 if (msg->payload.banList->has_query && msg->payload.banList->query) {
943 /* Create banlist message and add banentrys */
944 sendmsg = Ban_getBanList();
945 Client_send_message(client, sendmsg);
947 /* Clear banlist and set the new one */
949 Ban_putBanList(msg, msg->payload.banList->n_bans);
953 /* Permission denied for all these messages. Not implemented. */
956 case ContextActionAdd:
960 sendPermissionDenied(client, "Not supported by uMurmur");
964 Log_warn("Message %d not handled", msg->messageType);
973 Client_close(client);