rename player -> user
[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                 if (msg->payload.authenticate->n_celt_versions > MAX_CODECS)
148                         Log_warn("Client has more than %d CELT codecs. Ignoring %d codecs",
149                                          MAX_CODECS, msg->payload.authenticate->n_celt_versions - MAX_CODECS);
150                 
151                 Log_debug("Client %d has %d CELT codecs", client->sessionId, msg->payload.authenticate->n_celt_versions);
152                 if (msg->payload.authenticate->n_celt_versions > 0) {
153                         int i;
154                         client->codec_count = msg->payload.authenticate->n_celt_versions > MAX_CODECS ?
155                                 MAX_CODECS : msg->payload.authenticate->n_celt_versions;
156                         for (i = 0; i < client->codec_count; i++) {
157                                 client->codecs[i] = msg->payload.authenticate->celt_versions[i];
158                                 Log_debug("Client %d CELT codec ver 0x%x", client->sessionId, client->codecs[i]);
159                         }
160                 } else {
161                         client->codecs[0] = (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                                 if (target->has_links || target->has_children)
417                                         Log_warn("Whisper to children or linked channels not implemented. Ignoring.");
418                                 Voicetarget_add_channel(client, targetId, target->channel_id);
419                         }
420                 }
421                 break;
422         }
423         case Version:
424                 Log_debug("Version message received");
425                 if (msg->payload.version->has_version) {
426                         client->version = msg->payload.version->version;
427                         Log_debug("Client version 0x%x", client->version);
428                 }
429                 if (msg->payload.version->release) {
430                         if (client->release) free(client->release);
431                         client->release = strdup(msg->payload.version->release);
432                         Log_debug("Client release %s", client->release);
433                 }
434                 if (msg->payload.version->os) {
435                         if (client->os) free(client->os);                       
436                         client->os = strdup(msg->payload.version->os);
437                         Log_debug("Client OS %s", client->os);
438                 }
439                 break;
440         case PermissionQuery:
441                 Msg_inc_ref(msg); /* Re-use message */
442                 msg->payload.permissionQuery->has_permissions = true;
443                 msg->payload.permissionQuery->permissions = PERM_DEFAULT;
444                 
445                 Client_send_message(client, msg);
446                 break;
447         case UDPTunnel:
448                 Client_voiceMsg(client, msg->payload.UDPTunnel->packet.data, msg->payload.UDPTunnel->packet.len);
449             break;
450         case ChannelState:
451         {
452                 channel_t *ch_itr, *parent, *newchan;
453                 int leave_id;           
454                 /* Don't allow any changes to existing channels */
455                 if (msg->payload.channelState->has_channel_id) {
456                         sendPermissionDenied(client, "Not supported by uMurmur");
457                         break;
458                 }
459                 /* Must have parent */
460                 if (!msg->payload.channelState->has_parent) {
461                         sendPermissionDenied(client, "Not supported by uMurmur");
462                         break;
463                 }
464                 /* Must have name */
465                 if (msg->payload.channelState->name == NULL) {
466                         sendPermissionDenied(client, "Not supported by uMurmur");
467                         break;
468                 }
469                 /* Must be temporary channel */
470                 if (msg->payload.channelState->temporary != true) {
471                         sendPermissionDenied(client, "Only temporary channels are supported by uMurmur");
472                         break;
473                 }
474                 /* Check channel name is OK */
475                 if (strlen(msg->payload.channelState->name) > MAX_TEXT) {
476                         sendPermissionDenied(client, "Channel name too long");
477                         break;
478                 }
479                         
480                 parent = Chan_fromId(msg->payload.channelState->parent);
481                 if (parent == NULL)
482                         break;
483                 ch_itr = NULL;
484                 while (Chan_iterate_siblings(parent, &ch_itr) != NULL) {
485                         if (strcmp(ch_itr->name, msg->payload.channelState->name) == 0) {
486                                 sendPermissionDenied(client, "Channel already exists");
487                                 break;
488                         }
489                 }
490                 if (ch_itr != NULL)
491                         break;
492                 
493                 /* Disallow temporary channels as siblings to temporary channels */
494                 if (parent->temporary) {
495                         sendPermissionDenied(client, "Parent channel is temporary channel");
496                         break;
497                 }
498                         
499                 /* XXX - Murmur looks for "\\w" and sends perm denied if not found.
500                  * I don't know why so I don't do that here...
501                  */
502
503                 /* Create the channel */
504                 newchan = Chan_createChannel(msg->payload.channelState->name,
505                                                                          msg->payload.channelState->description);
506                 newchan->temporary = true;
507                 Chan_addChannel(parent, newchan);
508                 msg->payload.channelState->has_channel_id = true;
509                 msg->payload.channelState->channel_id = newchan->id;
510                 Msg_inc_ref(msg);
511                 Client_send_message_except(NULL, msg);
512
513                 /* Join the creating user */
514                 sendmsg = Msg_create(UserState);
515                 sendmsg->payload.userState->has_session = true;
516                 sendmsg->payload.userState->session = client->sessionId;
517                 sendmsg->payload.userState->has_channel_id = true;
518                 sendmsg->payload.userState->channel_id = newchan->id;
519                 Client_send_message_except(NULL, sendmsg);
520                 
521                 leave_id = Chan_userJoin(newchan, client);
522                 if (leave_id > 0) {
523                         Log_debug("Removing channel ID %d", leave_id);
524                         sendmsg = Msg_create(ChannelRemove);
525                         sendmsg->payload.channelRemove->channel_id = leave_id;
526                         Client_send_message_except(NULL, sendmsg);
527                 }
528         }               
529         break;
530
531                 /* Permission denied for all these messages. Not implemented. */
532         case ChannelRemove:
533         case ContextAction:
534         case ContextActionAdd:
535         case ACL:
536         case BanList:
537         case UserList:
538         case QueryUsers:
539                 sendPermissionDenied(client, "Not supported by uMurmur");
540                 break;
541                                 
542         default:
543                 Log_warn("Message %d not handled", msg->messageType);
544                 break;
545         }
546 out:
547         Msg_free(msg);
548         return;
549         
550 disconnect:
551         Msg_free(msg);
552         Client_close(client);
553 }
554