1 /* Copyright (C) 2009, Martin Johansson <martin@fatbob.nu>
2 Copyright (C) 2005-2009, 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>
42 extern channel_t *defaultChan;
44 static void sendServerReject(client_t *client, const char *reason, MumbleProto__Reject__RejectType type)
46 message_t *msg = Msg_create(Reject);
47 msg->payload.reject->reason = strdup(reason);
48 msg->payload.reject->type = type;
49 msg->payload.reject->has_type = true;
50 Client_send_message(client, msg);
53 static void sendPermissionDenied(client_t *client, const char *reason)
55 message_t *msg = Msg_create(PermissionDenied);
56 msg->payload.permissionDenied->has_type = true;
57 msg->payload.permissionDenied->type = MUMBLE_PROTO__PERMISSION_DENIED__DENY_TYPE__Text;
58 msg->payload.permissionDenied->reason = strdup(reason);
59 Client_send_message(client, msg);
62 void Mh_handle_message(client_t *client, message_t *msg)
65 channel_t *ch_itr = NULL;
68 switch (msg->messageType) {
71 * 1. Check stuff, Serverreject if not ok
72 * 2. Setup UDP encryption -> MessageCryptSetup
74 * 4. MessageChannelAdd + MessageChannelDescUpdate for all channels
75 * 5. (MessageChannelLink)
76 * 6. MessageServerJoin
77 * 7. MessagePlayerMove
78 * 8. MessageServerJoin for all connected users
79 * 9. PlayerDeaf/PlayerMute/PlayerSelfMuteDeaf for all users it applies to
80 * 10. MessageServerSync
83 Log_debug("Authenticate message received");
84 Log_debug("Username: %s", msg->payload.authenticate->username);
86 client->authenticated = true;
89 while (Client_iterate(&client_itr) != NULL) {
90 if (!IS_AUTH(client_itr))
92 if (strncmp(client_itr->playerName, msg->payload.authenticate->username, MAX_TEXT) == 0) {
94 sprintf(buf, "Username already in use");
95 Log_debug("Username already in use");
96 sendServerReject(client, buf, MUMBLE_PROTO__REJECT__REJECT_TYPE__UsernameInUse);
100 if (msg->payload.authenticate->password && strncmp(getStrConf(PASSPHRASE), msg->payload.authenticate->password, MAX_TEXT) != 0) {
102 sprintf(buf, "Wrong server password");
103 Log_debug("Wrong server password: %s", msg->payload.authenticate->password);
104 sendServerReject(client, buf, MUMBLE_PROTO__REJECT__REJECT_TYPE__WrongServerPW);
107 if (strlen(msg->payload.authenticate->username) == 0 ||
108 strlen(msg->payload.authenticate->username) >= MAX_TEXT) { /* XXX - other invalid names? */
110 sprintf(buf, "Invalid username");
111 Log_debug("Invalid username");
112 sendServerReject(client, buf, MUMBLE_PROTO__REJECT__REJECT_TYPE__InvalidUsername);
116 if (Client_count() >= getIntConf(MAX_CLIENTS)) {
118 sprintf(buf, "Server is full (max %d users)", getIntConf(MAX_CLIENTS));
119 sendServerReject(client, buf, MUMBLE_PROTO__REJECT__REJECT_TYPE__ServerFull);
123 /* Name & password */
124 strncpy(client->playerName, msg->payload.authenticate->username, MAX_TEXT);
125 client->playerId = client->sessionId;
128 /* XXX - Kick ghost? */
130 /* Setup UDP encryption */
131 CryptState_init(&client->cryptState);
132 CryptState_genKey(&client->cryptState);
133 sendmsg = Msg_create(CryptSetup);
134 sendmsg->payload.cryptSetup->has_key = true;
135 sendmsg->payload.cryptSetup->key.data = client->cryptState.raw_key;
136 sendmsg->payload.cryptSetup->key.len = AES_BLOCK_SIZE;
137 sendmsg->payload.cryptSetup->has_server_nonce = true;
138 sendmsg->payload.cryptSetup->server_nonce.data = client->cryptState.encrypt_iv;
139 sendmsg->payload.cryptSetup->server_nonce.len = AES_BLOCK_SIZE;
140 sendmsg->payload.cryptSetup->has_client_nonce = true;
141 sendmsg->payload.cryptSetup->client_nonce.data = client->cryptState.decrypt_iv;
142 sendmsg->payload.cryptSetup->client_nonce.len = AES_BLOCK_SIZE;
143 Client_send_message(client, sendmsg);
146 Chan_playerJoin(defaultChan, client); /* Join default channel */
148 /* Iterate channels and send channel info */
150 Chan_iterate(&ch_itr);
152 sendmsg = Msg_create(ChannelState);
153 sendmsg->payload.channelState->has_channel_id = true;
154 sendmsg->payload.channelState->channel_id = ch_itr->id;
155 if (ch_itr->id != 0) {
156 sendmsg->payload.channelState->has_parent = true;
157 sendmsg->payload.channelState->parent = ch_itr->parent->id;
159 sendmsg->payload.channelState->name = strdup(ch_itr->name);
160 if (strlen(ch_itr->desc) > 0) {
161 sendmsg->payload.channelState->description = strdup(ch_itr->desc);
163 Log_debug("Send channel info: %s", sendmsg->payload.channelState->name);
164 Client_send_message(client, sendmsg);
166 Chan_iterate(&ch_itr);
167 } while (ch_itr != NULL);
169 /* Not supporting channel links yet */
171 /* Send user state for connecting user to other users */
172 sendmsg = Msg_create(UserState);
173 sendmsg->payload.userState->has_session = true;
174 sendmsg->payload.userState->session = client->sessionId;
175 sendmsg->payload.userState->has_user_id = true;
176 sendmsg->payload.userState->user_id = client->playerId;
177 sendmsg->payload.userState->name = strdup(client->playerName);
178 sendmsg->payload.userState->has_channel_id = true;
179 sendmsg->payload.userState->channel_id = ((channel_t *)client->channel)->id;
181 Client_send_message_except(client, sendmsg);
184 while (Client_iterate(&client_itr) != NULL) {
185 if (!IS_AUTH(client_itr))
187 sendmsg = Msg_create(UserState);
188 sendmsg->payload.userState->has_session = true;
189 sendmsg->payload.userState->session = client->sessionId;
190 sendmsg->payload.userState->name = strdup(client->playerName);
191 sendmsg->payload.userState->has_channel_id = true;
192 sendmsg->payload.userState->channel_id = ((channel_t *)client->channel)->id;
194 /* XXX - check if self_* is correct */
196 sendmsg->payload.userState->has_self_deaf = true;
197 sendmsg->payload.userState->self_deaf = true;
200 sendmsg->payload.userState->has_self_mute = true;
201 sendmsg->payload.userState->self_mute = true;
203 Client_send_message(client, sendmsg);
207 sendmsg = Msg_create(ServerSync);
208 sendmsg->payload.serverSync->has_session = true;
209 sendmsg->payload.serverSync->session = client->sessionId;
210 sendmsg->payload.serverSync->welcome_text = strdup(getStrConf(WELCOMETEXT));
211 sendmsg->payload.serverSync->has_max_bandwidth = true;
212 sendmsg->payload.serverSync->max_bandwidth = getIntConf(MAX_BANDWIDTH);
213 sendmsg->payload.serverSync->has_allow_html = true;
214 sendmsg->payload.serverSync->allow_html = false; /* Support this? */
215 Client_send_message(client, sendmsg);
217 Log_info("User %s authenticated", client->playerName);
223 if (msg->payload.ping->has_good)
224 client->cryptState.uiRemoteGood = msg->payload.ping->good;
225 if (msg->payload.ping->has_late)
226 client->cryptState.uiRemoteLate = msg->payload.ping->late;
227 if (msg->payload.ping->has_lost)
228 client->cryptState.uiRemoteLost = msg->payload.ping->lost;
229 if (msg->payload.ping->has_resync)
230 client->cryptState.uiRemoteResync = msg->payload.ping->resync;
232 Log_debug("Ping <-: %d %d %d %d",
233 client->cryptState.uiRemoteGood, client->cryptState.uiRemoteLate,
234 client->cryptState.uiRemoteLost, client->cryptState.uiRemoteResync
237 /* Ignoring the double values since they don't seem to be used */
239 sendmsg = Msg_create(Ping);
240 timestamp = msg->payload.ping->timestamp;
242 sendmsg->payload.ping->timestamp = timestamp;
244 sendmsg->payload.ping->good = client->cryptState.uiGood;
245 sendmsg->payload.ping->has_good = true;
246 sendmsg->payload.ping->late = client->cryptState.uiLate;
247 sendmsg->payload.ping->has_late = true;
248 sendmsg->payload.ping->lost = client->cryptState.uiLost;
249 sendmsg->payload.ping->has_lost = true;
250 sendmsg->payload.ping->resync = client->cryptState.uiResync;
251 sendmsg->payload.ping->has_resync = true;
253 Client_send_message(client, sendmsg);
254 Log_debug("Ping ->: %d %d %d %d",
255 client->cryptState.uiGood, client->cryptState.uiLate,
256 client->cryptState.uiLost, client->cryptState.uiResync);
261 Log_debug("Voice channel crypt resync requested");
262 if (!msg->payload.cryptSetup->has_client_nonce) {
263 sendmsg = Msg_create(CryptSetup);
264 sendmsg->payload.cryptSetup->has_server_nonce = true;
265 memcpy(sendmsg->payload.cryptSetup->server_nonce.data, client->cryptState.decrypt_iv, AES_BLOCK_SIZE);
266 sendmsg->payload.cryptSetup->server_nonce.len = AES_BLOCK_SIZE;
267 Client_send_message(client, sendmsg);
269 memcpy(client->cryptState.decrypt_iv, msg->payload.cryptSetup->client_nonce.data, AES_BLOCK_SIZE);
270 client->cryptState.uiResync++;
274 /* Only allow state changes for for the self user */
275 if (msg->payload.userState->has_session &&
276 msg->payload.userState->session != client->sessionId) {
277 sendPermissionDenied(client, "Permission denied");
280 if (msg->payload.userState->has_user_id || msg->payload.userState->has_mute ||
281 msg->payload.userState->has_deaf || msg->payload.userState->has_suppress ||
282 msg->payload.userState->has_texture) {
284 sendPermissionDenied(client, "Not supported by uMurmur");
287 if (msg->payload.userState->has_self_deaf) {
288 client->deaf = msg->payload.userState->self_deaf;
290 if (msg->payload.userState->has_self_mute) {
291 client->mute = msg->payload.userState->self_mute;
293 if (msg->payload.userState->has_channel_id) {
294 Chan_playerJoin_id(msg->payload.userState->channel_id, client);
298 msg->payload.userState->has_actor = true;
299 msg->payload.userState->actor = client->sessionId;
300 Client_send_message_except(NULL, msg);
305 if (msg->payload.textMessage.bTree)
306 sendPermissionDenied(client, "Tree message not supported");
307 else if (msg->payload.textMessage.channel != -1) { /* To channel */
308 channel_t *ch_itr = NULL;
310 Chan_iterate(&ch_itr);
311 } while (ch_itr != NULL && ch_itr->id != msg->payload.textMessage.channel);
313 Log_warn("Channel id %d not found - ignoring.", msg->payload.textMessage.channel);
316 list_iterate(itr, &ch_itr->clients) {
318 c = list_get_entry(itr, client_t, chan_node);
319 if (c != client && !c->deaf) {
321 Client_send_message(c, msg);
322 Log_debug("Text message to player ID %d", c->playerId);
326 } else { /* To player */
327 client_t *itr = NULL;
328 while (Client_iterate(&itr) != NULL) {
331 if (itr->playerId == msg->payload.textMessage.victim) {
334 Client_send_message(itr, msg);
340 Log_warn("TextMessage: Player ID %d not found", msg->payload.textMessage.victim);
350 sendmsg = Msg_create(Version); /* Re-use message */
351 Log_debug("Version message received");
352 sendmsg->payload.version->has_version = true;
353 sendmsg->payload.version->version = (1 << 16) | (2 << 8) | 0; /* XXX fix */
354 sendmsg->payload.version->release = "Phony donkey";
355 sendmsg->payload.version->os = "OpenWRT";
357 Client_send_message(client, sendmsg);
360 Msg_inc_ref(msg); /* Re-use message */
362 /* XXX - fill in version */
364 Client_send_message(client, msg);
367 Client_voiceMsg(client, msg->payload.UDPTunnel->packet.data, msg->payload.UDPTunnel->packet.len);
369 /* Permission denied for all these messages. Not implemented. */
373 case ContextActionAdd:
376 sendPermissionDenied(client, "Not supported by uMurmur");
380 Log_warn("Message %d not handled", msg->messageType);
387 Client_close(client);