できた。ちょっとパッチ。テストするのが面倒だからなぁ、投稿するかどうかは不明。
Index: libsylph/procheader.c
===================================================================
--- libsylph/procheader.c (revision 2362)
+++ libsylph/procheader.c (working copy)
@@ -690,7 +690,7 @@
MSG_SET_TMP_FLAGS(msginfo->flags, MSG_MIME);
} else if (!charset) {
procmime_scan_content_type_str
- (hp, NULL, &charset, NULL, NULL);
+ (hp, NULL, &charset, NULL, NULL, NULL);
}
break;
case H_SEEN:
Index: libsylph/procmime.c
===================================================================
--- libsylph/procmime.c (revision 2362)
+++ libsylph/procmime.c (working copy)
@@ -69,6 +69,7 @@
g_free(mimeinfo->boundary);
g_free(mimeinfo->content_disposition);
g_free(mimeinfo->filename);
+ g_free(mimeinfo->smime_type);
g_free(mimeinfo->sigstatus);
g_free(mimeinfo->sigstatus_full);
@@ -379,14 +380,17 @@
g_free(mimeinfo->charset);
g_free(mimeinfo->name);
g_free(mimeinfo->boundary);
+ g_free(mimeinfo->smime_type);
mimeinfo->content_type = NULL;
mimeinfo->charset = NULL;
mimeinfo->name = NULL;
mimeinfo->boundary = NULL;
+ mimeinfo->smime_type = NULL;
procmime_scan_content_type_str(content_type, &mimeinfo->content_type,
&mimeinfo->charset, &mimeinfo->name,
- &mimeinfo->boundary);
+ &mimeinfo->boundary,
+ &mimeinfo->smime_type);
mimeinfo->mime_type = procmime_scan_mime_type(mimeinfo->content_type);
if (mimeinfo->mime_type == MIME_MULTIPART && !mimeinfo->boundary)
@@ -706,7 +710,8 @@
void procmime_scan_content_type_str(const gchar *content_type,
gchar **mime_type, gchar **charset,
- gchar **name, gchar **boundary)
+ gchar **name, gchar **boundary,
+ gchar **smime_type)
{
MimeParams *mparams;
GSList *cur;
@@ -730,6 +735,10 @@
!g_ascii_strcasecmp(param->name, "boundary")) {
*boundary = g_strdup(param->value);
boundary = NULL;
+ } else if (smime_type &&
+ !g_ascii_strcasecmp(param->name, "smime-type")) {
+ *smime_type = g_strdup(param->value);
+ smime_type = NULL;
}
}
Index: libsylph/procmime.h
===================================================================
--- libsylph/procmime.h (revision 2362)
+++ libsylph/procmime.h (working copy)
@@ -102,6 +102,7 @@
gchar *charset;
gchar *name;
gchar *boundary;
+ gchar *smime_type;
gchar *content_disposition;
gchar *filename;
@@ -155,7 +156,8 @@
gchar **mime_type,
gchar **charset,
gchar **name,
- gchar **boundary);
+ gchar **boundary,
+ gchar **smime_type);
void procmime_scan_content_disposition (MimeInfo *mimeinfo,
const gchar *content_disposition);
MimeInfo *procmime_scan_mime_header (FILE *fp);
Index: src/compose.c
===================================================================
--- src/compose.c (revision 2362)
+++ src/compose.c (working copy)
@@ -1410,7 +1410,8 @@
if (hentry[H_CONTENT_TYPE].body != NULL) {
procmime_scan_content_type_str(hentry[H_CONTENT_TYPE].body,
- NULL, &charset, NULL, NULL);
+ NULL, &charset, NULL, NULL,
+ NULL);
g_free(hentry[H_CONTENT_TYPE].body);
hentry[H_CONTENT_TYPE].body = NULL;
}
Index: src/rfc2015.c
===================================================================
--- src/rfc2015.c (revision 2362)
+++ src/rfc2015.c (working copy)
@@ -364,7 +364,8 @@
}
#endif
-static gpgme_data_t pgp_decrypt(MsgInfo *msginfo, MimeInfo *partinfo, FILE *fp)
+static gpgme_data_t pgp_decrypt(MsgInfo *msginfo, MimeInfo *partinfo, FILE *fp,
+ gboolean pgp)
{
gpgme_ctx_t ctx = NULL;
gpgme_error_t err;
@@ -372,6 +373,7 @@
struct passphrase_cb_info_s info;
gpgme_verify_result_t verifyresult = NULL;
const gchar *result = NULL;
+ const gchar *filename;
memset(&info, 0, sizeof info);
@@ -380,13 +382,37 @@
debug_print("gpgme_new failed: %s\n", gpgme_strerror(err));
goto leave;
}
+ if (!pgp) {
+ err = gpgme_set_protocol(ctx, GPGME_PROTOCOL_CMS);
+ if (err) {
+ debug_print("gpgme_set_protocol failed: %s\n",
+ gpgme_strerror(err));
+ goto leave;
+ }
+ }
- err = gpgme_data_new_from_filepart(&cipher, NULL, fp,
- partinfo->fpos, partinfo->size);
- if (err) {
- debug_print("gpgme_data_new_from_filepart failed: %s\n",
- gpgme_strerror(err));
- goto leave;
+ if (pgp) {
+ err = gpgme_data_new_from_filepart(&cipher, NULL, fp,
+ partinfo->fpos, partinfo->size);
+ if (err) {
+ debug_print("gpgme_data_new_from_filepart failed: %s\n",
+ gpgme_strerror(err));
+ goto leave;
+ }
+ } else {
+ filename = procmime_get_tmp_file_name(partinfo);
+ if (procmime_get_part_fp(filename, fp, partinfo) < 0) {
+ g_warning("Can't get the S/MIME data file.");
+ g_free(filename);
+ goto leave;
+ }
+ err = gpgme_data_new_from_file(&cipher, filename, 1);
+ g_free(filename);
+ if (err) {
+ debug_print("gpgme_data_new_from_file failed: %s\n",
+ gpgme_strerror(err));
+ goto leave;
+ }
}
err = gpgme_data_new(&plain);
@@ -538,12 +564,23 @@
gint rfc2015_is_encrypted(MimeInfo *mimeinfo)
{
- if (!mimeinfo || mimeinfo->mime_type != MIME_MULTIPART)
+ if (!mimeinfo)
return 0;
- if (g_ascii_strcasecmp(mimeinfo->content_type, "multipart/encrypted"))
- return 0;
- /* fixme: we should check the protocol parameter */
- return 1;
+
+ /* PGP */
+ if (mimeinfo->mime_type == MIME_MULTIPART &&
+ !g_ascii_strcasecmp(mimeinfo->content_type, "multipart/encrypted")) {
+ /* fixme: we should check the protocol parameter */
+ return 1;
+ }
+
+ /* S/MIME */
+ if (!g_ascii_strcasecmp(mimeinfo->content_type, "application/pkcs7-mime") &&
+ !g_ascii_strcasecmp(mimeinfo->smime_type, "enveloped-data")) {
+ return 1;
+ }
+
+ return 0;
}
gboolean rfc2015_msg_is_encrypted(const gchar *file)
@@ -625,47 +662,72 @@
gchar buf[BUFFSIZE];
gint in_cline;
gpgme_error_t err;
+ gboolean multi = FALSE;
g_return_if_fail(msginfo != NULL);
g_return_if_fail(mimeinfo != NULL);
g_return_if_fail(fp != NULL);
- g_return_if_fail(mimeinfo->mime_type == MIME_MULTIPART);
+ multi = (mimeinfo->mime_type == MIME_MULTIPART);
- debug_print("** decrypting multipart/encrypted message\n");
+ debug_print("** decrypting multipart/encrypted or application/pkcs7-mime message\n");
/* skip headers */
if (fseek(fp, mimeinfo->fpos, SEEK_SET) < 0)
perror("fseek");
tmpinfo = procmime_scan_mime_header(fp);
- if (!tmpinfo || tmpinfo->mime_type != MIME_MULTIPART) {
+ if (!tmpinfo) {
DECRYPTION_ABORT();
}
- procmime_scan_multipart_message(tmpinfo, fp);
+ if (multi) {
+ if (tmpinfo->mime_type == MIME_MULTIPART) {
+ procmime_scan_multipart_message(tmpinfo, fp);
+ partinfo = tmpinfo->children;
+ } else {
+ DECRYPTION_ABORT();
+ }
+ } else {
+ partinfo = tmpinfo;
+ }
- /* check that we have the 2 parts */
- partinfo = tmpinfo->children;
- if (!partinfo || !partinfo->next) {
+ if (!partinfo) {
DECRYPTION_ABORT();
}
- if (!g_ascii_strcasecmp(partinfo->content_type,
+ if (multi && !g_ascii_strcasecmp(partinfo->content_type,
"application/pgp-encrypted")) {
+ /* check that we have the 2 parts */
+ if (!partinfo->next) {
+ DECRYPTION_ABORT();
+ }
/* Fixme: check that the version is 1 */
ver_ok = 1;
+
+ partinfo = partinfo->next;
+ if (ver_ok &&
+ !g_ascii_strcasecmp(partinfo->content_type,
+ "application/octet-stream")) {
+ if (partinfo->next) {
+ g_warning("oops: pgp_encrypted with more than 2 parts");
+ }
+ } else {
+ DECRYPTION_ABORT();
+ }
+
+ debug_print("** yep, it is pgp encrypted\n");
}
- partinfo = partinfo->next;
- if (ver_ok &&
- !g_ascii_strcasecmp(partinfo->content_type,
- "application/octet-stream")) {
- if (partinfo->next)
- g_warning("oops: pgp_encrypted with more than 2 parts");
- } else {
- DECRYPTION_ABORT();
+
+ if (!g_ascii_strcasecmp(partinfo->content_type,
+ "application/pkcs7-mime")) {
+ if (!g_ascii_strcasecmp(partinfo->smime_type,
+ "enveloped-data")) {
+ ver_ok = 1; /*???*/
+ } else {
+ DECRYPTION_ABORT();
+ }
+ debug_print("** yep, it is smime encrypted\n");
}
- debug_print("** yep, it is pgp encrypted\n");
-
- plain = pgp_decrypt(msginfo, partinfo, fp);
+ plain = pgp_decrypt(msginfo, partinfo, fp, multi);
if (!plain) {
DECRYPTION_ABORT();
}
RFC も何も見てないので、 偶然うちの (mutt から送った) S/MIME メッセージを見ることができただけかもしれないし、 セキュリティについても知らない。保証はしないよ。
とくに outlook とのやりとりなんかのバッドノウハウはまったく知らない。