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 leave_id = Chan_playerJoin_id(msg->payload.userState->channel_id, client);
331 /* XXX - need to send update to remove channel if temporary */
332 Log_debug("Removing channel ID %d", leave_id);
333 sendmsg = Msg_create(ChannelRemove);
334 sendmsg->payload.channelRemove->channel_id = leave_id;
337 if (msg->payload.userState->plugin_context != NULL) {
339 free(client->context);
340 client->context = strdup(msg->payload.userState->plugin_context);
341 if (client->context == NULL)
342 Log_fatal("Out of memory");
344 break; /* Don't inform other users about this state */
349 msg->payload.userState->has_actor = true;
350 msg->payload.userState->actor = client->sessionId;
351 Client_send_message_except(NULL, msg);
353 /* Need to send remove channel message _after_ UserState message */
355 Client_send_message_except(NULL, sendmsg);
358 msg->payload.textMessage->has_actor = true;
359 msg->payload.textMessage->actor = client->sessionId;
361 /* XXX - HTML is allowed and can't be turned off */
362 if (msg->payload.textMessage->n_tree_id > 0) {
363 sendPermissionDenied(client, "Tree message not supported");
367 if (msg->payload.textMessage->n_channel_id > 0) { /* To channel */
370 for (i = 0; i < msg->payload.textMessage->n_channel_id; i++) {
373 Chan_iterate(&ch_itr);
374 } while (ch_itr != NULL && ch_itr->id != msg->payload.textMessage->channel_id[i]);
376 Log_warn("Channel id %d not found - ignoring.", msg->payload.textMessage->channel_id[i]);
379 list_iterate(itr, &ch_itr->clients) {
381 c = list_get_entry(itr, client_t, chan_node);
382 if (c != client && !c->deaf) {
384 Client_send_message(c, msg);
385 Log_debug("Text message to session ID %d", c->sessionId);
391 if (msg->payload.textMessage->n_session > 0) { /* To user */
394 for (i = 0; i < msg->payload.textMessage->n_session; i++) {
396 while (Client_iterate(&itr) != NULL) {
399 if (itr->sessionId == msg->payload.textMessage->session[i]) {
402 Client_send_message(itr, msg);
403 Log_debug("Text message to session ID %d", itr->sessionId);
409 Log_warn("TextMessage: Session ID %d not found", msg->payload.textMessage->session[i]);
416 int i, j, count, targetId = msg->payload.voiceTarget->id;
417 struct _MumbleProto__VoiceTarget__Target *target;
419 if (!targetId || targetId >= 0x1f)
421 Voicetarget_add_id(client, targetId);
422 count = msg->payload.voiceTarget->n_targets;
425 for (i = 0; i < count; i++) {
426 target = msg->payload.voiceTarget->targets[i];
427 for (j = 0; j < target->n_session; j++)
428 Voicetarget_add_session(client, targetId, target->session[j]);
429 if (target->has_channel_id) {
430 if (target->has_links || target->has_children)
431 Log_warn("Whisper to children or linked channels not implemented. Ignoring.");
432 Voicetarget_add_channel(client, targetId, target->channel_id);
438 Log_debug("Version message received");
439 if (msg->payload.version->has_version) {
440 client->version = msg->payload.version->version;
441 Log_debug("Client version 0x%x", client->version);
443 if (msg->payload.version->release) {
444 if (client->release) free(client->release);
445 client->release = strdup(msg->payload.version->release);
446 Log_debug("Client release %s", client->release);
448 if (msg->payload.version->os) {
449 if (client->os) free(client->os);
450 client->os = strdup(msg->payload.version->os);
451 Log_debug("Client OS %s", client->os);
454 case PermissionQuery:
455 Msg_inc_ref(msg); /* Re-use message */
456 msg->payload.permissionQuery->has_permissions = true;
457 msg->payload.permissionQuery->permissions = PERM_DEFAULT;
459 Client_send_message(client, msg);
462 Client_voiceMsg(client, msg->payload.UDPTunnel->packet.data, msg->payload.UDPTunnel->packet.len);
466 channel_t *ch_itr, *parent, *newchan;
468 /* Don't allow any changes to existing channels */
469 if (msg->payload.channelState->has_channel_id) {
470 sendPermissionDenied(client, "Not supported by uMurmur");
473 /* Must have parent */
474 if (!msg->payload.channelState->has_parent) {
475 sendPermissionDenied(client, "Not supported by uMurmur");
479 if (msg->payload.channelState->name == NULL) {
480 sendPermissionDenied(client, "Not supported by uMurmur");
483 /* Must be temporary channel */
484 if (msg->payload.channelState->temporary != true) {
485 sendPermissionDenied(client, "Only temporary channels are supported by uMurmur");
488 /* Check channel name is OK */
489 if (strlen(msg->payload.channelState->name) > MAX_TEXT) {
490 sendPermissionDenied(client, "Channel name too long");
494 parent = Chan_fromId(msg->payload.channelState->parent);
498 while (Chan_iterate_siblings(parent, &ch_itr) != NULL) {
499 if (strcmp(ch_itr->name, msg->payload.channelState->name) == 0) {
500 sendPermissionDenied(client, "Channel already exists");
504 /* XXX - Murmur looks for "\\w" and sends perm denied if not found.
505 * I don't know why so I don't do that here...
508 /* Create the channel */
509 newchan = Chan_createChannel(msg->payload.channelState->name,
510 msg->payload.channelState->description);
511 newchan->temporary = true;
512 Chan_addChannel(parent, newchan);
513 msg->payload.channelState->has_channel_id = true;
514 msg->payload.channelState->channel_id = newchan->id;
516 Client_send_message_except(NULL, msg);
518 /* Join the creating user */
519 sendmsg = Msg_create(UserState);
520 sendmsg->payload.userState->has_session = true;
521 sendmsg->payload.userState->session = client->sessionId;
522 sendmsg->payload.userState->has_channel_id = true;
523 sendmsg->payload.userState->channel_id = newchan->id;
524 Client_send_message_except(NULL, sendmsg);
525 Chan_playerJoin(newchan, client);
529 /* Permission denied for all these messages. Not implemented. */
532 case ContextActionAdd:
537 sendPermissionDenied(client, "Not supported by uMurmur");
541 Log_warn("Message %d not handled", msg->messageType);
550 Client_close(client);