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
 

Reply via email to