Hi,
I discovered some crashes when using mcabber with PGP encryption. I've
created a patch that fixes these issues for me.
It is only tested on OpenBSD/i386 5.6.
An issue including the patch has also been created on bitbucket.
https://bitbucket.org/McKael/mcabber-crew/issue/134/crashes-while-using-pgp-encryption
Sven
--- mcabber/pgp.c.orig Thu May 08 18:38:40 2014 +0200
+++ mcabber/pgp.c Sun Feb 01 20:55:22 2015 +0100
@@ -209,11 +209,18 @@
gpgme_set_protocol(ctx, GPGME_PROTOCOL_OpenPGP);
- // Surround the given data with the prefix & suffix
- data = g_new(char, sizeof(prefix) + sizeof(suffix) + strlen(gpg_data));
- strcpy(data, prefix);
- strcat(data, gpg_data);
- strcat(data, suffix);
+ // Surround the given data with the prefix & suffix (prefix + suffix are
0-terminated)
+ // so there is enough space
+ const int buf_len = sizeof(prefix) + sizeof(suffix) + strlen(gpg_data) + 1;
+ data = g_new(char, buf_len);
+ const int written_data = snprintf(data, buf_len, "%s%s%s", prefix, gpg_data,
suffix);
+ if ((written_data == -1) || (written_data > buf_len)) {
+ scr_LogPrint(LPRINT_LOGNORM|LPRINT_NOTUTF8,
+ "GPGME verification failed: could not construct buffer. %d
!= %d",
+ written_data, buf_len);
+ g_free(data);
+ return NULL;
+ }
err = gpgme_data_new_from_mem(&data_sign, data, strlen(data), 0);
if (!err) {
@@ -223,19 +230,26 @@
if (!err) {
gpgme_verify_result_t vr = gpgme_op_verify_result(ctx);
if (vr && vr->signatures) {
- char *r = vr->signatures->fpr;
- // Found the fingerprint. Let's try to get the key id.
- if (!gpgme_get_key(ctx, r, &key, 0) && key) {
- r = key->subkeys->keyid;
- gpgme_key_release(key);
- }
- // r is a static variable, let's copy it.
- verified_key = g_strdup(r);
- *sigsum = vr->signatures->summary;
- // For some reason summary could be 0 when status is 0 too,
- // which means the signature is valid...
- if (!*sigsum && !vr->signatures->status)
- *sigsum = GPGME_SIGSUM_GREEN;
+ gpgme_signature_t s = NULL;
+ // check all signatures and stop if the first could be verified
+ for(s = vr->signatures;
+ (s != NULL) && (verified_key != NULL);
+ s = s->next) {
+ // Found the fingerprint. Let's try to get the key id.
+ if (NULL != s->fpr) {
+ if (!gpgme_get_key(ctx, s->fpr, &key, 0)) {
+ if (key) {
+ verified_key = g_strdup(key->subkeys->keyid);
+ gpgme_key_release(key);
+ }
+ }
+ }
+ *sigsum = s->summary;
+ // For some reason summary could be 0 when status is 0 too,
+ // which means the signature is valid...
+ if ((!*sigsum) && (!s->status))
+ *sigsum = GPGME_SIGSUM_GREEN;
+ }
}
}
gpgme_data_release(data_text);
@@ -348,11 +362,17 @@
if (!(p && strchr(p, ':')))
gpgme_set_passphrase_cb(ctx, passphrase_cb, 0);
- // Surround the given data with the prefix & suffix
- data = g_new(char, sizeof(prefix) + sizeof(suffix) + strlen(gpg_data));
- strcpy(data, prefix);
- strcat(data, gpg_data);
- strcat(data, suffix);
+ // Surround the given data with the prefix & suffix (prefix + suffix are
0-terminated)
+ // so there is enough space
+ const int buf_len = sizeof(prefix) + sizeof(suffix) + strlen(gpg_data) + 1;
+ data = g_new(char, buf_len);
+ const int written_data = snprintf(data, buf_len, "%s%s%s", prefix, gpg_data,
suffix);
+ if ((written_data == -1) || (written_data > buf_len)) {
+ scr_LogPrint(LPRINT_LOGNORM|LPRINT_NOTUTF8,
+ "GPGME verification failed: could not construct buffer.");
+ g_free(data);
+ return NULL;
+ }
err = gpgme_data_new_from_mem(&in, data, strlen(data), 0);
if (!err) {
@@ -388,8 +408,9 @@
{
gpgme_ctx_t ctx;
gpgme_data_t in, out;
- char *encrypted_data = NULL, *edata;
- size_t nread;
+ char *encrypted_data = NULL, *edata = NULL;
+ char *copy_encrypted_data = NULL;
+ size_t nread = 0;
gpgme_key_t key;
gpgme_error_t err;
@@ -415,8 +436,14 @@
err = gpgme_data_new(&out);
if (!err) {
err = gpgme_op_encrypt(ctx, keys, GPGME_ENCRYPT_ALWAYS_TRUST, in, out);
- if (!err)
+ if (!err) {
encrypted_data = gpgme_data_release_and_get_mem(out, &nread);
+ if (encrypted_data) {
+ // We need to add a trailing NULL
+ copy_encrypted_data = g_strndup(encrypted_data, nread);
+ free(encrypted_data);
+ }
+ }
else
gpgme_data_release(out);
}
@@ -431,9 +458,9 @@
scr_LogPrint(LPRINT_LOGNORM|LPRINT_NOTUTF8,
"GPGME encryption error: %s", gpgme_strerror(err));
gpgme_release(ctx);
- edata = strip_header_footer(encrypted_data);
- if (encrypted_data)
- free(encrypted_data);
+ edata = strip_header_footer(copy_encrypted_data);
+ g_free(copy_encrypted_data);
+
return edata;
}
--- mcabber/xmpp.c.orig Thu May 08 18:38:40 2014 +0200
+++ mcabber/xmpp.c Sun Feb 01 20:55:22 2015 +0100
@@ -822,6 +822,7 @@
break;
case LM_SSL_STATUS_CERT_FINGERPRINT_MISMATCH: {
char fpr[49];
+ memset(fpr, 0, sizeof(fpr));
fingerprint_to_hex((const unsigned char*)lm_ssl_get_fingerprint(ssl),
fpr);
scr_LogPrint(LPRINT_LOGNORM,
@@ -1811,6 +1812,8 @@
LmMessageHandler *handler;
GError *error = NULL;
+ memset(fpr, 0, sizeof(fpr));
+
xmpp_disconnect();
servername = settings_opt_get("server");