Add mutex for csCrypt usage in Murmur.

This commit is contained in:
Mikkel Krautz 2016-06-03 21:29:34 +02:00
parent f260bd1913
commit f03b74db2d
3 changed files with 37 additions and 10 deletions

View File

@ -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<QSslCertificate> peerCertificateChain() const;

View File

@ -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<const char *>(uSource->csCrypt.raw_key), AES_BLOCK_SIZE));
mpcrypt.set_server_nonce(std::string(reinterpret_cast<const char *>(uSource->csCrypt.encrypt_iv), AES_BLOCK_SIZE));
mpcrypt.set_client_nonce(std::string(reinterpret_cast<const char *>(uSource->csCrypt.decrypt_iv), AES_BLOCK_SIZE));
sendMessage(uSource, mpcrypt);
uSource->csCrypt.genKey();
MumbleProto::CryptSetup mpcrypt;
mpcrypt.set_key(std::string(reinterpret_cast<const char *>(uSource->csCrypt.raw_key), AES_BLOCK_SIZE));
mpcrypt.set_server_nonce(std::string(reinterpret_cast<const char *>(uSource->csCrypt.encrypt_iv), AES_BLOCK_SIZE));
mpcrypt.set_client_nonce(std::string(reinterpret_cast<const char *>(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<const char *>(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<QSslCertificate> &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);

View File

@ -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<const unsigned char *>(encrypt), reinterpret_cast<unsigned char *>(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<char *>(((reinterpret_cast<quint64>(ebuffer) + 8) & ~7) + 4);
#else
STACKVAR(char, buffer, len+4);
#endif
u->csCrypt.encrypt(reinterpret_cast<const unsigned char *>(data), reinterpret_cast<unsigned char *>(buffer), len);
{
QMutexLocker wl(&u->qmCrypt);
if (!u->csCrypt.isValid()) {
return;
}
u->csCrypt.encrypt(reinterpret_cast<const unsigned char *>(data), reinterpret_cast<unsigned char *>(buffer),
len);
}
#ifdef Q_OS_WIN
DWORD dwFlow = 0;
if (Meta::hQoS)