static gboolean decrypt_start (SeahorseToolMode *mode, const gchar *uri, gpgme_data_t uridata, SeahorsePGPOperation *pop, GError **err) { gpgme_data_t plain; gpgme_error_t gerr; gchar *touri; /* File to decrypt to */ touri = seahorse_util_remove_suffix (uri, _("Choose Decrypted File Name for '%s'")); if (!touri) return FALSE; /* Open necessary files, release these with the operation */ plain = seahorse_vfs_data_create (touri, SEAHORSE_VFS_WRITE | SEAHORSE_VFS_DELAY, err); g_free (touri); if (!plain) return FALSE; g_object_set_data_full (G_OBJECT (pop), "plain-data", plain, (GDestroyNotify)gpgme_data_release); /* Start actual decryption */ gerr = gpgme_op_decrypt_verify_start (pop->gctx, uridata, plain); if (gerr != 0) { seahorse_util_gpgme_to_error (gerr, err); return FALSE; } return TRUE; }
/* Decrypt data from INDATA to OUTDATE. If WITH_VERIFY is set, a signature of PGP/MIME combined message is also verified the same way as with op_gpgme_verify. */ int op_gpgme_decrypt (protocol_t protocol, gpgme_data_t indata, gpgme_data_t outdata, engine_filter_t filter, void *hwnd, int with_verify) { gpgme_error_t err; closure_data_t cld; gpgme_ctx_t ctx = NULL; (void)hwnd; cld = xcalloc (1, sizeof *cld); cld->closure = decrypt_closure; cld->filter = filter; cld->with_verify = with_verify; err = gpgme_new (&ctx); if (err) goto leave; gpgme_set_progress_cb (ctx, NULL, cld); switch (protocol) { case PROTOCOL_OPENPGP: /* Gpgme's default. */ break; case PROTOCOL_SMIME: err = gpgme_set_protocol (ctx, GPGME_PROTOCOL_CMS); break; default: err = gpg_error (GPG_ERR_UNSUPPORTED_PROTOCOL); break; } if (err) goto leave; /* Note: We do no error checking for the next call because some backends may not implement a command hanler at all. */ gpgme_set_passphrase_cb (ctx, passphrase_callback_box, &cld->pw_cb); cld->pw_cb.ctx = ctx; if (with_verify) err = gpgme_op_decrypt_verify_start (ctx, indata, outdata); else err = gpgme_op_decrypt_start (ctx, indata, outdata); leave: if (err) { xfree (cld); gpgme_release (ctx); } else engine_private_set_cancel (filter, ctx); return err; }
/** * crypto: SeahorseServiceCrypto context * ktype: "openpgp" * flags: FLAG_QUIET for no notification * crypttext: the text to decrypt * cryptlength: the length of the crypto text * cleartext: the decrypted text (out) * clearlength: The length of the clear text (out) * signer: the signer if the text is signed (out) * textmode: TRUE to switch textmode on * ascii_armor: TRUE to switch ascii armor on * error: a potential error (out) * * Decrypts any buffer (text and data). Can be used by DBus API functions * * Returns TRUE on success **/ static gboolean crypto_decrypt_generic (SeahorseServiceCrypto *crypto, const char *ktype, int flags, const char *crypttext, gsize cryptlength, char **cleartext, gsize *clearlength, char **signer, gboolean textmode, gboolean ascii_armor, GError **error) { gpgme_verify_result_t status; gpgme_error_t gerr; SeahorseGpgmeOperation *pop; gpgme_data_t plain, cipher; gboolean ret = TRUE; GQuark keyid; if (!g_str_equal (ktype, g_quark_to_string (SEAHORSE_PGP))) { g_set_error (error, SEAHORSE_DBUS_ERROR, SEAHORSE_DBUS_ERROR_INVALID, _("Invalid key type for decryption: %s"), ktype); return FALSE; } /* * TODO: Once we support different kinds of keys that support encryption * then all this logic will need to change. */ pop = seahorse_gpgme_operation_new (NULL); /* new data from text */ gerr = gpgme_data_new_from_mem (&cipher, crypttext, cryptlength, FALSE); g_return_val_if_fail (GPG_IS_OK (gerr), FALSE); gerr = gpgme_data_new (&plain); g_return_val_if_fail (GPG_IS_OK (gerr), FALSE); /* encrypt with armor */ gpgme_set_textmode (pop->gctx, textmode); gpgme_set_armor (pop->gctx, ascii_armor); /* Do the decryption */ gerr = gpgme_op_decrypt_verify_start (pop->gctx, cipher, plain); /* Frees plain */ ret = process_crypto_result (pop, gerr, plain, cleartext, clearlength, error); if (ret) { *signer = NULL; status = gpgme_op_verify_result (pop->gctx); if (status->signatures) { if (!(flags & FLAG_QUIET)) notify_signatures (NULL, status); if (status->signatures->summary & GPGME_SIGSUM_GREEN || status->signatures->summary & GPGME_SIGSUM_VALID || status->signatures->summary & GPGME_SIGSUM_KEY_MISSING) { keyid = seahorse_pgp_key_canonize_id (status->signatures->fpr); *signer = seahorse_context_id_to_dbus (SCTX_APP (), keyid); } } } g_object_unref (pop); gpgme_data_release (cipher); return ret; }
static gpg_error_t gpa_file_decrypt_operation_start (GpaFileDecryptOperation *op, gpa_file_item_t file_item) { gpg_error_t err; if (file_item->direct_in) { /* No copy is made. */ err = gpgme_data_new_from_mem (&op->cipher, file_item->direct_in, file_item->direct_in_len, 0); if (err) { gpa_gpgme_warning (err); return err; } err = gpgme_data_new (&op->plain); if (err) { gpa_gpgme_warning (err); gpgme_data_release (op->cipher); op->plain = NULL; return err; } gpgme_set_protocol (GPA_OPERATION (op)->context->ctx, is_cms_data (file_item->direct_in, file_item->direct_in_len) ? GPGME_PROTOCOL_CMS : GPGME_PROTOCOL_OpenPGP); } else { gchar *cipher_filename = file_item->filename_in; char *filename_used; file_item->filename_out = destination_filename (cipher_filename); /* Open the files */ op->cipher_fd = gpa_open_input (cipher_filename, &op->cipher, GPA_OPERATION (op)->window); if (op->cipher_fd == -1) /* FIXME: Error value. */ return gpg_error (GPG_ERR_GENERAL); op->plain_fd = gpa_open_output (file_item->filename_out, &op->plain, GPA_OPERATION (op)->window, &filename_used); if (op->plain_fd == -1) { gpgme_data_release (op->cipher); close (op->cipher_fd); xfree (filename_used); /* FIXME: Error value. */ return gpg_error (GPG_ERR_GENERAL); } xfree (file_item->filename_out); file_item->filename_out = filename_used; gpgme_set_protocol (GPA_OPERATION (op)->context->ctx, is_cms_file (cipher_filename) ? GPGME_PROTOCOL_CMS : GPGME_PROTOCOL_OpenPGP); } /* Start the operation. */ err = gpgme_op_decrypt_verify_start (GPA_OPERATION (op)->context->ctx, op->cipher, op->plain); if (err) { gpa_gpgme_warning (err); gpgme_data_release (op->plain); op->plain = NULL; close (op->plain_fd); op->plain_fd = -1; gpgme_data_release (op->cipher); op->cipher = NULL; close (op->cipher_fd); op->cipher_fd = -1; return err; } /* Show and update the progress dialog. */ gtk_widget_show_all (GPA_FILE_OPERATION (op)->progress_dialog); gpa_progress_dialog_set_label (GPA_PROGRESS_DIALOG (GPA_FILE_OPERATION (op)->progress_dialog), file_item->direct_name ? file_item->direct_name : file_item->filename_in); return 0; }