[svn] GPGol - r93 - trunk/src
svn author wk
cvs at cvs.gnupg.org
Tue Sep 13 19:21:30 CEST 2005
Author: wk
Date: 2005-09-13 19:21:29 +0200 (Tue, 13 Sep 2005)
New Revision: 93
Modified:
trunk/src/ChangeLog
trunk/src/engine-gpgme.c
trunk/src/engine.h
trunk/src/gpgmsg.cpp
trunk/src/pgpmime.c
trunk/src/pgpmime.h
trunk/src/util.h
Log:
Add some new features - not fully working yet.
Modified: trunk/src/ChangeLog
===================================================================
--- trunk/src/ChangeLog 2005-09-09 05:29:48 UTC (rev 92)
+++ trunk/src/ChangeLog 2005-09-13 17:21:29 UTC (rev 93)
@@ -1,5 +1,23 @@
-2004-09-08 Timo Schulz <ts at g10code.com>
+2005-09-13 Werner Koch <wk at g10code.com>
+ * pgpmime.c (pgpmime_decrypt): New arg ATTESTATION.
+ * engine-gpgme.c (add_verify_attestation): New.
+ (op_decrypt, op_verify_detached_sig, op_verify_detached_sig)
+ (op_verify_detached_sig): Add new arg ATTESTATION. Changed all
+ callers.
+ (at_sig_summary, at_sig_validity, add_verify_attestation): New.
+ The code has been taken and modified from Mutt's crypt-gpgme.c and
+ entirely been writen by g10 Code.
+ (at_fingerprint): Ditto.
+
+ * gpgmsg.cpp (class GpgMsgImpl): New member ATTESTATION. Use it
+ in all calls to the functions above.
+
+ * gpgmsg.cpp (decryptAttachment, decrypt): Save plaintext back
+ into the MAPI if desired.
+
+g2004-09-08 Timo Schulz <ts at g10code.com>
+
* passphrase-dialog.c (lod_recipbox): Use gpgme directly
to resolve the keyids to userids.
* usermap.c, usermap.h: Removed.
Modified: trunk/src/engine-gpgme.c
===================================================================
--- trunk/src/engine-gpgme.c 2005-09-09 05:29:48 UTC (rev 92)
+++ trunk/src/engine-gpgme.c 2005-09-13 17:21:29 UTC (rev 93)
@@ -48,6 +48,14 @@
static char *debug_file = NULL;
static int init_done = 0;
+
+static void add_verify_attestation (gpgme_data_t at,
+ gpgme_ctx_t ctx,
+ gpgme_verify_result_t res,
+ const char *filename);
+
+
+
static void
cleanup (void)
{
@@ -474,9 +482,11 @@
/* Run the decryption. Decrypts INBUF to OUTBUF, caller must xfree
the result at OUTBUF. TTL is the time in seconds to cache a
passphrase. If FILENAME is not NULL it will be displayed along
- with status outputs. */
+ with status outputs. If ATTESTATION is not NULL a text with the
+ result of the signature verification will get printed to it. */
int
-op_decrypt (const char *inbuf, char **outbuf, int ttl, const char *filename)
+op_decrypt (const char *inbuf, char **outbuf, int ttl, const char *filename,
+ gpgme_data_t attestation)
{
struct decrypt_key_s dk;
gpgme_data_t in = NULL;
@@ -524,6 +534,8 @@
res = gpgme_op_verify_result (ctx);
if (res && res->signatures)
verify_dialog_box (res, filename);
+ if (res && res->signatures && attestation)
+ add_verify_attestation (attestation, ctx, res, filename);
}
else if (gpgme_err_code (err) == GPG_ERR_DECRYPT_FAILED)
{
@@ -560,10 +572,12 @@
/* Decrypt the GPGME data object IN into the data object OUT. Returns
0 on success or an gpgme error code on failure. If FILENAME is not
- NULL it will be displayed along with status outputs. */
+ NULL it will be displayed along with status outputs. If ATTESTATION
+ is not NULL a text with the result of the signature verification
+ will get printed to it. */
static int
decrypt_stream (gpgme_data_t in, gpgme_data_t out, int ttl,
- const char *filename)
+ const char *filename, gpgme_data_t attestation)
{
struct decrypt_key_s dk;
gpgme_ctx_t ctx = NULL;
@@ -590,6 +604,8 @@
res = gpgme_op_verify_result (ctx);
if (res && res->signatures)
verify_dialog_box (res, filename);
+ if (res && res->signatures && attestation)
+ add_verify_attestation (attestation, ctx, res, filename);
}
else if (gpgme_err_code (err) == GPG_ERR_DECRYPT_FAILED)
{
@@ -625,7 +641,7 @@
outputs. */
int
op_decrypt_stream (LPSTREAM instream, LPSTREAM outstream, int ttl,
- const char *filename)
+ const char *filename, gpgme_data_t attestation)
{
struct gpgme_data_cbs cbs;
gpgme_data_t in = NULL;
@@ -640,7 +656,7 @@
if (!err)
err = gpgme_data_new_from_cbs (&out, &cbs, outstream);
if (!err)
- err = decrypt_stream (in, out, ttl, filename);
+ err = decrypt_stream (in, out, ttl, filename, attestation);
if (in)
gpgme_data_release (in);
@@ -656,7 +672,7 @@
outputs. */
int
op_decrypt_stream_to_buffer (LPSTREAM instream, char **outbuf, int ttl,
- const char *filename)
+ const char *filename, gpgme_data_t attestation)
{
struct gpgme_data_cbs cbs;
gpgme_data_t in = NULL;
@@ -672,7 +688,7 @@
if (!err)
err = gpgme_data_new (&out);
if (!err)
- err = decrypt_stream (in, out, ttl, filename);
+ err = decrypt_stream (in, out, ttl, filename, attestation);
if (!err)
{
/* Return the buffer but first make sure it is a string. */
@@ -697,7 +713,7 @@
outputs. */
int
op_decrypt_stream_to_gpgme (LPSTREAM instream, gpgme_data_t out, int ttl,
- const char *filename)
+ const char *filename, gpgme_data_t attestation)
{
struct gpgme_data_cbs cbs;
gpgme_data_t in = NULL;
@@ -708,7 +724,7 @@
err = gpgme_data_new_from_cbs (&in, &cbs, instream);
if (!err)
- err = decrypt_stream (in, out, ttl, filename);
+ err = decrypt_stream (in, out, ttl, filename, attestation);
if (in)
gpgme_data_release (in);
@@ -722,9 +738,12 @@
OUTBUF. If OUTBUF is NULL only the verification result will be
displayed (this is suitable for PGP/MIME messages). A dialog box
will show the result of the verification. If FILENAME is not NULL
- it will be displayed along with status outputs. */
+ it will be displayed along with status outputs. If ATTESTATION is
+ not NULL a text with the result of the signature verification will
+ get printed to it. */
int
-op_verify (const char *inbuf, char **outbuf, const char *filename)
+op_verify (const char *inbuf, char **outbuf, const char *filename,
+ gpgme_data_t attestation)
{
gpgme_data_t in = NULL;
gpgme_data_t out = NULL;
@@ -765,6 +784,8 @@
}
if (res)
verify_dialog_box (res, filename);
+ if (res && attestation)
+ add_verify_attestation (attestation, ctx, res, filename);
leave:
if (out)
@@ -779,10 +800,12 @@
/* Verify a detached message where the data is to be read from the
DATA_STREAM and the signature itself is expected to be the string
SIG_STRING. FILENAME will be shown by the verification status
- dialog box. */
+ dialog box. If ATTESTATION is not NULL a text with the result of
+ the signature verification will get printed to it. */
int
op_verify_detached_sig (LPSTREAM data_stream,
- const char *sig_string, const char *filename)
+ const char *sig_string, const char *filename,
+ gpgme_data_t attestation)
{
struct gpgme_data_cbs cbs;
gpgme_data_t data = NULL;
@@ -815,6 +838,8 @@
res = gpgme_op_verify_result (ctx);
if (res)
verify_dialog_box (res, filename);
+ if (res && attestation)
+ add_verify_attestation (attestation, ctx, res, filename);
}
leave:
@@ -828,7 +853,335 @@
}
+
+static void
+at_puts (gpgme_data_t a, const char *s)
+{
+ gpgme_data_write (a, s, strlen (s));
+}
+static void
+at_print_time (gpgme_data_t a, time_t t)
+{
+ char buf[200];
+
+ strftime (buf, sizeof (buf)-1, "%c", localtime (&t));
+ at_puts (a, buf);
+}
+
+static void
+at_fingerprint (gpgme_data_t a, gpgme_key_t key)
+{
+ const char *s;
+ int i, is_pgp;
+ char *buf, *p;
+ const char *prefix = _("Fingerprint: ");
+
+ if (!key)
+ return;
+ s = key->subkeys ? key->subkeys->fpr : NULL;
+ if (!s)
+ return;
+ is_pgp = (key->protocol == GPGME_PROTOCOL_OpenPGP);
+
+ buf = xmalloc ( strlen (prefix) + strlen(s) * 4 + 2 );
+ p = stpcpy (buf, prefix);
+ if (is_pgp && strlen (s) == 40)
+ {
+ /* v4 style formatted. */
+ for (i=0; *s && s[1] && s[2] && s[3] && s[4]; s += 4, i++)
+ {
+ *p++ = s[0];
+ *p++ = s[1];
+ *p++ = s[2];
+ *p++ = s[3];
+ *p++ = ' ';
+ if (i == 4)
+ *p++ = ' ';
+ }
+ }
+ else
+ {
+ /* v3 style or X.509 formatted. */
+ for (i=0; *s && s[1] && s[2]; s += 2, i++)
+ {
+ *p++ = s[0];
+ *p++ = s[1];
+ *p++ = is_pgp? ' ':':';
+ if (is_pgp && i == 7)
+ *p++ = ' ';
+ }
+ }
+
+ /* Just in case print remaining odd digits */
+ for (; *s; s++)
+ *p++ = *s;
+ *p++ = '\n';
+ *p = 0;
+ at_puts (a, buf);
+ xfree (buf);
+}
+
+
+/* Print common attributes of the signature summary SUM. Returns
+ trues if a severe warning has been encountered. */
+static int
+at_sig_summary (gpgme_data_t a,
+ unsigned long sum, gpgme_signature_t sig, gpgme_key_t key)
+{
+ int severe = 0;
+
+ if ((sum & GPGME_SIGSUM_VALID))
+ at_puts (a, _("This signature is valid\n"));
+ if ((sum & GPGME_SIGSUM_GREEN))
+ at_puts (a, _("signature state is \"green\"\n"));
+ if ((sum & GPGME_SIGSUM_RED))
+ at_puts (a, _("signature state is \"red\"\n"));
+
+ if ((sum & GPGME_SIGSUM_KEY_REVOKED))
+ {
+ at_puts (a, _("Warning: One of the keys has been revoked\n"));
+ severe = 1;
+ }
+
+ if ((sum & GPGME_SIGSUM_KEY_EXPIRED))
+ {
+ time_t t = key->subkeys->expires ? key->subkeys->expires : 0;
+
+ if (t)
+ {
+ at_puts (a, _("Warning: The key used to create the "
+ "signature expired at: "));
+ at_print_time (a, t);
+ at_puts (a, "\n");
+ }
+ else
+ at_puts (a, _("Warning: At least one certification key "
+ "has expired\n"));
+ }
+
+ if ((sum & GPGME_SIGSUM_SIG_EXPIRED))
+ {
+ at_puts (a, _("Warning: The signature expired at: "));
+ at_print_time (a, sig ? sig->exp_timestamp : 0);
+ at_puts (a, "\n");
+ }
+
+ if ((sum & GPGME_SIGSUM_KEY_MISSING))
+ at_puts (a, _("Can't verify due to a missing key or certificate\n"));
+
+ if ((sum & GPGME_SIGSUM_CRL_MISSING))
+ {
+ at_puts (a, _("The CRL is not available\n"));
+ severe = 1;
+ }
+
+ if ((sum & GPGME_SIGSUM_CRL_TOO_OLD))
+ {
+ at_puts (a, _("Available CRL is too old\n"));
+ severe = 1;
+ }
+
+ if ((sum & GPGME_SIGSUM_BAD_POLICY))
+ at_puts (a, _("A policy requirement was not met\n"));
+
+ if ((sum & GPGME_SIGSUM_SYS_ERROR))
+ {
+ const char *t0 = NULL, *t1 = NULL;
+
+ at_puts (a, _("A system error occured"));
+
+ /* Try to figure out some more detailed system error information. */
+ if (sig)
+ {
+ t0 = "";
+ t1 = sig->wrong_key_usage ? "Wrong_Key_Usage" : "";
+ }
+
+ if (t0 || t1)
+ {
+ at_puts (a, ": ");
+ if (t0)
+ at_puts (a, t0);
+ if (t1 && !(t0 && !strcmp (t0, t1)))
+ {
+ if (t0)
+ at_puts (a, ",");
+ at_puts (a, t1);
+ }
+ }
+ at_puts (a, "\n");
+ }
+
+ return severe;
+}
+
+
+/* Print the validity of a key used for one signature. */
+static void
+at_sig_validity (gpgme_data_t a, gpgme_signature_t sig)
+{
+ const char *txt = NULL;
+
+ switch (sig ? sig->validity : 0)
+ {
+ case GPGME_VALIDITY_UNKNOWN:
+ txt = _("WARNING: We have NO indication whether "
+ "the key belongs to the person named "
+ "as shown above\n");
+ break;
+ case GPGME_VALIDITY_UNDEFINED:
+ break;
+ case GPGME_VALIDITY_NEVER:
+ txt = _("WARNING: The key does NOT BELONG to "
+ "the person named as shown above\n");
+ break;
+ case GPGME_VALIDITY_MARGINAL:
+ txt = _("WARNING: It is NOT certain that the key "
+ "belongs to the person named as shown above\n");
+ break;
+ case GPGME_VALIDITY_FULL:
+ case GPGME_VALIDITY_ULTIMATE:
+ txt = NULL;
+ break;
+ }
+
+ if (txt)
+ at_puts (a, txt);
+}
+
+
+/* Print a text with the attestation of the signature verification
+ (which is in RES) to A. FILENAME may also be used in the
+ attestation. */
+static void
+add_verify_attestation (gpgme_data_t a, gpgme_ctx_t ctx,
+ gpgme_verify_result_t res, const char *filename)
+{
+ time_t created;
+ const char *fpr, *uid;
+ gpgme_key_t key = NULL;
+ int i, anybad = 0, anywarn = 0;
+ unsigned int sum;
+ gpgme_user_id_t uids = NULL;
+ gpgme_signature_t sig;
+ gpgme_error_t err;
+
+ if (!gpgme_data_seek (a, 0, SEEK_CUR))
+ {
+ /* Nothing yet written to the stream. Insert the curretn time. */
+ at_puts (a, _("Verification started at: "));
+ at_print_time (a, time (NULL));
+ at_puts (a, "\n\n");
+ }
+
+ at_puts (a, _("Verification result for: "));
+ at_puts (a, filename ? filename : _("[unnamed part]"));
+ at_puts (a, "\n");
+ if (res)
+ {
+ for (sig = res->signatures; sig; sig = sig->next)
+ {
+ created = sig->timestamp;
+ fpr = sig->fpr;
+ sum = sig->summary;
+
+ if (gpg_err_code (sig->status) != GPG_ERR_NO_ERROR)
+ anybad = 1;
+
+ err = gpgme_get_key (ctx, fpr, &key, 0);
+ uid = !err && key->uids && key->uids->uid ? key->uids->uid : "[?]";
+
+ if ((sum & GPGME_SIGSUM_GREEN))
+ {
+ at_puts (a, _("Good signature from: "));
+ at_puts (a, uid);
+ at_puts (a, "\n");
+ for (i = 1, uids = key->uids; uids; i++, uids = uids->next)
+ {
+ if (uids->revoked)
+ continue;
+ at_puts (a, _(" aka: "));
+ at_puts (a, uids->uid);
+ at_puts (a, "\n");
+ }
+ at_puts (a, _(" created: "));
+ at_print_time (a, created);
+ at_puts (a, "\n");
+ if (at_sig_summary (a, sum, sig, key))
+ anywarn = 1;
+ at_sig_validity (a, sig);
+ }
+ else if ((sum & GPGME_SIGSUM_RED))
+ {
+ at_puts (a, _("*BAD* signature claimed to be from: "));
+ at_puts (a, uid);
+ at_puts (a, "\n");
+ at_sig_summary (a, sum, sig, key);
+ }
+ else if (!anybad && key && (key->protocol == GPGME_PROTOCOL_OpenPGP))
+ { /* We can't decide (yellow) but this is a PGP key with a
+ good signature, so we display what a PGP user
+ expects: The name, fingerprint and the key validity
+ (which is neither fully or ultimate). */
+ at_puts (a, _("Good signature from: "));
+ at_puts (a, uid);
+ at_puts (a, "\n");
+ at_puts (a, _(" created: "));
+ at_print_time (a, created);
+ at_puts (a, "\n");
+ at_sig_validity (a, sig);
+ at_fingerprint (a, key);
+ if (at_sig_summary (a, sum, sig, key))
+ anywarn = 1;
+ }
+ else /* can't decide (yellow) */
+ {
+ at_puts (a, _("Error checking signature"));
+ at_puts (a, "\n");
+ at_sig_summary (a, sum, sig, key);
+ }
+
+ gpgme_key_release (key);
+ }
+
+ if (!anybad )
+ {
+ gpgme_sig_notation_t notation;
+
+ for (sig = res->signatures; sig; sig = sig->next)
+ {
+ if (!sig->notations)
+ continue;
+ at_puts (a, _("*** Begin Notation (signature by: "));
+ at_puts (a, sig->fpr);
+ at_puts (a, ") ***\n");
+ for (notation = sig->notations; notation;
+ notation = notation->next)
+ {
+ if (notation->name)
+ {
+ at_puts (a, notation->name);
+ at_puts (a, "=");
+ }
+ if (notation->value)
+ {
+ at_puts (a, notation->value);
+ if (!(*notation->value
+ && (notation->value[strlen (notation->value)-1]
+ =='\n')))
+ at_puts (a, "\n");
+ }
+ }
+ at_puts (a, _("*** End Notation ***\n"));
+ }
+ }
+ }
+ at_puts (a, "\n");
+}
+
+
+
/* Try to find a key for each item in array NAMES. If one ore more
items were not found, they are stored as malloced strings to the
Modified: trunk/src/engine.h
===================================================================
--- trunk/src/engine.h 2005-09-09 05:29:48 UTC (rev 92)
+++ trunk/src/engine.h 2005-09-13 17:21:29 UTC (rev 93)
@@ -57,17 +57,20 @@
gpgme_key_t sign_key, int ttl);
int op_decrypt (const char *inbuf, char **outbuf, int ttl,
- const char *filename);
+ const char *filename, gpgme_data_t attestation);
int op_decrypt_stream (LPSTREAM instream, LPSTREAM outstream, int ttl,
- const char *filename);
+ const char *filename, gpgme_data_t attestation);
int op_decrypt_stream_to_buffer (LPSTREAM instream, char **outbuf, int ttl,
- const char *filename);
+ const char *filename,
+ gpgme_data_t attestation);
int op_decrypt_stream_to_gpgme (LPSTREAM instream, gpgme_data_t out, int ttl,
- const char *filename);
+ const char *filename,
+ gpgme_data_t attestation);
-int op_verify (const char *inbuf, char **outbuf, const char *filename);
+int op_verify (const char *inbuf, char **outbuf, const char *filename,
+ gpgme_data_t attestation);
int op_verify_detached_sig (LPSTREAM data, const char *sig,
- const char *filename);
+ const char *filename, gpgme_data_t attestation);
int op_export_keys (const char *pattern[], const char *outfile);
Modified: trunk/src/gpgmsg.cpp
===================================================================
--- trunk/src/gpgmsg.cpp 2005-09-09 05:29:48 UTC (rev 92)
+++ trunk/src/gpgmsg.cpp 2005-09-13 17:21:29 UTC (rev 93)
@@ -101,6 +101,8 @@
is_pgpmime = false;
silent = false;
+ attestation = NULL;
+
attach.att_table = NULL;
attach.rows = NULL;
}
@@ -112,6 +114,9 @@
xfree (body);
xfree (body_plain);
+ if (attestation)
+ gpgme_data_release (attestation);
+
if (attach.att_table)
{
attach.att_table->Release ();
@@ -196,8 +201,12 @@
char *body_plain; /* Plaintext version of BODY or NULL. */
bool is_pgpmime; /* True if the message is a PGP/MIME encrypted one. */
bool silent; /* Don't pop up message boxes. Currently this
- is only used with decryption. g*/
+ is only used with decryption. */
+ /* If not NULL, collect attestation information here. */
+ gpgme_data_t attestation;
+
+
/* This structure collects the information about attachments. */
struct
{
@@ -207,6 +216,7 @@
void loadBody (void);
bool isPgpmimeVersionPart (int pos);
+ void writeAttestation (void);
attach_info_t gatherAttachmentInfo (void);
int encrypt_and_sign (HWND hwnd, bool sign);
};
@@ -666,8 +676,110 @@
}
+/* Write an Attestation to the current message. */
+void
+GpgMsgImpl::writeAttestation (void)
+{
+ HRESULT hr;
+ ULONG newpos;
+ SPropValue prop;
+ LPATTACH newatt = NULL;
+ LPSTREAM to = NULL;
+ char *buffer = NULL;
+ ULONG nwritten;
+ if (!message || !attestation)
+ return;
+ hr = message->CreateAttach (NULL, 0, &newpos, &newatt);
+ if (hr != S_OK)
+ {
+ log_error ("%s:%s: can't create attachment: hr=%#lx\n",
+ __FILE__, __func__, hr);
+ goto leave;
+ }
+
+ prop.ulPropTag = PR_ATTACH_METHOD;
+ prop.Value.ul = ATTACH_BY_VALUE;
+ hr = HrSetOneProp (newatt, &prop);
+ if (hr != S_OK)
+ {
+ log_error ("%s:%s: can't set attach method: hr=%#lx\n",
+ __FILE__, __func__, hr);
+ goto leave;
+ }
+
+ prop.ulPropTag = PR_ATTACH_LONG_FILENAME_A;
+ prop.Value.lpszA = "GPGol-Attestation.txt";
+ hr = HrSetOneProp (newatt, &prop);
+ if (hr != S_OK)
+ {
+ log_error ("%s:%s: can't set attach filename: hr=%#lx\n",
+ __FILE__, __func__, hr);
+ goto leave;
+ }
+
+ hr = newatt->OpenProperty (PR_ATTACH_DATA_BIN, &IID_IStream, 0,
+ MAPI_CREATE|MAPI_MODIFY, (LPUNKNOWN*)&to);
+ if (FAILED (hr))
+ {
+ log_error ("%s:%s: can't create output stream: hr=%#lx\n",
+ __FILE__, __func__, hr);
+ goto leave;
+ }
+
+
+ if (gpgme_data_write (attestation, "", 1) != 1
+ || !(buffer = gpgme_data_release_and_get_mem (attestation, NULL)))
+ {
+ attestation = NULL;
+ log_error ("%s:%s: gpgme_data_write failed\n", __FILE__, __func__);
+ goto leave;
+ }
+ attestation = NULL;
+
+ log_debug ("writing attestation `%s'\n", buffer);
+
+ hr = to->Write (buffer, strlen (buffer), &nwritten);
+ if (hr != S_OK)
+ {
+ log_debug ("%s:%s: Write failed: hr=%#lx", __FILE__, __func__, hr);
+ goto leave;
+ }
+
+ to->Commit (0);
+ to->Release ();
+ to = NULL;
+
+ hr = newatt->SaveChanges (0);
+ if (hr != S_OK)
+ {
+ log_error ("%s:%s: SaveChanges(attachment) failed: hr=%#lx\n",
+ __FILE__, __func__, hr);
+ goto leave;
+ }
+ hr = message->SaveChanges (KEEP_OPEN_READWRITE|FORCE_SAVE);
+ if (hr != S_OK)
+ {
+ log_error ("%s:%s: SaveChanges(message) failed: hr=%#lx\n",
+ __FILE__, __func__, hr);
+ goto leave;
+ }
+
+
+ leave:
+ if (to)
+ {
+ to->Revert ();
+ to->Release ();
+ }
+ if (newatt)
+ newatt->Release ();
+ xfree (buffer);
+}
+
+
+
/* Decrypt the message MSG and update the window. HWND identifies the
current window. */
int
@@ -711,8 +823,8 @@
means of update_display and the SetWindowText API). Thus it
happens sometimes that the ciphertext is still displayed
although the MAPI calls in loadBody returned the plaintext
- (becuase we once used set_message_body). The effect is that
- when cliching the decrypt button, we won't have any
+ (because we once used set_message_body). The effect is that
+ when clicking the decrypt button, we won't have any
ciphertext to decrypt and thus get to here. We try solving
this by updating the window if we also have a cached entry.
@@ -744,6 +856,14 @@
return 0;
}
+ /* We always want an attestation. Note that we ignore any error
+ because that would anyway be a out of core situation and thus we
+ can't do much about it. */
+ if (!attestation)
+ gpgme_data_new (&attestation);
+
+
+ /* Process according to type of message. */
if (is_pgpmime)
{
LPATTACH att;
@@ -789,7 +909,7 @@
return gpg_error (GPG_ERR_GENERAL);
}
- err = pgpmime_decrypt (from, opt.passwd_ttl, &plaintext);
+ err = pgpmime_decrypt (from, opt.passwd_ttl, &plaintext, attestation);
from->Release ();
att->Release ();
@@ -797,9 +917,10 @@
pgpmime_succeeded = 1;
}
else if (mtype == OPENPGP_CLEARSIG)
- err = op_verify (getOrigText (), NULL, NULL);
+ err = op_verify (getOrigText (), NULL, NULL, attestation);
else if (*getOrigText())
- err = op_decrypt (getOrigText (), &plaintext, opt.passwd_ttl, NULL);
+ err = op_decrypt (getOrigText (), &plaintext, opt.passwd_ttl,
+ NULL, attestation);
else
err = gpg_error (GPG_ERR_NO_DATA);
if (err)
@@ -836,11 +957,19 @@
plaintext = NULL;
msgcache_put (body_plain, 0, message);
- /* XXX: find a way to handle text/html message in a better way! */
- /* I have disabled the kludge to see what happens to a html
- message. */
- if (!silent && /*is_html ||*/ update_display (hwnd, this, exchange_cb))
+ if (opt.save_decrypted_attach)
{
+ /* User wants us to replace the encrypted message with the
+ plaintext version. */
+ hr = message->SaveChanges (KEEP_OPEN_READWRITE|FORCE_SAVE);
+ if (FAILED (hr))
+ log_debug ("%s:%s: SaveChanges failed: hr=%#lx",
+ __FILE__, __func__, hr);
+ update_display (hwnd, this, exchange_cb);
+
+ }
+ else if (!silent && update_display (hwnd, this, exchange_cb))
+ {
const char s[] =
"The message text cannot be displayed.\n"
"You have to save the decrypted message to view it.\n"
@@ -912,6 +1041,8 @@
}
}
+ writeAttestation ();
+
release_attach_info (table);
log_debug ("%s:%s: leave (rc=%d)\n", __FILE__, __func__, err);
return err;
@@ -1793,7 +1924,7 @@
goto leave;
}
err = op_verify_detached_sig (stream, sig_data,
- table[pos_data].filename);
+ table[pos_data].filename, attestation);
if (err)
{
log_debug ("%s:%s: verify detached signature failed: %s",
@@ -1827,6 +1958,9 @@
HRESULT hr;
LPATTACH att;
int method, err;
+ LPATTACH newatt = NULL;
+ char *outname = NULL;
+
log_debug ("%s:%s: processing attachment %d", __FILE__, __func__, pos);
@@ -1885,14 +2019,13 @@
else if (method == ATTACH_BY_VALUE)
{
char *s;
- char *outname;
char *suggested_name;
LPSTREAM from, to;
suggested_name = get_attach_filename (att);
if (suggested_name)
log_debug ("%s:%s: attachment %d, filename `%s'",
- __FILE__, __func__, pos, suggested_name);
+ __FILE__, __func__, pos, suggested_name);
/* Strip of know extensions or use a default name. */
if (!suggested_name)
{
@@ -1907,58 +2040,138 @@
{
*s = 0;
}
- outname = get_save_filename (hwnd, suggested_name);
- xfree (suggested_name);
-
+ if (opt.save_decrypted_attach)
+ outname = suggested_name;
+ else
+ {
+ outname = get_save_filename (hwnd, suggested_name);
+ xfree (suggested_name);
+ }
+
hr = att->OpenProperty (PR_ATTACH_DATA_BIN, &IID_IStream,
0, 0, (LPUNKNOWN*) &from);
if (FAILED (hr))
{
log_error ("%s:%s: can't open data of attachment %d: hr=%#lx",
__FILE__, __func__, pos, hr);
- xfree (outname);
goto leave;
}
- hr = OpenStreamOnFile (MAPIAllocateBuffer, MAPIFreeBuffer,
- (STGM_CREATE | STGM_READWRITE),
- outname, NULL, &to);
- if (FAILED (hr))
+
+ if (opt.save_decrypted_attach) /* Decrypt and save in the MAPI. */
{
- log_error ("%s:%s: can't create stream for `%s': hr=%#lx\n",
- __FILE__, __func__, outname, hr);
+ ULONG newpos;
+ SPropValue prop;
+
+ hr = message->CreateAttach (NULL, 0, &newpos, &newatt);
+ if (hr != S_OK)
+ {
+ log_error ("%s:%s: can't create attachment: hr=%#lx\n",
+ __FILE__, __func__, hr);
+ goto leave;
+ }
+
+ prop.ulPropTag = PR_ATTACH_METHOD;
+ prop.Value.ul = ATTACH_BY_VALUE;
+ hr = HrSetOneProp (newatt, &prop);
+ if (hr != S_OK)
+ {
+ log_error ("%s:%s: can't set attach method: hr=%#lx\n",
+ __FILE__, __func__, hr);
+ goto leave;
+ }
+
+ prop.ulPropTag = PR_ATTACH_LONG_FILENAME_A;
+ prop.Value.lpszA = outname;
+ hr = HrSetOneProp (newatt, &prop);
+ if (hr != S_OK)
+ {
+ log_error ("%s:%s: can't set attach filename: hr=%#lx\n",
+ __FILE__, __func__, hr);
+ goto leave;
+ }
+ log_debug ("%s:%s: setting filename of attachment %d/%ld to `%s'",
+ __FILE__, __func__, pos, newpos, outname);
+
+
+ hr = newatt->OpenProperty (PR_ATTACH_DATA_BIN, &IID_IStream, 0,
+ MAPI_CREATE|MAPI_MODIFY, (LPUNKNOWN*)&to);
+ if (FAILED (hr))
+ {
+ log_error ("%s:%s: can't create output stream: hr=%#lx\n",
+ __FILE__, __func__, hr);
+ goto leave;
+ }
+
+ err = op_decrypt_stream (from, to, ttl, filename, attestation);
+ if (err)
+ {
+ log_debug ("%s:%s: decrypt stream failed: %s",
+ __FILE__, __func__, op_strerror (err));
+ to->Revert ();
+ to->Release ();
+ from->Release ();
+ MessageBox (hwnd, op_strerror (err),
+ "GPG Attachment Decryption", MB_ICONERROR|MB_OK);
+ goto leave;
+ }
+
+ to->Commit (0);
+ to->Release ();
from->Release ();
- xfree (outname);
- goto leave;
+
+ hr = newatt->SaveChanges (0);
+ if (hr != S_OK)
+ {
+ log_error ("%s:%s: SaveChanges failed: hr=%#lx\n",
+ __FILE__, __func__, hr);
+ goto leave;
+ }
+
+ /* Delete the orginal attachment. FIXME: Should we really do
+ that or better just mark it in the table and delete
+ later? */
+ att->Release ();
+ att = NULL;
+ if (message->DeleteAttach (pos, 0, NULL, 0) == S_OK)
+ log_error ("%s:%s: failed to delete attacghment %d: %s",
+ __FILE__, __func__, pos, op_strerror (err));
+
}
+ else /* Save attachment to a file. */
+ {
+ hr = OpenStreamOnFile (MAPIAllocateBuffer, MAPIFreeBuffer,
+ (STGM_CREATE | STGM_READWRITE),
+ outname, NULL, &to);
+ if (FAILED (hr))
+ {
+ log_error ("%s:%s: can't create stream for `%s': hr=%#lx\n",
+ __FILE__, __func__, outname, hr);
+ from->Release ();
+ goto leave;
+ }
- err = op_decrypt_stream (from, to, ttl, filename);
- if (err)
- {
- log_debug ("%s:%s: decrypt stream failed: %s",
- __FILE__, __func__, op_strerror (err));
- to->Revert ();
+ err = op_decrypt_stream (from, to, ttl, filename, attestation);
+ if (err)
+ {
+ log_debug ("%s:%s: decrypt stream failed: %s",
+ __FILE__, __func__, op_strerror (err));
+ to->Revert ();
+ to->Release ();
+ from->Release ();
+ MessageBox (hwnd, op_strerror (err),
+ "GPG Attachment Decryption", MB_ICONERROR|MB_OK);
+ /* FIXME: We might need to delete outname now. However a
+ sensible implementation of the stream object should have
+ done it through the Revert call. */
+ goto leave;
+ }
+
+ to->Commit (0);
to->Release ();
from->Release ();
- MessageBox (hwnd, op_strerror (err),
- "GPG Attachment Decryption", MB_ICONERROR|MB_OK);
- /* FIXME: We might need to delete outname now. However a
- sensible implementation of the stream object should have
- done it trhough the Revert call. */
- xfree (outname);
- goto leave;
}
-
- to->Commit (0);
- to->Release ();
- from->Release ();
-
- /* Hmmm: Why are we deleting the attachment now?????
- Disabled until clarified. FIXME */
- //if (message->DeleteAttach (pos, 0, NULL, 0) == S_OK)
- // show error;
-
- xfree (outname);
+
}
else
{
@@ -1967,8 +2180,11 @@
}
leave:
- /* Close this attachment. */
- att->Release ();
+ xfree (outname);
+ if (newatt)
+ newatt->Release ();
+ if (att)
+ att->Release ();
}
Modified: trunk/src/pgpmime.c
===================================================================
--- trunk/src/pgpmime.c 2005-09-09 05:29:48 UTC (rev 92)
+++ trunk/src/pgpmime.c 2005-09-13 17:21:29 UTC (rev 93)
@@ -273,9 +273,12 @@
/* Decrypt the PGP/MIME INSTREAM (i.e the second part of the
multipart/mixed) and allow saving of all attachments. On success a
- newly allocated body will be stored at BODY. */
+ newly allocated body will be stored at BODY. If ATTESTATION is not
+ NULL a text with the result of the signature verification will get
+ printed to it. */
int
-pgpmime_decrypt (LPSTREAM instream, int ttl, char **body)
+pgpmime_decrypt (LPSTREAM instream, int ttl, char **body,
+ gpgme_data_t attestation)
{
gpg_error_t err;
struct gpgme_data_cbs cbs;
@@ -302,7 +305,8 @@
if (err)
goto leave;
- err = op_decrypt_stream_to_gpgme (instream, plaintext, ttl, NULL);
+ err = op_decrypt_stream_to_gpgme (instream, plaintext, ttl,
+ NULL, NULL);
if (!err && (ctx->parser_error || ctx->line_too_long))
err = gpg_error (GPG_ERR_GENERAL);
Modified: trunk/src/pgpmime.h
===================================================================
--- trunk/src/pgpmime.h 2005-09-09 05:29:48 UTC (rev 92)
+++ trunk/src/pgpmime.h 2005-09-13 17:21:29 UTC (rev 93)
@@ -28,7 +28,8 @@
#endif
#endif
-int pgpmime_decrypt (LPSTREAM instream, int ttl, char **body);
+int pgpmime_decrypt (LPSTREAM instream, int ttl, char **body,
+ gpgme_data_t attestation);
Modified: trunk/src/util.h
===================================================================
--- trunk/src/util.h 2005-09-09 05:29:48 UTC (rev 92)
+++ trunk/src/util.h 2005-09-13 17:21:29 UTC (rev 93)
@@ -43,7 +43,11 @@
} while(0)
+/* i18n stuff (dummies for now). */
+#define _(a) (a)
+
+
/*-- common.c --*/
void* xmalloc (size_t n);
void* xcalloc (size_t m, size_t n);
More information about the Gnupg-commits
mailing list