Greetings!
This patch makes use of the new gpgme API. However, it brings licq to crash very often and I don't know why. I suppose that it is because I removed locking. The new gpgme library is thread-safe, but you have to call a certain function for each thread. Now I want to ask whether the main licq daemon which receives/sends messages is a single thread or not?
Richard Hirner
diff -Naur licq-20040423/configure.in licq-gpg/configure.in --- licq-20040423/configure.in 2004-04-05 12:28:14.000000000 +0200 +++ licq-gpg/configure.in 2004-05-19 00:18:54.770922432 +0200 @@ -148,7 +148,14 @@ LICQ_CHECK_OPENSSL dnl Check for gpgme -AC_CHECK_LIB(gpgme,gpgme_check_version) +AC_PATH_PROG(GPGME_CONFIG, gpgme-config) +if [ test -n "$GPGME_CONFIG" ]; then + CPPFLAGS="$CPPFLAGS `$GPGME_CONFIG --thread=pthread --cflags`" + LDFLAGS="$LDFLAGS `$GPGME_CONFIG --thread=pthread --libs`" + AC_DEFINE([HAVE_LIBGPGME], [], [we are using libgpgme]) +else + AC_MSG_ERROR([Unable to find gpgme-config; install libgpgme-devel]) +fi dnl Switch to C++ mode and check for needed C++ headers AC_LANG_SAVE diff -Naur licq-20040423/include/licq_gpg.h licq-gpg/include/licq_gpg.h --- licq-20040423/include/licq_gpg.h 2004-03-21 12:12:19.000000000 +0100 +++ licq-gpg/include/licq_gpg.h 2004-05-19 00:19:04.921379328 +0200 @@ -17,27 +17,14 @@ char *Encrypt(const char *, const char *, unsigned long); void Start(); +#ifdef HAVE_LIBGPGME protected: CIniFile mKeysIni; -#ifdef HAVE_LIBGPGME - GpgmeCtx mCtx; -#endif + gpgme_ctx_t mCtx; char *mGPGPassphrase; - void gpgmeLock(); - void gpgmeUnlock(); - static const char *PassphraseCallback(void *, const char *, void **); -}; - -class CGPGMEMutex -{ -public: - ~CGPGMEMutex(); - CGPGMEMutex(); - bool Lock(); - -protected: - static pthread_mutex_t mutex; + static gpgme_error_t PassphraseCallback(void *, const char *, const char *, int, int); +#endif }; diff -Naur licq-20040423/src/gpg.cpp licq-gpg/src/gpg.cpp --- licq-20040423/src/gpg.cpp 2004-03-21 17:28:29.000000000 +0100 +++ licq-gpg/src/gpg.cpp 2004-05-19 00:19:16.224660968 +0200 @@ -40,31 +40,29 @@ #ifdef HAVE_LIBGPGME if (!mCtx) return 0; - size_t nRead = 0; - GpgmeData cipher, plain; + gpgme_data_t cipher, plain; - CGPGMEMutex mutex; - if (!mutex.Lock()) return 0; - if (gpgme_data_new(&cipher) != GPGME_No_Error) return 0; - char *buf = strdup(szCipher); - GpgmeError err; - gpgme_data_write(cipher, buf, strlen(buf)); - free(buf); - - if (gpgme_data_new(&plain) != GPGME_No_Error) + if (gpgme_data_new_from_mem(&cipher, szCipher, strlen(szCipher), 0) != GPG_ERR_NO_ERROR) return 0; + if (gpgme_data_new(&plain) != GPG_ERR_NO_ERROR) { gpgme_data_release(cipher); return 0; } - if ((err = gpgme_op_decrypt(mCtx, cipher, plain)) != GPGME_No_Error) - gLog.Warn("%sgpgme message decryption failed: %s\n", L_WARNxSTR, gpgme_strerror(err)); + char *buf = 0; + gpgme_error_t err; + if ((err = gpgme_op_decrypt(mCtx, cipher, plain)) == GPG_ERR_NO_ERROR) + { + size_t nRead = 0; + buf = gpgme_data_release_and_get_mem(plain, &nRead); + if (!buf) return 0; + buf = (char *)realloc(buf, nRead+1); + buf[nRead] = 0; + } + else + gLog.Warn("%sgpgme message decryption failed\n", L_WARNxSTR); gpgme_data_release(cipher); - buf = gpgme_data_release_and_get_mem(plain, &nRead); - if (!buf) return 0; - buf = (char *)realloc(buf, nRead+1); - buf[nRead] = 0; return buf; #else return 0; @@ -79,47 +77,43 @@ if (!mCtx) return 0; if (!szPlain) return 0; - char szUser[MAX_LINE_LEN], buf[MAX_LINE_LEN]; + char szUser[MAX_LINE_LEN], szKeyId[MAX_LINE_LEN]; sprintf(szUser, "%s.%lu", szId, nPPID); mKeysIni.SetSection("keys"); - if (!mKeysIni.ReadStr(szUser, buf)) return 0; + if (!mKeysIni.ReadStr(szUser, szKeyId)) return 0; gLog.Info("[GPG] Encrypting message to %s.\n", szId); - CGPGMEMutex mutex; - if (!mutex.Lock()) return 0; - GpgmeRecipients rcps; - GpgmeData plain = 0, cipher = 0; - GpgmeError err; + gpgme_key_t rcpt[2]; + gpgme_data_t plain = 0, cipher = 0; + gpgme_error_t err; char *szCipher = 0; + size_t nRead; + + memset(rcpt, 0, sizeof(gpgme_key_t)*2); - if (gpgme_recipients_new(&rcps) != GPGME_No_Error) return 0; - if (gpgme_recipients_add_name_with_validity(rcps, buf, GPGME_VALIDITY_FULL) != GPGME_No_Error) - gLog.Error("%sCouldn't use gpgme recipient: %s\n", L_ERRORxSTR, buf); + if ((err = gpgme_get_key(mCtx, szKeyId, rcpt, 0)) != GPG_ERR_NO_ERROR) + gLog.Error("%s[GPG] Couldn't get key \"%s\"\n", L_ERRORxSTR, szKeyId); else { - if (gpgme_data_new_from_mem(&plain, szPlain, strlen(szPlain), 1) == GPGME_No_Error && - gpgme_data_new(&cipher) == GPGME_No_Error) + if (gpgme_data_new_from_mem(&plain, szPlain, strlen(szPlain), 0) == GPG_ERR_NO_ERROR && + gpgme_data_new(&cipher) == GPG_ERR_NO_ERROR) { - if ((err = gpgme_op_encrypt(mCtx, rcps, plain, cipher)) == GPGME_No_Error) - { - size_t nRead; - if (gpgme_data_read(cipher, 0, 0, &nRead) == GPGME_No_Error) - { - szCipher = (char *)malloc(nRead+1); - memset(szCipher, 0, nRead+1); - gpgme_data_read(cipher, szCipher, nRead, &nRead); - } + if ((err = gpgme_op_encrypt(mCtx, rcpt, GPGME_ENCRYPT_ALWAYS_TRUST, plain, cipher)) == GPG_ERR_NO_ERROR) + { + szCipher = gpgme_data_release_and_get_mem(cipher, &nRead); + cipher = 0; + // blob -> char * (append terminating \0) + szCipher = (char *)realloc(szCipher, nRead + 1); + szCipher[nRead] = 0; } else - gLog.Error("%sEncryption failed: %s\n", L_ERRORxSTR, gpgme_strerror(err)); + gLog.Error("%s[GPG] Encryption failed\n", L_ERRORxSTR); } - if (cipher) gpgme_data_release(cipher); if (plain) gpgme_data_release(plain); + gpgme_key_unref(rcpt[0]); } - - gpgme_recipients_release(rcps); return szCipher; #else return 0; @@ -138,10 +132,10 @@ mKeysIni.ReadStr("passphrase", buf); mGPGPassphrase = strdup(buf); const char *gpgme_ver = gpgme_check_version(0); - gLog.Info("%sgpgme library found: %s\n", L_INITxSTR, gpgme_ver); + gLog.Info("%s[GPG] gpgme library found: %s\n", L_INITxSTR, gpgme_ver); - if (gpgme_engine_check_version(GPGME_PROTOCOL_OpenPGP) != GPGME_No_Error) - gLog.Error("%sgpgme engine OpenPGP not found!\n", L_ERRORxSTR); + if (gpgme_engine_check_version(GPGME_PROTOCOL_OpenPGP) != GPG_ERR_NO_ERROR) + gLog.Error("%s[GPG] gpgme engine OpenPGP not found!\n", L_ERRORxSTR); gpgme_new(&mCtx); gpgme_set_protocol(mCtx, GPGME_PROTOCOL_OpenPGP); @@ -150,30 +144,12 @@ #endif } - -const char *CGPGHelper::PassphraseCallback(void *, const char *, void **) -{ - return gGPGHelper.mGPGPassphrase; -} - - - -/*** GPGME lock for thread safety ***/ - -pthread_mutex_t CGPGMEMutex::mutex; - -CGPGMEMutex::~CGPGMEMutex() -{ - pthread_mutex_unlock(&mutex); -} - -CGPGMEMutex::CGPGMEMutex() -{ - pthread_mutex_init(&mutex, 0); -} - -bool CGPGMEMutex::Lock() +#ifdef HAVE_LIBGPGME +gpgme_error_t CGPGHelper::PassphraseCallback(void *, const char *, const char *, int, int fd) { - return pthread_mutex_lock(&mutex) == 0; + write(fd, gGPGHelper.mGPGPassphrase, strlen(gGPGHelper.mGPGPassphrase)); + write(fd, "\n", 1); + return 0; } +#endif