[svn] GpgOL - r177 - in trunk: po src
svn author wk
cvs at cvs.gnupg.org
Thu Sep 13 13:53:44 CEST 2007
Author: wk
Date: 2007-09-13 13:53:15 +0200 (Thu, 13 Sep 2007)
New Revision: 177
Modified:
trunk/po/de.po
trunk/po/sv.po
trunk/src/ChangeLog
trunk/src/common.c
trunk/src/engine-gpgme.c
trunk/src/engine.c
trunk/src/engine.h
trunk/src/mimemaker.c
trunk/src/xmalloc.h
Log:
Creating PGP/MIME signed mails works now - kind of:
becuase the passphrase dialog runs in a second thread, the windows are not
properly cleaned up lated.
Modified: trunk/po/de.po
===================================================================
--- trunk/po/de.po 2007-09-12 16:40:23 UTC (rev 176)
+++ trunk/po/de.po 2007-09-13 11:53:15 UTC (rev 177)
@@ -7,7 +7,7 @@
msgstr ""
"Project-Id-Version: GPGol 0.9.4\n"
"Report-Msgid-Bugs-To: bug-gpgol at g10code.com\n"
-"POT-Creation-Date: 2007-09-06 21:27+0200\n"
+"POT-Creation-Date: 2007-09-11 20:30+0200\n"
"PO-Revision-Date: 2007-04-13 12:55+0200\n"
"Last-Translator: Werner Koch <wk at gnupg.org>\n"
"Language-Team: de\n"
@@ -23,62 +23,62 @@
msgid "Select GPG Key Manager"
msgstr "Das Schlüsselverwaltungsprogramm festlegen"
-#: src/engine-gpgme.c:1004
+#: src/engine-gpgme.c:1099
msgid "Fingerprint: "
msgstr "Fingerabdruck: "
-#: src/engine-gpgme.c:1061
+#: src/engine-gpgme.c:1156
msgid "This signature is valid\n"
msgstr "Diese Unterschrift ist korrekt\n"
-#: src/engine-gpgme.c:1063
+#: src/engine-gpgme.c:1158
msgid "signature state is \"green\"\n"
msgstr "Status der Unterschrift ist \"grün\"\n"
-#: src/engine-gpgme.c:1065
+#: src/engine-gpgme.c:1160
msgid "signature state is \"red\"\n"
msgstr "Status der Unterschrift ist \"rot\"\n"
-#: src/engine-gpgme.c:1069
+#: src/engine-gpgme.c:1164
msgid "Warning: One of the keys has been revoked\n"
msgstr "Warnung: Einer der Schlüssel wurde widerrufen\n"
-#: src/engine-gpgme.c:1079
+#: src/engine-gpgme.c:1174
msgid "Warning: The key used to create the signature expired at: "
msgstr ""
"Warnung: Der Schlüssel mit der diese Unterschrift erzeugt wurde verfiel am: "
-#: src/engine-gpgme.c:1085
+#: src/engine-gpgme.c:1180
msgid "Warning: At least one certification key has expired\n"
msgstr ""
"Warnung: Mindestens einer der Zertifizierungsschlüssel ist abgelaufen\n"
-#: src/engine-gpgme.c:1091
+#: src/engine-gpgme.c:1186
msgid "Warning: The signature expired at: "
msgstr "Die Unterschrift verfiel am: "
-#: src/engine-gpgme.c:1097
+#: src/engine-gpgme.c:1192
msgid "Can't verify due to a missing key or certificate\n"
msgstr ""
"Aufrund eines fehlenden Schlüssels ist eine Überprüfung nicht möglich\n"
-#: src/engine-gpgme.c:1101
+#: src/engine-gpgme.c:1196
msgid "The CRL is not available\n"
msgstr "Die CRL ist nicht verfügbar\n"
-#: src/engine-gpgme.c:1107
+#: src/engine-gpgme.c:1202
msgid "Available CRL is too old\n"
msgstr "Die vorhandene CRL ist zu alt\n"
-#: src/engine-gpgme.c:1112
+#: src/engine-gpgme.c:1207
msgid "A policy requirement was not met\n"
msgstr "Eine Richtlinie wurde nicht erfüllt\n"
-#: src/engine-gpgme.c:1118
+#: src/engine-gpgme.c:1213
msgid "A system error occured"
msgstr "Ein Systemfehler ist aufgetreten"
-#: src/engine-gpgme.c:1155
+#: src/engine-gpgme.c:1250
msgid ""
"WARNING: We have NO indication whether the key belongs to the person named "
"as shown above\n"
@@ -86,12 +86,12 @@
"WARNUNG: Es gibt keinen Hinweis darauf, ob der Schlüssel wirklich der Person "
"gehört, die oben angezeigt ist\n"
-#: src/engine-gpgme.c:1162
+#: src/engine-gpgme.c:1257
msgid "WARNING: The key does NOT BELONG to the person named as shown above\n"
msgstr ""
"WARNUNG: Der Schlüssel gehört NICHT der Person die oben angezeigt ist\n"
-#: src/engine-gpgme.c:1166
+#: src/engine-gpgme.c:1261
msgid ""
"WARNING: It is NOT certain that the key belongs to the person named as shown "
"above\n"
@@ -99,43 +99,43 @@
"WARNING: Es ist nicht sicher, daß der Schlüssel der Person gehört, die oben "
"angezeigt ist\n"
-#: src/engine-gpgme.c:1199
+#: src/engine-gpgme.c:1294
msgid "Verification started at: "
msgstr "Überprüfung begann am: "
-#: src/engine-gpgme.c:1204
+#: src/engine-gpgme.c:1299
msgid "Verification result for: "
msgstr "Prüfungsresultat für: "
-#: src/engine-gpgme.c:1205
+#: src/engine-gpgme.c:1300
msgid "[unnamed part]"
msgstr "[Unbenannter Teil]"
-#: src/engine-gpgme.c:1223 src/engine-gpgme.c:1253
+#: src/engine-gpgme.c:1318 src/engine-gpgme.c:1348
msgid "Good signature from: "
msgstr "Korrekte Unterschrift von: "
-#: src/engine-gpgme.c:1230
+#: src/engine-gpgme.c:1325
msgid " aka: "
msgstr " alias: "
-#: src/engine-gpgme.c:1234 src/engine-gpgme.c:1256
+#: src/engine-gpgme.c:1329 src/engine-gpgme.c:1351
msgid " created: "
msgstr " erzeugt: "
-#: src/engine-gpgme.c:1243
+#: src/engine-gpgme.c:1338
msgid "*BAD* signature claimed to be from: "
msgstr "*FALSCHE* Unterschrift, vorgeblich von: "
-#: src/engine-gpgme.c:1266
+#: src/engine-gpgme.c:1361
msgid "Error checking signature"
msgstr "Fehler beim Prüfen der Unterschrift"
-#: src/engine-gpgme.c:1282
+#: src/engine-gpgme.c:1377
msgid "*** Begin Notation (signature by: "
msgstr "*** Anfang Notation (Unterschrift von: "
-#: src/engine-gpgme.c:1302
+#: src/engine-gpgme.c:1397
msgid "*** End Notation ***\n"
msgstr "*** Ende Notation ***\n"
Modified: trunk/po/sv.po
===================================================================
--- trunk/po/sv.po 2007-09-12 16:40:23 UTC (rev 176)
+++ trunk/po/sv.po 2007-09-13 11:53:15 UTC (rev 177)
@@ -7,7 +7,7 @@
msgstr ""
"Project-Id-Version: GPGol\n"
"Report-Msgid-Bugs-To: bug-gpgol at g10code.com\n"
-"POT-Creation-Date: 2007-09-06 21:27+0200\n"
+"POT-Creation-Date: 2007-09-11 20:30+0200\n"
"PO-Revision-Date: 2006-12-12 23:52+0100\n"
"Last-Translator: Daniel Nylander <po at danielnylander.se>\n"
"Language-Team: Swedish <tp-sv at listor.tp-sv.se>\n"
@@ -23,59 +23,59 @@
msgid "Select GPG Key Manager"
msgstr "Välj GPG-nyckelhanterare"
-#: src/engine-gpgme.c:1004
+#: src/engine-gpgme.c:1099
msgid "Fingerprint: "
msgstr "Fingeravtryck: "
-#: src/engine-gpgme.c:1061
+#: src/engine-gpgme.c:1156
msgid "This signature is valid\n"
msgstr "Den här signaturen är giltig\n"
-#: src/engine-gpgme.c:1063
+#: src/engine-gpgme.c:1158
msgid "signature state is \"green\"\n"
msgstr "signaturens tillstånd är \"grön\"\n"
-#: src/engine-gpgme.c:1065
+#: src/engine-gpgme.c:1160
msgid "signature state is \"red\"\n"
msgstr "signaturens tillstånd är \"röd\"\n"
-#: src/engine-gpgme.c:1069
+#: src/engine-gpgme.c:1164
msgid "Warning: One of the keys has been revoked\n"
msgstr "Varning: En av nycklarna har spärrats\n"
-#: src/engine-gpgme.c:1079
+#: src/engine-gpgme.c:1174
msgid "Warning: The key used to create the signature expired at: "
msgstr "Varning: Nyckeln som användes för att skapa signaturen gick ut den: "
-#: src/engine-gpgme.c:1085
+#: src/engine-gpgme.c:1180
msgid "Warning: At least one certification key has expired\n"
msgstr "Varning: Åtminstone en certifieringsnyckel har gått ut\n"
-#: src/engine-gpgme.c:1091
+#: src/engine-gpgme.c:1186
msgid "Warning: The signature expired at: "
msgstr "Varning: Signaturen gick ut den: "
-#: src/engine-gpgme.c:1097
+#: src/engine-gpgme.c:1192
msgid "Can't verify due to a missing key or certificate\n"
msgstr "Kan inte validera på grund av en saknad nyckel eller certifikat\n"
-#: src/engine-gpgme.c:1101
+#: src/engine-gpgme.c:1196
msgid "The CRL is not available\n"
msgstr "Spärrlistan är inte tillgänglig\n"
-#: src/engine-gpgme.c:1107
+#: src/engine-gpgme.c:1202
msgid "Available CRL is too old\n"
msgstr "Tillgänglig spärrlista är för gammal\n"
-#: src/engine-gpgme.c:1112
+#: src/engine-gpgme.c:1207
msgid "A policy requirement was not met\n"
msgstr "Ett policykrav matchades inte\n"
-#: src/engine-gpgme.c:1118
+#: src/engine-gpgme.c:1213
msgid "A system error occured"
msgstr "Ett systemfel inträffade"
-#: src/engine-gpgme.c:1155
+#: src/engine-gpgme.c:1250
msgid ""
"WARNING: We have NO indication whether the key belongs to the person named "
"as shown above\n"
@@ -83,11 +83,11 @@
"VARNING: Vi har INGA indikationer på huruvida nyckeln tillhör personen vars "
"namn visas ovanför\n"
-#: src/engine-gpgme.c:1162
+#: src/engine-gpgme.c:1257
msgid "WARNING: The key does NOT BELONG to the person named as shown above\n"
msgstr "VARNING: Nyckeln TILLHÖR INTE personen vars namn visas ovanför\n"
-#: src/engine-gpgme.c:1166
+#: src/engine-gpgme.c:1261
msgid ""
"WARNING: It is NOT certain that the key belongs to the person named as shown "
"above\n"
@@ -95,43 +95,43 @@
"VARNING: Det är INTE säkert att nyckeln tillhör den person vars namn visas "
"ovanför\n"
-#: src/engine-gpgme.c:1199
+#: src/engine-gpgme.c:1294
msgid "Verification started at: "
msgstr "Validering startad: "
-#: src/engine-gpgme.c:1204
+#: src/engine-gpgme.c:1299
msgid "Verification result for: "
msgstr "Valideringsresultat för: "
-#: src/engine-gpgme.c:1205
+#: src/engine-gpgme.c:1300
msgid "[unnamed part]"
msgstr "[ej namngiven del]"
-#: src/engine-gpgme.c:1223 src/engine-gpgme.c:1253
+#: src/engine-gpgme.c:1318 src/engine-gpgme.c:1348
msgid "Good signature from: "
msgstr "Korrekt signatur från: "
-#: src/engine-gpgme.c:1230
+#: src/engine-gpgme.c:1325
msgid " aka: "
msgstr "även känd som:"
-#: src/engine-gpgme.c:1234 src/engine-gpgme.c:1256
+#: src/engine-gpgme.c:1329 src/engine-gpgme.c:1351
msgid " created: "
msgstr " skapad: "
-#: src/engine-gpgme.c:1243
+#: src/engine-gpgme.c:1338
msgid "*BAD* signature claimed to be from: "
msgstr "*FELAKTIG* signatur hävdades komma från: "
-#: src/engine-gpgme.c:1266
+#: src/engine-gpgme.c:1361
msgid "Error checking signature"
msgstr "Fel vid kontroll av signatur"
-#: src/engine-gpgme.c:1282
+#: src/engine-gpgme.c:1377
msgid "*** Begin Notation (signature by: "
msgstr "*** Notation start (signatur av: "
-#: src/engine-gpgme.c:1302
+#: src/engine-gpgme.c:1397
msgid "*** End Notation ***\n"
msgstr "*** Notation slut ***\n"
Modified: trunk/src/ChangeLog
===================================================================
--- trunk/src/ChangeLog 2007-09-12 16:40:23 UTC (rev 176)
+++ trunk/src/ChangeLog 2007-09-13 11:53:15 UTC (rev 177)
@@ -1,3 +1,7 @@
+2007-09-13 Werner Koch <wk at g10code.com>
+
+ * common.c (xrealloc): New.
+
2007-09-11 Werner Koch <wk at g10code.com>
* engine-gpgme.c (op_encrypt_data): New.
Modified: trunk/src/common.c
===================================================================
--- trunk/src/common.c 2007-09-12 16:40:23 UTC (rev 176)
+++ trunk/src/common.c 2007-09-13 11:53:15 UTC (rev 177)
@@ -167,6 +167,15 @@
return p;
}
+void *
+xrealloc (void *a, size_t n)
+{
+ void *p = realloc (a, n);
+ if (!p)
+ out_of_core ();
+ return p;
+}
+
char*
xstrdup (const char *s)
{
Modified: trunk/src/engine-gpgme.c
===================================================================
--- trunk/src/engine-gpgme.c 2007-09-12 16:40:23 UTC (rev 176)
+++ trunk/src/engine-gpgme.c 2007-09-13 11:53:15 UTC (rev 177)
@@ -50,6 +50,8 @@
static DWORD WINAPI waiter_thread (void *dummy);
+static void update_passphrase_cache (int err,
+ struct passphrase_cb_s *pass_cb_value);
static void add_verify_attestation (gpgme_data_t at,
gpgme_ctx_t ctx,
gpgme_verify_result_t res,
@@ -70,7 +72,7 @@
/* Enable or disable GPGME debug mode. */
void
-op_set_debug_mode (int val, const char *file)
+op_gpgme_set_debug_mode (int val, const char *file)
{
const char *s= "GPGME_DEBUG";
@@ -88,7 +90,7 @@
/* Cleanup static resources. */
void
-op_deinit (void)
+op_gpgme_deinit (void)
{
cleanup ();
}
@@ -96,7 +98,7 @@
/* Initialize the operation system. */
int
-op_init (void)
+op_gpgme_init (void)
{
gpgme_error_t err;
@@ -148,6 +150,7 @@
gpgme_ctx_t ctx;
gpg_error_t err;
void *filter;
+ void *pass_cb;
(void)dummy;
@@ -164,6 +167,10 @@
{
gpgme_get_progress_cb (ctx, NULL, &filter);
engine_gpgme_finished (filter, err);
+ gpgme_get_passphrase_cb (ctx, NULL, &pass_cb);
+ if (pass_cb)
+ update_passphrase_cache (err, (struct passphrase_cb_s *)pass_cb);
+ xfree (pass_cb);
gpgme_release (ctx);
}
else if (err)
@@ -294,7 +301,7 @@
*outbuf = NULL;
- op_init ();
+ op_gpgme_init ();
err = gpgme_new (&ctx);
if (err)
goto leave;
@@ -549,9 +556,10 @@
just for this notification. We abuse the gpgme_set_progress_cb
value for storing the pointer with the gpgme context. */
int
-op_encrypt_data (gpgme_data_t indata, gpgme_data_t outdata,
- void *notify_data, /* FIXME: Add hwnd */
- char **recipients, gpgme_key_t sign_key, int ttl)
+op_gpgme_encrypt_data (protocol_t protocol,
+ gpgme_data_t indata, gpgme_data_t outdata,
+ void *notify_data, /* FIXME: Add hwnd */
+ char **recipients, gpgme_key_t sign_key, int ttl)
{
gpg_error_t err;
struct passphrase_cb_s cb;
@@ -569,6 +577,12 @@
err = gpgme_new (&ctx);
if (err)
goto leave;
+ if (protocol == PROTOCOL_SMIME)
+ {
+ err = gpgme_set_protocol (ctx, GPGME_PROTOCOL_CMS);
+ if (err)
+ goto leave;
+ }
gpgme_set_progress_cb (ctx, NULL, notify_data);
gpgme_set_armor (ctx, 1);
@@ -599,6 +613,61 @@
}
+/* Created a detached signature for INDATA and write it to OUTDATA.
+ On termination of the signing command engine_gpgme_finished() is
+ called with NOTIFY_DATA as the first argument. */
+int
+op_gpgme_sign_data (protocol_t protocol,
+ gpgme_data_t indata, gpgme_data_t outdata,
+ void *notify_data /* FIXME: Add hwnd */)
+{
+ gpg_error_t err;
+ struct passphrase_cb_s *cb;
+ gpgme_ctx_t ctx = NULL;
+ gpgme_key_t sign_key = NULL;
+
+ if (signer_dialog_box (&sign_key, NULL, 0) == -1)
+ {
+ log_debug ("%s:%s: leave (dialog failed)\n", SRCNAME, __func__);
+ return gpg_error (GPG_ERR_CANCELED);
+ }
+
+ cb = xcalloc (1, sizeof *cb);
+ cb->ttl = 0 /*FIXME: ttl*/;
+
+ err = gpgme_new (&ctx);
+ if (err)
+ goto leave;
+ if (protocol == PROTOCOL_SMIME)
+ {
+ err = gpgme_set_protocol (ctx, GPGME_PROTOCOL_CMS);
+ if (err)
+ goto leave;
+ }
+
+ gpgme_set_progress_cb (ctx, NULL, notify_data);
+
+ gpgme_set_armor (ctx, 1);
+ gpgme_set_passphrase_cb (ctx, passphrase_callback_box, cb);
+ cb->ctx = ctx;
+ err = gpgme_signers_add (ctx, sign_key);
+ if (!err)
+ err = gpgme_op_sign_start (ctx, indata, outdata, GPGME_SIG_MODE_DETACH);
+
+ leave:
+ if (ctx && err)
+ {
+ xfree (cb);
+ gpgme_release (ctx);
+ }
+ gpgme_key_unref (sign_key);
+ return err;
+}
+
+
+
+
+
/* Sign and encrypt the data in INBUF into a newly allocated buffer at
OUTBUF. Caller needs to free the returned buffer using gpgme_free. */
@@ -617,7 +686,7 @@
cb.decrypt_cmd = 0;
*outbuf = NULL;
- op_init ();
+ op_gpgme_init ();
err = gpgme_new (&ctx);
if (err)
@@ -740,7 +809,7 @@
gpgme_error_t err;
*outbuf = NULL;
- op_init ();
+ op_gpgme_init ();
memset (&cb, 0, sizeof cb);
cb.ttl = ttl;
@@ -1028,7 +1097,7 @@
if (outbuf)
*outbuf = NULL;
- op_init ();
+ op_gpgme_init ();
err = gpgme_new (&ctx);
if (err)
@@ -1092,7 +1161,7 @@
cbs.read = stream_read_cb;
cbs.write = stream_write_cb;
- op_init ();
+ op_gpgme_init ();
err = gpgme_new (&ctx);
if (err)
@@ -1142,7 +1211,7 @@
gpgme_error_t err;
gpgme_verify_result_t res = NULL;
- op_init ();
+ op_gpgme_init ();
err = gpgme_new (&ctx);
if (err)
@@ -1191,7 +1260,7 @@
gpgme_error_t err;
gpgme_verify_result_t res = NULL;
- op_init ();
+ op_gpgme_init ();
err = gpgme_new (&ctx);
if (err)
Modified: trunk/src/engine.c
===================================================================
--- trunk/src/engine.c 2007-09-12 16:40:23 UTC (rev 176)
+++ trunk/src/engine.c 2007-09-13 11:53:15 UTC (rev 177)
@@ -267,7 +267,7 @@
int
engine_init (void)
{
- op_init ();
+ op_gpgme_init ();
return 0;
}
@@ -276,7 +276,7 @@
void
engine_deinit (void)
{
- op_deinit ();
+ op_gpgme_deinit ();
}
@@ -509,58 +509,41 @@
/* Start an encryption operation to all RECIPEINTS using PROTOCOL
RECIPIENTS is a NULL terminated array of rfc2822 addresses. FILTER
- is an object create by engine_create_filter. The caller needs to
+ is an object created by engine_create_filter. The caller needs to
call engine_wait to finish the operation. A filter object may not
be reused after having been used through this function. However,
the lifetime of the filter object lasts until the final engine_wait
- or engine_cabcel. */
+ or engine_cancel. */
int
engine_encrypt_start (engine_filter_t filter,
protocol_t protocol, char **recipients)
{
gpg_error_t err;
- err = op_encrypt_data (filter->indata, filter->outdata,
- filter, recipients, NULL, 0);
+ err = op_gpgme_encrypt_data (protocol, filter->indata, filter->outdata,
+ filter, recipients, NULL, 0);
return err;
}
-
-
-/* Release a KEY. Do nothing if KEY is NULL. */
-void
-engine_release_key (engine_keyinfo_t key)
+/* Start an detached signing operation.
+ FILTER
+ is an object created by engine_create_filter. The caller needs to
+ call engine_wait to finish the operation. A filter object may not
+ be reused after having been used through this function. However,
+ the lifetime of the filter object lasts until the final engine_wait
+ or engine_cancel. */
+int
+engine_sign_start (engine_filter_t filter, protocol_t protocol)
{
- if (!key)
- return;
- gpgme_key_release (key->gpgme.key);
- key->gpgme.key = NULL;
+ gpg_error_t err;
+
+ err = op_gpgme_sign_data (protocol, filter->indata, filter->outdata,
+ filter);
+ return err;
}
-/* Return a signing key and store it at the R_KEY. the caller sahll
- set ENCRYPTING to true if the message will also be encrypted. On
- error true is returned and NULL stored at R_KEY. Not ethat
- depending on the actual engine use the retruned key might be NULL -
- thus this shall not be used as an error indication. */
-int
-engine_get_signer_key (engine_keyinfo_t *r_key, int encrypting)
-{
- engine_keyinfo_t key;
- gpgme_key_t sign_key = NULL;
- *r_key = NULL;
- if (signer_dialog_box (&sign_key, NULL, encrypting) == -1)
- {
- log_debug ("%s:%s: failed to get key from dialog\n", SRCNAME, __func__);
- return gpg_error (GPG_ERR_CANCELED);
- }
- key = xcalloc (1, sizeof **r_key);
- key->gpgme.key = sign_key;
- *r_key = key;
- return 0;
-}
-
Modified: trunk/src/engine.h
===================================================================
--- trunk/src/engine.h 2007-09-12 16:40:23 UTC (rev 176)
+++ trunk/src/engine.h 2007-09-13 11:53:15 UTC (rev 177)
@@ -66,12 +66,10 @@
int engine_encrypt_start (engine_filter_t filter,
protocol_t protocol, char **recipients);
+int engine_sign_start (engine_filter_t filter, protocol_t protocol);
-void engine_release_key (engine_keyinfo_t key);
-int engine_get_signer_key (engine_keyinfo_t *r_key, int encrypting);
-
#ifdef __cplusplus
}
#endif
Modified: trunk/src/mimemaker.c
===================================================================
--- trunk/src/mimemaker.c 2007-09-12 16:40:23 UTC (rev 176)
+++ trunk/src/mimemaker.c 2007-09-13 11:53:15 UTC (rev 177)
@@ -62,10 +62,20 @@
struct sink_s
{
void *cb_data;
+ sink_t extrasink;
int (*writefnc)(sink_t sink, const void *data, size_t datalen);
};
+/* Object used to collect data in a memory buffer. */
+struct databuf_s
+{
+ size_t len; /* Used length. */
+ size_t size; /* Allocated length of BUF. */
+ char *buf; /* Malloced buffer. */
+};
+
+
/*** local prototypes ***/
static int write_multistring (sink_t sink, const char *text1,
...) GPGOL_GCC_A_SENTINEL(0);
@@ -419,6 +429,14 @@
outbuf[outidx++] = tohex ((*p>>4)&15);
outbuf[outidx++] = tohex (*p&15);
}
+ else if (!outidx && datalen >= 5 && !memcmp (p, "From ", 5))
+ {
+ /* Protect the 'F' so that MTAs won't prefix the "From "
+ with an '>' */
+ outbuf[outidx++] = '=';
+ outbuf[outidx++] = tohex ((*p>>4)&15);
+ outbuf[outidx++] = tohex (*p&15);
+ }
else if (*p >= '!' && *p <= '~' && *p != '=')
{
do_softlf (1);
@@ -713,6 +731,12 @@
We better protect it by forcing QP encoding. */
need_qp = 1;
}
+ else if (len == 1 && datalen >= 5 && !memcmp (p, "From ", 5))
+ {
+ /* The usual From hack is required so that MTAs do not
+ prefix it with an '>'. */
+ need_qp = 1;
+ }
}
if (len > maxlen)
maxlen = len;
@@ -1012,7 +1036,7 @@
proparray.aulPropTag[0] = PR_BODY_HTML;
IMessage_DeleteProps (message, &proparray, NULL);
}
-
+
/* Save the Changes. */
hr = IMessage_SaveChanges (message, KEEP_OPEN_READWRITE|FORCE_SAVE);
if (hr)
@@ -1026,6 +1050,64 @@
}
+
+/* Sink write method used by mime_sign. We write the data to the
+ filter and also to the EXTRASINK but we don't pass a flush request
+ to EXTRASINK. */
+static int
+sink_hashing_write (sink_t hashsink, const void *data, size_t datalen)
+{
+ int rc;
+ engine_filter_t filter = hashsink->cb_data;
+
+ if (!filter || !hashsink->extrasink)
+ {
+ log_error ("%s:%s: sink not setup for writing", SRCNAME, __func__);
+ return -1;
+ }
+
+ rc = engine_filter (filter, data, datalen);
+ if (!rc && data && datalen)
+ write_buffer (hashsink->extrasink, data, datalen);
+ return rc;
+}
+
+/* This function is called by the filter to collect the output which
+ is a detached signature. */
+static int
+collect_signature (void *opaque, const void *data, size_t datalen)
+{
+ struct databuf_s *db = opaque;
+
+ if (db->len + datalen >= db->size)
+ {
+ db->size += datalen + 1024;
+ db->buf = xrealloc (db->buf, db->size);
+ }
+ memcpy (db->buf + db->len, data, datalen);
+ db->len += datalen;
+
+ return 0;
+}
+
+
+/* Helper to create the signing header. This includes enough space
+ for later fixup of the micalg parameter. */
+ static void
+create_top_signing_header (char *buffer, size_t buflen, protocol_t protocol,
+ const char *boundary, const char *micalg)
+{
+ snprintf (buffer, buflen,
+ "MIME-Version: 1.0\r\n"
+ "Content-Type: multipart/signed;\r\n"
+ "\tprotocol=\"application/%s\";\r\n"
+ "\tmicalg=%-15.15s;\r\n"
+ "\tboundary=\"%s\"\r\n"
+ "\r\n",
+ (protocol==PROTOCOL_OPENPGP? "pgp-signature":"pkcs7-signature"),
+ micalg, boundary);
+}
+
/* Sign the MESSAGE using PROTOCOL. If PROTOCOL is PROTOCOL_UNKNOWN
the engine decides what protocol to use. On return MESSAGE is
modified so that sending it will result in a properly MOSS (that is
@@ -1040,13 +1122,20 @@
LPATTACH attach;
struct sink_s sinkmem;
sink_t sink = &sinkmem;
+ struct sink_s hashsinkmem;
+ sink_t hashsink = &hashsinkmem;
char boundary[BOUNDARYSIZE+1];
char inner_boundary[BOUNDARYSIZE+1];
mapi_attach_item_t *att_table = NULL;
char *body = NULL;
int n_att_usable;
+ char top_header[BOUNDARYSIZE+200];
+ engine_filter_t filter;
+ struct databuf_s sigbuffer;
memset (sink, 0, sizeof *sink);
+ memset (hashsink, 0, sizeof *hashsink);
+ memset (&sigbuffer, 0, sizeof sigbuffer);
protocol = check_protocol (protocol);
if (protocol == PROTOCOL_UNKNOWN)
@@ -1056,6 +1145,12 @@
if (!attach)
return -1;
+ /* Prepare the signing. */
+ if (engine_create_filter (&filter, collect_signature, &sigbuffer))
+ goto failure;
+ if (engine_sign_start (filter, protocol))
+ goto failure;
+
/* Get the attachment info and the body. */
body = mapi_get_body (message, NULL);
if (body && !*body)
@@ -1073,60 +1168,66 @@
/* Write the top header. */
generate_boundary (boundary);
- rc = write_multistring (sink,
- "MIME-Version: 1.0\r\n"
- "Content-Type: multipart/signed;\r\n"
- "\tprotocol=\"application/",
- (protocol == PROTOCOL_OPENPGP
- ? "pgp-signature"
- : "pkcs7-signature"),
- "\";\r\n\tboundary=\"",
- boundary,
- "\"\r\n",
- NULL);
- if (rc)
+ create_top_signing_header (top_header, sizeof top_header,
+ protocol, boundary, "xxx");
+ if ((rc = write_string (sink, top_header)))
goto failure;
-
+
+ /* Create the inner boundary if we have a body and at least one
+ attachment or more than one attachment. */
if ((body && n_att_usable) || n_att_usable > 1)
- {
- /* A body and at least one attachment or more than one attachment */
- generate_boundary (inner_boundary);
- if ((rc = write_boundary (sink, boundary, 0)))
- goto failure;
- if ((rc=write_multistring (sink,
- "Content-Type: multipart/mixed;\r\n",
- "\tboundary=\"", inner_boundary, "\"\r\n",
- NULL)))
- goto failure;
- }
- else /* Only one part. */
+ generate_boundary (inner_boundary);
+ else
*inner_boundary = 0;
+ /* Write the boundary so that it is not included in the hashing. */
+ if ((rc = write_boundary (sink, boundary, 0)))
+ goto failure;
+ /* Create a new sink for hashing and wire/hash our content. */
+ hashsink->cb_data = filter;
+ hashsink->extrasink = sink;
+ hashsink->writefnc = sink_hashing_write;
+
+ /* Note that OL2003 will add an extra line after the multipart
+ header, thus we do the same to avoid running all through an
+ IConverterSession first. */
+ if (*inner_boundary
+ && (rc=write_multistring (hashsink,
+ "Content-Type: multipart/mixed;\r\n",
+ "\tboundary=\"", inner_boundary, "\"\r\n",
+ "\r\n", /* <-- extra line */
+ NULL)))
+ goto failure;
+
+
if (body)
- rc = write_part (sink, body, strlen (body),
- *inner_boundary? inner_boundary : boundary, NULL, 1);
+ rc = write_part (hashsink, body, strlen (body),
+ *inner_boundary? inner_boundary : NULL, NULL, 1);
if (!rc && n_att_usable)
- rc = write_attachments (sink, message, att_table,
- *inner_boundary? inner_boundary : boundary);
+ rc = write_attachments (hashsink, message, att_table,
+ *inner_boundary? inner_boundary : NULL);
if (rc)
goto failure;
-
xfree (body);
body = NULL;
/* Finish the possible multipart/mixed. */
- if (*inner_boundary)
- {
- rc = write_boundary (sink, inner_boundary, 1);
- if (rc)
- goto failure;
- }
+ if (*inner_boundary && (rc = write_boundary (hashsink, inner_boundary, 1)))
+ goto failure;
+ /* Here we are ready with the hashing. Flush the filter and wait
+ for the signing process to finish. */
+ if ((rc = write_buffer (hashsink, NULL, 0)))
+ goto failure;
+ if ((rc = engine_wait (filter)))
+ goto failure;
+ filter = NULL; /* Not valid anymore. */
+ hashsink->cb_data = NULL; /* Not needed anymore. */
+
- /* Write signature attachment. We don't write it directly but use a
- placeholder. */
+ /* Write signature attachment. */
if ((rc = write_boundary (sink, boundary, 0)))
goto failure;
@@ -1137,43 +1238,88 @@
goto failure;
/* If we would add "Content-Transfer-Encoding: 7bit\r\n" to this
- attachment, Outlooks does not processed with sending and even
- does not return any error. A wild guess is that while OL adds
- this header itself, it detects that it already exists and somehow
- gets into a problem. It is not a problem with the other parts,
+ attachment, Outlooks does not proceed with sending and even does
+ not return any error. A wild guess is that while OL adds this
+ header itself, it detects that it already exists and somehow gets
+ into a problem. It is not a problem with the other parts,
though. Hmmm, triggered by the top levels CT protocol parameter?
- Any way, it is not required that we add it as we won't hash
+ Anyway, it is not required that we add it as we won't hash
it. */
if ((rc = write_string (sink, "\r\n")))
goto failure;
- /* Let the placeholder start with the prefix of a boundary so that
- it won't accidently occur in the actual content. */
- if ((rc = write_string (sink, "--=-=@SIGNATURE@\r\n\r\n")))
+ /* Write the signature. We add an extra CR,LF which should not harm
+ and a terminating 0. */
+ collect_signature (&sigbuffer, "\r\n", 3);
+ if ((rc = write_string (sink, sigbuffer.buf)))
goto failure;
+
/* Write the final boundary and finish the attachment. */
if ((rc = write_boundary (sink, boundary, 1)))
goto failure;
+ /* Fixup the micalg parameter. */
+ {
+ HRESULT hr;
+ LARGE_INTEGER off;
+ LPSTREAM stream = sink->cb_data;
+
+ off.QuadPart = 0;
+ hr = IStream_Seek (stream, off, STREAM_SEEK_SET, NULL);
+ if (hr)
+ {
+ log_error ("%s:%s: seeking back to the begin failed: hr=%#lx",
+ SRCNAME, __func__, hr);
+ goto failure;
+ }
+
+ create_top_signing_header (top_header, sizeof top_header,
+ protocol, boundary, "pgp-sha1");
+
+ hr = IStream_Write (stream, top_header, strlen (top_header), NULL);
+ if (hr)
+ {
+ log_error ("%s:%s: writing fixed micalg failed: hr=%#lx",
+ SRCNAME, __func__, hr);
+ goto failure;
+ }
+
+ /* Better seek again to the end. */
+ off.QuadPart = 0;
+ hr = IStream_Seek (stream, off, STREAM_SEEK_END, NULL);
+ if (hr)
+ {
+ log_error ("%s:%s: seeking back to the end failed: hr=%#lx",
+ SRCNAME, __func__, hr);
+ goto failure;
+ }
+ }
+
+
if (close_mapi_attachment (&attach, sink))
goto failure;
if (finalize_message (message, att_table))
goto failure;
+ mapi_to_mime (message, "c:\\tmp\\x.msg");
+
result = 0; /* Everything is fine, fall through the cleanup now. */
failure:
+ engine_cancel (filter);
cancel_mapi_attachment (&attach, sink);
xfree (body);
mapi_release_attach_table (att_table);
+ xfree (sigbuffer.buf);
return result;
}
+
/* Sink write method used by mime_encrypt. */
static int
sink_encryption_write (sink_t encsink, const void *data, size_t datalen)
Modified: trunk/src/xmalloc.h
===================================================================
--- trunk/src/xmalloc.h 2007-09-12 16:40:23 UTC (rev 176)
+++ trunk/src/xmalloc.h 2007-09-13 11:53:15 UTC (rev 177)
@@ -32,6 +32,7 @@
/*-- common.c --*/
void* xmalloc (size_t n);
void* xcalloc (size_t m, size_t n);
+void *xrealloc (void *a, size_t n);
char* xstrdup (const char *s);
void xfree (void *p);
void out_of_core (void);
More information about the Gnupg-commits
mailing list