2009-12-03 (Thu) [長年日記]

_ さらに sylpheed で S/MIME 暗号化も

これでできるんじゃないだろうか*1。 明らかにハックなので、鍵選択で PGP と混在させた場合も考えてないし、署名 + 暗号化のケースも作ってないし、なにより関数名が pgp_encrypt のまま。

diff -u src/rfc2015.c src/rfc2015.c
--- src/rfc2015.c	(working copy)
+++ src/rfc2015.c	(working copy)
@@ -39,6 +39,8 @@
 #include "procmime.h"
 #include "procheader.h"
 #include "base64.h"
+#define B64_LINE_SIZE		57
+#define B64_BUFFSIZE		77
 #include "uuencode.h"
 #include "unmime.h"
 #include "codeconv.h"
@@ -373,7 +375,6 @@
 	struct passphrase_cb_info_s info;
 	gpgme_verify_result_t verifyresult = NULL;
 	const gchar *result = NULL;
-	const gchar *filename;

 	memset(&info, 0, sizeof info);

@@ -400,6 +401,7 @@
 			goto leave;
 		}
 	} else {
+		gchar *filename;
 		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.");
@@ -853,7 +855,15 @@
 	if (!err)
 		err = gpgme_data_new(&cipher);
 	if (!err) {
-		gpgme_set_armor(ctx, 1);
+		if ((*kset)->protocol == GPGME_PROTOCOL_OpenPGP) {
+			gpgme_set_armor(ctx, 1);
+			debug_print("pgp_encrypt(): PGP\n");
+		} else {
+			err = gpgme_set_protocol(ctx, (*kset)->protocol);
+			debug_print("pgp_encrypt(): S/MIME\n");
+		}
+	}
+	if (!err) {
 		err = (gpgme_data_seek(plain, 0, SEEK_SET) == -1) ?
 			gpgme_error_from_errno(errno) : 0;
 		if (!err) {
@@ -940,6 +950,7 @@
 	ssize_t bytesRW = 0;
 	gint mime_version_seen = 0;
 	gchar *boundary;
+	gboolean smime;

 	boundary = generate_mime_boundary("Encrypt");

@@ -949,6 +960,7 @@
 		debug_print("error creating recipient list\n");
 		goto failure;
 	}
+	smime = ((*kset)->protocol == GPGME_PROTOCOL_CMS);

 	/* Open the source file */
 	if ((fp = g_fopen(file, "rb")) == NULL) {
@@ -1083,7 +1095,16 @@
 	if (!mime_version_seen)
 		fputs("MIME-Version: 1.0\r\n", fp);

+	if (smime)
 	fprintf(fp,
+	        "Content-Type: application/pkcs7-mime;"
+		" smime-type=\"enveloped-data\";\r\n"
+		" name=\"smime.p7m\"\r\n"
+		"Content-Disposition: attachment; filename=\"smime.p7m\"\r\n"
+		"Content-Transfer-Encoding: base64\r\n"
+		"\r\n");
+	else
+	fprintf(fp,
 	        "Content-Type: multipart/encrypted;"
 	        " protocol=\"application/pgp-encrypted\";\r\n"
 	        " boundary=\"%s\"\r\n"
@@ -1111,7 +1132,19 @@

 	bytesRW = gpgme_data_read(cipher, buf, BUFFSIZE);
 	while (bytesRW > 0) {
-		fwrite(buf, bytesRW, 1, fp);
+		if (smime) {
+			gchar outbuf[B64_BUFFSIZE];
+			gint l;
+
+			for (i = 0; i < bytesRW; i += B64_LINE_SIZE) {
+				l = MIN(B64_LINE_SIZE, bytesRW - i);
+				base64_encode(outbuf, (guchar *)buf + i, l);
+				fputs(outbuf, fp);
+				fputc('\n', fp);
+			}
+		} else {
+			fwrite(buf, bytesRW, 1, fp);
+		}
 		bytesRW = gpgme_data_read(cipher, buf, BUFFSIZE);
 	}

@@ -1122,6 +1155,7 @@
 	}

 	/* and the final boundary */
+	if (!smime)
 	fprintf(fp,
 	        "\r\n"
 	        "--%s--\r\n",
only in patch2:
--- src/select-keys.c	(revision 2362)
+++ src/select-keys.c	(working copy)
@@ -159,6 +159,7 @@
     const char *text[N_COL_TITLES];
     char *algo_buf;
     int row;
+    gboolean uid_shown = FALSE;

     /* first check whether the key is capable of encryption which is not
      * the case for revoked, expired or sign-only keys */
@@ -175,9 +176,15 @@
     text[COL_KEYID] = s;

     s = key->uids->name;
+    if (!(s && *s) && key->protocol == GPGME_PROTOCOL_CMS) {
+	s = key->uids->uid;
+	uid_shown = TRUE;
+    }
     text[COL_NAME] = s;

     s = key->uids->email;
+    if (!(s && *s) && key->protocol == GPGME_PROTOCOL_CMS && key->uids->next)
+	s = (uid_shown ? (key->uids->next ? key->uids->next->uid : NULL) : key->uids->uid);
     text[COL_EMAIL] = s;

     switch (key->uids->validity)
@@ -218,6 +225,7 @@
     gpgme_error_t err;
     gpgme_key_t key;
     int running=0;
+    int smime;

     g_return_if_fail (sk);
     clist = sk->clist;
@@ -235,6 +243,15 @@
     while (gtk_events_pending ())
         gtk_main_iteration ();

+  for (smime = 0; smime < 2; smime++) {
+    if (smime) {
+	err = gpgme_set_protocol(ctx, GPGME_PROTOCOL_CMS);
+	if (err) {
+	    debug_print ("** gpgme_set_protocol(GPGME_PROTOCOL_CMS) failed: %s",
+	                 gpgme_strerror(err));
+	    continue;
+	}
+    }
     err = gpgme_op_keylist_start (ctx, pattern, 0);
     if (err) {
         debug_print ("** gpgme_op_keylist_start(%s) failed: %s",
@@ -257,6 +274,7 @@
                      gpgme_strerror (err));
         gpgme_op_keylist_end(ctx);
     }
+  }
     sk->select_ctx = NULL;
     gpgme_release (ctx);
     /*gtk_clist_thaw (select_keys.clist);*/
@@ -421,7 +439,8 @@
     row = GPOINTER_TO_INT(sk->clist->selection->data);
     key = gtk_clist_get_row_data(sk->clist, row);
     if (key) {
-        if ( key->uids->validity < GPGME_VALIDITY_FULL ) {
+        if ( key->uids->validity < GPGME_VALIDITY_FULL &&
+	     key->protocol == GPGME_PROTOCOL_OpenPGP ) {
             use_key = use_untrusted(key);
             if (!use_key) {
                 debug_print ("** Key untrusted, will not encrypt");

gpgme のほうで base64 エンコードしてくれたりは、しないのかな。

*1 なぜか、ちょっと前まで動いていたのに、"Not implemented" エラーが出るようになっちゃったので、わからない

[]

«前の日記(2009-11-30 (Mon)) 最新