Patch by J Sisson: sprintf -> snprintf
[umurmur.git] / src / messagehandler.c
1 /* Copyright (C) 2009-2010, Martin Johansson <martin@fatbob.nu>
2    Copyright (C) 2005-2010, Thorvald Natvig <thorvald@natvig.com>
3
4    All rights reserved.
5
6    Redistribution and use in source and binary forms, with or without
7    modification, are permitted provided that the following conditions
8    are met:
9
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.
18
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.
30 */
31 #include <string.h>
32 #include <stdlib.h>
33
34 #include "log.h"
35 #include "list.h"
36 #include "client.h"
37 #include "messages.h"
38 #include "messagehandler.h"
39 #include "crypt.h"
40 #include "channel.h"
41 #include "conf.h"
42 #include "voicetarget.h"
43
44 #define MAX_TEXT 512
45 #define MAX_USERNAME 128
46
47 extern channel_t *defaultChan;
48 extern int iCodecAlpha, iCodecBeta;
49 extern bool_t bPreferAlpha;
50
51 static void sendServerReject(client_t *client, const char *reason, MumbleProto__Reject__RejectType type)
52 {
53         message_t *msg = Msg_create(Reject);
54         msg->payload.reject->reason = strdup(reason);
55         msg->payload.reject->type = type;
56         msg->payload.reject->has_type = true;
57         Client_send_message(client, msg);
58         
59         Log_info_client(client, "Server reject reason: %s", reason);
60 }
61
62 static void sendPermissionDenied(client_t *client, const char *reason)
63 {
64         message_t *msg = Msg_create(PermissionDenied);
65         msg->payload.permissionDenied->has_type = true;
66         msg->payload.permissionDenied->type = MUMBLE_PROTO__PERMISSION_DENIED__DENY_TYPE__Text;
67         msg->payload.permissionDenied->reason = strdup(reason);
68         Client_send_message(client, msg);
69 }
70
71 void Mh_handle_message(client_t *client, message_t *msg)
72 {
73         message_t *sendmsg = NULL;
74         channel_t *ch_itr = NULL;
75         client_t *client_itr;
76
77         if (!client->authenticated && !(msg->messageType == Authenticate ||
78                                                                         msg->messageType == Version)) {
79                 goto out;
80         }
81         
82         switch (msg->messageType) {
83         case UDPTunnel:
84         case Ping:
85         case CryptSetup:
86         case VoiceTarget:
87         case UserStats:
88         case PermissionQuery:
89                 break;
90         default:
91                 Timer_restart(&client->idleTime);
92         }
93         
94         switch (msg->messageType) {
95         case Authenticate:
96                 Log_debug("Authenticate message received");
97                 
98                 if (IS_AUTH(client) || !msg->payload.authenticate->username) {
99                         /* Authenticate message might be sent when a token is set by the user.*/
100                         if (msg->payload.authenticate->n_tokens > 0) {
101                                 Log_debug("Tokens in auth message from %s", client->username);
102                         }
103                         break;
104                 }
105                 
106                 client->authenticated = true;
107                 
108                 client_itr = NULL;
109                 while (Client_iterate(&client_itr) != NULL) {
110                         if (!IS_AUTH(client_itr))
111                                 continue;
112                         if (client_itr->username && strncmp(client_itr->username, msg->payload.authenticate->username, MAX_USERNAME) == 0) {
113                                 char buf[64];
114                                 sprintf(buf, "Username already in use");
115                                 Log_debug("Username already in use");
116                                 sendServerReject(client, buf, MUMBLE_PROTO__REJECT__REJECT_TYPE__UsernameInUse);
117                                 goto disconnect;
118                         }                               
119                 }
120                 if (strlen(getStrConf(PASSPHRASE)) > 0) {
121                         if (!msg->payload.authenticate->password ||
122                                 (msg->payload.authenticate->password &&
123                                  strncmp(getStrConf(PASSPHRASE), msg->payload.authenticate->password, MAX_TEXT) != 0)) {
124                                 char buf[64];
125                                 sprintf(buf, "Wrong server password");
126                                 sendServerReject(client, buf, MUMBLE_PROTO__REJECT__REJECT_TYPE__WrongServerPW);
127                                 Log_debug("Wrong server password: '%s'", msg->payload.authenticate->password != NULL ?
128                                                   msg->payload.authenticate->password : "(null)");
129                                 goto disconnect;
130                         }
131                 }                               
132                 if (strlen(msg->payload.authenticate->username) == 0 ||
133                         strlen(msg->payload.authenticate->username) >= MAX_USERNAME) { /* XXX - other invalid names? */
134                         char buf[64];
135                         sprintf(buf, "Invalid username");
136                         Log_debug("Invalid username");
137                         sendServerReject(client, buf, MUMBLE_PROTO__REJECT__REJECT_TYPE__InvalidUsername);
138                         goto disconnect;
139                 }                               
140
141                 if (Client_count() >= getIntConf(MAX_CLIENTS)) {
142                         char buf[64];
143                         snprintf(buf, 64, "Server is full (max %d users)", getIntConf(MAX_CLIENTS));
144                         sendServerReject(client, buf, MUMBLE_PROTO__REJECT__REJECT_TYPE__ServerFull);
145                         goto disconnect;
146                 }
147                 
148                 /* Name & password */
149                 client->username = strdup(msg->payload.authenticate->username);                         
150                 
151                 /* Setup UDP encryption */
152                 CryptState_init(&client->cryptState);
153                 CryptState_genKey(&client->cryptState);
154                 sendmsg = Msg_create(CryptSetup);
155                 sendmsg->payload.cryptSetup->has_key = true;
156                 sendmsg->payload.cryptSetup->key.data = client->cryptState.raw_key;
157                 sendmsg->payload.cryptSetup->key.len = AES_BLOCK_SIZE;
158                 sendmsg->payload.cryptSetup->has_server_nonce = true;
159                 sendmsg->payload.cryptSetup->server_nonce.data = client->cryptState.encrypt_iv;
160                 sendmsg->payload.cryptSetup->server_nonce.len = AES_BLOCK_SIZE;
161                 sendmsg->payload.cryptSetup->has_client_nonce = true;
162                 sendmsg->payload.cryptSetup->client_nonce.data = client->cryptState.decrypt_iv;
163                 sendmsg->payload.cryptSetup->client_nonce.len = AES_BLOCK_SIZE;
164                 Client_send_message(client, sendmsg);
165
166                 /* Channel stuff */
167                 Chan_userJoin(defaultChan, client); /* Join default channel */
168
169                 /* Codec version */             
170                 Log_debug("Client %d has %d CELT codecs", client->sessionId,
171                                   msg->payload.authenticate->n_celt_versions);
172                 if (msg->payload.authenticate->n_celt_versions > 0) {
173                         int i;
174                         codec_t *codec_itr;
175                         client->codec_count = msg->payload.authenticate->n_celt_versions;
176                         
177                         for (i = 0; i < client->codec_count; i++)
178                         Client_codec_add(client, msg->payload.authenticate->celt_versions[i]);
179                         codec_itr = NULL;
180                         while (Client_codec_iterate(client, &codec_itr) != NULL)
181                                 Log_debug("Client %d CELT codec ver 0x%x", client->sessionId, codec_itr->codec);
182                                 
183                 } else {
184                         Client_codec_add(client, (int32_t)0x8000000a);
185                         client->codec_count = 1;
186                 }
187                 
188                 recheckCodecVersions();
189                 
190                 sendmsg = Msg_create(CodecVersion);
191                 sendmsg->payload.codecVersion->alpha = iCodecAlpha;
192                 sendmsg->payload.codecVersion->beta = iCodecBeta;
193                 sendmsg->payload.codecVersion->prefer_alpha = bPreferAlpha;
194                 Client_send_message(client, sendmsg);
195                 
196                 /* Iterate channels and send channel info */
197                 ch_itr = NULL;
198                 while (Chan_iterate(&ch_itr) != NULL) {
199                         sendmsg = Msg_create(ChannelState);
200                         sendmsg->payload.channelState->has_channel_id = true;
201                         sendmsg->payload.channelState->channel_id = ch_itr->id;
202                         if (ch_itr->id != 0) {
203                                 sendmsg->payload.channelState->has_parent = true;
204                                 sendmsg->payload.channelState->parent = ch_itr->parent->id;
205                         }
206                         sendmsg->payload.channelState->name = strdup(ch_itr->name);
207                         if (ch_itr->desc)
208                                 sendmsg->payload.channelState->description = strdup(ch_itr->desc);
209                         Log_debug("Send channel info: %s", sendmsg->payload.channelState->name);
210                         Client_send_message(client, sendmsg);                   
211                 }
212
213                 /* Iterate channels and send channel links info */
214                 ch_itr = NULL;
215                 while (Chan_iterate(&ch_itr) != NULL) {
216                         if (ch_itr->linkcount > 0) { /* Has links */
217                                 uint32_t *links;
218                                 int i = 0;
219                                 struct dlist *itr;
220                                 
221                                 sendmsg = Msg_create(ChannelState);
222                                 sendmsg->payload.channelState->has_channel_id = true;
223                                 sendmsg->payload.channelState->channel_id = ch_itr->id;
224                                 sendmsg->payload.channelState->n_links = ch_itr->linkcount;
225                                 
226                                 links = (uint32_t *)malloc(ch_itr->linkcount * sizeof(uint32_t));
227                                 list_iterate(itr, &ch_itr->channel_links) { /* Iterate links */
228                                         channel_t *ch;
229                                         ch = list_get_entry(itr, channel_t, link_node);
230                                         links[i++] = ch->id;
231                                 }
232                                 sendmsg->payload.channelState->links = links;
233                                 Client_send_message(client, sendmsg);
234                         }
235                 }
236                 
237                 /* Send user state for connecting user to other users */
238                 sendmsg = Msg_create(UserState);
239                 sendmsg->payload.userState->has_session = true;
240                 sendmsg->payload.userState->session = client->sessionId;
241                 sendmsg->payload.userState->name = strdup(client->username);
242                 sendmsg->payload.userState->has_channel_id = true;
243                 sendmsg->payload.userState->channel_id = ((channel_t *)client->channel)->id;
244
245                 Client_send_message_except(client, sendmsg);
246
247                 client_itr = NULL;
248                 while (Client_iterate(&client_itr) != NULL) {
249                         if (!IS_AUTH(client_itr))
250                                 continue;
251                         sendmsg = Msg_create(UserState);
252                         sendmsg->payload.userState->has_session = true;
253                         sendmsg->payload.userState->session = client_itr->sessionId;
254                         sendmsg->payload.userState->name = strdup(client_itr->username);
255                         sendmsg->payload.userState->has_channel_id = true;
256                         sendmsg->payload.userState->channel_id = ((channel_t *)client_itr->channel)->id;
257
258                         /* Only self_mute/deaf supported */
259                         if (client_itr->deaf) {
260                                 sendmsg->payload.userState->has_self_deaf = true;
261                                 sendmsg->payload.userState->self_deaf = true;
262                         }
263                         if (client_itr->mute) {
264                                 sendmsg->payload.userState->has_self_mute = true;
265                                 sendmsg->payload.userState->self_mute = true;
266                         }
267                         if (client_itr->recording) {
268                                 sendmsg->payload.userState->has_recording = true;
269                                 sendmsg->payload.userState->recording = true;
270                         }
271                         Client_send_message(client, sendmsg);
272                 }
273
274                 /* Sync message */
275                 sendmsg = Msg_create(ServerSync);
276                 sendmsg->payload.serverSync->has_session = true;
277                 sendmsg->payload.serverSync->session = client->sessionId;
278                 sendmsg->payload.serverSync->welcome_text = strdup(getStrConf(WELCOMETEXT));
279                 sendmsg->payload.serverSync->has_max_bandwidth = true;
280                 sendmsg->payload.serverSync->max_bandwidth = getIntConf(MAX_BANDWIDTH);
281                 Client_send_message(client, sendmsg);
282
283                 /* Server config message */
284                 sendmsg = Msg_create(ServerConfig);             
285                 sendmsg->payload.serverConfig->has_allow_html = true;
286                 sendmsg->payload.serverConfig->allow_html = true; /* Support this? */
287                 sendmsg->payload.serverConfig->has_message_length = true;
288                 sendmsg->payload.serverConfig->message_length = MAX_TEXT; /* Hardcoded */
289                 sendmsg->payload.serverConfig->has_image_message_length = true;
290                 sendmsg->payload.serverConfig->image_message_length = 0; /* XXX */
291                 Client_send_message(client, sendmsg);
292
293                 Log_info_client(client, "User %s authenticated", client->username);
294                 break;
295                 
296         case Ping:
297                 if (msg->payload.ping->has_good)
298                         client->cryptState.uiRemoteGood = msg->payload.ping->good;
299                 if (msg->payload.ping->has_late)
300                         client->cryptState.uiRemoteLate = msg->payload.ping->late;
301                 if (msg->payload.ping->has_lost)
302                         client->cryptState.uiRemoteLost = msg->payload.ping->lost;
303                 if (msg->payload.ping->has_resync)
304                         client->cryptState.uiRemoteResync = msg->payload.ping->resync;
305
306                 Log_debug("Ping <-: %d %d %d %d",
307                                   client->cryptState.uiRemoteGood, client->cryptState.uiRemoteLate,
308                                   client->cryptState.uiRemoteLost, client->cryptState.uiRemoteResync
309                         );
310                 
311                 client->UDPPingAvg = msg->payload.ping->udp_ping_avg;
312                 client->UDPPingVar = msg->payload.ping->udp_ping_var;
313                 client->TCPPingAvg = msg->payload.ping->tcp_ping_avg;
314                 client->TCPPingVar = msg->payload.ping->tcp_ping_var;
315                 client->UDPPackets = msg->payload.ping->udp_packets;
316                 client->TCPPackets = msg->payload.ping->tcp_packets;
317                 
318                 sendmsg = Msg_create(Ping);
319
320                 sendmsg->payload.ping->timestamp = msg->payload.ping->timestamp;
321                 sendmsg->payload.ping->has_timestamp = true;
322                 sendmsg->payload.ping->good = client->cryptState.uiGood;
323                 sendmsg->payload.ping->has_good = true;
324                 sendmsg->payload.ping->late = client->cryptState.uiLate;
325                 sendmsg->payload.ping->has_late = true;
326                 sendmsg->payload.ping->lost = client->cryptState.uiLost;
327                 sendmsg->payload.ping->has_lost = true;
328                 sendmsg->payload.ping->resync = client->cryptState.uiResync;
329                 sendmsg->payload.ping->has_resync = true;
330
331                 Client_send_message(client, sendmsg);
332                 Log_debug("Ping ->: %d %d %d %d",
333                                   client->cryptState.uiGood, client->cryptState.uiLate,
334                                   client->cryptState.uiLost, client->cryptState.uiResync);
335
336                 break;
337         case CryptSetup:
338                 Log_debug("Voice channel crypt resync requested");
339                 if (!msg->payload.cryptSetup->has_client_nonce) {
340                         sendmsg = Msg_create(CryptSetup);
341                         sendmsg->payload.cryptSetup->has_server_nonce = true;
342                         sendmsg->payload.cryptSetup->server_nonce.data = client->cryptState.decrypt_iv;
343                         sendmsg->payload.cryptSetup->server_nonce.len = AES_BLOCK_SIZE;
344                         Client_send_message(client, sendmsg);
345                 } else {
346                         memcpy(client->cryptState.decrypt_iv, msg->payload.cryptSetup->client_nonce.data, AES_BLOCK_SIZE);
347                         client->cryptState.uiResync++;
348                 }
349                 break;
350         case UserState:
351                 /* Only allow state changes for for the self user */
352                 if (msg->payload.userState->has_session &&
353                         msg->payload.userState->session != client->sessionId) {
354                         sendPermissionDenied(client, "Permission denied");
355                         break;
356                 }
357                 if (msg->payload.userState->has_user_id || msg->payload.userState->has_mute ||
358                         msg->payload.userState->has_deaf || msg->payload.userState->has_suppress ||
359                         msg->payload.userState->has_texture) {
360                         
361                         sendPermissionDenied(client, "Not supported by uMurmur");
362                         break;
363                 }
364                 
365                 msg->payload.userState->has_session = true;
366                 msg->payload.userState->session = client->sessionId;
367                 msg->payload.userState->has_actor = true;
368                 msg->payload.userState->actor = client->sessionId;
369
370                 if (msg->payload.userState->has_self_deaf) {
371                         client->deaf = msg->payload.userState->self_deaf;
372                 }
373                 if (msg->payload.userState->has_self_mute) {
374                         client->mute = msg->payload.userState->self_mute;
375                         if (!client->mute) {
376                                 msg->payload.userState->has_self_deaf = true;
377                                 msg->payload.userState->self_deaf = false;
378                                 client->deaf = false;
379                         }
380                 }
381                 if (msg->payload.userState->has_recording &&
382                         msg->payload.userState->recording != client->recording) {
383                         client->recording = msg->payload.userState->recording;
384                         char *message;
385                         uint32_t *tree_id;
386                         
387                         message = malloc(strlen(client->username) + 32);
388                         if (!message)
389                                 Log_fatal("Out of memory");
390                         tree_id = malloc(sizeof(uint32_t));
391                         if (!tree_id)
392                                 Log_fatal("Out of memory");
393                         *tree_id = 0;
394                         sendmsg = Msg_create(TextMessage);
395                         sendmsg->payload.textMessage->message = message;
396                         sendmsg->payload.textMessage->n_tree_id = 1;
397                         sendmsg->payload.textMessage->tree_id = tree_id;
398                         if (client->recording)
399                                 sprintf(message, "User %s started recording", client->username);
400                         else
401                                 sprintf(message, "User %s stopped recording", client->username);
402                         Client_send_message_except_ver(NULL, sendmsg, ~0x010203);
403                         sendmsg = NULL;
404                 }
405                 if (msg->payload.userState->has_channel_id) {
406                         int leave_id;
407                         if (!Chan_userJoin_id_test(msg->payload.userState->channel_id))
408                                 break;
409                         leave_id = Chan_userJoin_id(msg->payload.userState->channel_id, client);
410                         if (leave_id > 0) {
411                                 Log_debug("Removing channel ID %d", leave_id);
412                                 sendmsg = Msg_create(ChannelRemove);
413                                 sendmsg->payload.channelRemove->channel_id = leave_id;
414                         }
415                 }
416                 if (msg->payload.userState->has_plugin_context) {
417                         if (client->context)
418                                 free(client->context);
419                         client->context = malloc(msg->payload.userState->plugin_context.len);
420                         if (client->context == NULL)
421                                 Log_fatal("Out of memory");
422                         memcpy(client->context, msg->payload.userState->plugin_context.data,
423                                    msg->payload.userState->plugin_context.len);
424                         
425                         break; /* Don't inform other users about this state */
426                 }
427                 /* Re-use message */
428                 Msg_inc_ref(msg);
429                                 
430                 Client_send_message_except(NULL, msg);
431
432                 /* Need to send remove channel message _after_ UserState message */
433                 if (sendmsg != NULL)
434                         Client_send_message_except(NULL, sendmsg);
435                 break;
436                 
437         case TextMessage:
438                 msg->payload.textMessage->has_actor = true;
439                 msg->payload.textMessage->actor = client->sessionId;
440
441                 /* XXX - HTML is allowed and can't be turned off */
442                 if (msg->payload.textMessage->n_tree_id > 0) {
443                         sendPermissionDenied(client, "Tree message not supported");
444                         break;
445                 }
446                         
447                 if (msg->payload.textMessage->n_channel_id > 0) { /* To channel */
448                         int i;
449                         channel_t *ch_itr;
450                         for (i = 0; i < msg->payload.textMessage->n_channel_id; i++) {
451                                 ch_itr = NULL;
452                                 do {
453                                         Chan_iterate(&ch_itr);
454                                 } while (ch_itr != NULL && ch_itr->id != msg->payload.textMessage->channel_id[i]);
455                                 if (ch_itr != NULL) {
456                                         struct dlist *itr;
457                                         list_iterate(itr, &ch_itr->clients) {
458                                                 client_t *c;
459                                                 c = list_get_entry(itr, client_t, chan_node);
460                                                 if (c != client && !c->deaf) {
461                                                         Msg_inc_ref(msg);
462                                                         Client_send_message(c, msg);
463                                                         Log_debug("Text message to session ID %d", c->sessionId);
464                                                 }
465                                         }
466                                 }
467                         } /* for */
468                 }
469                 if (msg->payload.textMessage->n_session > 0) { /* To user */
470                         int i;
471                         client_t *itr;
472                         for (i = 0; i < msg->payload.textMessage->n_session; i++) {
473                                 itr = NULL;
474                                 while (Client_iterate(&itr) != NULL) {
475                                         if (!IS_AUTH(itr))
476                                                 continue;
477                                         if (itr->sessionId == msg->payload.textMessage->session[i]) {
478                                                 if (!itr->deaf) {
479                                                         Msg_inc_ref(msg);
480                                                         Client_send_message(itr, msg);
481                                                         Log_debug("Text message to session ID %d", itr->sessionId);
482                                                 }
483                                                 break;
484                                         }
485                                 }
486                                 if (itr == NULL)
487                                         Log_warn("TextMessage: Session ID %d not found", msg->payload.textMessage->session[i]);
488                         } /* for */
489                 }
490                 break;
491
492         case VoiceTarget:
493         {
494                 int i, j, count, targetId = msg->payload.voiceTarget->id;
495                 struct _MumbleProto__VoiceTarget__Target *target;
496
497                 if (!targetId || targetId >= 0x1f)
498                         break;
499                 Voicetarget_add_id(client, targetId);
500                 count = msg->payload.voiceTarget->n_targets;
501                 if (!count)
502                         break;
503                 for (i = 0; i < count; i++) {
504                         target = msg->payload.voiceTarget->targets[i];
505                         for (j = 0; j < target->n_session; j++)
506                                 Voicetarget_add_session(client, targetId, target->session[j]);
507                         if (target->has_channel_id) {
508                                 bool_t linked = false, children = false;
509                                 if (target->has_links)
510                                         linked = target->links;
511                                 if (target->has_children)
512                                         children = target->children;
513                                 Voicetarget_add_channel(client, targetId, target->channel_id, linked, children);
514                         }
515                 }
516                 break;
517         }
518         case Version:
519                 Log_debug("Version message received");
520                 if (msg->payload.version->has_version) {
521                         client->version = msg->payload.version->version;
522                         Log_debug("Client version 0x%x", client->version);
523                 }
524                 if (msg->payload.version->release) {
525                         if (client->release) free(client->release);
526                         client->release = strdup(msg->payload.version->release);
527                         Log_debug("Client release %s", client->release);
528                 }
529                 if (msg->payload.version->os) {
530                         if (client->os) free(client->os);                       
531                         client->os = strdup(msg->payload.version->os);
532                         Log_debug("Client OS %s", client->os);
533                 }
534                 if (msg->payload.version->os_version) {
535                         if (client->os_version) free(client->os_version);                       
536                         client->os_version = strdup(msg->payload.version->os_version);
537                         Log_debug("Client OS version %s", client->os_version);
538                 }
539                 break;
540         case PermissionQuery:
541                 Msg_inc_ref(msg); /* Re-use message */
542                 msg->payload.permissionQuery->has_permissions = true;
543                 msg->payload.permissionQuery->permissions = PERM_DEFAULT;
544                 
545                 Client_send_message(client, msg);
546                 break;
547         case UDPTunnel:
548                 client->bUDP = false;
549                 Client_voiceMsg(client, msg->payload.UDPTunnel->packet.data, msg->payload.UDPTunnel->packet.len);
550             break;
551         case ChannelState:
552         {
553                 channel_t *ch_itr, *parent, *newchan;
554                 int leave_id;           
555                 /* Don't allow any changes to existing channels */
556                 if (msg->payload.channelState->has_channel_id) {
557                         sendPermissionDenied(client, "Not supported by uMurmur");
558                         break;
559                 }
560                 /* Must have parent */
561                 if (!msg->payload.channelState->has_parent) {
562                         sendPermissionDenied(client, "Not supported by uMurmur");
563                         break;
564                 }
565                 /* Must have name */
566                 if (msg->payload.channelState->name == NULL) {
567                         sendPermissionDenied(client, "Not supported by uMurmur");
568                         break;
569                 }
570                 /* Must be temporary channel */
571                 if (msg->payload.channelState->temporary != true) {
572                         sendPermissionDenied(client, "Only temporary channels are supported by uMurmur");
573                         break;
574                 }
575                 /* Check channel name is OK */
576                 if (strlen(msg->payload.channelState->name) > MAX_TEXT) {
577                         sendPermissionDenied(client, "Channel name too long");
578                         break;
579                 }
580                         
581                 parent = Chan_fromId(msg->payload.channelState->parent);
582                 if (parent == NULL)
583                         break;
584                 ch_itr = NULL;
585                 while (Chan_iterate_siblings(parent, &ch_itr) != NULL) {
586                         if (strcmp(ch_itr->name, msg->payload.channelState->name) == 0) {
587                                 sendPermissionDenied(client, "Channel already exists");
588                                 break;
589                         }
590                 }
591                 if (ch_itr != NULL)
592                         break;
593                 
594                 /* Disallow temporary channels as siblings to temporary channels */
595                 if (parent->temporary) {
596                         sendPermissionDenied(client, "Parent channel is temporary channel");
597                         break;
598                 }
599                         
600                 /* XXX - Murmur looks for "\\w" and sends perm denied if not found.
601                  * I don't know why so I don't do that here...
602                  */
603
604                 /* Create the channel */
605                 newchan = Chan_createChannel(msg->payload.channelState->name,
606                                                                          msg->payload.channelState->description);
607                 newchan->temporary = true;
608                 Chan_addChannel(parent, newchan);
609                 msg->payload.channelState->has_channel_id = true;
610                 msg->payload.channelState->channel_id = newchan->id;
611                 Msg_inc_ref(msg);
612                 Client_send_message_except(NULL, msg);
613
614                 /* Join the creating user */
615                 sendmsg = Msg_create(UserState);
616                 sendmsg->payload.userState->has_session = true;
617                 sendmsg->payload.userState->session = client->sessionId;
618                 sendmsg->payload.userState->has_channel_id = true;
619                 sendmsg->payload.userState->channel_id = newchan->id;
620                 Client_send_message_except(NULL, sendmsg);
621                 
622                 leave_id = Chan_userJoin(newchan, client);
623                 if (leave_id > 0) {
624                         Log_debug("Removing channel ID %d", leave_id);
625                         sendmsg = Msg_create(ChannelRemove);
626                         sendmsg->payload.channelRemove->channel_id = leave_id;
627                         Client_send_message_except(NULL, sendmsg);
628                 }
629         }               
630         break;
631
632         case UserStats:
633         {
634                 client_t *target = NULL;
635                 codec_t *codec_itr = NULL;
636                 int i;
637                 bool_t details = true;
638                 
639                 if (msg->payload.userStats->has_stats_only)
640                         details = !msg->payload.userStats->stats_only;
641                 
642                 if (!msg->payload.userStats->has_session)
643                         sendPermissionDenied(client, "Not supported by uMurmur");
644                 while (Client_iterate(&target) != NULL) {
645                         if (!IS_AUTH(target))
646                                 continue;
647                         if (target->sessionId == msg->payload.userStats->session)
648                                 break;
649                 }
650                 if (!target) /* Not found */
651                         break;
652                 
653                 /*
654                  * Differences from Murmur:
655                  * o Ignoring certificates intentionally
656                  * o Ignoring channel local determining
657                  */
658                 
659                 sendmsg = Msg_create(UserStats);
660                 sendmsg->payload.userStats->session = msg->payload.userStats->session;
661                 sendmsg->payload.userStats->from_client->has_good = true;
662                 sendmsg->payload.userStats->from_client->good = target->cryptState.uiGood;
663                 sendmsg->payload.userStats->from_client->has_late = true;
664                 sendmsg->payload.userStats->from_client->late = target->cryptState.uiLate;
665                 sendmsg->payload.userStats->from_client->has_lost = true;
666                 sendmsg->payload.userStats->from_client->lost = target->cryptState.uiLost;
667                 sendmsg->payload.userStats->from_client->has_resync = true;
668                 sendmsg->payload.userStats->from_client->resync = target->cryptState.uiResync;
669                 
670                 sendmsg->payload.userStats->from_server->has_good = true;
671                 sendmsg->payload.userStats->from_server->good = target->cryptState.uiRemoteGood;
672                 sendmsg->payload.userStats->from_server->has_late = true;
673                 sendmsg->payload.userStats->from_server->late = target->cryptState.uiRemoteLate;
674                 sendmsg->payload.userStats->from_server->has_lost = true;
675                 sendmsg->payload.userStats->from_server->lost = target->cryptState.uiRemoteLost;
676                 sendmsg->payload.userStats->from_server->has_resync = true;
677                 sendmsg->payload.userStats->from_server->resync = target->cryptState.uiRemoteResync;
678
679                 sendmsg->payload.userStats->has_udp_packets = true;
680                 sendmsg->payload.userStats->udp_packets = target->UDPPackets;
681                 sendmsg->payload.userStats->has_udp_ping_avg = true;
682                 sendmsg->payload.userStats->udp_ping_avg = target->UDPPingAvg;
683                 sendmsg->payload.userStats->has_udp_ping_var = true;
684                 sendmsg->payload.userStats->udp_ping_var = target->UDPPingVar;
685                 
686                 sendmsg->payload.userStats->has_tcp_ping_avg = true;
687                 sendmsg->payload.userStats->tcp_ping_avg = target->TCPPingAvg;
688                 sendmsg->payload.userStats->has_tcp_ping_var = true;
689                 sendmsg->payload.userStats->tcp_ping_var = target->TCPPingVar;
690                 sendmsg->payload.userStats->has_tcp_packets = true;
691                 sendmsg->payload.userStats->tcp_packets = target->TCPPackets;
692                 
693                 if (details) {
694
695                         sendmsg->payload.userStats->version->has_version = true;
696                         sendmsg->payload.userStats->version->version = target->version;
697                         sendmsg->payload.userStats->version->release = strdup(target->release);
698                         sendmsg->payload.userStats->version->os = strdup(target->os);
699                         sendmsg->payload.userStats->version->os_version = strdup(target->os_version);
700                         
701                         sendmsg->payload.userStats->n_celt_versions = target->codec_count;
702                         sendmsg->payload.userStats->celt_versions = malloc(sizeof(int32_t) * target->codec_count);
703                         if (!sendmsg->payload.userStats->celt_versions)
704                                 Log_fatal("Out of memory");
705                         i = 0;
706                         while (Client_codec_iterate(target, &codec_itr) != NULL)
707                                 sendmsg->payload.userStats->celt_versions[i++] = codec_itr->codec;
708
709                         /* Address */
710                         sendmsg->payload.userStats->has_address = true;
711                         sendmsg->payload.userStats->address.data = malloc(sizeof(uint8_t) * 16);
712                         if (!sendmsg->payload.userStats->address.data)
713                                 Log_fatal("Out of memory");
714                         memset(sendmsg->payload.userStats->address.data, 0, 16);
715                         /* ipv4 representation as ipv6 address. Supposedly correct. */
716                         memcpy(&sendmsg->payload.userStats->address.data[12], &target->remote_tcp.sin_addr, 4);
717                         sendmsg->payload.userStats->address.len = 16;
718                 }
719                 /* BW */
720                 sendmsg->payload.userStats->has_bandwidth = true;
721                 sendmsg->payload.userStats->bandwidth = target->availableBandwidth;
722                 
723                 /* Onlinesecs */
724                 sendmsg->payload.userStats->has_onlinesecs = true;
725                 sendmsg->payload.userStats->onlinesecs = Timer_elapsed(&target->connectTime) / 1000000LL;               
726                 /* Idlesecs */
727                 sendmsg->payload.userStats->has_idlesecs = true;
728                 sendmsg->payload.userStats->idlesecs = Timer_elapsed(&target->idleTime) / 1000000LL;            
729                 Client_send_message(client, sendmsg);
730         }
731         break;
732                 /* Permission denied for all these messages. Not implemented. */
733         case ChannelRemove:
734         case ContextAction:
735         case ContextActionAdd:
736         case ACL:
737         case BanList:
738         case UserList:
739         case QueryUsers:
740                 sendPermissionDenied(client, "Not supported by uMurmur");
741                 break;
742                                 
743         default:
744                 Log_warn("Message %d not handled", msg->messageType);
745                 break;
746         }
747 out:
748         Msg_free(msg);
749         return;
750         
751 disconnect:
752         Msg_free(msg);
753         Client_close(client);
754 }
755