gmime r1332 - in trunk: . gmime mono tests



Author: fejj
Date: Wed Jun  4 03:44:35 2008
New Revision: 1332
URL: http://svn.gnome.org/viewvc/gmime?rev=1332&view=rev

Log:
2008-06-03  Jeffrey Stedfast  <fejj novell com>

	* tests/test-pgpmime.c: Updated to test for
	multipart/encrypted+sign

	* gmime/gmime-multipart-encrypted.c (g_mime_multipart_encrypted_encrypt):
	Changed to take 'sign' and 'userid' arguments so that it is
	possible to both sign and encrypt the content.
	(g_mime_multipart_encrypted_decrypt): Updated to save the
	GMimeSignatureValidity from our call ot
	g_mime_cipher_context_decrypt() so that callers can choose to get
	the signer validity (in the case where the encrypted part was also
	signed).
	(g_mime_multipart_encrypted_get_signature_validity): New function.

	* gmime/gmime-gpg-context.c (gpg_decrypt): Updated to return a
	GMimeSignatureValidity.
	(gpg_ctx_parse_signer_info): Split out from gpg_ctx_parse_status()
	to parse signer info.
	(gpg_ctx_parse_status): Updated VERIFY mode to call
	gpg_ctx_parse_signer_info() and made DECRYPT also call it so that
	we properly collect signer info when the encrypted stream was also
	signed.
	(gpg_encrypt): Respect the 'sign' argument.

	* gmime/gmime-cipher-context.c (g_mime_cipher_context_decrypt):
	Now returns a GMimeSignatureValidity in case the encrypted stream
	was also signed.



Modified:
   trunk/ChangeLog
   trunk/gmime/gmime-cipher-context.c
   trunk/gmime/gmime-cipher-context.h
   trunk/gmime/gmime-gpg-context.c
   trunk/gmime/gmime-multipart-encrypted.c
   trunk/gmime/gmime-multipart-encrypted.h
   trunk/mono/gmime-api.raw
   trunk/tests/test-pgpmime.c

Modified: trunk/gmime/gmime-cipher-context.c
==============================================================================
--- trunk/gmime/gmime-cipher-context.c	(original)
+++ trunk/gmime/gmime-cipher-context.c	Wed Jun  4 03:44:35 2008
@@ -59,8 +59,8 @@
 			   GMimeStream *istream, GMimeStream *ostream,
 			   GError **err);
 
-static int cipher_decrypt (GMimeCipherContext *ctx, GMimeStream *istream,
-			   GMimeStream *ostream, GError **err);
+static GMimeSignatureValidity *cipher_decrypt (GMimeCipherContext *ctx, GMimeStream *istream,
+					       GMimeStream *ostream, GError **err);
 
 static int cipher_import_keys (GMimeCipherContext *ctx, GMimeStream *istream,
 			       GError **err);
@@ -298,14 +298,14 @@
 }
 
 
-static int
+static GMimeSignatureValidity *
 cipher_decrypt (GMimeCipherContext *ctx, GMimeStream *istream,
 		GMimeStream *ostream, GError **err)
 {
 	g_set_error (err, GMIME_ERROR_QUARK, GMIME_ERROR_NOT_SUPPORTED,
 		     "Decryption is not supported by this cipher");
 	
-	return -1;
+	return NULL;
 }
 
 
@@ -319,15 +319,24 @@
  * Decrypts the ciphertext input stream and writes the resulting
  * cleartext to the output stream.
  *
- * Returns: %0 on success or %-1 for fail.
+ * If the encrypted input stream was also signed, the returned
+ * #GMimeSignatureValidity will have signer information included and
+ * the signature status will be one of #GMIME_SIGNATURE_STATUS_GOOD,
+ * #GMIME_SIGNATURE_STATUS_BAD, or #GMIME_SIGNATURE_STATUS_UNKNOWN.
+ *
+ * If the encrypted input text was not signed, then the signature
+ * status of the returned #GMimeSignatureValidity will be
+ * #GMIME_SIGNATURE_STATUS_NONE.
+ *
+ * Returns: a #GMimeSignatureValidity on success or %NULL on error.
  **/
-int
+GMimeSignatureValidity *
 g_mime_cipher_context_decrypt (GMimeCipherContext *ctx, GMimeStream *istream,
 			       GMimeStream *ostream, GError **err)
 {
-	g_return_val_if_fail (GMIME_IS_CIPHER_CONTEXT (ctx), -1);
-	g_return_val_if_fail (GMIME_IS_STREAM (istream), -1);
-	g_return_val_if_fail (GMIME_IS_STREAM (ostream), -1);
+	g_return_val_if_fail (GMIME_IS_CIPHER_CONTEXT (ctx), NULL);
+	g_return_val_if_fail (GMIME_IS_STREAM (istream), NULL);
+	g_return_val_if_fail (GMIME_IS_STREAM (ostream), NULL);
 	
 	return GMIME_CIPHER_CONTEXT_GET_CLASS (ctx)->decrypt (ctx, istream, ostream, err);
 }
@@ -786,7 +795,7 @@
  * Returns: a #GMimeSignatureStatus value.
  **/
 GMimeSignatureStatus
