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