static void geanypg_encrypt(encrypt_data * ed, gpgme_key_t * recp, int sign, int flags) { /* FACTORIZE */ gpgme_data_t plain, cipher; gpgme_error_t err; FILE * tempfile; tempfile = tmpfile(); if (!(tempfile)) { g_warning("%s: %s.", _("couldn't create tempfile"), strerror(errno)); return ; } gpgme_data_new_from_stream(&cipher, tempfile); gpgme_data_set_encoding(cipher, GPGME_DATA_ENCODING_ARMOR); geanypg_load_buffer(&plain); /* do the actual encryption */ if (sign) err = gpgme_op_encrypt_sign(ed->ctx, recp, flags, plain, cipher); else err = gpgme_op_encrypt(ed->ctx, recp, flags, plain, cipher); if (err != GPG_ERR_NO_ERROR && gpgme_err_code(err) != GPG_ERR_CANCELED) geanypg_show_err_msg(err); else if(gpgme_err_code(err) != GPG_ERR_CANCELED) { rewind(tempfile); geanypg_write_file(tempfile); } fclose(tempfile); /* release buffers */ gpgme_data_release(plain); gpgme_data_release(cipher); }
static void check_result (gpgme_verify_result_t result, int summary, char *fpr, gpgme_error_t status, gpgme_validity_t validity) { gpgme_signature_t sig; sig = result->signatures; if (!sig || sig->next) { fprintf (stderr, "%s:%i: Unexpected number of signatures\n", __FILE__, __LINE__); got_errors = 1; } if (sig->summary != summary) { fprintf (stderr, "%s:%i: Unexpected signature summary: " "want=0x%x have=0x%x\n", __FILE__, __LINE__, summary, sig->summary); got_errors = 1; } if (strcmp (sig->fpr, fpr)) { fprintf (stderr, "%s:%i: Unexpected fingerprint: %s\n", __FILE__, __LINE__, sig->fpr); got_errors = 1; } if (gpgme_err_code (sig->status) != status) { fprintf (stderr, "%s:%i: Unexpected signature status: %s\n", __FILE__, __LINE__, gpgme_strerror (sig->status)); got_errors = 1; } if (sig->notations) { fprintf (stderr, "%s:%i: Unexpected notation data\n", __FILE__, __LINE__); got_errors = 1; } if (sig->wrong_key_usage) { fprintf (stderr, "%s:%i: Unexpectedly wrong key usage\n", __FILE__, __LINE__); got_errors = 1; } if (sig->validity != validity) { fprintf (stderr, "%s:%i: Unexpected validity: %i\n", __FILE__, __LINE__, sig->validity); got_errors = 1; } if (gpgme_err_code (sig->validity_reason) != GPG_ERR_NO_ERROR) { fprintf (stderr, "%s:%i: Unexpected validity reason: %s\n", __FILE__, __LINE__, gpgme_strerror (sig->validity_reason)); got_errors = 1; } }
void crypto_asym::build_context() { #if GPGME_SUPPORT gpgme_error_t err = gpgme_new(&context); if(gpgme_err_code(err) != GPG_ERR_NO_ERROR) throw Erange("crypto_asym::crypto_asym", string(gettext("Failed creating GPGME context: ")) + tools_gpgme_strerror_r(err)); err = gpgme_set_protocol(context, GPGME_PROTOCOL_OpenPGP); if(gpgme_err_code(err) != GPG_ERR_NO_ERROR) throw Erange("crypto_asym::crypto_asym", string(gettext("Failed setting GPGME context with OpenPGP protocol: ")) + tools_gpgme_strerror_r(err)); gpgme_set_passphrase_cb(context, read_passphrase, (void *)this); #endif }
/** * seahorse_util_handle_gpgme: * @err: Error value * * Shows an error dialog for @err. **/ void seahorse_util_handle_gpgme (gpgme_error_t err, const char* desc, ...) { gchar *t = NULL; switch (gpgme_err_code(err)) { case GPG_ERR_CANCELED: case GPG_ERR_NO_ERROR: case GPG_ERR_ECANCELED: return; default: break; } va_list ap; va_start(ap, desc); if (desc) t = g_strdup_vprintf (desc, ap); va_end(ap); seahorse_util_show_error (NULL, t, gpgme_strerror (err)); g_free(t); }
QString CryptPlugWrapper::errorIdToText(int errId, bool &isPassphraseError) { const GpgME::Error err(errId); isPassphraseError = err.isCanceled() || gpgme_err_code(errId) == GPG_ERR_NO_SECKEY ; // FIXME: more? return QString::fromLocal8Bit(err.asString()); }
static PyObject * pygpgme_keyiter_next(PyGpgmeKeyIter *self) { gpgme_key_t key = NULL; gpgme_error_t err; PyObject *ret; Py_BEGIN_ALLOW_THREADS; err = gpgme_op_keylist_next(self->ctx->ctx, &key); Py_END_ALLOW_THREADS; /* end iteration */ if (gpgme_err_source(err) == GPG_ERR_SOURCE_GPGME && gpgme_err_code(err) == GPG_ERR_EOF) { PyErr_SetNone(PyExc_StopIteration); return NULL; } if (pygpgme_check_error(err)) return NULL; if (key == NULL) Py_RETURN_NONE; ret = pygpgme_key_new(key); gpgme_key_unref(key); return ret; }
void crypto_asym::decrypt(generic_file & ciphered, generic_file & clear) { #if GPGME_SUPPORT generic_file_overlay_for_gpgme o_clear = &clear; generic_file_overlay_for_gpgme o_ciphered = &ciphered; gpgme_error_t err = gpgme_op_decrypt_verify(context, o_ciphered.get_gpgme_handle(), o_clear.get_gpgme_handle()); signing_result.clear(); switch(gpgme_err_code(err)) { case GPG_ERR_NO_ERROR: fill_signing_result(); break; case GPG_ERR_INV_VALUE: throw SRC_BUG; case GPG_ERR_NO_DATA: throw Erange("crypto_asym::decrypt", gettext("No data to decrypt")); case GPG_ERR_DECRYPT_FAILED: throw Erange("crypto_asym::decrypt", gettext("Invalid Cipher text")); case GPG_ERR_BAD_PASSPHRASE: throw Erange("crypto_asym::decrypt", gettext("Failed retreiving passphrase")); default: throw Erange("crypto_asym::decrypt", string(gettext("Unexpected error reported by GPGME: ")) + tools_gpgme_strerror_r(err)); } #else throw Efeature("Asymetric Strong encryption algorithms using GPGME"); #endif }
/** * zif_utils_gpg_check_signature: **/ static gboolean zif_utils_gpg_check_signature (gpgme_signature_t signature, GError **error) { gboolean ret = FALSE; /* look at the signature status */ switch (gpgme_err_code (signature->status)) { case GPG_ERR_NO_ERROR: ret = TRUE; break; case GPG_ERR_SIG_EXPIRED: case GPG_ERR_KEY_EXPIRED: g_set_error (error, ZIF_UTILS_ERROR, ZIF_UTILS_ERROR_FAILED, "valid signature '%s' has expired", signature->fpr); break; case GPG_ERR_CERT_REVOKED: g_set_error (error, ZIF_UTILS_ERROR, ZIF_UTILS_ERROR_FAILED, "valid signature '%s' has been revoked", signature->fpr); break; case GPG_ERR_BAD_SIGNATURE: g_set_error (error, ZIF_UTILS_ERROR, ZIF_UTILS_ERROR_FAILED, "'%s' is not a valid signature", signature->fpr); break; case GPG_ERR_NO_PUBKEY: g_set_error (error, ZIF_UTILS_ERROR, ZIF_UTILS_ERROR_FAILED, "Could not check signature '%s' as no public key", signature->fpr); break; default: g_set_error (error, ZIF_UTILS_ERROR, ZIF_UTILS_ERROR_FAILED, "gpgme failed to verify signature '%s'", signature->fpr); break; } return ret; }
static const gchar *get_owner_trust_str(unsigned long owner_trust) { switch (gpgme_err_code(owner_trust)) { case GPGME_VALIDITY_NEVER: return _("Untrusted"); case GPGME_VALIDITY_MARGINAL: return _("Marginal"); case GPGME_VALIDITY_FULL: return _("Full"); case GPGME_VALIDITY_ULTIMATE: return _("Ultimate"); default: return _("Unknown"); } }
void crypto_asym::set_signatories(const std::vector<std::string> & signatories) { #if GPGME_SUPPORT gpgme_key_t *signatories_key = NULL; if(signatories.empty()) { gpgme_signers_clear(context); has_signatories = false; } else { build_key_list(signatories, signatories_key, true); try { gpgme_signers_clear(context); gpgme_key_t *ptr = signatories_key; gpgme_error_t err; if(ptr == NULL) throw SRC_BUG; // build_key_list failed while(*ptr != NULL) { err = gpgme_signers_add(context, *ptr); switch(gpgme_err_code(err)) { case GPG_ERR_NO_ERROR: break; default: throw Erange("crypto_asym::encrypt", string(gettext("Unexpected error reported by GPGME: ")) + tools_gpgme_strerror_r(err)); } ++ptr; } } catch(...) { release_key_list(signatories_key); gpgme_signers_clear(context); has_signatories = false; throw; } release_key_list(signatories_key); has_signatories = true; } #else throw Efeature("Asymetric Strong encryption algorithms using GPGME"); #endif }
static gboolean signing_key_is_revoked (gpgme_signature_t signature) { /* In my testing, GPGME does not set the GPGME_SIGSUM_KEY_REVOKED summary * bit on a revoked signing key but rather GPGME_SIGSUM_SYS_ERROR and the * status field shows GPG_ERR_CERT_REVOKED. Turns out GPGME is expecting * GPG_ERR_CERT_REVOKED in the validity_reason field which would then set * the summary bit. * * Reported to GPGME: https://bugs.g10code.com/gnupg/issue1929 */ return (signature->summary & GPGME_SIGSUM_KEY_REVOKED) || ((signature->summary & GPGME_SIGSUM_SYS_ERROR) && gpgme_err_code (signature->status) == GPG_ERR_CERT_REVOKED); }
void crypto_asym::encrypt(const vector<string> & recipients_email, generic_file & clear, generic_file & ciphered) { #if GPGME_SUPPORT gpgme_key_t *ciphering_keys = NULL; build_key_list(recipients_email, ciphering_keys, false); try { generic_file_overlay_for_gpgme o_clear = &clear; generic_file_overlay_for_gpgme o_ciphered = &ciphered; gpgme_error_t err; if(!has_signatories) err = gpgme_op_encrypt(context, ciphering_keys, (gpgme_encrypt_flags_t)(GPGME_ENCRYPT_NO_ENCRYPT_TO|GPGME_ENCRYPT_ALWAYS_TRUST), o_clear.get_gpgme_handle(), o_ciphered.get_gpgme_handle()); else err = gpgme_op_encrypt_sign(context, ciphering_keys, (gpgme_encrypt_flags_t)(GPGME_ENCRYPT_NO_ENCRYPT_TO|GPGME_ENCRYPT_ALWAYS_TRUST), o_clear.get_gpgme_handle(), o_ciphered.get_gpgme_handle()); switch(gpgme_err_code(err)) { case GPG_ERR_NO_ERROR: break; case GPG_ERR_INV_VALUE: throw SRC_BUG; case GPG_ERR_UNUSABLE_PUBKEY: throw Erange("crypto_asym::encrypt", gettext("Key found but users are not all trusted")); default: throw Erange("crypto_asym::encrypt", string(gettext("Unexpected error reported by GPGME: ")) + tools_gpgme_strerror_r(err)); } } catch(...) { release_key_list(ciphering_keys); throw; } release_key_list(ciphering_keys); #else throw Efeature("Asymetric Strong encryption algorithms using GPGME"); #endif }
/** * seahorse_util_gpgme_to_error * @gerr GPGME error * @err Resulting GError object **/ void seahorse_util_gpgme_to_error (gpgme_error_t gerr, GError** err) { gpgme_err_code_t code; /* Make sure this is actually an error */ g_assert (gerr != 0); code = gpgme_err_code (gerr); /* Special case some error messages */ if (code == GPG_ERR_DECRYPT_FAILED) { g_set_error (err, SEAHORSE_GPGME_ERROR, code, "%s", _("Decryption failed. You probably do not have the decryption key.")); } else { g_set_error (err, SEAHORSE_GPGME_ERROR, code, "%s", gpgme_strerror (gerr)); } }
static void show_auditlog (gpgme_ctx_t ctx) { gpgme_error_t err; gpgme_data_t data; err = gpgme_data_new (&data); fail_if_err (err); err = gpgme_op_getauditlog (ctx, data, 0); if (err) { fprintf (stderr, "%s:%i: Can't get audit log: %s\n", __FILE__, __LINE__, gpgme_strerror (err)); if (gpgme_err_code (err) != GPG_ERR_ASS_UNKNOWN_CMD) got_errors = 1; } print_data (data); gpgme_data_release (data); }
/* Not that this closure is called in the context of the waiter_thread. */ static void decrypt_closure (closure_data_t cld, gpgme_ctx_t ctx, gpg_error_t err) { update_passphrase_cache (err, &cld->pw_cb); if (!err && !cld->with_verify) ; else if (!err) { gpgme_verify_result_t res; /* Decryption succeeded. Now check the state of the signatures. */ res = gpgme_op_verify_result (ctx); if (res && res->signatures) verify_dialog_box (gpgme_get_protocol (ctx), res, NULL); } else if (gpg_err_code (err) == GPG_ERR_DECRYPT_FAILED) { /* The decryption failed. See whether we can figure out a more suitable error code. */ gpgme_decrypt_result_t res; res = gpgme_op_decrypt_result (ctx); if (res && res->recipients && gpgme_err_code (res->recipients->status) == GPG_ERR_NO_SECKEY) err = gpg_error (GPG_ERR_NO_SECKEY); /* Fixme: return the keyids */ } else { /* Decryption failed for other reasons. */ } /* If the passphrase callback indicated a cancel operation, change the the error code accordingly. */ if (err && (cld->pw_cb.opts & OPT_FLAG_CANCEL)) err = gpg_error (GPG_ERR_CANCELED); engine_private_finished (cld->filter, err); }
gpgme_data_t seahorse_gpgme_data_new () { gpgme_error_t gerr; gpgme_data_t data; gerr = gpgme_data_new (&data); if (!GPG_IS_OK (gerr)) { if (gpgme_err_code_to_errno (gerr) == ENOMEM || gpgme_err_code (gerr) == GPG_ERR_ENOMEM) { g_error ("%s: failed to allocate gpgme_data_t", G_STRLOC); } else { /* The only reason this should fail is above */ g_assert_not_reached (); /* Just in case */ abort (); } } return data; }
gpgme_data_t seahorse_gpgme_data_new_from_mem (const char *buffer, size_t size, gboolean copy) { gpgme_data_t data; gpgme_error_t gerr; gerr = gpgme_data_new_from_mem (&data, buffer, size, copy ? 1 : 0); if (!GPG_IS_OK (gerr)) { if (gpgme_err_code_to_errno (gerr) == ENOMEM || gpgme_err_code (gerr) == GPG_ERR_ENOMEM) { g_error ("%s: failed to allocate gpgme_data_t", G_STRLOC); } else { /* The only reason this should fail is above */ g_assert_not_reached (); /* Just in case */ abort (); } } return data; }
int main (int argc, char **argv) { gpgme_error_t err; gpgme_ctx_t ctx; gpgme_key_t key; gpgme_keylist_result_t result; int i = 0; init_gpgme (GPGME_PROTOCOL_CMS); err = gpgme_new (&ctx); fail_if_err (err); gpgme_set_protocol (ctx, GPGME_PROTOCOL_CMS); err = gpgme_op_keylist_start (ctx, NULL, 0); fail_if_err (err); while (!(err = gpgme_op_keylist_next (ctx, &key))) { if (!keys[i].fpr) { fprintf (stderr, "More keys returned than expected\n"); exit (1); } if (strcmp (key->subkeys->fpr, keys[i].fpr)) { fprintf (stderr, "Warning: Skipping unknown key %s\n", key->subkeys->fpr); gpgme_key_unref (key); continue; } else printf ("Checking key %s\n", key->subkeys->fpr); /* Global key flags. */ if (key->revoked) { fprintf (stderr, "Key unexpectedly revoked\n"); exit (1); } if (key->expired) { fprintf (stderr, "Key unexpectedly expired\n"); exit (1); } if (key->disabled) { fprintf (stderr, "Key unexpectedly disabled\n"); exit (1); } if (key->invalid) { fprintf (stderr, "Key unexpectedly invalid\n"); exit (1); } if (key->can_encrypt != keys[i].secret) { fprintf (stderr, "Key unexpectedly%s usable for encryption\n", key->can_encrypt ? "" : " not"); exit (1); } if (key->can_sign != keys[i].secret) { fprintf (stderr, "Key unexpectedly%s usable for signing\n", key->can_sign ? "" : " not"); exit (1); } if (!key->can_certify) { fprintf (stderr, "Key unexpectedly unusable for certifications\n"); exit (1); } if (key->secret != keys[i].secret) { fprintf (stderr, "Key unexpectedly%s secret\n", key->secret ? "" : " not"); exit (1); } if (key->protocol != GPGME_PROTOCOL_CMS) { fprintf (stderr, "Key has unexpected protocol: %s\n", gpgme_get_protocol_name (key->protocol)); exit (1); } if (!key->issuer_serial) { fprintf (stderr, "Key unexpectedly misses issuer serial\n"); exit (1); } if (strcmp (key->issuer_serial, keys[i].issuer_serial)) { fprintf (stderr, "Key has unexpected issuer serial: %s\n", key->issuer_serial); exit (1); } if (!key->issuer_name) { fprintf (stderr, "Key unexpectedly misses issuer name\n"); exit (1); } if (strcmp (key->issuer_name, keys[i].issuer_name)) { fprintf (stderr, "Key has unexpected issuer name: %s\n", key->issuer_name); exit (1); } if (key->chain_id && !keys[i].chain_id) { fprintf (stderr, "Key unexpectedly carries chain ID: %s\n", key->chain_id); exit (1); } if (!key->chain_id && keys[i].chain_id) { fprintf (stderr, "Key unexpectedly carries no chain ID\n"); exit (1); } if (key->chain_id && strcmp (key->chain_id, keys[i].chain_id)) { fprintf (stderr, "Key carries unexpected chain ID: %s\n", key->chain_id); exit (1); } if (key->owner_trust != GPGME_VALIDITY_UNKNOWN) { fprintf (stderr, "Key has unexpected owner trust: %i\n", key->owner_trust); exit (1); } if (!key->subkeys || key->subkeys->next) { fprintf (stderr, "Key has unexpected number of subkeys\n"); exit (1); } /* Primary key. */ if (key->subkeys->revoked) { fprintf (stderr, "Primary key unexpectedly revoked\n"); exit (1); } if (key->subkeys->expired) { fprintf (stderr, "Primary key unexpectedly expired\n"); exit (1); } if (key->subkeys->disabled) { fprintf (stderr, "Primary key unexpectedly disabled\n"); exit (1); } if (key->subkeys->invalid) { fprintf (stderr, "Primary key unexpectedly invalid\n"); exit (1); } if (key->subkeys->can_encrypt != keys[i].secret) { fprintf (stderr, "Key unexpectedly%s usable for encryption\n", key->subkeys->can_encrypt ? "" : " not"); exit (1); } if (key->subkeys->can_sign != keys[i].secret) { fprintf (stderr, "Key unexpectedly%s usable for signing\n", key->subkeys->can_sign ? "" : " not"); exit (1); } if (!key->subkeys->can_certify) { fprintf (stderr, "Primary key unexpectedly unusable for certifications\n"); exit (1); } if (key->subkeys->secret != keys[i].secret) { fprintf (stderr, "Primary Key unexpectedly%s secret\n", key->secret ? "" : " not"); exit (1); } if (key->subkeys->pubkey_algo != GPGME_PK_RSA) { fprintf (stderr, "Primary key has unexpected public key algo: %s\n", gpgme_pubkey_algo_name (key->subkeys->pubkey_algo)); exit (1); } if (key->subkeys->length != keys[i].key_length) { fprintf (stderr, "Primary key has unexpected length: %i\n", key->subkeys->length); exit (1); } if (strcmp (key->subkeys->keyid, &keys[i].fpr[40 - 16])) { fprintf (stderr, "Primary key has unexpected key ID: %s\n", key->subkeys->keyid); exit (1); } if (strcmp (key->subkeys->fpr, keys[i].fpr)) { fprintf (stderr, "Primary key has unexpected fingerprint: %s\n", key->subkeys->fpr); exit (1); } if (key->subkeys->timestamp != keys[i].timestamp) { fprintf (stderr, "Primary key unexpected timestamp: %lu\n", key->subkeys->timestamp); exit (1); } if (key->subkeys->expires != keys[i].expires) { fprintf (stderr, "Primary key unexpectedly expires: %lu\n", key->subkeys->expires); exit (1); } /* Be tolerant against a missing email (ie, older gpgsm versions). */ if (!key->uids || (key->uids->next && !keys[i].email)) { fprintf (stderr, "Key has unexpected number of user IDs\n"); exit (1); } if (key->uids->revoked) { fprintf (stderr, "User ID unexpectedly revoked\n"); exit (1); } if (key->uids->invalid) { fprintf (stderr, "User ID unexpectedly invalid\n"); exit (1); } if (key->uids->validity != keys[i].validity) { fprintf (stderr, "User ID unexpectedly validity: %i\n", key->uids->validity); exit (1); } if (key->uids->signatures) { fprintf (stderr, "User ID unexpectedly signed\n"); exit (1); } if (!key->uids->name || key->uids->name[0]) { fprintf (stderr, "Unexpected name in user ID: %s\n", key->uids->name); exit (1); } if (!key->uids->comment || key->uids->comment[0]) { fprintf (stderr, "Unexpected comment in user ID: %s\n", key->uids->comment); exit (1); } if (!key->uids->email || key->uids->email[0]) { fprintf (stderr, "Unexpected email in user ID: %s\n", key->uids->email); exit (1); } if (!key->uids->uid || strcmp (key->uids->uid, keys[i].uid)) { fprintf (stderr, "Unexpected uid in user ID: %s\n", key->uids->uid); exit (1); } if (key->uids->next && strcmp (key->uids->next->uid, keys[i].email)) { fprintf (stderr, "Unexpected email in user ID: %s\n", key->uids->next->uid); exit (1); } if (key->uids->next && strcmp (key->uids->next->uid, keys[i].email)) { fprintf (stderr, "Unexpected email in user ID: %s\n", key->uids->next->uid); exit (1); } gpgme_key_unref (key); i++; } if (gpgme_err_code (err) != GPG_ERR_EOF) fail_if_err (err); err = gpgme_op_keylist_end (ctx); fail_if_err (err); result = gpgme_op_keylist_result (ctx); if (result->truncated) { fprintf (stderr, "Key listing unexpectedly truncated\n"); exit (1); } if (keys[i].fpr) { fprintf (stderr, "Less keys returned than expected\n"); exit (1); } gpgme_release (ctx); return 0; }
/* The main GPG encryption routine for libfko. */ int gpgme_encrypt(fko_ctx_t fko_ctx, unsigned char *indata, size_t in_len, const char *pw, unsigned char **out, size_t *out_len) { char *tmp_buf; int res; gpgme_ctx_t gpg_ctx = NULL; gpgme_data_t cipher = NULL; gpgme_data_t plaintext = NULL; gpgme_key_t key[2] = { NULL, NULL }; gpgme_error_t err; /* Initialize gpgme */ res = init_gpgme(fko_ctx); if(res != FKO_SUCCESS) return(res); gpg_ctx = fko_ctx->gpg_ctx; /* Initialize the plaintext data (place into gpgme_data object) */ err = gpgme_data_new_from_mem(&plaintext, (char*)indata, in_len, 1); if(gpg_err_code(err) != GPG_ERR_NO_ERROR) { gpgme_release(gpg_ctx); fko_ctx->gpg_ctx = NULL; fko_ctx->gpg_err = err; return(FKO_ERROR_GPGME_PLAINTEXT_DATA_OBJ); } /* Set protocol */ err = gpgme_set_protocol(gpg_ctx, GPGME_PROTOCOL_OpenPGP); if(gpg_err_code(err) != GPG_ERR_NO_ERROR) { gpgme_data_release(plaintext); gpgme_release(gpg_ctx); fko_ctx->gpg_ctx = NULL; fko_ctx->gpg_err = err; return(FKO_ERROR_GPGME_SET_PROTOCOL); } /* Set ascii-armor off (we will be base64-encoding the encrypted data * ourselves. */ gpgme_set_armor(gpg_ctx, 0); /* The gpgme_encrypt.... functions take a recipient key array, so we add * our single key here. */ key[0] = fko_ctx->recipient_key; /* Create the buffer for our encrypted data. */ err = gpgme_data_new(&cipher); if(gpg_err_code(err) != GPG_ERR_NO_ERROR) { gpgme_data_release(plaintext); gpgme_release(gpg_ctx); fko_ctx->gpg_ctx = NULL; fko_ctx->gpg_err = err; return(FKO_ERROR_GPGME_CIPHER_DATA_OBJ); } /* Here we add the signer to the gpgme context if there is one. */ if(fko_ctx->gpg_signer != NULL) { gpgme_signers_clear(gpg_ctx); err = gpgme_signers_add(gpg_ctx, fko_ctx->signer_key); if(gpg_err_code(err) != GPG_ERR_NO_ERROR) { gpgme_data_release(plaintext); gpgme_data_release(cipher); gpgme_release(gpg_ctx); fko_ctx->gpg_ctx = NULL; fko_ctx->gpg_err = err; return(FKO_ERROR_GPGME_ADD_SIGNER); } } /* Set the passphrase callback. */ gpgme_set_passphrase_cb(gpg_ctx, my_passphrase_cb, (void*)pw); /* Encrypt and sign (if a sig was provided) the SPA data. */ if(fko_ctx->gpg_signer == NULL) err = gpgme_op_encrypt( gpg_ctx, key, GPGME_ENCRYPT_ALWAYS_TRUST, plaintext, cipher ); else err = gpgme_op_encrypt_sign( gpg_ctx, key, GPGME_ENCRYPT_ALWAYS_TRUST, plaintext, cipher ); if(gpg_err_code(err) != GPG_ERR_NO_ERROR) { gpgme_data_release(plaintext); gpgme_data_release(cipher); gpgme_release(gpg_ctx); fko_ctx->gpg_ctx = NULL; fko_ctx->gpg_err = err; if(gpgme_err_code(err) == GPG_ERR_CANCELED) return(FKO_ERROR_GPGME_BAD_PASSPHRASE); return(FKO_ERROR_GPGME_ENCRYPT_SIGN); } /* Done with the plaintext. */ gpgme_data_release(plaintext); /* Get the encrypted data and its length from the gpgme data object. * BTW, this does free the memory used by cipher. */ tmp_buf = gpgme_data_release_and_get_mem(cipher, out_len); *out = malloc(*out_len); /* This is freed upon fko_ctx destruction. */ if(*out == NULL) res = FKO_ERROR_MEMORY_ALLOCATION; else { memcpy(*out, tmp_buf, *out_len); res = FKO_SUCCESS; } gpgme_free(tmp_buf); return(res); }
QString QalfCrypto::sign(QString &message, QString &key) { gpgme_key_t gpgkey ; gpgme_data_t signature ; gpgme_data_t msg ; gpgme_verify_result_t verification ; gpgme_signature_t signatures ; gpgme_error_t result ; char * buffer ; gpgme_set_passphrase_cb(context,&passphrase_callback,NULL) ; result = gpgme_set_protocol(context,GPGME_PROTOCOL_OpenPGP) ; Q_ASSERT(gpgme_err_code(result) == GPG_ERR_NO_ERROR) ; gpgme_set_armor(context,1) ; gpgme_set_textmode(context,1) ; gpgme_signers_clear(context) ; result = gpgme_set_keylist_mode(context,GPGME_KEYLIST_MODE_LOCAL) ; // retrieving key result = gpgme_get_key(context, key.toAscii().data(),&gpgkey,1) ; Q_ASSERT(result == GPG_ERR_NO_ERROR) ; Q_ASSERT(gpgkey != 0) ; // signing result = gpgme_signers_add(context,gpgkey) ; Q_ASSERT(result == GPG_ERR_NO_ERROR) ; result = gpgme_data_new(&signature); Q_ASSERT(result == GPG_ERR_NO_ERROR) ; int message_length = message.toAscii().size() ; char * message_char = (char *) calloc(message_length+1,sizeof(char)) ; memcpy(message_char,message.toAscii().data(),message_length) ; // printf("memcmp : %d\n",memcmp(message_char,"1fc36e1d41a93c1d79f6872198f426129320d287",message_length+1)) ; result = gpgme_data_new_from_mem(&msg,message_char,message_length,0) ; gpgme_data_seek(signature,0,SEEK_SET) ; gpgme_data_seek(msg,0,SEEK_SET) ; result = gpgme_op_sign(context, msg,signature, GPGME_SIG_MODE_DETACH) ; Q_ASSERT(gpgme_err_code(result) == GPG_ERR_NO_ERROR || gpgme_err_code(result) == GPG_ERR_BAD_PASSPHRASE || gpgme_err_code(result) == GPG_ERR_CANCELED) ; // gpgme_data_seek(signature,0,SEEK_SET) ; // gpgme_data_seek(msg,0,SEEK_SET) ; // // result = gpgme_op_verify (context, signature, msg , 0) ; // Q_ASSERT(gpgme_err_code(result) != GPG_ERR_INV_VALUE) ; // Q_ASSERT(gpgme_err_code(result) != GPG_ERR_NO_DATA) ; // Q_ASSERT(result == GPG_ERR_NO_ERROR) ; // // verification = gpgme_op_verify_result(context) ; // Q_ASSERT(verification != 0) ; // // signatures = verification->signatures ; // Q_ASSERT(verification->signatures != 0) ; // result = signatures->status ; // printf("status : %d\n",gpgme_err_code(result)) ; // printf("signature summary : %d\n",signatures->summary) ; // Q_ASSERT(signatures->summary == GPGME_SIGSUM_VALID | GPGME_SIGSUM_GREEN) ; // QString signatureStr ; buffer = (char *) calloc(2048,sizeof(char)) ; gpgme_data_seek(signature,0,SEEK_SET) ; gpgme_data_read(signature,buffer,2048) ; signatureStr += buffer ; qDebug() << "signature" << signatureStr ; gpgme_data_release(signature) ; gpgme_key_unref(gpgkey) ; gpgme_data_release(msg) ; return signatureStr ; }
/** * data: optional, will be added to the title, can be NULL * status: the gpgme status * * Basing on the status a notification is created an displayed * */ static void notify_signatures (const gchar* data, gpgme_verify_result_t status) { const gchar *icon = NULL; SeahorseObject *object; gchar *title, *body, *unesc_data; gboolean sig = FALSE; GSList *rawids; GList *keys; /* Discover the key in question */ rawids = g_slist_append (NULL, status->signatures->fpr); keys = seahorse_context_discover_objects (SCTX_APP (), SEAHORSE_PGP, rawids); g_slist_free (rawids); g_return_if_fail (keys != NULL); object = SEAHORSE_OBJECT (keys->data); g_list_free (keys); /* Figure out what to display */ switch (gpgme_err_code (status->signatures->status)) { case GPG_ERR_KEY_EXPIRED: /* TRANSLATORS: <key id='xxx'> is a custom markup tag, do not translate. */ body = _("Signed by <i><key id='%s'/> <b>expired</b></i> on %s."); title = _("Invalid Signature"); icon = ICON_PREFIX "seahorse-sign-bad.png"; sig = TRUE; break; /* TRANSLATORS: <key id='xxx'> is a custom markup tag, do not translate. */ case GPG_ERR_SIG_EXPIRED: body = _("Signed by <i><key id='%s'/></i> on %s <b>Expired</b>."); title = _("Expired Signature"); icon = ICON_PREFIX "seahorse-sign-bad.png"; sig = TRUE; break; /* TRANSLATORS: <key id='xxx'> is a custom markup tag, do not translate. */ case GPG_ERR_CERT_REVOKED: body = _("Signed by <i><key id='%s'/> <b>Revoked</b></i> on %s."); title = _("Revoked Signature"); icon = ICON_PREFIX "seahorse-sign-bad.png"; sig = TRUE; break; case GPG_ERR_NO_ERROR: /* TRANSLATORS: <key id='xxx'> is a custom markup tag, do not translate. */ body = _("Signed by <i><key id='%s'/></i> on %s."); title = _("Good Signature"); icon = ICON_PREFIX "seahorse-sign-ok.png"; sig = TRUE; break; case GPG_ERR_NO_PUBKEY: body = _("Signing key not in keyring."); title = _("Unknown Signature"); icon = ICON_PREFIX "seahorse-sign-unknown.png"; break; case GPG_ERR_BAD_SIGNATURE: body = _("Bad or forged signature. The signed data was modified."); title = _("Bad Signature"); icon = ICON_PREFIX "seahorse-sign-bad.png"; break; case GPG_ERR_NO_DATA: return; default: if (!GPG_IS_OK (status->signatures->status)) seahorse_gpgme_handle_error (status->signatures->status, _("Couldn't verify signature.")); return; }; if (sig) { gchar *date = seahorse_util_get_display_date_string (status->signatures->timestamp); gchar *id = seahorse_context_id_to_dbus (SCTX_APP (), seahorse_object_get_id (object)); body = g_markup_printf_escaped (body, id, date); g_free (date); g_free (id); } else { body = g_strdup (body); } if (data) { data = seahorse_util_uri_get_last (data); unesc_data = g_uri_unescape_string (data, NULL); title = g_strdup_printf ("%s: %s", unesc_data, title); g_free (unesc_data); } else { title = g_strdup (title); } seahorse_notification_display (title, body, !sig, icon, NULL); g_free(title); g_free(body); }
int main (int argc, char **argv) { int last_argc = -1; gpgme_error_t err; gpgme_ctx_t ctx; gpgme_key_t key; gpgme_keylist_result_t result; gpgme_key_t keyarray[100]; int keyidx = 0; gpgme_data_t out; gpgme_protocol_t protocol = GPGME_PROTOCOL_OpenPGP; gpgme_export_mode_t mode = 0; if (argc) { argc--; argv++; } while (argc && last_argc != argc ) { last_argc = argc; if (!strcmp (*argv, "--")) { argc--; argv++; break; } else if (!strcmp (*argv, "--help")) show_usage (0); else if (!strcmp (*argv, "--verbose")) { verbose = 1; argc--; argv++; } else if (!strcmp (*argv, "--openpgp")) { protocol = GPGME_PROTOCOL_OpenPGP; argc--; argv++; } else if (!strcmp (*argv, "--cms")) { protocol = GPGME_PROTOCOL_CMS; argc--; argv++; } else if (!strcmp (*argv, "--extern")) { mode |= GPGME_EXPORT_MODE_EXTERN; argc--; argv++; } else if (!strcmp (*argv, "--secret")) { mode |= GPGME_EXPORT_MODE_SECRET; argc--; argv++; } else if (!strcmp (*argv, "--raw")) { mode |= GPGME_EXPORT_MODE_RAW; argc--; argv++; } else if (!strcmp (*argv, "--pkcs12")) { mode |= GPGME_EXPORT_MODE_PKCS12; argc--; argv++; } else if (!strncmp (*argv, "--", 2)) show_usage (1); } if (!argc) show_usage (1); init_gpgme (protocol); err = gpgme_new (&ctx); fail_if_err (err); gpgme_set_protocol (ctx, protocol); /* Lookup the keys. */ err = gpgme_op_keylist_ext_start (ctx, (const char**)argv, 0, 0); fail_if_err (err); while (!(err = gpgme_op_keylist_next (ctx, &key))) { printf ("keyid: %s (fpr: %s)\n", key->subkeys?nonnull (key->subkeys->keyid):"?", key->subkeys?nonnull (key->subkeys->fpr):"?"); if (keyidx < DIM (keyarray)-1) keyarray[keyidx++] = key; else { fprintf (stderr, PGM": too many keys" "- skipping this key\n"); gpgme_key_unref (key); } } if (gpgme_err_code (err) != GPG_ERR_EOF) fail_if_err (err); err = gpgme_op_keylist_end (ctx); fail_if_err (err); keyarray[keyidx] = NULL; result = gpgme_op_keylist_result (ctx); if (result->truncated) { fprintf (stderr, PGM ": key listing unexpectedly truncated\n"); exit (1); } /* Now for the actual export. */ if ((mode & GPGME_EXPORT_MODE_EXTERN)) printf ("sending keys to keyserver\n"); if ((mode & GPGME_EXPORT_MODE_SECRET)) printf ("exporting secret keys!\n"); err = gpgme_data_new (&out); fail_if_err (err); gpgme_set_armor (ctx, 1); err = gpgme_op_export_keys (ctx, keyarray, mode, (mode & GPGME_KEYLIST_MODE_EXTERN)? NULL:out); fail_if_err (err); fflush (NULL); if (!(mode & GPGME_KEYLIST_MODE_EXTERN)) { fputs ("Begin Result:\n", stdout); print_data (out); fputs ("End Result.\n", stdout); } /* Cleanup. */ gpgme_data_release (out); for (keyidx=0; keyarray[keyidx]; keyidx++) gpgme_key_unref (keyarray[keyidx]); gpgme_release (ctx); return 0; }
int main (int argc, char **argv) { round_t round = TEST_INITIALIZER; char *text_filename = make_filename ("t-data-1.txt"); char *longer_text_filename = make_filename ("t-data-2.txt"); const char *missing_filename = "this-file-surely-does-not-exist"; gpgme_error_t err = 0; gpgme_data_t data; while (++round) { switch (round) { case TEST_INVALID_ARGUMENT: err = gpgme_data_new (NULL); if (!err) { fprintf (stderr, "%s:%d: gpgme_data_new on NULL pointer succeeded " "unexpectedly\n", __FILE__, __LINE__); exit (1); } continue; case TEST_INOUT_NONE: err = gpgme_data_new (&data); break; case TEST_INOUT_MEM_NO_COPY: err = gpgme_data_new_from_mem (&data, text, strlen (text), 0); break; case TEST_INOUT_MEM_COPY: err = gpgme_data_new_from_mem (&data, text, strlen (text), 1); break; case TEST_INOUT_MEM_FROM_FILE_COPY: err = gpgme_data_new_from_file (&data, text_filename, 1); break; case TEST_INOUT_MEM_FROM_INEXISTANT_FILE: err = gpgme_data_new_from_file (&data, missing_filename, 1); if (!err) { fprintf (stderr, "%s:%d: gpgme_data_new_from_file on inexistant " "file succeeded unexpectedly\n", __FILE__, __LINE__); exit (1); } continue; case TEST_INOUT_MEM_FROM_FILE_NO_COPY: err = gpgme_data_new_from_file (&data, text_filename, 0); /* This is not implemented yet. */ if (gpgme_err_code (err) == GPG_ERR_NOT_IMPLEMENTED || gpgme_err_code (err) == GPG_ERR_INV_VALUE) continue; break; case TEST_INOUT_MEM_FROM_FILE_PART_BY_NAME: err = gpgme_data_new_from_filepart (&data, longer_text_filename, 0, strlen (text), strlen (text)); break; case TEST_INOUT_MEM_FROM_INEXISTANT_FILE_PART: err = gpgme_data_new_from_filepart (&data, missing_filename, 0, strlen (text), strlen (text)); if (!err) { fprintf (stderr, "%s:%d: gpgme_data_new_from_file on inexistant " "file succeeded unexpectedly\n", __FILE__, __LINE__); exit (1); } continue; case TEST_INOUT_MEM_FROM_FILE_PART_BY_FP: { FILE *fp = fopen (longer_text_filename, "rb"); if (! fp) { fprintf (stderr, "%s:%d: fopen: %s\n", __FILE__, __LINE__, strerror (errno)); exit (1); } err = gpgme_data_new_from_filepart (&data, 0, fp, strlen (text), strlen (text)); } break; case TEST_END: goto out; case TEST_INITIALIZER: /* Shouldn't happen. */ fprintf (stderr, "%s:%d: impossible condition\n", __FILE__, __LINE__); exit (1); } fail_if_err (err); read_test (round, data); write_test (round, data); gpgme_data_release (data); } out: free (text_filename); free (longer_text_filename); return 0; }
G_MODULE_EXPORT gboolean on_gpgme_sign_ok_clicked (BastileWidget *swidget, GtkWindow *parent) { BastileSignCheck check; BastileSignOptions options = 0; BastileObject *signer; GtkWidget *w; gpgme_error_t err; BastileObject *to_sign; /* Figure out choice */ check = SIGN_CHECK_NO_ANSWER; w = GTK_WIDGET (bastile_widget_get_widget (swidget, "sign-choice-not")); g_return_val_if_fail (w != NULL, FALSE); if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (w))) check = SIGN_CHECK_NONE; else { w = GTK_WIDGET (bastile_widget_get_widget (swidget, "sign-choice-casual")); g_return_val_if_fail (w != NULL, FALSE); if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (w))) check = SIGN_CHECK_CASUAL; else { w = GTK_WIDGET (bastile_widget_get_widget (swidget, "sign-choice-careful")); g_return_val_if_fail (w != NULL, FALSE); if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (w))) check = SIGN_CHECK_CAREFUL; } } /* Local signature */ w = GTK_WIDGET (bastile_widget_get_widget (swidget, "sign-option-local")); g_return_val_if_fail (w != NULL, FALSE); if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (w))) options |= SIGN_LOCAL; /* Revocable signature */ w = GTK_WIDGET (bastile_widget_get_widget (swidget, "sign-option-revocable")); g_return_val_if_fail (w != NULL, FALSE); if (!gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (w))) options |= SIGN_NO_REVOKE; /* Signer */ w = GTK_WIDGET (bastile_widget_get_widget (swidget, "signer-select")); g_return_val_if_fail (w != NULL, FALSE); signer = bastile_combo_keys_get_active (GTK_COMBO_BOX (w)); g_assert (!signer || (BASTILE_IS_GPGME_KEY (signer) && bastile_object_get_usage (BASTILE_OBJECT (signer)) == BASTILE_USAGE_PRIVATE_KEY)); to_sign = g_object_get_data (G_OBJECT (swidget), "to-sign"); if (BASTILE_IS_GPGME_UID (to_sign)) err = bastile_gpgme_key_op_sign_uid (BASTILE_GPGME_UID (to_sign), BASTILE_GPGME_KEY (signer), check, options); else if (BASTILE_IS_GPGME_KEY (to_sign)) err = bastile_gpgme_key_op_sign (BASTILE_GPGME_KEY (to_sign), BASTILE_GPGME_KEY (signer), check, options); else g_assert (FALSE); if (!GPG_IS_OK (err)) { if (gpgme_err_code (err) == GPG_ERR_EALREADY) { w = gtk_message_dialog_new (parent, GTK_DIALOG_MODAL, GTK_MESSAGE_INFO, GTK_BUTTONS_CLOSE, _("This key was already signed by\n\"%s\""), bastile_object_get_label (signer)); gtk_dialog_run (GTK_DIALOG (w)); gtk_widget_destroy (w); } else bastile_gpgme_handle_error (err, _("Couldn't sign key")); } bastile_widget_destroy (swidget); return TRUE; }
void crypto_asym::build_key_list(const vector<string> & recipients_email, gpgme_key_t * & ciphering_keys, bool signatories) { U_I size = recipients_email.size() + 1; ciphering_keys = new (nothrow) gpgme_key_t[size]; if(ciphering_keys == NULL) throw Ememory("crypto_asym::build_key_list"); // clearing all fields in order to be able to know which // index has been allocated and need to be restored in case of error for(U_I i = 0; i < size ; ++i) ciphering_keys[i] = NULL; try { gpgme_error_t err = GPG_ERR_NO_ERROR; gpgme_user_id_t id = NULL; bool found = false; bool eof = false; bool loop = false; U_I offset = 0; // for each recipient, listing all keys to find a match for(U_I i = 0; i < recipients_email.size(); ++i) { err = gpgme_op_keylist_start(context, NULL, 0); switch(gpgme_err_code(err)) { case GPG_ERR_NO_ERROR: break; case GPG_ERR_INV_VALUE: throw SRC_BUG; default: throw Erange("crypto_asym::decrypt", string(gettext("Unexpected error reported by GPGME: ")) + tools_gpgme_strerror_r(err)); } found = false; eof = false; do { // getting the next key err = gpgme_op_keylist_next(context, &(ciphering_keys[i - offset])); switch(gpgme_err_code(err)) { case GPG_ERR_EOF: eof = true; break; case GPG_ERR_NO_ERROR: id = ciphering_keys[i - offset]->uids; loop = true; // for each key, listing all identies associated with it to find a match do { found = (strncmp(recipients_email[i].c_str(), id->email, recipients_email[i].size()) == 0); if(found) { if(ciphering_keys[i - offset]->revoked || ciphering_keys[i - offset]->expired || ciphering_keys[i - offset]->disabled || ciphering_keys[i - offset]->invalid) found = false; if(signatories) { if(!ciphering_keys[i - offset]->can_sign) found = false; } else { if(!ciphering_keys[i - offset]->can_encrypt) found = false; } } if(!found && id->next != NULL) id = id->next; else loop = false; } while(loop); // if not identity match found for that key deleting the key if(!found) { gpgme_key_unref(ciphering_keys[i - offset]); ciphering_keys[i - offset] = NULL; } break; default: throw Erange("crypto_asym::decrypt", string(gettext("Unexpected error reported by GPGME: ")) + tools_gpgme_strerror_r(err)); } } while(!found && !eof); // if we exit before gpgme_op_keylist_next() return GPG_ERR_EOF // we must update the state of the context to end the key listing operation if(!eof) (void)gpgme_op_keylist_end(context); if(!found) { if(signatories) get_ui().printf(gettext("No valid signing key could be find for %S"), &(recipients_email[i])); else get_ui().printf(gettext("No valid encryption key could be find for %S"), &(recipients_email[i])); get_ui().pause("Do you want to continue without this recipient?"); ++offset; } } // if no recipient could be found at all aborting the operation if(offset + 1 >= size) { if(signatories) throw Erange("crypto_asym::build_key_list", gettext("No signatory remain with a valid key, signing is impossible, aborting")); else throw Erange("crypto_asym::build_key_list", gettext("No recipient remain with a valid key, encryption is impossible, aborting")); } // the key list must end wth a NULL entry if(ciphering_keys[size - 1 - offset] != NULL) throw SRC_BUG; } catch(...) { release_key_list(ciphering_keys); throw; } }
static gpgme_key_t fill_clist (struct select_keys_s *sk, const char *pattern, gpgme_protocol_t proto) { GtkCMCList *clist; gpgme_ctx_t ctx; gpgme_error_t err; gpgme_key_t key; int running=0; int num_results = 0; gboolean exact_match = FALSE; gpgme_key_t last_key = NULL; gpgme_user_id_t last_uid = NULL; cm_return_val_if_fail (sk, NULL); clist = sk->clist; cm_return_val_if_fail (clist, NULL); debug_print ("select_keys:fill_clist: pattern '%s' proto %d\n", pattern, proto); /*gtk_cmclist_freeze (select_keys.clist);*/ err = gpgme_new (&ctx); g_assert (!err); gpgme_set_protocol(ctx, proto); sk->select_ctx = ctx; update_progress (sk, ++running, pattern); while (gtk_events_pending ()) gtk_main_iteration (); err = gpgme_op_keylist_start (ctx, pattern, 0); if (err) { debug_print ("** gpgme_op_keylist_start(%s) failed: %s", pattern, gpgme_strerror (err)); sk->select_ctx = NULL; gpgme_release(ctx); return NULL; } update_progress (sk, ++running, pattern); while ( !(err = gpgme_op_keylist_next ( ctx, &key )) ) { gpgme_user_id_t uid = key->uids; if (!key->can_encrypt || key->revoked || key->expired || key->disabled) continue; debug_print ("%% %s:%d: insert\n", __FILE__ ,__LINE__ ); set_row (clist, key, proto ); for (; uid; uid = uid->next) { gchar *raw_mail = NULL; if (!uid->email) continue; if (uid->revoked || uid->invalid) continue; raw_mail = g_strdup(uid->email); extract_address(raw_mail); if (!strcasecmp(pattern, raw_mail)) { exact_match = TRUE; last_uid = uid; g_free(raw_mail); break; } g_free(raw_mail); } num_results++; last_key = key; key = NULL; update_progress (sk, ++running, pattern); while (gtk_events_pending ()) gtk_main_iteration (); } if (exact_match == TRUE && num_results == 1) { if (last_key->uids->validity < GPGME_VALIDITY_FULL && !use_untrusted(last_key, last_uid, proto)) exact_match = FALSE; } debug_print ("%% %s:%d: ready\n", __FILE__ ,__LINE__ ); if (gpgme_err_code(err) != GPG_ERR_EOF) { debug_print ("** gpgme_op_keylist_next failed: %s", gpgme_strerror (err)); gpgme_op_keylist_end(ctx); } if (!exact_match || num_results != 1) { sk->select_ctx = NULL; gpgme_release (ctx); } /*gtk_cmclist_thaw (select_keys.clist);*/ return (exact_match == TRUE && num_results == 1 ? last_key:NULL); }
static gpgme_key_t* prompt_recipients (gpgme_key_t *signkey) { gpgme_error_t gerr = 0; CryptUIKeyset *keyset; gpgme_ctx_t ctx; gpgme_key_t key; GArray *keys; gchar **recips; gchar *signer; *signkey = NULL; keyset = cryptui_keyset_new ("openpgp", TRUE); if (cryptui_keyset_get_count (keyset) == 0) { cryptui_need_to_get_keys (); } else { recips = cryptui_prompt_recipients (keyset, _("Choose Recipients"), &signer); if (recips) { gpgme_check_version (NULL); gerr = gpgme_engine_check_version (GPGME_PROTOCOL_OpenPGP); g_return_val_if_fail (gerr == 0, NULL); gerr = gpgme_new (&ctx); g_return_val_if_fail (gerr == 0, NULL); if (signer) { /* Load up the GPGME secret key */ gchar *id = cryptui_keyset_key_raw_keyid (keyset, signer); gerr = gpgme_get_key (ctx, id, signkey, 1); g_free (id); /* A more descriptive error message */ if (GPG_ERR_EOF == gpgme_err_code (gerr)) gerr = gpgme_error (GPG_ERR_NOT_FOUND); } if (gerr == 0) { gchar **ids; guint num; /* Load up the GPGME keys */ ids = cryptui_keyset_keys_raw_keyids (keyset, (const gchar**)recips); num = g_strv_length (ids); keys = g_array_new (TRUE, TRUE, sizeof (gpgme_key_t)); gerr = gpgme_op_keylist_ext_start (ctx, (const gchar**)ids, 0, 0); g_free (ids); if (gerr == 0) { while ((gerr = gpgme_op_keylist_next (ctx, &key)) == 0) g_array_append_val (keys, key); gpgme_op_keylist_end (ctx); } /* Ignore EOF error */ if (GPG_ERR_EOF == gpgme_err_code (gerr)) gerr = 0; if (gerr == 0 && num != keys->len) g_warning ("couldn't load all the keys (%d/%d) from GPGME", keys->len, num); } gpgme_release (ctx); } g_object_unref (keyset); if (!recips) return NULL; g_strfreev (recips); g_free (signer); if (gerr == 0 && keys->len) return (gpgme_key_t*)g_array_free (keys, FALSE); /* When failure, free all our return values */ seahorse_util_free_keys ((gpgme_key_t*)g_array_free (keys, FALSE)); if (*signkey) gpgme_key_unref (*signkey); seahorse_util_handle_gpgme (gerr, _("Couldn't load keys")); } return NULL; }