-g_mime_signature_validity_get_status (GMimeSignatureValidity *validity)
+g_mime_signature_validity_get_status (const GMimeSignatureValidity *validity)
 {
 	g_return_val_if_fail (validity != NULL, GMIME_SIGNATURE_STATUS_NONE);
 	
@@ -820,7 +829,7 @@
  * Returns: a user-readable string containing any status information.
  **/
 const char *
-g_mime_signature_validity_get_details (GMimeSignatureValidity *validity)
+g_mime_signature_validity_get_details (const GMimeSignatureValidity *validity)
 {
 	g_return_val_if_fail (validity != NULL, NULL);
 	
@@ -855,7 +864,7 @@
  * as trust and cipher keys.
  **/
 const GMimeSigner *
-g_mime_signature_validity_get_signers (GMimeSignatureValidity *validity)
+g_mime_signature_validity_get_signers (const GMimeSignatureValidity *validity)
 {
 	g_return_val_if_fail (validity != NULL, NULL);
 	

Modified: trunk/gmime/gmime-cipher-context.h
==============================================================================
--- trunk/gmime/gmime-cipher-context.h	(original)
+++ trunk/gmime/gmime-cipher-context.h	Wed Jun  4 03:44:35 2008
@@ -107,7 +107,7 @@
 						  GMimeStream *istream, GMimeStream *ostream,
 						  GError **err);
 	
-	int                      (* decrypt)     (GMimeCipherContext *ctx, GMimeStream *istream,
+	GMimeSignatureValidity * (* decrypt)     (GMimeCipherContext *ctx, GMimeStream *istream,
 						  GMimeStream *ostream, GError **err);
 	
 	int                      (* import_keys) (GMimeCipherContext *ctx, GMimeStream *istream,
@@ -139,8 +139,8 @@
 						    GMimeStream *istream, GMimeStream *ostream,
 						    GError **err);
 
-int                  g_mime_cipher_context_decrypt (GMimeCipherContext *ctx, GMimeStream *istream,
-						    GMimeStream *ostream, GError **err);
+GMimeSignatureValidity *g_mime_cipher_context_decrypt (GMimeCipherContext *ctx, GMimeStream *istream,
+						       GMimeStream *ostream, GError **err);
 
 /* key/certificate routines */
 int                  g_mime_cipher_context_import_keys (GMimeCipherContext *ctx, GMimeStream *istream,
@@ -306,13 +306,13 @@
 GMimeSignatureValidity *g_mime_signature_validity_new (void);
 void                    g_mime_signature_validity_free (GMimeSignatureValidity *validity);
 
-GMimeSignatureStatus    g_mime_signature_validity_get_status (GMimeSignatureValidity *validity);
+GMimeSignatureStatus    g_mime_signature_validity_get_status (const GMimeSignatureValidity *validity);
 void                    g_mime_signature_validity_set_status (GMimeSignatureValidity *validity, GMimeSignatureStatus status);
 
-const char             *g_mime_signature_validity_get_details (GMimeSignatureValidity *validity);
+const char             *g_mime_signature_validity_get_details (const GMimeSignatureValidity *validity);
 void                    g_mime_signature_validity_set_details (GMimeSignatureValidity *validity, const char *details);
 
-const GMimeSigner      *g_mime_signature_validity_get_signers (GMimeSignatureValidity *validity);
+const GMimeSigner      *g_mime_signature_validity_get_signers (const GMimeSignatureValidity *validity);
 void                    g_mime_signature_validity_add_signer  (GMimeSignatureValidity *validity, GMimeSigner *signer);
 
 G_END_DECLS

Modified: trunk/gmime/gmime-gpg-context.c
==============================================================================
--- trunk/gmime/gmime-gpg-context.c	(original)
+++ trunk/gmime/gmime-gpg-context.c	Wed Jun  4 03:44:35 2008
@@ -88,8 +88,8 @@
 			GMimeStream *istream, GMimeStream *ostream,
 			GError **err);
 
-static int gpg_decrypt (GMimeCipherContext *ctx, GMimeStream *istream,
-			GMimeStream *ostream, GError **err);
+static GMimeSignatureValidity *gpg_decrypt (GMimeCipherContext *ctx, GMimeStream *istream,
+					    GMimeStream *ostream, GError **err);
 
 static int gpg_import_keys (GMimeCipherContext *ctx, GMimeStream *istream,
 			    GError **err);
@@ -236,6 +236,7 @@
 	GPG_CTX_MODE_SIGN,
 	GPG_CTX_MODE_VERIFY,
 	GPG_CTX_MODE_ENCRYPT,
+	GPG_CTX_MODE_SIGN_ENCRYPT,
 	GPG_CTX_MODE_DECRYPT,
 	GPG_CTX_MODE_IMPORT,
 	GPG_CTX_MODE_EXPORT,
@@ -413,7 +414,9 @@
 static void
 gpg_ctx_add_recipient (struct _GpgCtx *gpg, const char *keyid)
 {
-	if (gpg->mode != GPG_CTX_MODE_ENCRYPT && gpg->mode != GPG_CTX_MODE_EXPORT)
+	if (gpg->mode != GPG_CTX_MODE_ENCRYPT &&
+	    gpg->mode != GPG_CTX_MODE_SIGN_ENCRYPT &&
+	    gpg->mode != GPG_CTX_MODE_EXPORT)
 		return;
 	
 	if (!gpg->recipients)
@@ -613,10 +616,16 @@
 			g_ptr_array_add (argv, gpg->sigfile);
 		g_ptr_array_add (argv, "-");
 		break;
+	case GPG_CTX_MODE_SIGN_ENCRYPT:
+		g_ptr_array_add (argv,  "--sign");
+		
+		/* fall thru... */
 	case GPG_CTX_MODE_ENCRYPT:
 		g_ptr_array_add (argv,  "--encrypt");
+		
 		if (gpg->armor)
 			g_ptr_array_add (argv, "--armor");
+		
 		if (gpg->always_trust)
 			g_ptr_array_add (argv, "--always-trust");
 		
@@ -624,6 +633,7 @@
 			g_ptr_array_add (argv, "-u");
 			g_ptr_array_add (argv, (char *) gpg->userid);
 		}
+		
 		if (gpg->recipients) {
 			for (i = 0; i < gpg->recipients->len; i++) {
 				g_ptr_array_add (argv, "-r");
@@ -784,12 +794,127 @@
 	return inptr;
 }
 
+static void
+gpg_ctx_parse_signer_info (struct _GpgCtx *gpg, char *status)
+{
+	GMimeSigner *signer;
+	
+	if (!strncmp (status, "SIG_ID ", 7)) {
+		/* not sure if this contains anything we care about... */
+	} else if (!strncmp (status, "GOODSIG ", 8)) {
+		gpg->goodsig = TRUE;
+		status += 8;
+		
+		signer = g_mime_signer_new ();
+		signer->status = GMIME_SIGNER_STATUS_GOOD;
+		gpg->signer->next = signer;
+		gpg->signer = signer;
+		
+		/* get the key id of the signer */
+		status = next_token (status, &signer->keyid);
+		
+		/* the rest of the string is the signer's name */
+		signer->name = g_strdup (status);
+	} else if (!strncmp (status, "BADSIG ", 7)) {
+		gpg->badsig = TRUE;
+		status += 7;
+		
+		signer = g_mime_signer_new ();
+		signer->status = GMIME_SIGNER_STATUS_BAD;
+		gpg->signer->next = signer;
+		gpg->signer = signer;
+		
+		/* get the key id of the signer */
+		status = next_token (status, &signer->keyid);
+		
+		/* the rest of the string is the signer's name */
+		signer->name = g_strdup (status);
+	} else if (!strncmp (status, "ERRSIG ", 7)) {
+		/* Note: NO_PUBKEY often comes after an ERRSIG */
+		gpg->errsig = TRUE;
+		status += 7;
+		
+		signer = g_mime_signer_new ();
+		signer->status = GMIME_SIGNER_STATUS_ERROR;
+		gpg->signer->next = signer;
+		gpg->signer = signer;
+		
+		/* get the key id of the signer */
+		status = next_token (status, &signer->keyid);
+		
+		/* skip the pubkey_algo */
+		status = next_token (status, NULL);
+		
+		/* skip the digest_algo */
+		status = next_token (status, NULL);
+		
+		/* skip the class */
+		status = next_token (status, NULL);
+		
+		/* get the signature expiration date (or 0 for never) */
+		signer->expires = strtoul (status, NULL, 10);
+		status = next_token (status, NULL);
+		
+		/* the last token is the 'rc' which we don't care about */
+	} else if (!strncmp (status, "NO_PUBKEY ", 10)) {
+		/* the only token is the keyid, but we've already got it */
+		gpg->signer->errors |= GMIME_SIGNER_ERROR_NO_PUBKEY;
+		gpg->nopubkey = TRUE;
+	} else if (!strncmp (status, "EXPSIG", 6)) {
+		/* FIXME: see what else we can glean from this... */
+		gpg->signer->errors |= GMIME_SIGNER_ERROR_EXPSIG;
+	} else if (!strncmp (status, "EXPKEYSIG", 9)) {
+		gpg->signer->errors |= GMIME_SIGNER_ERROR_EXPKEYSIG;
+	} else if (!strncmp (status, "REVKEYSIG", 9)) {
+		gpg->signer->errors |= GMIME_SIGNER_ERROR_REVKEYSIG;
+	} else if (!strncmp (status, "VALIDSIG ", 9)) {
+		char *inend;
+		
+		gpg->validsig = TRUE;
+		status += 9;
+		
+		signer = gpg->signer;
+		
+		/* the first token is the fingerprint */
+		status = next_token (status, &signer->fingerprint);
+		
+		/* the second token is the date the stream was signed YYYY-MM-DD */
+		status = next_token (status, NULL);
+		
+		/* the third token is the signature creation date (or 0 for unknown?) */
+		signer->created = strtoul (status, &inend, 10);
+		if (inend == status || *inend != ' ')
+			return;
+		
+		status = inend + 1;
+		
+		/* the fourth token is the signature expiration date (or 0 for never) */
+		signer->expires = strtoul (status, NULL, 10);
+		
+		/* ignore the rest... */
+	} else if (!strncmp (status, "TRUST_", 6)) {
+		status += 6;
+		
+		signer = gpg->signer;
+		if (!strncmp (status, "NEVER", 5)) {
+			signer->trust = GMIME_SIGNER_TRUST_NEVER;
+		} else if (!strncmp (status, "MARGINAL", 8)) {
+			signer->trust = GMIME_SIGNER_TRUST_MARGINAL;
+		} else if (!strncmp (status, "FULLY", 5)) {
+			signer->trust = GMIME_SIGNER_TRUST_FULLY;
+		} else if (!strncmp (status, "ULTIMATE", 8)) {
+			signer->trust = GMIME_SIGNER_TRUST_ULTIMATE;
+		} else if (!strncmp (status, "UNDEFINED", 9)) {
+			signer->trust = GMIME_SIGNER_TRUST_UNDEFINED;
+		}
+	}
+}
+
 static int
 gpg_ctx_parse_status (struct _GpgCtx *gpg, GError **err)
 {
 	size_t nread, nwritten;
 	register char *inptr;
-	GMimeSigner *signer;
 	char *status, *tmp;
 	int len;
 	
@@ -982,116 +1107,9 @@
 			}
 			break;
 		case GPG_CTX_MODE_VERIFY:
-			if (!strncmp (status, "SIG_ID ", 7)) {
-				/* not sure if this contains anything we care about... */
-			} else if (!strncmp (status, "GOODSIG ", 8)) {
-				gpg->goodsig = TRUE;
-				status += 8;
-				
-				signer = g_mime_signer_new ();
-				signer->status = GMIME_SIGNER_STATUS_GOOD;
-				gpg->signer->next = signer;
-				gpg->signer = signer;
-				
-				/* get the key id of the signer */
-				status = next_token (status, &signer->keyid);
-				
-				/* the rest of the string is the signer's name */
-				signer->name = g_strdup (status);
-			} else if (!strncmp (status, "BADSIG ", 7)) {
-				gpg->badsig = TRUE;
-				status += 7;
-				
-				signer = g_mime_signer_new ();
-				signer->status = GMIME_SIGNER_STATUS_BAD;
-				gpg->signer->next = signer;
-				gpg->signer = signer;
-				
-				/* get the key id of the signer */
-				status = next_token (status, &signer->keyid);
-				
-				/* the rest of the string is the signer's name */
-				signer->name = g_strdup (status);
-			} else if (!strncmp (status, "ERRSIG ", 7)) {
-				/* Note: NO_PUBKEY often comes after an ERRSIG */
-				gpg->errsig = TRUE;
-				status += 7;
-				
-				signer = g_mime_signer_new ();
-				signer->status = GMIME_SIGNER_STATUS_ERROR;
-				gpg->signer->next = signer;
-				gpg->signer = signer;
-				
-				/* get the key id of the signer */
-				status = next_token (status, &signer->keyid);
-				
-				/* skip the pubkey_algo */
-				status = next_token (status, NULL);
-				
-				/* skip the digest_algo */
-				status = next_token (status, NULL);
-				
-				/* skip the class */
-				status = next_token (status, NULL);
-				
-				/* get the signature expiration date (or 0 for never) */
-				signer->expires = strtoul (status, NULL, 10);
-				status = next_token (status, NULL);
-				
-				/* the last token is the 'rc' which we don't care about */
-			} else if (!strncmp (status, "NO_PUBKEY ", 10)) {
-				/* the only token is the keyid, but we've already got it */
-				gpg->signer->errors |= GMIME_SIGNER_ERROR_NO_PUBKEY;
-				gpg->nopubkey = TRUE;
-			} else if (!strncmp (status, "EXPSIG", 6)) {
-				/* FIXME: see what else we can glean from this... */
-				gpg->signer->errors |= GMIME_SIGNER_ERROR_EXPSIG;
-			} else if (!strncmp (status, "EXPKEYSIG", 9)) {
-				gpg->signer->errors |= GMIME_SIGNER_ERROR_EXPKEYSIG;
-			} else if (!strncmp (status, "REVKEYSIG", 9)) {
-				gpg->signer->errors |= GMIME_SIGNER_ERROR_REVKEYSIG;
-			} else if (!strncmp (status, "VALIDSIG ", 9)) {
-				char *inend;
-				
-				gpg->validsig = TRUE;
-				status += 9;
-				
-				signer = gpg->signer;
-				
-				/* the first token is the fingerprint */
-				status = next_token (status, &signer->fingerprint);
-				
-				/* the second token is the date the stream was signed YYYY-MM-DD */
-				status = next_token (status, NULL);
-				
-				/* the third token is the signature creation date (or 0 for unknown?) */
-				signer->created = strtoul (status, &inend, 10);
-				if (inend == status || *inend != ' ')
-					break;
-				
-				status = inend + 1;
-				
-				/* the fourth token is the signature expiration date (or 0 for never) */
-				signer->expires = strtoul (status, NULL, 10);
-				
-				/* ignore the rest... */
-			} else if (!strncmp (status, "TRUST_", 6)) {
-				status += 6;
-				
-				signer = gpg->signer;
-				if (!strncmp (status, "NEVER", 5)) {
-					signer->trust = GMIME_SIGNER_TRUST_NEVER;
-				} else if (!strncmp (status, "MARGINAL", 8)) {
-					signer->trust = GMIME_SIGNER_TRUST_MARGINAL;
-				} else if (!strncmp (status, "FULLY", 5)) {
-					signer->trust = GMIME_SIGNER_TRUST_FULLY;
-				} else if (!strncmp (status, "ULTIMATE", 8)) {
-					signer->trust = GMIME_SIGNER_TRUST_ULTIMATE;
-				} else if (!strncmp (status, "UNDEFINED", 9)) {
-					signer->trust = GMIME_SIGNER_TRUST_UNDEFINED;
-				}
-			}
+			gpg_ctx_parse_signer_info (gpg, status);
 			break;
+		case GPG_CTX_MODE_SIGN_ENCRYPT:
 		case GPG_CTX_MODE_ENCRYPT:
 			if (!strncmp (status, "BEGIN_ENCRYPTION", 16)) {
 				/* nothing to do... but we know to expect data on stdout soon */
@@ -1107,7 +1125,9 @@
 			if (!strncmp (status, "BEGIN_DECRYPTION", 16)) {
 				/* nothing to do... but we know to expect data on stdout soon */
 			} else if (!strncmp (status, "END_DECRYPTION", 14)) {
-				/* nothing to do, but we know the end is near? */
+				/* nothing to do, but we know we're done */
+			} else {
+				gpg_ctx_parse_signer_info (gpg, status);
 			}
 			break;
 		case GPG_CTX_MODE_IMPORT:
@@ -1350,6 +1370,7 @@
 	case GPG_CTX_MODE_VERIFY:
 		mode = "verify";
 		break;
+	case GPG_CTX_MODE_SIGN_ENCRYPT:
 	case GPG_CTX_MODE_ENCRYPT:
 		mode = "encrypt";
 		break;
@@ -1650,7 +1671,10 @@
 	int i;
 	
 	gpg = gpg_ctx_new (context->session, ctx->path);
-	gpg_ctx_set_mode (gpg, GPG_CTX_MODE_ENCRYPT);
+	if (sign)
+		gpg_ctx_set_mode (gpg, GPG_CTX_MODE_SIGN_ENCRYPT);
+	else
+		gpg_ctx_set_mode (gpg, GPG_CTX_MODE_ENCRYPT);
 	gpg_ctx_set_armor (gpg, TRUE);
 	gpg_ctx_set_userid (gpg, userid);
 	gpg_ctx_set_istream (gpg, istream);
@@ -1698,12 +1722,15 @@
 }
 
 
-static int
+static GMimeSignatureValidity *
 gpg_decrypt (GMimeCipherContext *context, GMimeStream *istream,
 	     GMimeStream *ostream, GError **err)
 {
 	GMimeGpgContext *ctx = (GMimeGpgContext *) context;
+	GMimeSignatureValidity *validity;
+	const char *diagnostics;
 	struct _GpgCtx *gpg;
+	int save;
 	
 	gpg = gpg_ctx_new (context->session, ctx->path);
 	gpg_ctx_set_mode (gpg, GPG_CTX_MODE_DECRYPT);
@@ -1716,7 +1743,7 @@
 			     errno ? g_strerror (errno) : _("Unknown"));
 		gpg_ctx_free (gpg);
 		
-		return -1;
+		return NULL;
 	}
 	
 	while (!gpg_ctx_op_complete (gpg)) {
@@ -1724,14 +1751,11 @@
 			gpg_ctx_op_cancel (gpg);
 			gpg_ctx_free (gpg);
 			
-			return -1;
+			return NULL;
 		}
 	}
 	
 	if (gpg_ctx_op_wait (gpg) != 0) {
-		const char *diagnostics;
-		int save;
-		
 		save = errno;
 		diagnostics = gpg_ctx_get_diagnostics (gpg);
 		errno = save;
@@ -1739,12 +1763,34 @@
 		g_set_error (err, GMIME_ERROR, errno, diagnostics);
 		gpg_ctx_free (gpg);
 		
-		return -1;
+		return NULL;
+	}
+	
+	diagnostics = gpg_ctx_get_diagnostics (gpg);
+	
+	validity = g_mime_signature_validity_new ();
+	g_mime_signature_validity_set_details (validity, diagnostics);
+	
+	if (gpg->signers) {
+		if (gpg->goodsig && !(gpg->badsig || gpg->errsig || gpg->nodata)) {
+			/* all signatures were good */
+			validity->status = GMIME_SIGNATURE_STATUS_GOOD;
+		} else if (gpg->badsig && !(gpg->goodsig && !gpg->errsig)) {
+			/* all signatures were bad */
+			validity->status = GMIME_SIGNATURE_STATUS_BAD;
+		} else if (!gpg->nodata) {
+			validity->status = GMIME_SIGNATURE_STATUS_UNKNOWN;
+		} else {
+			validity->status = GMIME_SIGNATURE_STATUS_BAD;
+		}
+		
+		validity->signers = gpg->signers;
+		gpg->signers = NULL;
 	}
 	
 	gpg_ctx_free (gpg);
 	
-	return 0;
+	return validity;
 }
 
 static int

Modified: trunk/gmime/gmime-multipart-encrypted.c
==============================================================================
--- trunk/gmime/gmime-multipart-encrypted.c	(original)
+++ trunk/gmime/gmime-multipart-encrypted.c	Wed Jun  4 03:44:35 2008
@@ -23,6 +23,7 @@
 #include <config.h>
 #endif
 
+#include <stdio.h>
 #include <string.h>
 
 #include "gmime-multipart-encrypted.h"
@@ -122,6 +123,7 @@
 {
 	mpe->protocol = NULL;
 	mpe->decrypted = NULL;
+	mpe->validity = NULL;
 }
 
 static void
@@ -134,6 +136,9 @@
 	if (mpe->decrypted)
 		g_object_unref (mpe->decrypted);
 	
+	if (mpe->validity)
+		g_mime_signature_validity_free (mpe->validity);
+	
 	G_OBJECT_CLASS (parent_class)->finalize (object);
 }
 
