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 extern channel_t *defaultChan;
49 extern int iCodecAlpha, iCodecBeta;
50 extern bool_t bPreferAlpha;
52 static void sendServerReject(client_t *client, const char *reason, MumbleProto__Reject__RejectType type)
54 message_t *msg = Msg_create(Reject);
55 msg->payload.reject->reason = strdup(reason);
56 msg->payload.reject->type = type;
57 msg->payload.reject->has_type = true;
58 Client_send_message(client, msg);
60 Log_info_client(client, "Server reject reason: %s", reason);
63 static void sendPermissionDenied(client_t *client, const char *reason)
65 message_t *msg = Msg_create(PermissionDenied);
66 msg->payload.permissionDenied->has_type = true;
67 msg->payload.permissionDenied->type = MUMBLE_PROTO__PERMISSION_DENIED__DENY_TYPE__Text;
68 msg->payload.permissionDenied->reason = strdup(reason);
69 Client_send_message(client, msg);
72 static void addTokens(client_t *client, message_t *msg)
75 if (client->tokencount + msg->payload.authenticate->n_tokens < MAX_TOKENS) {
76 /* Check lengths first */
77 for (i = 0; i < msg->payload.authenticate->n_tokens; i++) {
78 if (strlen(msg->payload.authenticate->tokens[i]) > MAX_TOKENSIZE - 1) {
79 sendPermissionDenied(client, "Too long token");
84 for (i = 0; i < msg->payload.authenticate->n_tokens; i++) {
85 Log_debug("Adding token '%s' to client '%s'", msg->payload.authenticate->tokens[i], client->username);
86 Client_token_add(client, msg->payload.authenticate->tokens[i]);
90 sendPermissionDenied(client, "Too many tokens");
93 void Mh_handle_message(client_t *client, message_t *msg)
95 message_t *sendmsg = NULL;
96 channel_t *ch_itr = NULL;
97 client_t *client_itr, *target;
99 if (!client->authenticated && !(msg->messageType == Authenticate ||
100 msg->messageType == Version)) {
104 switch (msg->messageType) {
110 case PermissionQuery:
113 Timer_restart(&client->idleTime);
116 switch (msg->messageType) {
118 Log_debug("Authenticate message received");
120 if (IS_AUTH(client) || !msg->payload.authenticate->username) {
121 /* Authenticate message might be sent when a tokens are changed by the user.*/
122 Client_token_free(client); /* Clear the token list */
123 if (msg->payload.authenticate->n_tokens > 0) {
124 Log_debug("Tokens in auth message from '%s'. n_tokens = %d", client->username,
125 msg->payload.authenticate->n_tokens);
126 addTokens(client, msg);
131 if (SSLi_getSHA1Hash(client->ssl, client->hash) && Ban_isBanned(client)) {
133 SSLi_hash2hex(client->hash, hexhash);
134 Log_info("Client with hash '%s' is banned. Disconnecting", hexhash);
138 client->authenticated = true;
141 while (Client_iterate(&client_itr) != NULL) {
142 if (!IS_AUTH(client_itr))
144 if (client_itr->username && strncmp(client_itr->username, msg->payload.authenticate->username, MAX_USERNAME) == 0) {
146 sprintf(buf, "Username already in use");
147 Log_debug("Username already in use");
148 sendServerReject(client, buf, MUMBLE_PROTO__REJECT__REJECT_TYPE__UsernameInUse);
152 if (strlen(getStrConf(PASSPHRASE)) > 0) {
153 if (!msg->payload.authenticate->password ||
154 (msg->payload.authenticate->password &&
155 strncmp(getStrConf(PASSPHRASE), msg->payload.authenticate->password, MAX_TEXT) != 0)) {
157 sprintf(buf, "Wrong server password");
158 sendServerReject(client, buf, MUMBLE_PROTO__REJECT__REJECT_TYPE__WrongServerPW);
159 Log_debug("Wrong server password: '%s'", msg->payload.authenticate->password != NULL ?
160 msg->payload.authenticate->password : "(null)");
164 if (strlen(msg->payload.authenticate->username) == 0 ||
165 strlen(msg->payload.authenticate->username) >= MAX_USERNAME) { /* XXX - other invalid names? */
167 sprintf(buf, "Invalid username");
168 Log_debug("Invalid username");
169 sendServerReject(client, buf, MUMBLE_PROTO__REJECT__REJECT_TYPE__InvalidUsername);
173 if (Client_count() >= getIntConf(MAX_CLIENTS)) {
175 snprintf(buf, 64, "Server is full (max %d users)", getIntConf(MAX_CLIENTS));
176 sendServerReject(client, buf, MUMBLE_PROTO__REJECT__REJECT_TYPE__ServerFull);
181 client->username = strdup(msg->payload.authenticate->username);
184 if (msg->payload.authenticate->n_tokens > 0)
185 addTokens(client, msg);
187 /* Check if admin PW among tokens */
188 if (strlen(getStrConf(ADMIN_PASSPHRASE)) > 0 &&
189 Client_token_match(client, getStrConf(ADMIN_PASSPHRASE))) {
190 client->isAdmin = true;
191 Log_info_client(client, "User provided admin password");
194 /* Setup UDP encryption */
195 CryptState_init(&client->cryptState);
196 CryptState_genKey(&client->cryptState);
197 sendmsg = Msg_create(CryptSetup);
198 sendmsg->payload.cryptSetup->has_key = true;
199 sendmsg->payload.cryptSetup->key.data = client->cryptState.raw_key;
200 sendmsg->payload.cryptSetup->key.len = AES_BLOCK_SIZE;
201 sendmsg->payload.cryptSetup->has_server_nonce = true;
202 sendmsg->payload.cryptSetup->server_nonce.data = client->cryptState.encrypt_iv;
203 sendmsg->payload.cryptSetup->server_nonce.len = AES_BLOCK_SIZE;
204 sendmsg->payload.cryptSetup->has_client_nonce = true;
205 sendmsg->payload.cryptSetup->client_nonce.data = client->cryptState.decrypt_iv;
206 sendmsg->payload.cryptSetup->client_nonce.len = AES_BLOCK_SIZE;
207 Client_send_message(client, sendmsg);
210 Chan_userJoin(defaultChan, client); /* Join default channel */
213 Log_debug("Client %d has %d CELT codecs", client->sessionId,
214 msg->payload.authenticate->n_celt_versions);
215 if (msg->payload.authenticate->n_celt_versions > 0) {
218 client->codec_count = msg->payload.authenticate->n_celt_versions;
220 for (i = 0; i < client->codec_count; i++)
221 Client_codec_add(client, msg->payload.authenticate->celt_versions[i]);
223 while (Client_codec_iterate(client, &codec_itr) != NULL)
224 Log_debug("Client %d CELT codec ver 0x%x", client->sessionId, codec_itr->codec);
227 Client_codec_add(client, (int32_t)0x8000000a);
228 client->codec_count = 1;
231 recheckCodecVersions();
233 sendmsg = Msg_create(CodecVersion);
234 sendmsg->payload.codecVersion->alpha = iCodecAlpha;
235 sendmsg->payload.codecVersion->beta = iCodecBeta;
236 sendmsg->payload.codecVersion->prefer_alpha = bPreferAlpha;
237 Client_send_message(client, sendmsg);
239 /* Iterate channels and send channel info */
241 while (Chan_iterate(&ch_itr) != NULL) {
242 sendmsg = Msg_create(ChannelState);
243 sendmsg->payload.channelState->has_channel_id = true;
244 sendmsg->payload.channelState->channel_id = ch_itr->id;
245 if (ch_itr->id != 0) {
246 sendmsg->payload.channelState->has_parent = true;
247 sendmsg->payload.channelState->parent = ch_itr->parent->id;
249 sendmsg->payload.channelState->name = strdup(ch_itr->name);
251 sendmsg->payload.channelState->description = strdup(ch_itr->desc);
252 Log_debug("Send channel info: %s", sendmsg->payload.channelState->name);
253 Client_send_message(client, sendmsg);
256 /* Iterate channels and send channel links info */
258 while (Chan_iterate(&ch_itr) != NULL) {
259 if (ch_itr->linkcount > 0) { /* Has links */
264 sendmsg = Msg_create(ChannelState);
265 sendmsg->payload.channelState->has_channel_id = true;
266 sendmsg->payload.channelState->channel_id = ch_itr->id;
267 sendmsg->payload.channelState->n_links = ch_itr->linkcount;
269 links = (uint32_t *)malloc(ch_itr->linkcount * sizeof(uint32_t));
270 list_iterate(itr, &ch_itr->channel_links) { /* Iterate links */
272 ch = list_get_entry(itr, channel_t, link_node);
275 sendmsg->payload.channelState->links = links;
276 Client_send_message(client, sendmsg);
280 /* Send user state for connecting user to other users */
281 sendmsg = Msg_create(UserState);
282 sendmsg->payload.userState->has_session = true;
283 sendmsg->payload.userState->session = client->sessionId;
284 sendmsg->payload.userState->name = strdup(client->username);
285 sendmsg->payload.userState->has_channel_id = true;
286 sendmsg->payload.userState->channel_id = ((channel_t *)client->channel)->id;
288 Client_send_message_except(client, sendmsg);
291 while (Client_iterate(&client_itr) != NULL) {
292 if (!IS_AUTH(client_itr))
294 sendmsg = Msg_create(UserState);
295 sendmsg->payload.userState->has_session = true;
296 sendmsg->payload.userState->session = client_itr->sessionId;
297 sendmsg->payload.userState->name = strdup(client_itr->username);
298 sendmsg->payload.userState->has_channel_id = true;
299 sendmsg->payload.userState->channel_id = ((channel_t *)client_itr->channel)->id;
301 if (client_itr->self_deaf) {
302 sendmsg->payload.userState->has_self_deaf = true;
303 sendmsg->payload.userState->self_deaf = true;
305 if (client_itr->self_mute) {
306 sendmsg->payload.userState->has_self_mute = true;
307 sendmsg->payload.userState->self_mute = true;
309 if (client_itr->deaf) {
310 sendmsg->payload.userState->has_deaf = true;
311 sendmsg->payload.userState->deaf = true;
313 if (client_itr->mute) {
314 sendmsg->payload.userState->has_mute = true;
315 sendmsg->payload.userState->mute = true;
317 if (client_itr->recording) {
318 sendmsg->payload.userState->has_recording = true;
319 sendmsg->payload.userState->recording = true;
321 Client_send_message(client, sendmsg);
325 sendmsg = Msg_create(ServerSync);
326 sendmsg->payload.serverSync->has_session = true;
327 sendmsg->payload.serverSync->session = client->sessionId;
328 sendmsg->payload.serverSync->welcome_text = strdup(getStrConf(WELCOMETEXT));
329 sendmsg->payload.serverSync->has_max_bandwidth = true;
330 sendmsg->payload.serverSync->max_bandwidth = getIntConf(MAX_BANDWIDTH);
331 Client_send_message(client, sendmsg);
333 /* Server config message */
334 sendmsg = Msg_create(ServerConfig);
335 sendmsg->payload.serverConfig->has_allow_html = true;
336 sendmsg->payload.serverConfig->allow_html = true; /* Support this? */
337 sendmsg->payload.serverConfig->has_message_length = true;
338 sendmsg->payload.serverConfig->message_length = MAX_TEXT; /* Hardcoded */
339 sendmsg->payload.serverConfig->has_image_message_length = true;
340 sendmsg->payload.serverConfig->image_message_length = 0; /* XXX */
341 Client_send_message(client, sendmsg);
343 Log_info_client(client, "User %s authenticated", client->username);
347 if (msg->payload.ping->has_good)
348 client->cryptState.uiRemoteGood = msg->payload.ping->good;
349 if (msg->payload.ping->has_late)
350 client->cryptState.uiRemoteLate = msg->payload.ping->late;
351 if (msg->payload.ping->has_lost)
352 client->cryptState.uiRemoteLost = msg->payload.ping->lost;
353 if (msg->payload.ping->has_resync)
354 client->cryptState.uiRemoteResync = msg->payload.ping->resync;
356 Log_debug("Ping <-: %d %d %d %d",
357 client->cryptState.uiRemoteGood, client->cryptState.uiRemoteLate,
358 client->cryptState.uiRemoteLost, client->cryptState.uiRemoteResync
361 client->UDPPingAvg = msg->payload.ping->udp_ping_avg;
362 client->UDPPingVar = msg->payload.ping->udp_ping_var;
363 client->TCPPingAvg = msg->payload.ping->tcp_ping_avg;
364 client->TCPPingVar = msg->payload.ping->tcp_ping_var;
365 client->UDPPackets = msg->payload.ping->udp_packets;
366 client->TCPPackets = msg->payload.ping->tcp_packets;
368 sendmsg = Msg_create(Ping);
370 sendmsg->payload.ping->timestamp = msg->payload.ping->timestamp;
371 sendmsg->payload.ping->has_timestamp = true;
372 sendmsg->payload.ping->good = client->cryptState.uiGood;
373 sendmsg->payload.ping->has_good = true;
374 sendmsg->payload.ping->late = client->cryptState.uiLate;
375 sendmsg->payload.ping->has_late = true;
376 sendmsg->payload.ping->lost = client->cryptState.uiLost;
377 sendmsg->payload.ping->has_lost = true;
378 sendmsg->payload.ping->resync = client->cryptState.uiResync;
379 sendmsg->payload.ping->has_resync = true;
381 Client_send_message(client, sendmsg);
382 Log_debug("Ping ->: %d %d %d %d",
383 client->cryptState.uiGood, client->cryptState.uiLate,
384 client->cryptState.uiLost, client->cryptState.uiResync);
388 Log_debug("Voice channel crypt resync requested");
389 if (!msg->payload.cryptSetup->has_client_nonce) {
390 sendmsg = Msg_create(CryptSetup);
391 sendmsg->payload.cryptSetup->has_server_nonce = true;
392 sendmsg->payload.cryptSetup->server_nonce.data = client->cryptState.decrypt_iv;
393 sendmsg->payload.cryptSetup->server_nonce.len = AES_BLOCK_SIZE;
394 Client_send_message(client, sendmsg);
396 memcpy(client->cryptState.decrypt_iv, msg->payload.cryptSetup->client_nonce.data, AES_BLOCK_SIZE);
397 client->cryptState.uiResync++;
402 /* Only allow state changes for for the self user unless an admin is issuing */
403 if (msg->payload.userState->has_session &&
404 msg->payload.userState->session != client->sessionId && !client->isAdmin) {
405 sendPermissionDenied(client, "Permission denied");
408 if (msg->payload.userState->has_session && msg->payload.userState->session != client->sessionId) {
409 while (Client_iterate(&target) != NULL) {
410 if (target->sessionId == msg->payload.userState->session)
413 if (target == NULL) {
414 Log_warn("Client with sessionID %d not found", msg->payload.userState->session);
419 if (msg->payload.userState->has_user_id || msg->payload.userState->has_suppress ||
420 msg->payload.userState->has_priority_speaker || msg->payload.userState->has_texture) {
421 sendPermissionDenied(client, "Not supported by uMurmur");
428 msg->payload.userState->has_session = true;
429 msg->payload.userState->session = target->sessionId;
430 msg->payload.userState->has_actor = true;
431 msg->payload.userState->actor = client->sessionId;
433 if (msg->payload.userState->has_deaf) {
434 target->deaf = msg->payload.userState->deaf;
436 msg->payload.userState->has_mute = true;
437 msg->payload.userState->mute = true;
440 if (msg->payload.userState->has_mute) {
441 target->mute = msg->payload.userState->mute;
443 msg->payload.userState->has_deaf = true;
444 msg->payload.userState->deaf = false;
445 target->deaf = false;
448 if (msg->payload.userState->has_self_deaf) {
449 client->self_deaf = msg->payload.userState->self_deaf;
450 if (client->self_deaf) {
451 msg->payload.userState->has_self_mute = true;
452 msg->payload.userState->self_mute = true;
455 if (msg->payload.userState->has_self_mute) {
456 client->self_mute = msg->payload.userState->self_mute;
457 if (!client->self_mute) {
458 msg->payload.userState->has_self_deaf = true;
459 msg->payload.userState->self_deaf = false;
460 client->self_deaf = false;
463 if (msg->payload.userState->has_recording &&
464 msg->payload.userState->recording != client->recording) {
465 client->recording = msg->payload.userState->recording;
469 message = malloc(strlen(client->username) + 32);
471 Log_fatal("Out of memory");
472 tree_id = malloc(sizeof(uint32_t));
474 Log_fatal("Out of memory");
476 sendmsg = Msg_create(TextMessage);
477 sendmsg->payload.textMessage->message = message;
478 sendmsg->payload.textMessage->n_tree_id = 1;
479 sendmsg->payload.textMessage->tree_id = tree_id;
480 if (client->recording)
481 sprintf(message, "User %s started recording", client->username);
483 sprintf(message, "User %s stopped recording", client->username);
484 Client_send_message_except_ver(NULL, sendmsg, ~0x010203);
487 if (msg->payload.userState->has_channel_id) {
489 channelJoinResult_t chjoin_rc = Chan_userJoin_id_test(msg->payload.userState->channel_id, target);
491 if (chjoin_rc != CHJOIN_OK) {
492 if (chjoin_rc == CHJOIN_WRONGPW) {
493 if (target == client && !client->isAdmin) {
494 sendPermissionDenied(client, "Wrong channel password");
497 /* Tricky one: if user hasn't the password, but is moved to the channel by admin then let
498 * the user in. Also let admin user in regardless of channel password.
499 * Take no action on other errors.
501 else if (!client->isAdmin)
507 leave_id = Chan_userJoin_id(msg->payload.userState->channel_id, target);
509 Log_debug("Removing channel ID %d", leave_id);
510 sendmsg = Msg_create(ChannelRemove);
511 sendmsg->payload.channelRemove->channel_id = leave_id;
514 if (msg->payload.userState->has_plugin_context) {
516 free(client->context);
517 client->context = malloc(msg->payload.userState->plugin_context.len);
518 if (client->context == NULL)
519 Log_fatal("Out of memory");
520 memcpy(client->context, msg->payload.userState->plugin_context.data,
521 msg->payload.userState->plugin_context.len);
523 break; /* Don't inform other users about this state */
528 Client_send_message_except(NULL, msg);
530 /* Need to send remove channel message _after_ UserState message */
532 Client_send_message_except(NULL, sendmsg);
536 if (!getBoolConf(ALLOW_TEXTMESSAGE))
538 msg->payload.textMessage->has_actor = true;
539 msg->payload.textMessage->actor = client->sessionId;
541 /* XXX - HTML is allowed and can't be turned off */
542 if (msg->payload.textMessage->n_tree_id > 0) {
543 sendPermissionDenied(client, "Tree message not supported");
547 if (msg->payload.textMessage->n_channel_id > 0) { /* To channel */
550 for (i = 0; i < msg->payload.textMessage->n_channel_id; i++) {
553 Chan_iterate(&ch_itr);
554 } while (ch_itr != NULL && ch_itr->id != msg->payload.textMessage->channel_id[i]);
555 if (ch_itr != NULL) {
557 list_iterate(itr, &ch_itr->clients) {
559 c = list_get_entry(itr, client_t, chan_node);
560 if (c != client && !c->deaf && !c->self_deaf) {
562 Client_send_message(c, msg);
563 Log_debug("Text message to session ID %d", c->sessionId);
569 if (msg->payload.textMessage->n_session > 0) { /* To user */
572 for (i = 0; i < msg->payload.textMessage->n_session; i++) {
574 while (Client_iterate(&itr) != NULL) {
577 if (itr->sessionId == msg->payload.textMessage->session[i]) {
578 if (!itr->deaf && !itr->self_deaf) {
580 Client_send_message(itr, msg);
581 Log_debug("Text message to session ID %d", itr->sessionId);
587 Log_warn("TextMessage: Session ID %d not found", msg->payload.textMessage->session[i]);
594 int i, j, count, targetId = msg->payload.voiceTarget->id;
595 struct _MumbleProto__VoiceTarget__Target *target;
597 if (!targetId || targetId >= 0x1f)
599 Voicetarget_add_id(client, targetId);
600 count = msg->payload.voiceTarget->n_targets;
603 for (i = 0; i < count; i++) {
604 target = msg->payload.voiceTarget->targets[i];
605 for (j = 0; j < target->n_session; j++)
606 Voicetarget_add_session(client, targetId, target->session[j]);
607 if (target->has_channel_id) {
608 bool_t linked = false, children = false;
609 if (target->has_links)
610 linked = target->links;
611 if (target->has_children)
612 children = target->children;
613 Voicetarget_add_channel(client, targetId, target->channel_id, linked, children);
619 Log_debug("Version message received");
620 if (msg->payload.version->has_version) {
621 client->version = msg->payload.version->version;
622 Log_debug("Client version 0x%x", client->version);
624 if (msg->payload.version->release) {
625 if (client->release) free(client->release);
626 client->release = strdup(msg->payload.version->release);
627 Log_debug("Client release %s", client->release);
629 if (msg->payload.version->os) {
630 if (client->os) free(client->os);
631 client->os = strdup(msg->payload.version->os);
632 Log_debug("Client OS %s", client->os);
634 if (msg->payload.version->os_version) {
635 if (client->os_version) free(client->os_version);
636 client->os_version = strdup(msg->payload.version->os_version);
637 Log_debug("Client OS version %s", client->os_version);
640 case PermissionQuery:
641 Msg_inc_ref(msg); /* Re-use message */
642 msg->payload.permissionQuery->has_permissions = true;
645 msg->payload.permissionQuery->permissions = PERM_ADMIN;
647 msg->payload.permissionQuery->permissions = PERM_DEFAULT;
649 if (!getBoolConf(ALLOW_TEXTMESSAGE))
650 msg->payload.permissionQuery->permissions &= ~PERM_TEXTMESSAGE;
651 if (!getBoolConf(ENABLE_BAN))
652 msg->payload.permissionQuery->permissions &= ~PERM_BAN;
654 Client_send_message(client, msg);
657 client->bUDP = false;
658 Client_voiceMsg(client, msg->payload.UDPTunnel->packet.data, msg->payload.UDPTunnel->packet.len);
662 channel_t *ch_itr, *parent, *newchan;
664 /* Don't allow any changes to existing channels */
665 if (msg->payload.channelState->has_channel_id) {
666 sendPermissionDenied(client, "Not supported by uMurmur");
669 /* Must have parent */
670 if (!msg->payload.channelState->has_parent) {
671 sendPermissionDenied(client, "Not supported by uMurmur");
675 if (msg->payload.channelState->name == NULL) {
676 sendPermissionDenied(client, "Not supported by uMurmur");
679 /* Must be temporary channel */
680 if (msg->payload.channelState->temporary != true) {
681 sendPermissionDenied(client, "Only temporary channels are supported by uMurmur");
684 /* Check channel name is OK */
685 if (strlen(msg->payload.channelState->name) > MAX_TEXT) {
686 sendPermissionDenied(client, "Channel name too long");
690 parent = Chan_fromId(msg->payload.channelState->parent);
694 while (Chan_iterate_siblings(parent, &ch_itr) != NULL) {
695 if (strcmp(ch_itr->name, msg->payload.channelState->name) == 0) {
696 sendPermissionDenied(client, "Channel already exists");
703 /* Disallow temporary channels as siblings to temporary channels */
704 if (parent->temporary) {
705 sendPermissionDenied(client, "Parent channel is temporary channel");
709 /* XXX - Murmur looks for "\\w" and sends perm denied if not found.
710 * I don't know why so I don't do that here...
713 /* Create the channel */
714 newchan = Chan_createChannel(msg->payload.channelState->name,
715 msg->payload.channelState->description);
716 newchan->temporary = true;
717 Chan_addChannel(parent, newchan);
718 msg->payload.channelState->has_channel_id = true;
719 msg->payload.channelState->channel_id = newchan->id;
721 Client_send_message_except(NULL, msg);
723 /* Join the creating user */
724 sendmsg = Msg_create(UserState);
725 sendmsg->payload.userState->has_session = true;
726 sendmsg->payload.userState->session = client->sessionId;
727 sendmsg->payload.userState->has_channel_id = true;
728 sendmsg->payload.userState->channel_id = newchan->id;
729 Client_send_message_except(NULL, sendmsg);
731 leave_id = Chan_userJoin(newchan, client);
733 Log_debug("Removing channel ID %d", leave_id);
734 sendmsg = Msg_create(ChannelRemove);
735 sendmsg->payload.channelRemove->channel_id = leave_id;
736 Client_send_message_except(NULL, sendmsg);
743 client_t *target = NULL;
744 codec_t *codec_itr = NULL;
746 bool_t details = true;
748 if (msg->payload.userStats->has_stats_only)
749 details = !msg->payload.userStats->stats_only;
751 if (!msg->payload.userStats->has_session)
752 sendPermissionDenied(client, "Not supported by uMurmur");
753 while (Client_iterate(&target) != NULL) {
754 if (!IS_AUTH(target))
756 if (target->sessionId == msg->payload.userStats->session)
759 if (!target) /* Not found */
763 * Differences from Murmur:
764 * o Ignoring certificates intentionally
765 * o Ignoring channel local determining
768 sendmsg = Msg_create(UserStats);
769 sendmsg->payload.userStats->session = msg->payload.userStats->session;
770 sendmsg->payload.userStats->from_client->has_good = true;
771 sendmsg->payload.userStats->from_client->good = target->cryptState.uiGood;
772 sendmsg->payload.userStats->from_client->has_late = true;
773 sendmsg->payload.userStats->from_client->late = target->cryptState.uiLate;
774 sendmsg->payload.userStats->from_client->has_lost = true;
775 sendmsg->payload.userStats->from_client->lost = target->cryptState.uiLost;
776 sendmsg->payload.userStats->from_client->has_resync = true;
777 sendmsg->payload.userStats->from_client->resync = target->cryptState.uiResync;
779 sendmsg->payload.userStats->from_server->has_good = true;
780 sendmsg->payload.userStats->from_server->good = target->cryptState.uiRemoteGood;
781 sendmsg->payload.userStats->from_server->has_late = true;
782 sendmsg->payload.userStats->from_server->late = target->cryptState.uiRemoteLate;
783 sendmsg->payload.userStats->from_server->has_lost = true;
784 sendmsg->payload.userStats->from_server->lost = target->cryptState.uiRemoteLost;
785 sendmsg->payload.userStats->from_server->has_resync = true;
786 sendmsg->payload.userStats->from_server->resync = target->cryptState.uiRemoteResync;
788 sendmsg->payload.userStats->has_udp_packets = true;
789 sendmsg->payload.userStats->udp_packets = target->UDPPackets;
790 sendmsg->payload.userStats->has_udp_ping_avg = true;
791 sendmsg->payload.userStats->udp_ping_avg = target->UDPPingAvg;
792 sendmsg->payload.userStats->has_udp_ping_var = true;
793 sendmsg->payload.userStats->udp_ping_var = target->UDPPingVar;
795 sendmsg->payload.userStats->has_tcp_ping_avg = true;
796 sendmsg->payload.userStats->tcp_ping_avg = target->TCPPingAvg;
797 sendmsg->payload.userStats->has_tcp_ping_var = true;
798 sendmsg->payload.userStats->tcp_ping_var = target->TCPPingVar;
799 sendmsg->payload.userStats->has_tcp_packets = true;
800 sendmsg->payload.userStats->tcp_packets = target->TCPPackets;
804 sendmsg->payload.userStats->version->has_version = true;
805 sendmsg->payload.userStats->version->version = target->version;
806 sendmsg->payload.userStats->version->release = strdup(target->release);
807 sendmsg->payload.userStats->version->os = strdup(target->os);
808 sendmsg->payload.userStats->version->os_version = strdup(target->os_version);
810 sendmsg->payload.userStats->n_celt_versions = target->codec_count;
811 sendmsg->payload.userStats->celt_versions = malloc(sizeof(int32_t) * target->codec_count);
812 if (!sendmsg->payload.userStats->celt_versions)
813 Log_fatal("Out of memory");
815 while (Client_codec_iterate(target, &codec_itr) != NULL)
816 sendmsg->payload.userStats->celt_versions[i++] = codec_itr->codec;
819 sendmsg->payload.userStats->has_address = true;
820 sendmsg->payload.userStats->address.data = malloc(sizeof(uint8_t) * 16);
821 if (!sendmsg->payload.userStats->address.data)
822 Log_fatal("Out of memory");
823 memset(sendmsg->payload.userStats->address.data, 0, 16);
824 /* ipv4 representation as ipv6 address. Supposedly correct. */
825 memcpy(&sendmsg->payload.userStats->address.data[12], &target->remote_tcp.sin_addr, 4);
826 memset(&sendmsg->payload.userStats->address.data[10], 0xff, 2); /* IPv4 */
827 sendmsg->payload.userStats->address.len = 16;
830 sendmsg->payload.userStats->has_bandwidth = true;
831 sendmsg->payload.userStats->bandwidth = target->availableBandwidth;
834 sendmsg->payload.userStats->has_onlinesecs = true;
835 sendmsg->payload.userStats->onlinesecs = Timer_elapsed(&target->connectTime) / 1000000LL;
837 sendmsg->payload.userStats->has_idlesecs = true;
838 sendmsg->payload.userStats->idlesecs = Timer_elapsed(&target->idleTime) / 1000000LL;
839 Client_send_message(client, sendmsg);
844 /* Only admin can issue this */
845 if (!client->isAdmin) {
846 sendPermissionDenied(client, "Permission denied");
849 while (Client_iterate(&target) != NULL) {
850 if (target->sessionId == msg->payload.userRemove->session)
853 if (target == NULL) {
854 Log_warn("Client with sessionId %d not found", msg->payload.userRemove->session);
857 msg->payload.userRemove->session = target->sessionId;
858 msg->payload.userRemove->has_actor = true;
859 msg->payload.userRemove->actor = client->sessionId;
861 if (msg->payload.userRemove->has_ban && msg->payload.userRemove->ban) {
862 if (!getBoolConf(ENABLE_BAN))
863 sendPermissionDenied(client, "Permission denied");
865 Ban_UserBan(target, msg->payload.userRemove->reason);
867 Log_info_client(target, "User kicked. Reason: '%s'",
868 strlen(msg->payload.userRemove->reason) == 0 ? "N/A" : msg->payload.userRemove->reason);
873 Client_send_message_except(NULL, msg);
874 Client_close(target);
877 /* Only admin can issue this */
878 if (!client->isAdmin) {
879 sendPermissionDenied(client, "Permission denied");
882 if (!getBoolConf(ENABLE_BAN)) {
883 sendPermissionDenied(client, "Permission denied");
886 if (msg->payload.banList->has_query && msg->payload.banList->query) {
887 /* Create banlist message and add banentrys */
888 sendmsg = Ban_getBanList();
889 Client_send_message(client, sendmsg);
891 /* Clear banlist and set the new one */
893 Ban_putBanList(msg, msg->payload.banList->n_bans);
897 /* Permission denied for all these messages. Not implemented. */
900 case ContextActionAdd:
904 sendPermissionDenied(client, "Not supported by uMurmur");
908 Log_warn("Message %d not handled", msg->messageType);
917 Client_close(client);