diff --git a/src/Connection.h b/src/Connection.h index 7060e2403..030f67037 100644 --- a/src/Connection.h +++ b/src/Connection.h @@ -67,6 +67,10 @@ class Connection : public QObject { qint64 activityTime() const; void resetActivityTime(); +#ifdef MURMUR + /// qmCrypt locks access to csCrypt. + QMutex qmCrypt; +#endif CryptState csCrypt; QList peerCertificateChain() const; diff --git a/src/murmur/Messages.cpp b/src/murmur/Messages.cpp index 12b7f7f00..52a9bd9c0 100644 --- a/src/murmur/Messages.cpp +++ b/src/murmur/Messages.cpp @@ -194,13 +194,17 @@ void Server::msgAuthenticate(ServerUser *uSource, MumbleProto::Authenticate &msg } // Setup UDP encryption - uSource->csCrypt.genKey(); + { + QMutexLocker l(&uSource->qmCrypt); - MumbleProto::CryptSetup mpcrypt; - mpcrypt.set_key(std::string(reinterpret_cast(uSource->csCrypt.raw_key), AES_BLOCK_SIZE)); - mpcrypt.set_server_nonce(std::string(reinterpret_cast(uSource->csCrypt.encrypt_iv), AES_BLOCK_SIZE)); - mpcrypt.set_client_nonce(std::string(reinterpret_cast(uSource->csCrypt.decrypt_iv), AES_BLOCK_SIZE)); - sendMessage(uSource, mpcrypt); + uSource->csCrypt.genKey(); + + MumbleProto::CryptSetup mpcrypt; + mpcrypt.set_key(std::string(reinterpret_cast(uSource->csCrypt.raw_key), AES_BLOCK_SIZE)); + mpcrypt.set_server_nonce(std::string(reinterpret_cast(uSource->csCrypt.encrypt_iv), AES_BLOCK_SIZE)); + mpcrypt.set_client_nonce(std::string(reinterpret_cast(uSource->csCrypt.decrypt_iv), AES_BLOCK_SIZE)); + sendMessage(uSource, mpcrypt); + } bool fake_celt_support = false; if (msg.celt_versions_size() > 0) { @@ -1400,6 +1404,9 @@ void Server::msgQueryUsers(ServerUser *uSource, MumbleProto::QueryUsers &msg) { void Server::msgPing(ServerUser *uSource, MumbleProto::Ping &msg) { MSG_SETUP_NO_UNIDLE(ServerUser::Authenticated); + + QMutexLocker l(&uSource->qmCrypt); + CryptState &cs=uSource->csCrypt; cs.uiRemoteGood = msg.good(); @@ -1428,6 +1435,9 @@ void Server::msgPing(ServerUser *uSource, MumbleProto::Ping &msg) { void Server::msgCryptSetup(ServerUser *uSource, MumbleProto::CryptSetup &msg) { MSG_SETUP_NO_UNIDLE(ServerUser::Authenticated); + + QMutexLocker l(&uSource->qmCrypt); + if (! msg.has_client_nonce()) { log(uSource, "Requested crypt-nonce resync"); msg.set_server_nonce(std::string(reinterpret_cast(uSource->csCrypt.encrypt_iv), AES_BLOCK_SIZE)); @@ -1605,7 +1615,6 @@ void Server::msgCodecVersion(ServerUser *, MumbleProto::CodecVersion &) { void Server::msgUserStats(ServerUser*uSource, MumbleProto::UserStats &msg) { MSG_SETUP_NO_UNIDLE(ServerUser::Authenticated); VICTIM_SETUP; - const CryptState &cs = pDstServerUser->csCrypt; const BandwidthRecord &bwr = pDstServerUser->bwr; const QList &certs = pDstServerUser->peerCertificateChain(); @@ -1636,6 +1645,9 @@ void Server::msgUserStats(ServerUser*uSource, MumbleProto::UserStats &msg) { if (local) { MumbleProto::UserStats_Stats *mpusss; + QMutexLocker l(&pDstServerUser->qmCrypt); + const CryptState &cs = pDstServerUser->csCrypt; + mpusss = msg.mutable_from_client(); mpusss->set_good(cs.uiGood); mpusss->set_late(cs.uiLate); diff --git a/src/murmur/Server.cpp b/src/murmur/Server.cpp index c5e2bf477..ebbf13b3e 100644 --- a/src/murmur/Server.cpp +++ b/src/murmur/Server.cpp @@ -820,7 +820,7 @@ void Server::run() { } else { // Unknown peer foreach(ServerUser *usr, qhHostUsers.value(ha)) { - if (usr->csCrypt.isValid() && checkDecrypt(usr, encrypt, buffer, len)) { + if (checkDecrypt(usr, encrypt, buffer, len)) { // checkDecrypt takes the User's qrwlCrypt lock. // Every time we relock, reverify users' existance. // The main thread might delete the user while the lock isn't held. unsigned int uiSession = usr->uiSession; @@ -879,6 +879,8 @@ void Server::run() { } bool Server::checkDecrypt(ServerUser *u, const char *encrypt, char *plain, unsigned int len) { + QMutexLocker l(&u->qmCrypt); + if (u->csCrypt.isValid() && u->csCrypt.decrypt(reinterpret_cast(encrypt), reinterpret_cast(plain), len)) return true; @@ -892,14 +894,23 @@ bool Server::checkDecrypt(ServerUser *u, const char *encrypt, char *plain, unsig } void Server::sendMessage(ServerUser *u, const char *data, int len, QByteArray &cache, bool force) { - if ((u->bUdp || force) && (u->sUdpSocket != INVALID_SOCKET) && u->csCrypt.isValid()) { + if ((u->bUdp || force) && (u->sUdpSocket != INVALID_SOCKET)) { #if defined(__LP64__) STACKVAR(char, ebuffer, len+4+16); char *buffer = reinterpret_cast(((reinterpret_cast(ebuffer) + 8) & ~7) + 4); #else STACKVAR(char, buffer, len+4); #endif - u->csCrypt.encrypt(reinterpret_cast(data), reinterpret_cast(buffer), len); + { + QMutexLocker wl(&u->qmCrypt); + + if (!u->csCrypt.isValid()) { + return; + } + + u->csCrypt.encrypt(reinterpret_cast(data), reinterpret_cast(buffer), + len); + } #ifdef Q_OS_WIN DWORD dwFlow = 0; if (Meta::hQoS)