KVIRC_API void printSSLCertificate(KviWindow * wnd, const char * description, KviSSLCertificate * c) { wnd->output(KVI_OUT_SSL, __tr2qs("[SSL]: %c%s"), KviControlCodes::Bold, description); wnd->output(KVI_OUT_SSL, __tr2qs("[SSL]: Version: %c%d"), KviControlCodes::Bold, c->version()); wnd->output(KVI_OUT_SSL, __tr2qs("[SSL]: Serial number: %c%d"), KviControlCodes::Bold, c->serialNumber()); wnd->output(KVI_OUT_SSL, __tr2qs("[SSL]: Subject:")); wnd->output(KVI_OUT_SSL, __tr2qs("[SSL]: Common name: %c%s"), KviControlCodes::Bold, c->subjectCommonName()); wnd->output(KVI_OUT_SSL, __tr2qs("[SSL]: Organization: %c%s"), KviControlCodes::Bold, c->subjectOrganization()); wnd->output(KVI_OUT_SSL, __tr2qs("[SSL]: Organizational unit: %c%s"), KviControlCodes::Bold, c->subjectOrganizationalUnit()); wnd->output(KVI_OUT_SSL, __tr2qs("[SSL]: Country: %c%s"), KviControlCodes::Bold, c->subjectCountry()); wnd->output(KVI_OUT_SSL, __tr2qs("[SSL]: State or province: %c%s"), KviControlCodes::Bold, c->subjectStateOrProvince()); wnd->output(KVI_OUT_SSL, __tr2qs("[SSL]: Locality: %c%s"), KviControlCodes::Bold, c->subjectLocality()); wnd->output(KVI_OUT_SSL, __tr2qs("[SSL]: Issuer:")); wnd->output(KVI_OUT_SSL, __tr2qs("[SSL]: Common name: %c%s"), KviControlCodes::Bold, c->issuerCommonName()); wnd->output(KVI_OUT_SSL, __tr2qs("[SSL]: Organization: %c%s"), KviControlCodes::Bold, c->issuerOrganization()); wnd->output(KVI_OUT_SSL, __tr2qs("[SSL]: Organizational unit: %c%s"), KviControlCodes::Bold, c->issuerOrganizationalUnit()); wnd->output(KVI_OUT_SSL, __tr2qs("[SSL]: Country: %c%s"), KviControlCodes::Bold, c->issuerCountry()); wnd->output(KVI_OUT_SSL, __tr2qs("[SSL]: State or province: %c%s"), KviControlCodes::Bold, c->issuerStateOrProvince()); wnd->output(KVI_OUT_SSL, __tr2qs("[SSL]: Locality: %c%s"), KviControlCodes::Bold, c->issuerLocality()); wnd->output(KVI_OUT_SSL, __tr2qs("[SSL]: Public key: %c%s (%d bits)"), KviControlCodes::Bold, c->publicKeyType(), c->publicKeyBits()); wnd->output(KVI_OUT_SSL, __tr2qs("[SSL]: Signature type: %c%s"), KviControlCodes::Bold, c->signatureType()); KviCString tmp = c->signatureContents(); if(tmp.len() > 40) { tmp.cutRight(tmp.len() - 40); tmp.append("..."); } wnd->output(KVI_OUT_SSL, __tr2qs("[SSL]: Signature contents: %c%s"), KviControlCodes::Bold, tmp.ptr()); }
KviIpcSentinel::KviIpcSentinel() : QWidget(0) { setObjectName("kvirc4_ipc_sentinel"); #if defined(COMPILE_ON_WINDOWS) || defined(COMPILE_ON_MINGW) setWindowTitle("kvirc4_ipc_sentinel"); setWindowFlags(Qt::FramelessWindowHint); #else #if defined(COMPILE_X11_SUPPORT) && defined(COMPILE_QX11INFO_SUPPORT) kvi_ipcLoadAtoms(); XChangeProperty(kvi_ipc_get_xdisplay(),winId(),kvi_atom_ipc_sentinel_window,XA_STRING,8, PropModeReplace,(const unsigned char *)kvi_sentinel_id.ptr(),kvi_sentinel_id.len()); kvi_ipcSetRemoteCommand(winId(),""); #endif //!COMPILE_NO_X #endif move(-50,-50); resize(1,1); #if defined(COMPILE_ON_WINDOWS) || defined(COMPILE_ON_MINGW) // we need to show the window once otherwise it will never get "realized" // and we will not be able to find it via FindWindow() show(); #endif hide(); }
KviCryptEngine::EncryptResult KviMircryptionEngine::encrypt(const char * plainText, KviCString & outBuffer) { KviCString szPlain = plainText; outBuffer = ""; if(m_bEncryptCBC) { if(!doEncryptCBC(szPlain, outBuffer)) return KviCryptEngine::EncryptError; } else { if(!doEncryptECB(szPlain, outBuffer)) return KviCryptEngine::EncryptError; } outBuffer.prepend("+OK "); if(outBuffer.len() > maxEncryptLen()) { if(maxEncryptLen() > 0) { setLastError(__tr2qs("Data buffer too long")); return KviCryptEngine::EncryptError; } } //outBuffer = MCPS2_STARTTAG; //outBuffer += MCPS2_ENDTAG; return KviCryptEngine::Encrypted; }
void decode(KviCString & szText, unsigned char ** buf, int *len) { // make sure its length is multiple of 12 (eventually pad with zeroes) if(szText.len() % 12) { int oldL = szText.len(); szText.setLen(szText.len() + (12 - (szText.len() % 12))); char * padB = szText.ptr() + oldL; char * padE = szText.ptr() + szText.len(); while(padB < padE)*padB++ = 0; } *len = (int)(szText.len() * 2) / 3; *buf = (unsigned char *)KviMemory::allocate(*len); unsigned char * p = (unsigned char *)szText.ptr(); unsigned char * e = p + szText.len(); int i; unsigned char * bufp = *buf; while(p < e) { quint32 * dw1 = (quint32 *)bufp; bufp += 4; quint32 * dw2 = (quint32 *)bufp; bufp += 4; *dw2 = 0; for(i=0;i < 6;i++)*dw2 |= (fake_base64dec(*p++)) << (i * 6); *dw1 = 0; for(i=0;i < 6;i++)*dw1 |= (fake_base64dec(*p++)) << (i * 6); } // FIXME: this is probably needed only on LittleEndian machines! byteswap_buffer(*buf,*len); }
bool KviMircryptionEngine::doEncryptCBC(KviCString & plain, KviCString & encoded) { // make sure it is a multiple of 8 bytes (eventually pad with zeroes) if(plain.len() % 8) { int oldL = plain.len(); plain.setLen(plain.len() + (8 - (plain.len() % 8))); char * padB = plain.ptr() + oldL; char * padE = plain.ptr() + plain.len(); while(padB < padE) *padB++ = 0; } int ll = plain.len() + 8; unsigned char * in = (unsigned char *)KviMemory::allocate(ll); InitVectorEngine::fillRandomIV(in, 8); KviMemory::copy(in + 8, plain.ptr(), plain.len()); // encrypt unsigned char * out = (unsigned char *)KviMemory::allocate(ll); BlowFish bf((unsigned char *)m_szEncryptKey.ptr(), m_szEncryptKey.len()); bf.ResetChain(); bf.Encrypt(in, out, ll, BlowFish::CBC); KviMemory::free(in); encoded.bufferToBase64((const char *)out, ll); KviMemory::free(out); encoded.prepend('*'); // prepend the signature return true; }
static Window kvi_x11_findIpcSentinel(Window win) { Atom type; int format; unsigned long nItems, after; unsigned char * data = nullptr; if(XGetWindowProperty(kvi_ipc_get_xdisplay(), win, kvi_atom_ipc_sentinel_window, 0, 32, false, XA_STRING, &type, &format, &nItems, &after, &data) == Success) { if((type == XA_STRING) && (format == 8)) { if((nItems == ((unsigned long)(kvi_sentinel_id.len()))) && data) { if(kvi_strEqualCSN((const char *)data, kvi_sentinel_id.ptr(), kvi_sentinel_id.len())) { XFree((char *)data); return win; } } } } Window root, parent; Window * children; unsigned int nChildren; if(!XQueryTree(kvi_ipc_get_xdisplay(), win, &root, &parent, &children, &nChildren)) { if(children) XFree((char *)children); return 0; } Window found = 0; for(size_t i = 0; !found && i < nChildren; ++i) found = kvi_x11_findIpcSentinel(children[i]); if(children) XFree((char *)children); return found; }
KviCryptEngine::EncryptResult KviRijndaelEngine::encrypt(const char * plainText, KviCString & outBuffer) { if(!m_pEncryptCipher) { setLastError(__tr2qs("Oops! Encryption cipher not initialized")); return KviCryptEngine::EncryptError; } int len = (int)kvi_strLen(plainText); char * buf = (char *)KviMemory::allocate(len + 16); // needed for the eventual padding unsigned char * iv = nullptr; if(m_bEncryptMode == CBC) { iv = (unsigned char *)KviMemory::allocate(MAX_IV_SIZE); InitVectorEngine::fillRandomIV(iv, MAX_IV_SIZE); } int retVal = m_pEncryptCipher->padEncrypt((const unsigned char *)plainText, len, (unsigned char *)buf, iv); if(retVal < 0) { KviMemory::free(buf); setLastErrorFromRijndaelErrorCode(retVal); return KviCryptEngine::EncryptError; } if(m_bEncryptMode == CBC) { // prepend the iv to the cyphered text buf = (char *)KviMemory::reallocate(buf, retVal + MAX_IV_SIZE); KviMemory::move(buf + MAX_IV_SIZE, buf, retVal); KviMemory::move(buf, iv, MAX_IV_SIZE); KviMemory::free(iv); retVal += MAX_IV_SIZE; } if(!binaryToAscii(buf, retVal, outBuffer)) { KviMemory::free(buf); return KviCryptEngine::EncryptError; } KviMemory::free(buf); if(outBuffer.len() > maxEncryptLen()) { if(maxEncryptLen() > 0) { setLastError(__tr2qs("Data buffer too long")); return KviCryptEngine::EncryptError; } } outBuffer.prepend(KviControlCodes::CryptEscape); return KviCryptEngine::Encrypted; }
bool KviWinampInterface::playMrl(const QString & mrl) { HWND hWinamp = find_winamp(this); if(hWinamp) { QTextCodec * c = mediaplayer_get_codec(); KviCString szMrl = c ? c->fromUnicode(mrl) : mrl.toUtf8(); COPYDATASTRUCT cds; cds.dwData = IPC_PLAYFILE; cds.lpData = (void *)szMrl.ptr(); cds.cbData = szMrl.len() + 1; // include space for null char SendMessage(hWinamp, WM_COPYDATA, (WPARAM)NULL, (LPARAM)&cds); return true; } return false; }
bool KviMircryptionEngine::doEncryptECB(KviCString & plain, KviCString & encoded) { // make sure it is a multiple of 8 bytes (eventually pad with zeroes) if(plain.len() % 8) { int oldL = plain.len(); plain.setLen(plain.len() + (8 - (plain.len() % 8))); char * padB = plain.ptr() + oldL; char * padE = plain.ptr() + plain.len(); while(padB < padE) *padB++ = 0; } unsigned char * out = (unsigned char *)KviMemory::allocate(plain.len()); // we use this to avoid endiannes problems BlowFish bf((unsigned char *)m_szEncryptKey.ptr(), m_szEncryptKey.len()); bf.ResetChain(); bf.Encrypt((unsigned char *)plain.ptr(), out, plain.len(), BlowFish::ECB); UglyBase64::encode(out, plain.len(), encoded); KviMemory::free(out); return true; }
bool KviCryptController::initializeEngine(KviCryptEngine * pEngine) { KviCString szEncryptKey; KviCString szDecryptKey; KviCString szEncKey = ""; KviCString szDecKey = ""; if(m_pEnableEncrypt->isChecked()) { bool bEcb=false, bOld=false; szEncryptKey = m_pEncryptKeyEdit->text(); if(kvi_strEqualCIN("ecb:",szEncryptKey.ptr(),4) && (szEncryptKey.len() > 4)) { szEncryptKey.cutLeft(4); bEcb=true; } else if(kvi_strEqualCIN("old:",szEncryptKey.ptr(),4) && (szEncryptKey.len() > 4)) { szEncryptKey.cutLeft(4); bOld=true; } else if(kvi_strEqualCIN("cbc:",szEncryptKey.ptr(),4)) { szEncryptKey.cutLeft(4); } if(m_pEncryptHexKeyCheck->isChecked()) { char * pcTmpKey; if(szEncryptKey.hexToBuffer(&pcTmpKey,false)) { szEncKey = pcTmpKey; KviCString::freeBuffer(pcTmpKey); } } else { szEncKey = szEncryptKey; } if(bEcb) szEncKey.prepend("ecb:"); else if(bOld) szEncKey.prepend("old:"); } if(m_pEnableDecrypt->isChecked()) { bool bEcb=false, bOld=false; szDecryptKey = m_pDecryptKeyEdit->text(); if(kvi_strEqualCIN("ecb:",szDecryptKey.ptr(),4) && (szDecryptKey.len() > 4)) { szDecryptKey.cutLeft(4); bEcb=true; } else if(kvi_strEqualCIN("old:",szDecryptKey.ptr(),4) && (szDecryptKey.len() > 4)) { szDecryptKey.cutLeft(4); bOld=true; } else if(kvi_strEqualCIN("cbc:",szDecryptKey.ptr(),4)) { szDecryptKey.cutLeft(4); } if(m_pDecryptHexKeyCheck->isChecked()) { char * pcTmpKey; if(szDecryptKey.hexToBuffer(&pcTmpKey,false)) { szDecKey = pcTmpKey; KviCString::freeBuffer(pcTmpKey); } } else { szDecKey = szDecryptKey; } if(bEcb) szDecKey.prepend("ecb:"); else if(bOld) szDecKey.prepend("old:"); } bool bRet = pEngine->init(szEncKey.ptr(),szEncKey.len(),szDecKey.ptr(),szDecKey.len()); return bRet; }
bool KviRijndaelEngine::init(const char * encKey, int encKeyLen, const char * decKey, int decKeyLen) { if(m_pEncryptCipher) { delete m_pEncryptCipher; m_pEncryptCipher = nullptr; } if(m_pDecryptCipher) { delete m_pDecryptCipher; m_pDecryptCipher = nullptr; } if(encKey && (encKeyLen > 0)) { if(!(decKey && (decKeyLen > 0))) { decKey = encKey; decKeyLen = encKeyLen; } // else all } else { // no encrypt key specified... if(decKey && decKeyLen) { encKey = decKey; encKeyLen = decKeyLen; } else { // both keys missing setLastError(__tr2qs("Missing both encryption and decryption key: at least one is needed")); return false; } } KviCString szTmpEncryptKey = KviCString(encKey, encKeyLen); KviCString szTmpDecryptKey = KviCString(decKey, decKeyLen); m_bEncryptMode = CBC; // default mode m_bDecryptMode = CBC; // default mode if(kvi_strEqualCIN("ecb:", szTmpEncryptKey.ptr(), 4) && (szTmpEncryptKey.len() > 4)) { szTmpEncryptKey.cutLeft(4); m_bEncryptMode = ECB; } else if(kvi_strEqualCIN("old:", szTmpEncryptKey.ptr(), 4) && (szTmpEncryptKey.len() > 4)) { szTmpEncryptKey.cutLeft(4); m_bEncryptMode = OldCBC; } else if(kvi_strEqualCIN("cbc:", szTmpEncryptKey.ptr(), 4) && (szTmpEncryptKey.len() > 4)) { szTmpEncryptKey.cutLeft(4); } if(kvi_strEqualCIN("ecb:", szTmpDecryptKey.ptr(), 4) && (szTmpDecryptKey.len() > 4)) { szTmpDecryptKey.cutLeft(4); m_bDecryptMode = ECB; } else if(kvi_strEqualCIN("old:", szTmpDecryptKey.ptr(), 4) && (szTmpDecryptKey.len() > 4)) { szTmpDecryptKey.cutLeft(4); m_bDecryptMode = OldCBC; } else if(kvi_strEqualCIN("cbc:", szTmpDecryptKey.ptr(), 4) && (szTmpDecryptKey.len() > 4)) { szTmpDecryptKey.cutLeft(4); } int defLen = getKeyLen(); szTmpEncryptKey.padRight(defLen); szTmpDecryptKey.padRight(defLen); m_pEncryptCipher = new Rijndael(); int retVal = m_pEncryptCipher->init( (m_bEncryptMode == ECB) ? Rijndael::ECB : Rijndael::CBC, Rijndael::Encrypt, (unsigned char *)szTmpEncryptKey.ptr(), getKeyLenId()); if(retVal != RIJNDAEL_SUCCESS) { delete m_pEncryptCipher; m_pEncryptCipher = nullptr; setLastErrorFromRijndaelErrorCode(retVal); return false; } m_pDecryptCipher = new Rijndael(); retVal = m_pDecryptCipher->init( (m_bEncryptMode == ECB) ? Rijndael::ECB : Rijndael::CBC, Rijndael::Decrypt, (unsigned char *)szTmpDecryptKey.ptr(), getKeyLenId()); if(retVal != RIJNDAEL_SUCCESS) { delete m_pEncryptCipher; m_pEncryptCipher = nullptr; delete m_pDecryptCipher; m_pDecryptCipher = nullptr; setLastErrorFromRijndaelErrorCode(retVal); return false; } return true; }
bool KviConfigurationFile::load() { // this is really faster than the old version :) // open the file KviFile f(m_szFileName); if(!f.open(QFile::ReadOnly)) return false; KviCString tmp; KviConfigurationFileGroup * p_group = 0; int iLoadBlockSize = LOAD_BLOCK_SIZE; char * buffer = (char *)KviMemory::allocate(iLoadBlockSize * sizeof(char)); int toRead; int readedLen; int remainingLen = 0; char * p = buffer; // start writing to the beginning of the buffer do { // compute the length to read toRead = iLoadBlockSize - remainingLen; if(toRead < 1) { // ops... a string longer than iLoadBlockSize - 1 chars iLoadBlockSize += LOAD_BLOCK_SIZE; int iOffset = p - buffer; buffer = (char *)KviMemory::reallocate(buffer,iLoadBlockSize * sizeof(char)); p = buffer + iOffset; toRead += LOAD_BLOCK_SIZE; } // do read readedLen = f.read(p,toRead); if(readedLen < toRead) { // check for errors if(readedLen <= 0) { if(readedLen < 0) { // error at all f.close(); KviMemory::free(buffer); return true; // nothing more to parse anyway } else { // just a zero byte read if(remainingLen == 0) { // there was nothing in the buffer f.close(); // nothing to parse anyway KviMemory::free(buffer); return true; } // there is something in the buffer but we have readed 0 bytes // this usually means that the last line in the file has no trailing newline // ...we just fake it :) *p = '\n'; readedLen = 1; } } else { // just readed something but less than expected // check if the last readed char is a newline // if it isn't, fake it if(*(p + readedLen - 1) != '\n') { *(p + readedLen) = '\n'; readedLen++; } } } // compute the end pointer char * endp = p + readedLen; p = buffer; // start from beginning of the data buffer at all // begin of the current string char * begin = p; // and loop while(p < endp) { // find a newline if(*p != '\n') { p++; continue; } // newline! *p = 0; // now begin points to the string that terminates in p // skip leading whitespace while((*begin == '\t') || (*begin == ' '))begin++; if(p == begin) { // empty line p++; begin = p; continue; } // now p > begin // check if there are trailing spaces (include CR so CRLF is trimmed too) char * trail = p - 1; p++; while(trail >= begin) { if((*trail == '\r') || (*trail == '\t') || (*trail == ' '))*trail = 0; else break; trail--; } // yeah, have some data in this line :D switch(*begin) { case 0: // empty line break; case '#': // comment: just skip it break; case '[': // group ? begin++; if(*begin && (*begin != ']')) { char * z = begin; #define COMPAT_WITH_OLD_CONFIGS #ifdef COMPAT_WITH_OLD_CONFIGS // run to the end of the string while(*z)z++; // run back to the trailing ']' while((z > begin) && (*z != ']'))z--; // if it is not ther just run back to the end of the string if(*z != ']')while(*z)z++; #else // new configs have it always encoded properly while(*z && (*z != ']'))z++; #endif *z = 0; tmp.hexDecode(begin); tmp.stripRightWhiteSpace(); // no external spaces in group names if(!tmp.isEmpty()) { QString szGroup = m_bLocal8Bit ? QString::fromLocal8Bit(tmp.ptr(),tmp.len()) : QString::fromUtf8(tmp.ptr(),tmp.len()); p_group = m_pDict->find(szGroup); if(!p_group) { p_group = new KviConfigurationFileGroup(17,false); p_group->setAutoDelete(true); m_pDict->insert(szGroup,p_group); } } } break; default: { // real data ? char * z = begin; while(*z && (*z != '='))z++; if(*z && (z != begin)) { *z = 0; tmp.hexDecode(begin); tmp.stripRightWhiteSpace(); // No external spaces at all in keys if(!tmp.isEmpty()) { QString szKey = m_bLocal8Bit ? QString::fromLocal8Bit(tmp.ptr(),tmp.len()) : QString::fromUtf8(tmp.ptr(),tmp.len()); z++; while(*z && ((*z == ' ') || (*z == '\t')))z++; if(*z) { tmp.hexDecode(z); QString * pVal = new QString( m_bLocal8Bit ? QString::fromLocal8Bit(tmp.ptr(),tmp.len()) : QString::fromUtf8(tmp.ptr(),tmp.len()) ); if(!p_group) { // ops...we're missing a group // use the default one p_group = new KviConfigurationFileGroup(17,false); p_group->setAutoDelete(true); m_pDict->insert(KVI_CONFIG_DEFAULT_GROUP,p_group); } p_group->replace(szKey,pVal); } else { // we in fact need this (mercy :D) // otherwise the empty options will be treated as non-existing ones // and will get the defaults (which is bad) QString * pVal = new QString(QString()); p_group->replace(szKey,pVal); } } } } break; } begin = p; } if(begin != endp) { // there is data with no trailing newline in the buffer remainingLen = endp-begin; if(buffer != begin) { KviMemory::move(buffer,begin,remainingLen); p = buffer + remainingLen; } // else p remains where it is } else { p = buffer; } } while(readedLen == toRead); f.close(); KviMemory::free(buffer); return true; }
bool KviFile::save(const KviCString & szData) { if(!save((kvi_u32_t)(szData.len()))) return false; return (write(szData.ptr(), szData.len()) == (unsigned int)szData.len()); }