Make logging more uniform. Fix copyright year
[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 "crypt.h"
39 #include "channel.h"
40 #include "conf.h"
41 #include "voicetarget.h"
42
43 extern channel_t *defaultChan;
44 extern int iCodecAlpha, iCodecBeta;
45 extern bool_t bPreferAlpha;
46
47 static void sendServerReject(client_t *client, const char *reason, MumbleProto__Reject__RejectType type)
48 {
49         message_t *msg = Msg_create(Reject);
50         msg->payload.reject->reason = strdup(reason);
51         msg->payload.reject->type = type;
52         msg->payload.reject->has_type = true;
53         Client_send_message(client, msg);
54         
55         Log_info("Server reject reason: %s. Disconnecting session %d - %s@%s:%d",
56                          reason,
57                          client->sessionId,
58                          client->playerName,
59                          inet_ntoa(client->remote_tcp.sin_addr),
60                          ntohs(client->remote_tcp.sin_port));
61         
62 }
63
64 static void sendPermissionDenied(client_t *client, const char *reason)
65 {
66         message_t *msg = Msg_create(PermissionDenied);
67         msg->payload.permissionDenied->has_type = true;
68         msg->payload.permissionDenied->type = MUMBLE_PROTO__PERMISSION_DENIED__DENY_TYPE__Text;
69         msg->payload.permissionDenied->reason = strdup(reason);
70         Client_send_message(client, msg);
71 }
72
73 void Mh_handle_message(client_t *client, message_t *msg)
74 {
75         message_t *sendmsg;
76         channel_t *ch_itr = NULL;
77         client_t *client_itr;
78         
79         switch (msg->messageType) {
80         case Authenticate:
81                 /*
82                  * 1. Check stuff, Serverreject if not ok
83                  * 2. Setup UDP encryption -> MessageCryptSetup
84                  * 3. (Enter channel)
85                  * 4. MessageChannelAdd + MessageChannelDescUpdate for all channels
86                  * 5. (MessageChannelLink)
87                  * 6. MessageServerJoin
88                  * 7. MessagePlayerMove
89                  * 8. MessageServerJoin for all connected users
90                  * 9. PlayerDeaf/PlayerMute/PlayerSelfMuteDeaf for all users it applies to
91                  * 10. MessageServerSync
92                  */
93                                 
94                 Log_debug("Authenticate message received");
95                 Log_debug("Username: %s", msg->payload.authenticate->username);
96                 
97                 client->authenticated = true;
98                 
99                 client_itr = NULL;
100                 while (Client_iterate(&client_itr) != NULL) {
101                         if (!IS_AUTH(client_itr))
102                                 continue;
103                         if (client_itr->playerName && strncmp(client_itr->playerName, msg->payload.authenticate->username, MAX_TEXT) == 0) {
104                                 char buf[64];
105                                 sprintf(buf, "Username already in use");
106                                 Log_debug("Username already in use");
107                                 sendServerReject(client, buf, MUMBLE_PROTO__REJECT__REJECT_TYPE__UsernameInUse);
108                                 goto disconnect;
109                         }                               
110                 }
111                 if (msg->payload.authenticate->password && strncmp(getStrConf(PASSPHRASE), msg->payload.authenticate->password, MAX_TEXT) != 0) {
112                         char buf[64];
113                         sprintf(buf, "Wrong server password");
114                         Log_debug("Wrong server password: %s", msg->payload.authenticate->password);
115                         sendServerReject(client, buf, MUMBLE_PROTO__REJECT__REJECT_TYPE__WrongServerPW);
116                         goto disconnect;
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->playerName = 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_playerJoin(defaultChan, client); /* Join default channel */
154
155                 /* Codec version */
156                 if (msg->payload.authenticate->n_celt_versions > MAX_CODECS)
157                         Log_warn("Client has more than %d CELT codecs. Ignoring %d codecs",
158                                          MAX_CODECS, msg->payload.authenticate->n_celt_versions - MAX_CODECS);
159                 
160                 Log_debug("Client %d has %d CELT codecs", client->sessionId, msg->payload.authenticate->n_celt_versions);
161                 if (msg->payload.authenticate->n_celt_versions > 0) {
162                         int i;
163                         client->codec_count = msg->payload.authenticate->n_celt_versions > MAX_CODECS ?
164                                 MAX_CODECS : msg->payload.authenticate->n_celt_versions;
165                         for (i = 0; i < client->codec_count; i++) {
166                                 client->codecs[i] = msg->payload.authenticate->celt_versions[i];
167                                 Log_debug("Client %d CELT codec ver 0x%x", client->sessionId, client->codecs[i]);
168                         }
169                 } else {
170                         client->codecs[0] = (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                 Chan_iterate(&ch_itr);
185                 do {
186                         sendmsg = Msg_create(ChannelState);
187                         sendmsg->payload.channelState->has_channel_id = true;
188                         sendmsg->payload.channelState->channel_id = ch_itr->id;
189                         if (ch_itr->id != 0) {
190                                 sendmsg->payload.channelState->has_parent = true;
191                                 sendmsg->payload.channelState->parent = ch_itr->parent->id;
192                         }
193                         sendmsg->payload.channelState->name = strdup(ch_itr->name);
194                         if (strlen(ch_itr->desc) > 0) {
195                                 sendmsg->payload.channelState->description = strdup(ch_itr->desc);
196                         }
197                         Log_debug("Send channel info: %s", sendmsg->payload.channelState->name);
198                         Client_send_message(client, sendmsg);
199                         
200                         Chan_iterate(&ch_itr);
201                 } while (ch_itr != NULL);
202
203                 /* Not supporting channel links yet */
204                 
205                 /* Send user state for connecting user to other users */
206                 sendmsg = Msg_create(UserState);
207                 sendmsg->payload.userState->has_session = true;
208                 sendmsg->payload.userState->session = client->sessionId;
209                 sendmsg->payload.userState->has_user_id = true;
210                 sendmsg->payload.userState->user_id = client->sessionId;
211                 sendmsg->payload.userState->name = strdup(client->playerName);
212                 sendmsg->payload.userState->has_channel_id = true;
213                 sendmsg->payload.userState->channel_id = ((channel_t *)client->channel)->id;
214                 
215                 Client_send_message_except(client, sendmsg);
216
217                 client_itr = NULL;
218                 while (Client_iterate(&client_itr) != NULL) {
219                         if (!IS_AUTH(client_itr))
220                                 continue;
221                         sendmsg = Msg_create(UserState);
222                         sendmsg->payload.userState->has_session = true;
223                         sendmsg->payload.userState->session = client_itr->sessionId;
224                         sendmsg->payload.userState->name = strdup(client_itr->playerName);
225                         sendmsg->payload.userState->has_channel_id = true;
226                         sendmsg->payload.userState->channel_id = ((channel_t *)client_itr->channel)->id;
227
228                         /* Only self_mute/deaf supported */
229                         if (client_itr->deaf) {
230                                 sendmsg->payload.userState->has_self_deaf = true;
231                                 sendmsg->payload.userState->self_deaf = true;
232                         }
233                         if (client_itr->mute) {
234                                 sendmsg->payload.userState->has_self_mute = true;
235                                 sendmsg->payload.userState->self_mute = true;
236                         }
237                         Client_send_message(client, sendmsg);
238                 }
239
240                 /* Sync message */
241                 sendmsg = Msg_create(ServerSync);
242                 sendmsg->payload.serverSync->has_session = true;
243                 sendmsg->payload.serverSync->session = client->sessionId;
244                 sendmsg->payload.serverSync->welcome_text = strdup(getStrConf(WELCOMETEXT));
245                 sendmsg->payload.serverSync->has_max_bandwidth = true;
246                 sendmsg->payload.serverSync->max_bandwidth = getIntConf(MAX_BANDWIDTH);
247                 sendmsg->payload.serverSync->has_allow_html = true;
248                 sendmsg->payload.serverSync->allow_html = true; /* Support this? */
249                 Client_send_message(client, sendmsg);
250                 
251                 Log_info("User %s authenticated", client->playerName);
252                 break;
253                 
254         case Ping:
255                 if (msg->payload.ping->has_good)
256                         client->cryptState.uiRemoteGood = msg->payload.ping->good;
257                 if (msg->payload.ping->has_late)
258                         client->cryptState.uiRemoteLate = msg->payload.ping->late;
259                 if (msg->payload.ping->has_lost)
260                         client->cryptState.uiRemoteLost = msg->payload.ping->lost;
261                 if (msg->payload.ping->has_resync)
262                         client->cryptState.uiRemoteResync = msg->payload.ping->resync;
263
264                 Log_debug("Ping <-: %d %d %d %d",
265                                   client->cryptState.uiRemoteGood, client->cryptState.uiRemoteLate,
266                                   client->cryptState.uiRemoteLost, client->cryptState.uiRemoteResync
267                         );
268                 
269                 /* Ignoring the double values since they don't seem to be used */
270                 
271                 sendmsg = Msg_create(Ping);
272
273                 sendmsg->payload.ping->timestamp = msg->payload.ping->timestamp;
274                 sendmsg->payload.ping->has_timestamp = true;
275                 sendmsg->payload.ping->good = client->cryptState.uiGood;
276                 sendmsg->payload.ping->has_good = true;
277                 sendmsg->payload.ping->late = client->cryptState.uiLate;
278                 sendmsg->payload.ping->has_late = true;
279                 sendmsg->payload.ping->lost = client->cryptState.uiLost;
280                 sendmsg->payload.ping->has_lost = true;
281                 sendmsg->payload.ping->resync = client->cryptState.uiResync;
282                 sendmsg->payload.ping->has_resync = true;
283
284                 Client_send_message(client, sendmsg);
285                 Log_debug("Ping ->: %d %d %d %d",
286                                   client->cryptState.uiGood, client->cryptState.uiLate,
287                                   client->cryptState.uiLost, client->cryptState.uiResync);
288
289                 break;
290         case CryptSetup:
291                 Log_debug("Voice channel crypt resync requested");
292                 if (!msg->payload.cryptSetup->has_client_nonce) {
293                         sendmsg = Msg_create(CryptSetup);
294                         sendmsg->payload.cryptSetup->has_server_nonce = true;
295                         sendmsg->payload.cryptSetup->server_nonce.data = client->cryptState.decrypt_iv;
296                         sendmsg->payload.cryptSetup->server_nonce.len = AES_BLOCK_SIZE;
297                         Client_send_message(client, sendmsg);
298                 } else {
299                         memcpy(client->cryptState.decrypt_iv, msg->payload.cryptSetup->client_nonce.data, AES_BLOCK_SIZE);
300                         client->cryptState.uiResync++;
301                 }
302                 break;
303         case UserState:
304                 /* Only allow state changes for for the self user */
305                 if (msg->payload.userState->has_session &&
306                         msg->payload.userState->session != client->sessionId) {
307                         sendPermissionDenied(client, "Permission denied");
308                         break;
309                 }
310                 if (msg->payload.userState->has_user_id || msg->payload.userState->has_mute ||
311                         msg->payload.userState->has_deaf || msg->payload.userState->has_suppress ||
312                         msg->payload.userState->has_texture) {
313                         
314                         sendPermissionDenied(client, "Not supported by uMurmur");
315                         break;
316                 }
317                 if (msg->payload.userState->has_self_deaf) {
318                         client->deaf = msg->payload.userState->self_deaf;
319                 }
320                 if (msg->payload.userState->has_self_mute) {
321                         client->mute = msg->payload.userState->self_mute;                       
322                 }
323                 if (msg->payload.userState->has_channel_id) {
324                         Chan_playerJoin_id(msg->payload.userState->channel_id, client);
325                 }
326                 if (msg->payload.userState->plugin_context != NULL) {
327                         if (client->context)
328                                 free(client->context);
329                         client->context = strdup(msg->payload.userState->plugin_context);
330                         if (client->context == NULL)
331                                 Log_fatal("Out of memory");
332                         
333                         break; /* Don't inform other users about this state */
334                 }
335                 
336                 /* Re-use message */
337                 Msg_inc_ref(msg);
338                 msg->payload.userState->has_actor = true;
339                 msg->payload.userState->actor = client->sessionId;
340                 Client_send_message_except(NULL, msg);
341                 break;
342         case TextMessage:
343                 msg->payload.textMessage->has_actor = true;
344                 msg->payload.textMessage->actor = client->sessionId;
345
346                 /* XXX - Allow HTML stuff? */
347                 
348                 if (msg->payload.textMessage->n_tree_id > 0) {
349                         sendPermissionDenied(client, "Tree message not supported");
350                         break;
351                 }
352                         
353                 if (msg->payload.textMessage->n_channel_id > 0) { /* To channel */
354                         int i;
355                         channel_t *ch_itr;
356                         for (i = 0; i < msg->payload.textMessage->n_channel_id; i++) {
357                                 ch_itr = NULL;
358                                 do {
359                                         Chan_iterate(&ch_itr);
360                                 } while (ch_itr != NULL && ch_itr->id != msg->payload.textMessage->channel_id[i]);
361                                 if (ch_itr == NULL)
362                                         Log_warn("Channel id %d not found - ignoring.", msg->payload.textMessage->channel_id[i]);
363                                 else {
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                 /* Permission denied for all these messages. Not implemented. */
451         case ChannelRemove:
452         case ChannelState:
453         case ContextAction:
454         case ContextActionAdd:
455         case ACL:
456         case BanList:
457         case UserList:
458         case QueryUsers:
459                 sendPermissionDenied(client, "Not supported by uMurmur");
460                 break;
461                                 
462         default:
463                 Log_warn("Message %d not handled", msg->messageType);
464                 break;
465         }
466         Msg_free(msg);
467         return;
468 disconnect:
469         Msg_free(msg);
470         Client_close(client);
471 }
472