1 /* Copyright (C) 2009-2010, Martin Johansson <martin@fatbob.nu>
2 Copyright (C) 2005-2010, Thorvald Natvig <thorvald@natvig.com>
6 Redistribution and use in source and binary forms, with or without
7 modification, are permitted provided that the following conditions
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.
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.
32 #include <openssl/aes.h>
41 #include "voicetarget.h"
43 extern channel_t *defaultChan;
44 extern int iCodecAlpha, iCodecBeta;
45 extern bool_t bPreferAlpha;
47 static void sendServerReject(client_t *client, const char *reason, MumbleProto__Reject__RejectType type)
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);
55 Log_info("Server reject reason: %s. Disconnecting session %d - %s@%s:%d",
59 inet_ntoa(client->remote_tcp.sin_addr),
60 ntohs(client->remote_tcp.sin_port));
64 static void sendPermissionDenied(client_t *client, const char *reason)
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);
73 void Mh_handle_message(client_t *client, message_t *msg)
75 message_t *sendmsg = NULL;
76 channel_t *ch_itr = NULL;
79 if (!client->authenticated && !(msg->messageType == Authenticate ||
80 msg->messageType == Version)) {
83 switch (msg->messageType) {
86 * 1. Check stuff, Serverreject if not ok
87 * 2. Setup UDP encryption -> MessageCryptSetup
89 * 4. MessageChannelAdd + MessageChannelDescUpdate for all channels
90 * 5. (MessageChannelLink)
91 * 6. MessageServerJoin
92 * 7. MessagePlayerMove
93 * 8. MessageServerJoin for all connected users
94 * 9. PlayerDeaf/PlayerMute/PlayerSelfMuteDeaf for all users it applies to
95 * 10. MessageServerSync
98 Log_debug("Authenticate message received");
99 Log_debug("Username: %s", msg->payload.authenticate->username);
101 client->authenticated = true;
104 while (Client_iterate(&client_itr) != NULL) {
105 if (!IS_AUTH(client_itr))
107 if (client_itr->playerName && strncmp(client_itr->playerName, msg->payload.authenticate->username, MAX_TEXT) == 0) {
109 sprintf(buf, "Username already in use");
110 Log_debug("Username already in use");
111 sendServerReject(client, buf, MUMBLE_PROTO__REJECT__REJECT_TYPE__UsernameInUse);
115 if (msg->payload.authenticate->password && strncmp(getStrConf(PASSPHRASE), msg->payload.authenticate->password, MAX_TEXT) != 0) {
117 sprintf(buf, "Wrong server password");
118 Log_debug("Wrong server password: %s", msg->payload.authenticate->password);
119 sendServerReject(client, buf, MUMBLE_PROTO__REJECT__REJECT_TYPE__WrongServerPW);
122 if (strlen(msg->payload.authenticate->username) == 0 ||
123 strlen(msg->payload.authenticate->username) >= MAX_TEXT) { /* XXX - other invalid names? */
125 sprintf(buf, "Invalid username");
126 Log_debug("Invalid username");
127 sendServerReject(client, buf, MUMBLE_PROTO__REJECT__REJECT_TYPE__InvalidUsername);
131 if (Client_count() >= getIntConf(MAX_CLIENTS)) {
133 sprintf(buf, "Server is full (max %d users)", getIntConf(MAX_CLIENTS));
134 sendServerReject(client, buf, MUMBLE_PROTO__REJECT__REJECT_TYPE__ServerFull);
138 /* Name & password */
139 client->playerName = strdup(msg->payload.authenticate->username);
141 /* Setup UDP encryption */
142 CryptState_init(&client->cryptState);
143 CryptState_genKey(&client->cryptState);
144 sendmsg = Msg_create(CryptSetup);
145 sendmsg->payload.cryptSetup->has_key = true;
146 sendmsg->payload.cryptSetup->key.data = client->cryptState.raw_key;
147 sendmsg->payload.cryptSetup->key.len = AES_BLOCK_SIZE;
148 sendmsg->payload.cryptSetup->has_server_nonce = true;
149 sendmsg->payload.cryptSetup->server_nonce.data = client->cryptState.encrypt_iv;
150 sendmsg->payload.cryptSetup->server_nonce.len = AES_BLOCK_SIZE;
151 sendmsg->payload.cryptSetup->has_client_nonce = true;
152 sendmsg->payload.cryptSetup->client_nonce.data = client->cryptState.decrypt_iv;
153 sendmsg->payload.cryptSetup->client_nonce.len = AES_BLOCK_SIZE;
154 Client_send_message(client, sendmsg);
157 Chan_playerJoin(defaultChan, client); /* Join default channel */
160 if (msg->payload.authenticate->n_celt_versions > MAX_CODECS)
161 Log_warn("Client has more than %d CELT codecs. Ignoring %d codecs",
162 MAX_CODECS, msg->payload.authenticate->n_celt_versions - MAX_CODECS);
164 Log_debug("Client %d has %d CELT codecs", client->sessionId, msg->payload.authenticate->n_celt_versions);
165 if (msg->payload.authenticate->n_celt_versions > 0) {
167 client->codec_count = msg->payload.authenticate->n_celt_versions > MAX_CODECS ?
168 MAX_CODECS : msg->payload.authenticate->n_celt_versions;
169 for (i = 0; i < client->codec_count; i++) {
170 client->codecs[i] = msg->payload.authenticate->celt_versions[i];
171 Log_debug("Client %d CELT codec ver 0x%x", client->sessionId, client->codecs[i]);
174 client->codecs[0] = (int32_t)0x8000000a;
175 client->codec_count = 1;
178 recheckCodecVersions();
180 sendmsg = Msg_create(CodecVersion);
181 sendmsg->payload.codecVersion->alpha = iCodecAlpha;
182 sendmsg->payload.codecVersion->beta = iCodecBeta;
183 sendmsg->payload.codecVersion->prefer_alpha = bPreferAlpha;
184 Client_send_message(client, sendmsg);
186 /* Iterate channels and send channel info */
188 Chan_iterate(&ch_itr);
190 sendmsg = Msg_create(ChannelState);
191 sendmsg->payload.channelState->has_channel_id = true;
192 sendmsg->payload.channelState->channel_id = ch_itr->id;
193 if (ch_itr->id != 0) {
194 sendmsg->payload.channelState->has_parent = true;
195 sendmsg->payload.channelState->parent = ch_itr->parent->id;
197 sendmsg->payload.channelState->name = strdup(ch_itr->name);
198 if (strlen(ch_itr->desc) > 0) {
199 sendmsg->payload.channelState->description = strdup(ch_itr->desc);
201 Log_debug("Send channel info: %s", sendmsg->payload.channelState->name);
202 Client_send_message(client, sendmsg);
204 Chan_iterate(&ch_itr);
205 } while (ch_itr != NULL);
207 /* Not supporting channel links yet */
209 /* Send user state for connecting user to other users */
210 sendmsg = Msg_create(UserState);
211 sendmsg->payload.userState->has_session = true;
212 sendmsg->payload.userState->session = client->sessionId;
213 sendmsg->payload.userState->has_user_id = true;
214 sendmsg->payload.userState->user_id = client->sessionId;
215 sendmsg->payload.userState->name = strdup(client->playerName);
216 sendmsg->payload.userState->has_channel_id = true;
217 sendmsg->payload.userState->channel_id = ((channel_t *)client->channel)->id;
219 Client_send_message_except(client, sendmsg);
222 while (Client_iterate(&client_itr) != NULL) {
223 if (!IS_AUTH(client_itr))
225 sendmsg = Msg_create(UserState);
226 sendmsg->payload.userState->has_session = true;
227 sendmsg->payload.userState->session = client_itr->sessionId;
228 sendmsg->payload.userState->name = strdup(client_itr->playerName);
229 sendmsg->payload.userState->has_channel_id = true;
230 sendmsg->payload.userState->channel_id = ((channel_t *)client_itr->channel)->id;
232 /* Only self_mute/deaf supported */
233 if (client_itr->deaf) {
234 sendmsg->payload.userState->has_self_deaf = true;
235 sendmsg->payload.userState->self_deaf = true;
237 if (client_itr->mute) {
238 sendmsg->payload.userState->has_self_mute = true;
239 sendmsg->payload.userState->self_mute = true;
241 Client_send_message(client, sendmsg);
245 sendmsg = Msg_create(ServerSync);
246 sendmsg->payload.serverSync->has_session = true;
247 sendmsg->payload.serverSync->session = client->sessionId;
248 sendmsg->payload.serverSync->welcome_text = strdup(getStrConf(WELCOMETEXT));
249 sendmsg->payload.serverSync->has_max_bandwidth = true;
250 sendmsg->payload.serverSync->max_bandwidth = getIntConf(MAX_BANDWIDTH);
251 sendmsg->payload.serverSync->has_allow_html = true;
252 sendmsg->payload.serverSync->allow_html = true; /* Support this? */
253 Client_send_message(client, sendmsg);
255 Log_info("User %s authenticated", client->playerName);
259 if (msg->payload.ping->has_good)
260 client->cryptState.uiRemoteGood = msg->payload.ping->good;
261 if (msg->payload.ping->has_late)
262 client->cryptState.uiRemoteLate = msg->payload.ping->late;
263 if (msg->payload.ping->has_lost)
264 client->cryptState.uiRemoteLost = msg->payload.ping->lost;
265 if (msg->payload.ping->has_resync)
266 client->cryptState.uiRemoteResync = msg->payload.ping->resync;
268 Log_debug("Ping <-: %d %d %d %d",
269 client->cryptState.uiRemoteGood, client->cryptState.uiRemoteLate,
270 client->cryptState.uiRemoteLost, client->cryptState.uiRemoteResync
273 /* Ignoring the double values since they don't seem to be used */
275 sendmsg = Msg_create(Ping);
277 sendmsg->payload.ping->timestamp = msg->payload.ping->timestamp;
278 sendmsg->payload.ping->has_timestamp = true;
279 sendmsg->payload.ping->good = client->cryptState.uiGood;
280 sendmsg->payload.ping->has_good = true;
281 sendmsg->payload.ping->late = client->cryptState.uiLate;
282 sendmsg->payload.ping->has_late = true;
283 sendmsg->payload.ping->lost = client->cryptState.uiLost;
284 sendmsg->payload.ping->has_lost = true;
285 sendmsg->payload.ping->resync = client->cryptState.uiResync;
286 sendmsg->payload.ping->has_resync = true;
288 Client_send_message(client, sendmsg);
289 Log_debug("Ping ->: %d %d %d %d",
290 client->cryptState.uiGood, client->cryptState.uiLate,
291 client->cryptState.uiLost, client->cryptState.uiResync);
295 Log_debug("Voice channel crypt resync requested");
296 if (!msg->payload.cryptSetup->has_client_nonce) {
297 sendmsg = Msg_create(CryptSetup);
298 sendmsg->payload.cryptSetup->has_server_nonce = true;
299 sendmsg->payload.cryptSetup->server_nonce.data = client->cryptState.decrypt_iv;
300 sendmsg->payload.cryptSetup->server_nonce.len = AES_BLOCK_SIZE;
301 Client_send_message(client, sendmsg);
303 memcpy(client->cryptState.decrypt_iv, msg->payload.cryptSetup->client_nonce.data, AES_BLOCK_SIZE);
304 client->cryptState.uiResync++;
308 /* Only allow state changes for for the self user */
309 if (msg->payload.userState->has_session &&
310 msg->payload.userState->session != client->sessionId) {
311 sendPermissionDenied(client, "Permission denied");
314 if (msg->payload.userState->has_user_id || msg->payload.userState->has_mute ||
315 msg->payload.userState->has_deaf || msg->payload.userState->has_suppress ||
316 msg->payload.userState->has_texture) {
318 sendPermissionDenied(client, "Not supported by uMurmur");
321 if (msg->payload.userState->has_self_deaf) {
322 client->deaf = msg->payload.userState->self_deaf;
324 if (msg->payload.userState->has_self_mute) {
325 client->mute = msg->payload.userState->self_mute;
327 if (msg->payload.userState->has_channel_id) {
329 if (!Chan_playerJoin_id_test(msg->payload.userState->channel_id))
331 leave_id = Chan_playerJoin_id(msg->payload.userState->channel_id, client);
333 Log_debug("Removing channel ID %d", leave_id);
334 sendmsg = Msg_create(ChannelRemove);
335 sendmsg->payload.channelRemove->channel_id = leave_id;
338 if (msg->payload.userState->plugin_context != NULL) {
340 free(client->context);
341 client->context = strdup(msg->payload.userState->plugin_context);
342 if (client->context == NULL)
343 Log_fatal("Out of memory");
345 break; /* Don't inform other users about this state */
350 msg->payload.userState->has_actor = true;
351 msg->payload.userState->actor = client->sessionId;
352 Client_send_message_except(NULL, msg);
354 /* Need to send remove channel message _after_ UserState message */
356 Client_send_message_except(NULL, sendmsg);
360 msg->payload.textMessage->has_actor = true;
361 msg->payload.textMessage->actor = client->sessionId;
363 /* XXX - HTML is allowed and can't be turned off */
364 if (msg->payload.textMessage->n_tree_id > 0) {
365 sendPermissionDenied(client, "Tree message not supported");
369 if (msg->payload.textMessage->n_channel_id > 0) { /* To channel */
372 for (i = 0; i < msg->payload.textMessage->n_channel_id; i++) {
375 Chan_iterate(&ch_itr);
376 } while (ch_itr != NULL && ch_itr->id != msg->payload.textMessage->channel_id[i]);
378 Log_warn("Channel id %d not found - ignoring.", msg->payload.textMessage->channel_id[i]);
381 list_iterate(itr, &ch_itr->clients) {
383 c = list_get_entry(itr, client_t, chan_node);
384 if (c != client && !c->deaf) {
386 Client_send_message(c, msg);
387 Log_debug("Text message to session ID %d", c->sessionId);
393 if (msg->payload.textMessage->n_session > 0) { /* To user */
396 for (i = 0; i < msg->payload.textMessage->n_session; i++) {
398 while (Client_iterate(&itr) != NULL) {
401 if (itr->sessionId == msg->payload.textMessage->session[i]) {
404 Client_send_message(itr, msg);
405 Log_debug("Text message to session ID %d", itr->sessionId);
411 Log_warn("TextMessage: Session ID %d not found", msg->payload.textMessage->session[i]);
418 int i, j, count, targetId = msg->payload.voiceTarget->id;
419 struct _MumbleProto__VoiceTarget__Target *target;
421 if (!targetId || targetId >= 0x1f)
423 Voicetarget_add_id(client, targetId);
424 count = msg->payload.voiceTarget->n_targets;
427 for (i = 0; i < count; i++) {
428 target = msg->payload.voiceTarget->targets[i];
429 for (j = 0; j < target->n_session; j++)
430 Voicetarget_add_session(client, targetId, target->session[j]);
431 if (target->has_channel_id) {
432 if (target->has_links || target->has_children)
433 Log_warn("Whisper to children or linked channels not implemented. Ignoring.");
434 Voicetarget_add_channel(client, targetId, target->channel_id);
440 Log_debug("Version message received");
441 if (msg->payload.version->has_version) {
442 client->version = msg->payload.version->version;
443 Log_debug("Client version 0x%x", client->version);
445 if (msg->payload.version->release) {
446 if (client->release) free(client->release);
447 client->release = strdup(msg->payload.version->release);
448 Log_debug("Client release %s", client->release);
450 if (msg->payload.version->os) {
451 if (client->os) free(client->os);
452 client->os = strdup(msg->payload.version->os);
453 Log_debug("Client OS %s", client->os);
456 case PermissionQuery:
457 Msg_inc_ref(msg); /* Re-use message */
458 msg->payload.permissionQuery->has_permissions = true;
459 msg->payload.permissionQuery->permissions = PERM_DEFAULT;
461 Client_send_message(client, msg);
464 Client_voiceMsg(client, msg->payload.UDPTunnel->packet.data, msg->payload.UDPTunnel->packet.len);
468 channel_t *ch_itr, *parent, *newchan;
470 /* Don't allow any changes to existing channels */
471 if (msg->payload.channelState->has_channel_id) {
472 sendPermissionDenied(client, "Not supported by uMurmur");
475 /* Must have parent */
476 if (!msg->payload.channelState->has_parent) {
477 sendPermissionDenied(client, "Not supported by uMurmur");
481 if (msg->payload.channelState->name == NULL) {
482 sendPermissionDenied(client, "Not supported by uMurmur");
485 /* Must be temporary channel */
486 if (msg->payload.channelState->temporary != true) {
487 sendPermissionDenied(client, "Only temporary channels are supported by uMurmur");
490 /* Check channel name is OK */
491 if (strlen(msg->payload.channelState->name) > MAX_TEXT) {
492 sendPermissionDenied(client, "Channel name too long");
496 parent = Chan_fromId(msg->payload.channelState->parent);
500 while (Chan_iterate_siblings(parent, &ch_itr) != NULL) {
501 if (strcmp(ch_itr->name, msg->payload.channelState->name) == 0) {
502 sendPermissionDenied(client, "Channel already exists");
509 /* Disallow temporary channels as siblings to temporary channels */
510 if (parent->temporary) {
511 sendPermissionDenied(client, "Parent channel is temporary channel");
515 /* XXX - Murmur looks for "\\w" and sends perm denied if not found.
516 * I don't know why so I don't do that here...
519 /* Create the channel */
520 newchan = Chan_createChannel(msg->payload.channelState->name,
521 msg->payload.channelState->description);
522 newchan->temporary = true;
523 Chan_addChannel(parent, newchan);
524 msg->payload.channelState->has_channel_id = true;
525 msg->payload.channelState->channel_id = newchan->id;
527 Client_send_message_except(NULL, msg);
529 /* Join the creating user */
530 sendmsg = Msg_create(UserState);
531 sendmsg->payload.userState->has_session = true;
532 sendmsg->payload.userState->session = client->sessionId;
533 sendmsg->payload.userState->has_channel_id = true;
534 sendmsg->payload.userState->channel_id = newchan->id;
535 Client_send_message_except(NULL, sendmsg);
537 leave_id = Chan_playerJoin(newchan, client);
539 Log_debug("Removing channel ID %d", leave_id);
540 sendmsg = Msg_create(ChannelRemove);
541 sendmsg->payload.channelRemove->channel_id = leave_id;
542 Client_send_message_except(NULL, sendmsg);
547 /* Permission denied for all these messages. Not implemented. */
550 case ContextActionAdd:
555 sendPermissionDenied(client, "Not supported by uMurmur");
559 Log_warn("Message %d not handled", msg->messageType);
568 Client_close(client);