void CDbxKyoto::ToggleEncryption() { HANDLE hSave1 = hSettingChangeEvent; hSettingChangeEvent = NULL; HANDLE hSave2 = hEventAddedEvent; hEventAddedEvent = NULL; HANDLE hSave3 = hEventDeletedEvent; hEventDeletedEvent = NULL; HANDLE hSave4 = hEventFilterAddedEvent; hEventFilterAddedEvent = NULL; mir_cslock lck(m_csDbAccess); ToggleSettingsEncryption(NULL); ToggleEventsEncryption(NULL); for (MCONTACT contactID = FindFirstContact(); contactID; contactID = FindNextContact(contactID)) { ToggleSettingsEncryption(contactID); ToggleEventsEncryption(contactID); } m_bEncrypted = !m_bEncrypted; DBCONTACTWRITESETTING dbcws = { "CryptoEngine", "DatabaseEncryption" }; dbcws.value.type = DBVT_BYTE; dbcws.value.bVal = m_bEncrypted; WriteContactSetting(NULL, &dbcws); hSettingChangeEvent = hSave1; hEventAddedEvent = hSave2; hEventDeletedEvent = hSave3; hEventFilterAddedEvent = hSave4; }
void CDbxKyoto::StoreKey() { size_t iKeyLength = m_crypto->getKeyLength(); BYTE *pKey = (BYTE*)_alloca(iKeyLength); m_crypto->getKey(pKey, iKeyLength); DBCONTACTWRITESETTING dbcws = { "CryptoEngine", "StoredKey" }; dbcws.value.type = DBVT_BLOB; dbcws.value.cpbVal = (WORD)iKeyLength; dbcws.value.pbVal = pKey; WriteContactSetting(NULL, &dbcws); SecureZeroMemory(pKey, iKeyLength); }
int CDbxKyoto::InitCrypt() { CRYPTO_PROVIDER *pProvider; bool bMissingKey = false; DBVARIANT dbv = { 0 }; dbv.type = DBVT_BLOB; if (GetContactSetting(NULL, "CryptoEngine", "Provider", &dbv)) { LBL_CreateProvider: CRYPTO_PROVIDER **ppProvs; int iNumProvs; Crypto_EnumProviders(&iNumProvs, &ppProvs); if (iNumProvs == 0) return 1; pProvider = ppProvs[0]; //!!!!!!!!!!!!!!!!!! DBCONTACTWRITESETTING dbcws = { "CryptoEngine", "Provider" }; dbcws.value.type = DBVT_BLOB; dbcws.value.pbVal = (PBYTE)pProvider->pszName; dbcws.value.cpbVal = (int)strlen(pProvider->pszName) + 1; WriteContactSetting(NULL, &dbcws); } else { if (dbv.type != DBVT_BLOB) { // old version, clean it up bMissingKey = true; goto LBL_CreateProvider; } pProvider = Crypto_GetProvider(LPCSTR(dbv.pbVal)); FreeVariant(&dbv); if (pProvider == NULL) goto LBL_CreateProvider; } if ((m_crypto = pProvider->pFactory()) == NULL) return 3; dbv.type = DBVT_BLOB; if (GetContactSetting(NULL, "CryptoEngine", "StoredKey", &dbv)) { bMissingKey = true; LBL_SetNewKey: m_crypto->generateKey(); // unencrypted key StoreKey(); } else { size_t iKeyLength = m_crypto->getKeyLength(); if (dbv.cpbVal != (WORD)iKeyLength) goto LBL_SetNewKey; if (!m_crypto->setKey(dbv.pbVal, iKeyLength)) if (!EnterPassword(dbv.pbVal, iKeyLength)) // password protected? return 4; FreeVariant(&dbv); } if (bMissingKey) EnumModuleNames(sttModuleEnum, this); dbv.type = DBVT_BYTE; if (!GetContactSetting(NULL, "CryptoEngine", "DatabaseEncryption", &dbv)) m_bEncrypted = dbv.bVal != 0; InitDialogs(); return 0; }
void CDb3Mmap::FillContacts() { OBJLIST<COldMeta> arMetas(10, NumericKeySortT); for (DWORD dwOffset = m_dbHeader.ofsFirstContact; dwOffset != 0;) { DBContact *p = (DBContact*)DBRead(dwOffset, NULL); if (p->signature != DBCONTACT_SIGNATURE) break; DWORD dwContactID; if (m_dbHeader.version >= DB_095_VERSION) { dwContactID = p->dwContactID; if (dwContactID > m_dwMaxContactId) m_dwMaxContactId = dwContactID + 1; } else dwContactID = m_dwMaxContactId++; DBCachedContact *cc = m_cache->AddContactToCache(dwContactID); cc->dwDriverData = dwOffset; CheckProto(cc, ""); DBVARIANT dbv; dbv.type = DBVT_DWORD; cc->nSubs = (0 != GetContactSetting(dwContactID, META_PROTO, "NumContacts", &dbv)) ? -1 : dbv.dVal; if (cc->nSubs != -1) { cc->pSubs = (MCONTACT*)mir_alloc(cc->nSubs*sizeof(MCONTACT)); for (int i = 0; i < cc->nSubs; i++) { char setting[100]; mir_snprintf(setting, SIZEOF(setting), "Handle%d", i); cc->pSubs[i] = (0 != GetContactSetting(dwContactID, META_PROTO, setting, &dbv)) ? NULL : dbv.dVal; } } cc->nDefault = (0 != GetContactSetting(dwContactID, META_PROTO, "Default", &dbv)) ? -1 : dbv.dVal; cc->parentID = (0 != GetContactSetting(dwContactID, META_PROTO, "ParentMeta", &dbv)) ? NULL : dbv.dVal; // whether we need conversion or not if (!GetContactSetting(dwContactID, META_PROTO, "MetaID", &dbv)) arMetas.insert(new COldMeta(dbv.dVal, cc)); dwOffset = p->ofsNext; } // no need in conversion? quit then if (m_bReadOnly || arMetas.getCount() == 0) return; DBVARIANT dbv; dbv.type = DBVT_DWORD; for (MCONTACT hh = FindFirstContact(); hh; hh = FindNextContact(hh)) { if (GetContactSetting(hh, META_PROTO, "MetaLink", &dbv)) continue; COldMeta *p = arMetas.find((COldMeta*)&dbv.dVal); if (p == NULL) continue; if (GetContactSetting(hh, META_PROTO, "ContactNumber", &dbv)) continue; DBCONTACTWRITESETTING dbws = { META_PROTO }; dbws.value.type = DBVT_DWORD; DBCachedContact *ccMeta = p->cc; if (int(dbv.dVal) < ccMeta->nSubs) { ccMeta->pSubs[dbv.dVal] = hh; char setting[100]; mir_snprintf(setting, SIZEOF(setting), "Handle%d", dbv.dVal); dbws.szSetting = setting; dbws.value.dVal = hh; WriteContactSetting(ccMeta->contactID, &dbws); } // store contact id instead of the old mc number dbws.szSetting = "ParentMeta"; dbws.value.dVal = ccMeta->contactID; WriteContactSetting(hh, &dbws); // wipe out old data from subcontacts DeleteContactSetting(hh, META_PROTO, "ContactNumber"); DeleteContactSetting(hh, META_PROTO, "MetaLink"); } for (int i = 0; i < arMetas.getCount(); i++) { COldMeta &p = arMetas[i]; DBCachedContact *ccMeta = p.cc; MCONTACT hContact = ccMeta->contactID; // we don't need it anymore if (!GetContactSetting(hContact, META_PROTO, "MetaID", &dbv)) { DeleteContactSetting(hContact, META_PROTO, "MetaID"); WipeContactHistory((DBContact*)DBRead(ccMeta->dwDriverData, NULL)); } for (int k = 0; k < ccMeta->nSubs; k++) { DBCachedContact *ccSub = m_cache->GetCachedContact(ccMeta->pSubs[k]); if (ccSub) { ccSub->parentID = hContact; MetaMergeHistory(ccMeta, ccSub); } } } }
void CDb3Mmap::ToggleSettingsEncryption(MCONTACT contactID) { DWORD ofsContact = GetContactOffset(contactID); if (ofsContact == 0) return; DBContact *contact = (DBContact*)DBRead(ofsContact, NULL); if (contact->ofsFirstSettings == 0) return; // fast cycle through all settings DBContactSettings *setting = (DBContactSettings*)DBRead(contact->ofsFirstSettings, NULL); DWORD offset = contact->ofsFirstSettings; char *szModule = GetModuleNameByOfs(setting->ofsModuleName); if (szModule == NULL) return; while (true) { OBJLIST<VarDescr> arSettings(10); char szSetting[256]; int bytesRemaining, len; DWORD ofsBlobPtr = offset + offsetof(DBContactSettings, blob), ofsNext = setting->ofsNext; PBYTE pBlob = (PBYTE)DBRead(ofsBlobPtr, &bytesRemaining); while (pBlob[0]) { NeedBytes(1); len = pBlob[0]; memcpy(szSetting, pBlob + 1, len); szSetting[len] = 0; NeedBytes(1 + pBlob[0]); MoveAlong(1 + pBlob[0]); NeedBytes(5); switch (pBlob[0]) { case DBVT_ASCIIZ: len = *(PWORD)(pBlob + 1); // we need to convert a string into utf8 and encrypt it if (!m_bEncrypted) { BYTE bSave = pBlob[len + 3]; pBlob[len + 3] = 0; arSettings.insert(new VarDescr(szSetting, mir_utf8encode((LPCSTR)pBlob + 3))); pBlob[len + 3] = bSave; } NeedBytes(3 + len); break; case DBVT_UTF8: len = *(PWORD)(pBlob + 1); // we need to encrypt these strings if (!m_bEncrypted) { BYTE bSave = pBlob[len + 3]; pBlob[len + 3] = 0; arSettings.insert(new VarDescr(szSetting, (LPCSTR)pBlob + 3)); pBlob[len + 3] = bSave; } NeedBytes(3 + len); break; case DBVT_ENCRYPTED: len = *(PWORD)(pBlob + 1); // we need to decrypt these strings if (m_bEncrypted && !IsSettingEncrypted(szModule, szSetting)) arSettings.insert(new VarDescr(szSetting, pBlob + 3, len)); NeedBytes(3 + len); break; case DBVT_BLOB: NeedBytes(3 + *(PWORD)(pBlob + 1)); break; } NeedBytes(3); MoveAlong(1 + GetSettingValueLength(pBlob)); NeedBytes(1); } for (int i = 0; i < arSettings.getCount(); i++) { VarDescr &p = arSettings[i]; if (!m_bEncrypted) { size_t encodedLen; BYTE *pResult = m_crypto->encodeString(p.szValue, &encodedLen); if (pResult != NULL) { DBCONTACTWRITESETTING dbcws = { szModule, p.szVar }; dbcws.value.type = DBVT_ENCRYPTED; dbcws.value.pbVal = pResult; dbcws.value.cpbVal = (WORD)encodedLen; WriteContactSetting(contactID, &dbcws); mir_free(pResult); } } else { size_t realLen; ptrA decoded(m_crypto->decodeString((PBYTE)(char*)p.szValue, p.iLen, &realLen)); if (decoded != NULL) { DBCONTACTWRITESETTING dbcws = { szModule, p.szVar }; dbcws.value.type = DBVT_UNENCRYPTED; dbcws.value.pszVal = decoded; dbcws.value.cchVal = (WORD)realLen; WriteContactSetting(contactID, &dbcws); } } } if (!ofsNext) break; setting = (DBContactSettings*)DBRead(offset = ofsNext, NULL); if ((szModule = GetModuleNameByOfs(setting->ofsModuleName)) == NULL) break; } }
int CDb3Mmap::InitCrypt() { if (m_dbHeader.version == DB_OLD_VERSION) return 0; CRYPTO_PROVIDER *pProvider; bool bMissingKey = false; DBVARIANT dbv = { 0 }; dbv.type = DBVT_BLOB; if (GetContactSetting(NULL, "CryptoEngine", "Provider", &dbv)) { LBL_CreateProvider: CRYPTO_PROVIDER **ppProvs; int iNumProvs; Crypto_EnumProviders(&iNumProvs, &ppProvs); if (iNumProvs == 0) return 1; if (iNumProvs > 1) { CSelectCryptoDialog dlg(ppProvs, iNumProvs); dlg.DoModal(); pProvider = dlg.GetSelected(); } else pProvider = ppProvs[0]; DBCONTACTWRITESETTING dbcws = { "CryptoEngine", "Provider" }; dbcws.value.type = DBVT_BLOB; dbcws.value.pbVal = (PBYTE)pProvider->pszName; dbcws.value.cpbVal = (int)mir_strlen(pProvider->pszName) + 1; WriteContactSetting(NULL, &dbcws); } else { if (dbv.type != DBVT_BLOB) { // old version, clean it up bMissingKey = true; goto LBL_CreateProvider; } pProvider = Crypto_GetProvider(LPCSTR(dbv.pbVal)); FreeVariant(&dbv); if (pProvider == NULL) goto LBL_CreateProvider; } if ((m_crypto = pProvider->pFactory()) == NULL) return 3; dbv.type = DBVT_BLOB; if (GetContactSetting(NULL, "CryptoEngine", "StoredKey", &dbv)) { bMissingKey = true; LBL_SetNewKey: m_crypto->generateKey(); // unencrypted key StoreKey(); } else { size_t iKeyLength = m_crypto->getKeyLength(); if (dbv.cpbVal != (WORD)iKeyLength) goto LBL_SetNewKey; if (!m_crypto->setKey(dbv.pbVal, iKeyLength)) { if (memcmp(m_dbHeader.signature, &dbSignatureE, sizeof(m_dbHeader.signature))) goto LBL_SetNewKey; if (!EnterPassword(dbv.pbVal, iKeyLength)) { // password protected? if (m_dbHeader.version >= DB_094_VERSION) return 4; // one of the early used version of mmap was replaced then by mmap_sa // simply remove old badly generated key bMissingKey = true; goto LBL_SetNewKey; } } FreeVariant(&dbv); } if (bMissingKey) EnumModuleNames(sttModuleEnum, this); dbv.type = DBVT_BYTE; if (!GetContactSetting(NULL, "CryptoEngine", "DatabaseEncryption", &dbv)) m_bEncrypted = dbv.bVal != 0; InitDialogs(); return 0; }