Fix potential segfault at checking server password when debugging enabled
[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
46 extern channel_t *defaultChan;
47 extern int iCodecAlpha, iCodecBeta;
48 extern bool_t bPreferAlpha;
49
50 static void sendServerReject(client_t *client, const char *reason, MumbleProto__Reject__RejectType type)
51 {
52         message_t *msg = Msg_create(Reject);
53         msg->payload.reject->reason = strdup(reason);
54         msg->payload.reject->type = type;
55         msg->payload.reject->has_type = true;
56         Client_send_message(client, msg);
57         
58         Log_info_client(client, "Server reject reason: %s", reason);
59 }
60
61 static void sendPermissionDenied(client_t *client, const char *reason)
62 {
63         message_t *msg = Msg_create(PermissionDenied);
64         msg->payload.permissionDenied->has_type = true;
65         msg->payload.permissionDenied->type = MUMBLE_PROTO__PERMISSION_DENIED__DENY_TYPE__Text;
66         msg->payload.permissionDenied->reason = strdup(reason);
67         Client_send_message(client, msg);
68 }
69
70 void Mh_handle_message(client_t *client, message_t *msg)
71 {
72         message_t *sendmsg = NULL;
73         channel_t *ch_itr = NULL;
74         client_t *client_itr;
75
76         if (!client->authenticated && !(msg->messageType == Authenticate ||
77                                                                         msg->messageType == Version)) {
78                 goto out;
79         }       
80         switch (msg->messageType) {
81         case Authenticate:
82                 Log_debug("Authenticate message received");
83                 
84                 if (IS_AUTH(client) || !msg->payload.authenticate->username) {
85                         /* Authenticate message might be sent when a token is set by the user.*/
86                         if (msg->payload.authenticate->n_tokens > 0) {
87                                 Log_debug("Tokens in auth message from %s", client->username);
88                         }
89                         break;
90                 }
91                 
92                 client->authenticated = true;
93                 
94                 client_itr = NULL;
95                 while (Client_iterate(&client_itr) != NULL) {
96                         if (!IS_AUTH(client_itr))
97                                 continue;
98                         if (client_itr->username && strncmp(client_itr->username, msg->payload.authenticate->username, MAX_TEXT) == 0) {
99                                 char buf[64];
100                                 sprintf(buf, "Username already in use");
101                                 Log_debug("Username already in use");
102                                 sendServerReject(client, buf, MUMBLE_PROTO__REJECT__REJECT_TYPE__UsernameInUse);
103                                 goto disconnect;
104                         }                               
105                 }
106                 if (strlen(getStrConf(PASSPHRASE)) > 0) {
107                         if (!msg->payload.authenticate->password ||
108                                 (msg->payload.authenticate->password &&
109                                  strncmp(getStrConf(PASSPHRASE), msg->payload.authenticate->password, MAX_TEXT) != 0)) {
110                                 char buf[64];
111                                 sprintf(buf, "Wrong server password");
112                                 sendServerReject(client, buf, MUMBLE_PROTO__REJECT__REJECT_TYPE__WrongServerPW);
113                                 Log_debug("Wrong server password: '%s'", msg->payload.authenticate->password != NULL ?
114                                                   msg->payload.authenticate->password : "(null)");
115                                 goto disconnect;
116                         }
117                 }                               
118                 if (strlen(msg->payload.authenticate->username) == 0 ||
119                         strlen(msg->payload.authenticate->username) >= MAX_TEXT) { /* XXX - other invalid names? */
120                         char buf[64];
121                         sprintf(buf, "Invalid username");
122                         Log_debug("Invalid username");
123                         sendServerReject(client, buf, MUMBLE_PROTO__REJECT__REJECT_TYPE__InvalidUsername);
124                         goto disconnect;
125                 }                               
126
127                 if (Client_count() >= getIntConf(MAX_CLIENTS)) {
128                         char buf[64];
129                         sprintf(buf, "Server is full (max %d users)", getIntConf(MAX_CLIENTS));
130                         sendServerReject(client, buf, MUMBLE_PROTO__REJECT__REJECT_TYPE__ServerFull);
131                         goto disconnect;
132                 }
133                 
134                 /* Name & password */
135                 client->username = strdup(msg->payload.authenticate->username);                         
136                 
137                 /* Setup UDP encryption */
138                 CryptState_init(&client->cryptState);
139                 CryptState_genKey(&client->cryptState);
140                 sendmsg = Msg_create(CryptSetup);
141                 sendmsg->payload.cryptSetup->has_key = true;
142                 sendmsg->payload.cryptSetup->key.data = client->cryptState.raw_key;
143                 sendmsg->payload.cryptSetup->key.len = AES_BLOCK_SIZE;
144                 sendmsg->payload.cryptSetup->has_server_nonce = true;
145                 sendmsg->payload.cryptSetup->server_nonce.data = client->cryptState.encrypt_iv;
146                 sendmsg->payload.cryptSetup->server_nonce.len = AES_BLOCK_SIZE;
147                 sendmsg->payload.cryptSetup->has_client_nonce = true;
148                 sendmsg->payload.cryptSetup->client_nonce.data = client->cryptState.decrypt_iv;
149                 sendmsg->payload.cryptSetup->client_nonce.len = AES_BLOCK_SIZE;
150                 Client_send_message(client, sendmsg);
151
152                 /* Channel stuff */
153                 Chan_userJoin(defaultChan, client); /* Join default channel */
154
155                 /* Codec version */             
156                 Log_debug("Client %d has %d CELT codecs", client->sessionId,
157                                   msg->payload.authenticate->n_celt_versions);
158                 if (msg->payload.authenticate->n_celt_versions > 0) {
159                         int i;
160                         codec_t *codec_itr;
161                         client->codec_count = msg->payload.authenticate->n_celt_versions;
162                         
163                         for (i = 0; i < client->codec_count; i++)
164                         Client_codec_add(client, msg->payload.authenticate->celt_versions[i]);
165                         codec_itr = NULL;
166                         while (Client_codec_iterate(client, &codec_itr) != NULL)
167                                 Log_debug("Client %d CELT codec ver 0x%x", client->sessionId, codec_itr->codec);
168                                 
169                 } else {
170                         Client_codec_add(client, (int32_t)0x8000000a);
171                         client->codec_count = 1;
172                 }
173                 
174                 recheckCodecVersions();
175                 
176                 sendmsg = Msg_create(CodecVersion);
177                 sendmsg->payload.codecVersion->alpha = iCodecAlpha;
178                 sendmsg->payload.codecVersion->beta = iCodecBeta;
179                 sendmsg->payload.codecVersion->prefer_alpha = bPreferAlpha;
180                 Client_send_message(client, sendmsg);
181                 
182                 /* Iterate channels and send channel info */
183                 ch_itr = NULL;
184                 while (Chan_iterate(&ch_itr) != NULL) {
185                         sendmsg = Msg_create(ChannelState);
186                         sendmsg->payload.channelState->has_channel_id = true;
187                         sendmsg->payload.channelState->channel_id = ch_itr->id;
188                         if (ch_itr->id != 0) {
189                                 sendmsg->payload.channelState->has_parent = true;
190                                 sendmsg->payload.channelState->parent = ch_itr->parent->id;
191                         }
192                         sendmsg->payload.channelState->name = strdup(ch_itr->name);
193                         if (ch_itr->desc)
194                                 sendmsg->payload.channelState->description = strdup(ch_itr->desc);
195                         Log_debug("Send channel info: %s", sendmsg->payload.channelState->name);
196                         Client_send_message(client, sendmsg);                   
197                 }
198
199                 /* Iterate channels and send channel links info */
200                 ch_itr = NULL;
201                 while (Chan_iterate(&ch_itr) != NULL) {
202                         if (ch_itr->linkcount > 0) { /* Has links */
203                                 uint32_t *links;
204                                 int i = 0;
205                                 struct dlist *itr;
206                                 
207                                 sendmsg = Msg_create(ChannelState);
208                                 sendmsg->payload.channelState->has_channel_id = true;
209                                 sendmsg->payload.channelState->channel_id = ch_itr->id;
210                                 sendmsg->payload.channelState->n_links = ch_itr->linkcount;
211                                 
212                                 links = (uint32_t *)malloc(ch_itr->linkcount * sizeof(uint32_t));
213                                 list_iterate(itr, &ch_itr->channel_links) { /* Iterate links */
214                                         channel_t *ch;
215                                         ch = list_get_entry(itr, channel_t, link_node);
216                                         links[i++] = ch->id;
217                                 }
218                                 sendmsg->payload.channelState->links = links;
219                                 Client_send_message(client, sendmsg);
220                         }
221                 }
222                 
223                 /* Send user state for connecting user to other users */
224                 sendmsg = Msg_create(UserState);
225                 sendmsg->payload.userState->has_session = true;
226                 sendmsg->payload.userState->session = client->sessionId;
227                 sendmsg->payload.userState->name = strdup(client->username);
228                 sendmsg->payload.userState->has_channel_id = true;
229                 sendmsg->payload.userState->channel_id = ((channel_t *)client->channel)->id;
230                 
231                 Client_send_message_except(client, sendmsg);
232
233                 client_itr = NULL;
234                 while (Client_iterate(&client_itr) != NULL) {
235                         if (!IS_AUTH(client_itr))
236                                 continue;
237                         sendmsg = Msg_create(UserState);
238                         sendmsg->payload.userState->has_session = true;
239                         sendmsg->payload.userState->session = client_itr->sessionId;
240                         sendmsg->payload.userState->name = strdup(client_itr->username);
241                         sendmsg->payload.userState->has_channel_id = true;
242                         sendmsg->payload.userState->channel_id = ((channel_t *)client_itr->channel)->id;
243
244                         /* Only self_mute/deaf supported */
245                         if (client_itr->deaf) {
246                                 sendmsg->payload.userState->has_self_deaf = true;
247                                 sendmsg->payload.userState->self_deaf = true;
248                         }
249                         if (client_itr->mute) {
250                                 sendmsg->payload.userState->has_self_mute = true;
251                                 sendmsg->payload.userState->self_mute = true;
252                         }
253                         Client_send_message(client, sendmsg);
254                 }
255
256                 /* Sync message */
257                 sendmsg = Msg_create(ServerSync);
258                 sendmsg->payload.serverSync->has_session = true;
259                 sendmsg->payload.serverSync->session = client->sessionId;
260                 sendmsg->payload.serverSync->welcome_text = strdup(getStrConf(WELCOMETEXT));
261                 sendmsg->payload.serverSync->has_max_bandwidth = true;
262                 sendmsg->payload.serverSync->max_bandwidth = getIntConf(MAX_BANDWIDTH);
263                 sendmsg->payload.serverSync->has_allow_html = true;
264                 sendmsg->payload.serverSync->allow_html = true; /* Support this? */
265                 Client_send_message(client, sendmsg);
266                 
267                 Log_info_client(client, "User %s authenticated", client->username);
268                 break;
269                 
270         case Ping:
271                 if (msg->payload.ping->has_good)
272                         client->cryptState.uiRemoteGood = msg->payload.ping->good;
273                 if (msg->payload.ping->has_late)
274                         client->cryptState.uiRemoteLate = msg->payload.ping->late;
275                 if (msg->payload.ping->has_lost)
276                         client->cryptState.uiRemoteLost = msg->payload.ping->lost;
277                 if (msg->payload.ping->has_resync)
278                         client->cryptState.uiRemoteResync = msg->payload.ping->resync;
279
280                 Log_debug("Ping <-: %d %d %d %d",
281                                   client->cryptState.uiRemoteGood, client->cryptState.uiRemoteLate,
282                                   client->cryptState.uiRemoteLost, client->cryptState.uiRemoteResync
283                         );
284                 
285                 /* Ignoring the double values since they don't seem to be used */
286                 
287                 sendmsg = Msg_create(Ping);
288
289                 sendmsg->payload.ping->timestamp = msg->payload.ping->timestamp;
290                 sendmsg->payload.ping->has_timestamp = true;
291                 sendmsg->payload.ping->good = client->cryptState.uiGood;
292                 sendmsg->payload.ping->has_good = true;
293                 sendmsg->payload.ping->late = client->cryptState.uiLate;
294                 sendmsg->payload.ping->has_late = true;
295                 sendmsg->payload.ping->lost = client->cryptState.uiLost;
296                 sendmsg->payload.ping->has_lost = true;
297                 sendmsg->payload.ping->resync = client->cryptState.uiResync;
298                 sendmsg->payload.ping->has_resync = true;
299
300                 Client_send_message(client, sendmsg);
301                 Log_debug("Ping ->: %d %d %d %d",
302                                   client->cryptState.uiGood, client->cryptState.uiLate,
303                                   client->cryptState.uiLost, client->cryptState.uiResync);
304
305                 break;
306         case CryptSetup:
307                 Log_debug("Voice channel crypt resync requested");
308                 if (!msg->payload.cryptSetup->has_client_nonce) {
309                         sendmsg = Msg_create(CryptSetup);
310                         sendmsg->payload.cryptSetup->has_server_nonce = true;
311                         sendmsg->payload.cryptSetup->server_nonce.data = client->cryptState.decrypt_iv;
312                         sendmsg->payload.cryptSetup->server_nonce.len = AES_BLOCK_SIZE;
313                         Client_send_message(client, sendmsg);
314                 } else {
315                         memcpy(client->cryptState.decrypt_iv, msg->payload.cryptSetup->client_nonce.data, AES_BLOCK_SIZE);
316                         client->cryptState.uiResync++;
317                 }
318                 break;
319         case UserState:
320                 /* Only allow state changes for for the self user */
321                 if (msg->payload.userState->has_session &&
322                         msg->payload.userState->session != client->sessionId) {
323                         sendPermissionDenied(client, "Permission denied");
324                         break;
325                 }
326                 if (msg->payload.userState->has_user_id || msg->payload.userState->has_mute ||
327                         msg->payload.userState->has_deaf || msg->payload.userState->has_suppress ||
328                         msg->payload.userState->has_texture) {
329                         
330                         sendPermissionDenied(client, "Not supported by uMurmur");
331                         break;
332                 }
333                 
334                 msg->payload.userState->has_session = true;
335                 msg->payload.userState->session = client->sessionId;
336                 msg->payload.userState->has_actor = true;
337                 msg->payload.userState->actor = client->sessionId;
338
339                 if (msg->payload.userState->has_self_deaf) {
340                         client->deaf = msg->payload.userState->self_deaf;
341                 }
342                 if (msg->payload.userState->has_self_mute) {
343                         client->mute = msg->payload.userState->self_mute;
344                         if (!client->mute) {
345                                 msg->payload.userState->has_self_deaf = true;
346                                 msg->payload.userState->self_deaf = false;
347                                 client->deaf = false;
348                         }
349                 }
350                 if (msg->payload.userState->has_channel_id) {
351                         int leave_id;
352                         if (!Chan_userJoin_id_test(msg->payload.userState->channel_id))
353                                 break;
354                         leave_id = Chan_userJoin_id(msg->payload.userState->channel_id, client);
355                         if (leave_id > 0) {
356                                 Log_debug("Removing channel ID %d", leave_id);
357                                 sendmsg = Msg_create(ChannelRemove);
358                                 sendmsg->payload.channelRemove->channel_id = leave_id;
359                         }
360                 }
361                 if (msg->payload.userState->plugin_context != NULL) {
362                         if (client->context)
363                                 free(client->context);
364                         client->context = strdup(msg->payload.userState->plugin_context);
365                         if (client->context == NULL)
366                                 Log_fatal("Out of memory");
367                         
368                         break; /* Don't inform other users about this state */
369                 }
370                 
371                 /* Re-use message */
372                 Msg_inc_ref(msg);
373                                 
374                 Client_send_message_except(NULL, msg);
375
376                 /* Need to send remove channel message _after_ UserState message */
377                 if (sendmsg != NULL)
378                         Client_send_message_except(NULL, sendmsg);
379                 break;
380                 
381         case TextMessage:
382                 msg->payload.textMessage->has_actor = true;
383                 msg->payload.textMessage->actor = client->sessionId;
384
385                 /* XXX - HTML is allowed and can't be turned off */
386                 if (msg->payload.textMessage->n_tree_id > 0) {
387                         sendPermissionDenied(client, "Tree message not supported");
388                         break;
389                 }
390                         
391                 if (msg->payload.textMessage->n_channel_id > 0) { /* To channel */
392                         int i;
393                         channel_t *ch_itr;
394                         for (i = 0; i < msg->payload.textMessage->n_channel_id; i++) {
395                                 ch_itr = NULL;
396                                 do {
397                                         Chan_iterate(&ch_itr);
398                                 } while (ch_itr != NULL && ch_itr->id != msg->payload.textMessage->channel_id[i]);
399                                 if (ch_itr != NULL) {
400                                         struct dlist *itr;
401                                         list_iterate(itr, &ch_itr->clients) {
402                                                 client_t *c;
403                                                 c = list_get_entry(itr, client_t, chan_node);
404                                                 if (c != client && !c->deaf) {
405                                                         Msg_inc_ref(msg);
406                                                         Client_send_message(c, msg);
407                                                         Log_debug("Text message to session ID %d", c->sessionId);
408                                                 }
409                                         }
410                                 }
411                         } /* for */
412                 }
413                 if (msg->payload.textMessage->n_session > 0) { /* To user */
414                         int i;
415                         client_t *itr;
416                         for (i = 0; i < msg->payload.textMessage->n_session; i++) {
417                                 itr = NULL;
418                                 while (Client_iterate(&itr) != NULL) {
419                                         if (!IS_AUTH(itr))
420                                                 continue;
421                                         if (itr->sessionId == msg->payload.textMessage->session[i]) {
422                                                 if (!itr->deaf) {
423                                                         Msg_inc_ref(msg);
424                                                         Client_send_message(itr, msg);
425                                                         Log_debug("Text message to session ID %d", itr->sessionId);
426                                                 }
427                                                 break;
428                                         }
429                                 }
430                                 if (itr == NULL)
431                                         Log_warn("TextMessage: Session ID %d not found", msg->payload.textMessage->session[i]);
432                         } /* for */
433                 }
434                 break;
435
436         case VoiceTarget:
437         {
438                 int i, j, count, targetId = msg->payload.voiceTarget->id;
439                 struct _MumbleProto__VoiceTarget__Target *target;
440
441                 if (!targetId || targetId >= 0x1f)
442                         break;
443                 Voicetarget_add_id(client, targetId);
444                 count = msg->payload.voiceTarget->n_targets;
445                 if (!count)
446                         break;
447                 for (i = 0; i < count; i++) {
448                         target = msg->payload.voiceTarget->targets[i];
449                         for (j = 0; j < target->n_session; j++)
450                                 Voicetarget_add_session(client, targetId, target->session[j]);
451                         if (target->has_channel_id) {
452                                 bool_t linked = false, children = false;
453                                 if (target->has_links)
454                                         linked = target->links;
455                                 if (target->has_children)
456                                         children = target->children;
457                                 Voicetarget_add_channel(client, targetId, target->channel_id, linked, children);
458                         }
459                 }
460                 break;
461         }
462         case Version:
463                 Log_debug("Version message received");
464                 if (msg->payload.version->has_version) {
465                         client->version = msg->payload.version->version;
466                         Log_debug("Client version 0x%x", client->version);
467                 }
468                 if (msg->payload.version->release) {
469                         if (client->release) free(client->release);
470                         client->release = strdup(msg->payload.version->release);
471                         Log_debug("Client release %s", client->release);
472                 }
473                 if (msg->payload.version->os) {
474                         if (client->os) free(client->os);                       
475                         client->os = strdup(msg->payload.version->os);
476                         Log_debug("Client OS %s", client->os);
477                 }
478                 break;
479         case PermissionQuery:
480                 Msg_inc_ref(msg); /* Re-use message */
481                 msg->payload.permissionQuery->has_permissions = true;
482                 msg->payload.permissionQuery->permissions = PERM_DEFAULT;
483                 
484                 Client_send_message(client, msg);
485                 break;
486         case UDPTunnel:
487                 client->bUDP = false;
488                 Client_voiceMsg(client, msg->payload.UDPTunnel->packet.data, msg->payload.UDPTunnel->packet.len);
489             break;
490         case ChannelState:
491         {
492                 channel_t *ch_itr, *parent, *newchan;
493                 int leave_id;           
494                 /* Don't allow any changes to existing channels */
495                 if (msg->payload.channelState->has_channel_id) {
496                         sendPermissionDenied(client, "Not supported by uMurmur");
497                         break;
498                 }
499                 /* Must have parent */
500                 if (!msg->payload.channelState->has_parent) {
501                         sendPermissionDenied(client, "Not supported by uMurmur");
502                         break;
503                 }
504                 /* Must have name */
505                 if (msg->payload.channelState->name == NULL) {
506                         sendPermissionDenied(client, "Not supported by uMurmur");
507                         break;
508                 }
509                 /* Must be temporary channel */
510                 if (msg->payload.channelState->temporary != true) {
511                         sendPermissionDenied(client, "Only temporary channels are supported by uMurmur");
512                         break;
513                 }
514                 /* Check channel name is OK */
515                 if (strlen(msg->payload.channelState->name) > MAX_TEXT) {
516                         sendPermissionDenied(client, "Channel name too long");
517                         break;
518                 }
519                         
520                 parent = Chan_fromId(msg->payload.channelState->parent);
521                 if (parent == NULL)
522                         break;
523                 ch_itr = NULL;
524                 while (Chan_iterate_siblings(parent, &ch_itr) != NULL) {
525                         if (strcmp(ch_itr->name, msg->payload.channelState->name) == 0) {
526                                 sendPermissionDenied(client, "Channel already exists");
527                                 break;
528                         }
529                 }
530                 if (ch_itr != NULL)
531                         break;
532                 
533                 /* Disallow temporary channels as siblings to temporary channels */
534                 if (parent->temporary) {
535                         sendPermissionDenied(client, "Parent channel is temporary channel");
536                         break;
537                 }
538                         
539                 /* XXX - Murmur looks for "\\w" and sends perm denied if not found.
540                  * I don't know why so I don't do that here...
541                  */
542
543                 /* Create the channel */
544                 newchan = Chan_createChannel(msg->payload.channelState->name,
545                                                                          msg->payload.channelState->description);
546                 newchan->temporary = true;
547                 Chan_addChannel(parent, newchan);
548                 msg->payload.channelState->has_channel_id = true;
549                 msg->payload.channelState->channel_id = newchan->id;
550                 Msg_inc_ref(msg);
551                 Client_send_message_except(NULL, msg);
552
553                 /* Join the creating user */
554                 sendmsg = Msg_create(UserState);
555                 sendmsg->payload.userState->has_session = true;
556                 sendmsg->payload.userState->session = client->sessionId;
557                 sendmsg->payload.userState->has_channel_id = true;
558                 sendmsg->payload.userState->channel_id = newchan->id;
559                 Client_send_message_except(NULL, sendmsg);
560                 
561                 leave_id = Chan_userJoin(newchan, client);
562                 if (leave_id > 0) {
563                         Log_debug("Removing channel ID %d", leave_id);
564                         sendmsg = Msg_create(ChannelRemove);
565                         sendmsg->payload.channelRemove->channel_id = leave_id;
566                         Client_send_message_except(NULL, sendmsg);
567                 }
568         }               
569         break;
570
571                 /* Permission denied for all these messages. Not implemented. */
572         case ChannelRemove:
573         case ContextAction:
574         case ContextActionAdd:
575         case ACL:
576         case BanList:
577         case UserList:
578         case QueryUsers:
579                 sendPermissionDenied(client, "Not supported by uMurmur");
580                 break;
581                                 
582         default:
583                 Log_warn("Message %d not handled", msg->messageType);
584                 break;
585         }
586 out:
587         Msg_free(msg);
588         return;
589         
590 disconnect:
591         Msg_free(msg);
592         Client_close(client);
593 }
594