@@ -228,13 +233,15 @@
  * @mpe: multipart/encrypted object
  * @content: MIME part to encrypt
  * @ctx: encryption cipher context
+ * @sign: %TRUE if the content should also be signed or %FALSE otherwise
+ * @userid: user id to use for signing (only used if @sign is %TRUE)
  * @recipients: an array of recipients to encrypt to
- * @err: exception
+ * @err: a #GError
  *
- * Attempts to encrypt the @content MIME part to the public keys of
- * @recipients using the @ctx encryption context. If successful, the
- * encrypted #GMimeObject is set as the encrypted part of the
- * multipart/encrypted object @mpe.
+ * Attempts to encrypt (and conditionally sign) the @content MIME part
+ * to the public keys of @recipients using the @ctx encryption
+ * context. If successful, the encrypted #GMimeObject is set as the
+ * encrypted part of the multipart/encrypted object @mpe.
  *
  * Returns: %0 on success or %-1 on fail. If the encryption fails, an
  * exception will be set on @err to provide information as to why the
@@ -242,7 +249,8 @@
  **/
 int
 g_mime_multipart_encrypted_encrypt (GMimeMultipartEncrypted *mpe, GMimeObject *content,
-				    GMimeCipherContext *ctx, GPtrArray *recipients,
+				    GMimeCipherContext *ctx, gboolean sign,
+				    const char *userid, GPtrArray *recipients,
 				    GError **err)
 {
 	GMimeStream *filtered_stream, *ciphertext, *stream;
@@ -273,7 +281,7 @@
 	
 	/* encrypt the content stream */
 	ciphertext = g_mime_stream_mem_new ();
-	if (g_mime_cipher_context_encrypt (ctx, FALSE, NULL, recipients, stream, ciphertext, err) == -1) {
+	if (g_mime_cipher_context_encrypt (ctx, sign, userid, recipients, stream, ciphertext, err) == -1) {
 		g_object_unref (ciphertext);
 		g_object_unref (stream);
 		return -1;
@@ -324,11 +332,16 @@
  * g_mime_multipart_encrypted_decrypt:
  * @mpe: multipart/encrypted object
  * @ctx: decryption cipher context
- * @err: exception
+ * @validity: a #GMimeSignatureValidity
+ * @err: a #GError
  *
  * Attempts to decrypt the encrypted MIME part contained within the
  * multipart/encrypted object @mpe using the @ctx decryption context.
  *
+ * If @validity is non-NULL, then on a successful decrypt operation,
+ * it will be updated to point to a newly-allocated
+ * #GMimeSignatureValidity with signature status information.
+ *
  * Returns: the decrypted MIME part on success or %NULL on fail. If the
  * decryption fails, an exception will be set on @err to provide
  * information as to why the failure occured.
@@ -339,9 +352,10 @@
 {
 	GMimeObject *decrypted, *version, *encrypted;
 	const GMimeContentType *mime_type;
-	GMimeDataWrapper *wrapper;
 	GMimeStream *stream, *ciphertext;
 	GMimeStream *filtered_stream;
+	GMimeSignatureValidity *sv;
+	GMimeDataWrapper *wrapper;
 	GMimeFilter *crlf_filter;
 	GMimeParser *parser;
 	const char *protocol;
@@ -362,7 +376,7 @@
 	if (protocol) {
 		/* make sure the protocol matches the cipher encrypt protocol */
 		if (g_ascii_strcasecmp (ctx->encrypt_protocol, protocol) != 0) {
-			g_set_error (err, GMIME_ERROR_QUARK, GMIME_ERROR_PROTOCOL_ERROR,
+			g_set_error (err, GMIME_ERROR, GMIME_ERROR_PROTOCOL_ERROR,
 				     "Failed to decrypt MIME part: protocol error");
 			
 			return NULL;
@@ -377,7 +391,7 @@
 	/* make sure the protocol matches the version part's content-type */
 	content_type = g_mime_content_type_to_string (version->content_type);
 	if (g_ascii_strcasecmp (content_type, protocol) != 0) {
-		g_set_error (err, GMIME_ERROR_QUARK, GMIME_ERROR_PROTOCOL_ERROR,
+		g_set_error (err, GMIME_ERROR, GMIME_ERROR_PROTOCOL_ERROR,
 			     "Failed to decrypt MIME part: protocol error");
 		
 		g_object_unref (version);
@@ -409,7 +423,7 @@
 	g_object_unref (crlf_filter);
 	
 	/* get the cleartext */
-	if (g_mime_cipher_context_decrypt (ctx, ciphertext, filtered_stream, err) == -1) {
+	if (!(sv = g_mime_cipher_context_decrypt (ctx, ciphertext, filtered_stream, err))) {
 		g_object_unref (filtered_stream);
 		g_object_unref (ciphertext);
 		g_object_unref (stream);
@@ -429,14 +443,39 @@
 	decrypted = g_mime_parser_construct_part (parser);
 	g_object_unref (parser);
 	
-	if (decrypted) {
-		/* cache the decrypted part */
-		g_object_ref (decrypted);
-		mpe->decrypted = decrypted;
-	} else {
-		g_set_error (err, GMIME_ERROR_QUARK, GMIME_ERROR_PARSE_ERROR,
+	if (!decrypted) {
+		g_set_error (err, GMIME_ERROR, GMIME_ERROR_PARSE_ERROR,
 			     "Failed to decrypt MIME part: parse error");
+		
+		g_mime_signature_validity_free (sv);
+		
+		return NULL;
 	}
 	
+	/* cache the decrypted part */
+	g_object_ref (decrypted);
+	mpe->decrypted = decrypted;
+	mpe->validity = sv;
+	
 	return decrypted;
 }
+
+
+/**
+ * g_mime_multipart_encrypted_get_signature_validity:
+ * @mpe: a #GMimeMultipartEncrypted
+ *
+ * Gets the signature validity of the encrypted MIME part.
+ *
+ * Note: This is only useful after calling
+ * g_mime_multipart_encrypted_decrypt().
+ *
+ * Returns: a #GMimeSignatureValidity.
+ **/
+const GMimeSignatureValidity *
+g_mime_multipart_encrypted_get_signature_validity (GMimeMultipartEncrypted *mpe)
+{
+	g_return_val_if_fail (GMIME_IS_MULTIPART_ENCRYPTED (mpe), NULL);
+	
+	return mpe->validity;
+}

Modified: trunk/gmime/gmime-multipart-encrypted.h
==============================================================================
--- trunk/gmime/gmime-multipart-encrypted.h	(original)
+++ trunk/gmime/gmime-multipart-encrypted.h	Wed Jun  4 03:44:35 2008
@@ -45,9 +45,9 @@
 struct _GMimeMultipartEncrypted {
 	GMimeMultipart parent_object;
 	
-	char *protocol;
-	
+	GMimeSignatureValidity *validity;
 	GMimeObject *decrypted;
+	char *protocol;
 };
 
 struct _GMimeMultipartEncryptedClass {
@@ -61,13 +61,16 @@
 GMimeMultipartEncrypted *g_mime_multipart_encrypted_new (void);
 
 int g_mime_multipart_encrypted_encrypt (GMimeMultipartEncrypted *mpe, GMimeObject *content,
-					GMimeCipherContext *ctx, GPtrArray *recipients,
+					GMimeCipherContext *ctx, gboolean sign,
+					const char *userid, GPtrArray *recipients,
 					GError **err);
 
 GMimeObject *g_mime_multipart_encrypted_decrypt (GMimeMultipartEncrypted *mpe,
 						 GMimeCipherContext *ctx,
 						 GError **err);
 
+const GMimeSignatureValidity *g_mime_multipart_encrypted_get_signature_validity (GMimeMultipartEncrypted *mpe);
+
 G_END_DECLS
 
 #endif /* __GMIME_MULTIPART_ENCRYPTED_H__ */

Modified: trunk/mono/gmime-api.raw
==============================================================================
--- trunk/mono/gmime-api.raw	(original)
+++ trunk/mono/gmime-api.raw	Wed Jun  4 03:44:35 2008
@@ -184,7 +184,7 @@
         </parameters>
       </virtual_method>
       <virtual_method name="Decrypt" cname="decrypt">
-        <return-type type="int" />
+        <return-type type="GMimeSignatureValidity*" />
         <parameters>
           <parameter type="GMimeCipherContext*" name="ctx" />
           <parameter type="GMimeStream*" name="istream" />
@@ -210,7 +210,7 @@
         </parameters>
       </virtual_method>
       <method name="Decrypt" cname="g_mime_cipher_context_decrypt">
-        <return-type type="int" />
+        <return-type type="GMimeSignatureValidity*" />
         <parameters>
           <parameter type="GMimeStream*" name="istream" />
           <parameter type="GMimeStream*" name="ostream" />
@@ -968,8 +968,9 @@
       </method>
     </object>
     <object name="MultipartEncrypted" cname="GMimeMultipartEncrypted" parent="GMimeMultipart">
-      <field name="Protocol" cname="protocol" type="char*" />
+      <field name="Validity" cname="validity" type="GMimeSignatureValidity*" />
       <field name="Decrypted" cname="decrypted" type="GMimeObject*" />
+      <field name="Protocol" cname="protocol" type="char*" />
       <method name="Decrypt" cname="g_mime_multipart_encrypted_decrypt">
         <return-type type="GMimeObject*" />
         <parameters>
@@ -982,10 +983,15 @@
         <parameters>
           <parameter type="GMimeObject*" name="content" />
           <parameter type="GMimeCipherContext*" name="ctx" />
+          <parameter type="gboolean" name="sign" />
+          <parameter type="const-char*" name="userid" />
           <parameter type="GPtrArray*" name="recipients" />
           <parameter type="GError**" name="err" />
         </parameters>
       </method>
+      <method name="GetSignatureValidity" cname="g_mime_multipart_encrypted_get_signature_validity">
+        <return-type type="const-GMimeSignatureValidity*" />
+      </method>
       <method name="GetType" cname="g_mime_multipart_encrypted_get_type" shared="true">
         <return-type type="GType" />
       </method>

Modified: trunk/tests/test-pgpmime.c
==============================================================================
--- trunk/tests/test-pgpmime.c	(original)
+++ trunk/tests/test-pgpmime.c	Wed Jun  4 03:44:35 2008
@@ -107,13 +107,14 @@
 
 
 static void
-print_verify_results (GMimeSignatureValidity *validity)
+print_verify_results (const GMimeSignatureValidity *validity)
 {
 	GMimeSigner *signer;
 	
 	switch (validity->status) {
 	case GMIME_SIGNATURE_STATUS_NONE:
-		fputs ("Unset\n", stdout);
+		fputs ("NONE\n", stdout);
+		break;
 	case GMIME_SIGNATURE_STATUS_GOOD:
 		fputs ("GOOD\n", stdout);
 		break;
@@ -271,9 +272,8 @@
 	g_object_unref (mps);
 	
 	stream = g_mime_stream_mem_new ();
-	g_mime_object_write_to_stream (GMIME_OBJECT (message), stream);
+	g_mime_object_write_to_stream ((GMimeObject *) message, stream);
 	g_mime_stream_reset (stream);
-	
 	g_object_unref (message);
 	
 	parser = g_mime_parser_new ();
@@ -308,16 +308,18 @@
 #define MULTIPART_ENCRYPTED_CONTENT "This is a test of multipart/encrypted.\n"
 
 static void
-test_multipart_encrypted (GMimeCipherContext *ctx)
+test_multipart_encrypted (GMimeCipherContext *ctx, gboolean sign)
 {
+	const GMimeSignatureValidity *sv;
 	GMimeStream *cleartext, *stream;
 	GMimeContentType *content_type;
 	GMimeMultipartEncrypted *mpe;
 	GMimeDataWrapper *content;
 	GMimeObject *decrypted;
-	GMimeMessage *message;
 	GPtrArray *recipients;
+	GMimeMessage *message;
 	Exception *ex = NULL;
+	GMimeParser *parser;
 	GByteArray *buf[2];
 	GError *err = NULL;
 	GMimePart *part;
@@ -347,7 +349,8 @@
 	/* encrypt the part */
 	recipients = g_ptr_array_new ();
 	g_ptr_array_add (recipients, "no user no domain");
-	g_mime_multipart_encrypted_encrypt (mpe, GMIME_OBJECT (part), ctx, recipients, &err);
+	g_mime_multipart_encrypted_encrypt (mpe, GMIME_OBJECT (part), ctx, sign,
+					    "no user no domain", recipients, &err);
 	g_ptr_array_free (recipients, TRUE);
 	g_object_unref (part);
 	
@@ -363,26 +366,65 @@
 	g_mime_message_set_sender (message, "\"Jeffrey Stedfast\" <fejj helixcode com>");
 	g_mime_message_set_reply_to (message, "fejj helixcode com");
 	g_mime_message_add_recipient (message, GMIME_RECIPIENT_TYPE_TO,
-				      "Federico Mena-Quintero", "federico helixcode com");
+				      "Federico Mena-Quintero",
+				      "federico helixcode com");
 	g_mime_message_set_subject (message, "This is a test message");
 	g_mime_object_set_header ((GMimeObject *) message, "X-Mailer", "main.c");
 	g_mime_message_set_mime_part (message, GMIME_OBJECT (mpe));
+	g_object_unref (mpe);
+	
+	stream = g_mime_stream_mem_new ();
+	g_mime_object_write_to_stream ((GMimeObject *) message, stream);
+	g_mime_stream_reset (stream);
+	g_object_unref (message);
+	
+	parser = g_mime_parser_new ();
+	g_mime_parser_init_with_stream (parser, stream);
+	g_object_unref (stream);
+	
+	message = g_mime_parser_construct_message (parser);
+	g_object_unref (parser);
+	
+	if (!GMIME_IS_MULTIPART_ENCRYPTED (message->mime_part)) {
+		ex = exception_new ("resultant top-level mime part not a multipart/encrypted?");
+		g_object_unref (message);
+		throw (ex);
+	}
+	
+	mpe = (GMimeMultipartEncrypted *) message->mime_part;
 	
 	/* okay, now to test our decrypt function... */
 	decrypted = g_mime_multipart_encrypted_decrypt (mpe, ctx, &err);
 	if (!decrypted || err != NULL) {
 		ex = exception_new ("decryption failed: %s", err->message);
+		g_object_unref (cleartext);
+		g_object_unref (mpe);
 		g_error_free (err);
 		throw (ex);
 	}
 	
+	sv = g_mime_multipart_encrypted_get_signature_validity (mpe);
+	v(print_verify_results (sv));
+	
+	if (sign) {
+		if (sv->status != GMIME_SIGNATURE_STATUS_GOOD)
+			ex = exception_new ("signature validity status expected to be GOOD");
+	} else {
+		if (sv->status != GMIME_SIGNATURE_STATUS_NONE)
+			ex = exception_new ("signature validity status expected to be NONE");
+	}
+	
+	g_object_unref (mpe);
+	
+	if (ex != NULL) {
+		g_object_unref (cleartext);
+		throw (ex);
+	}
+	
 	stream = g_mime_stream_mem_new ();
 	g_mime_object_write_to_stream (decrypted, stream);
 	g_object_unref (decrypted);
 	
-	g_object_unref (message);
-	g_object_unref (mpe);
-	
 	buf[0] = GMIME_STREAM_MEM (cleartext)->buffer;
 	buf[1] = GMIME_STREAM_MEM (stream)->buffer;
 	
@@ -480,12 +522,20 @@
 	
 	testsuite_check ("multipart/encrypted");
 	try {
-		test_multipart_encrypted (ctx);
+		test_multipart_encrypted (ctx, FALSE);
 		testsuite_check_passed ();
 	} catch (ex) {
 		testsuite_check_failed ("multipart/encrypted failed: %s", ex->message);
 	} finally;
 	
+	testsuite_check ("multipart/encrypted+sign");
+	try {
+		test_multipart_encrypted (ctx, TRUE);
+		testsuite_check_passed ();
+	} catch (ex) {
+		testsuite_check_failed ("multipart/encrypted+sign failed: %s", ex->message);
+	} finally;
+	
 	g_object_unref (session);
 	g_object_unref (ctx);
 	



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]