/** * sign_prepare: * @mime_part: MIME part * * Prepare a part (and all subparts) to be signed. To do this we need * to set the encoding of all parts (that are not already encoded to * either QP or Base64 or 7-bit) to QP. * * Ref: RFC 3156, sect. 3. **/ static void sign_prepare(GMimeObject * mime_part) { GMimeContentEncoding encoding; GMimeObject *subpart; if (GMIME_IS_MULTIPART(mime_part)) { GMimeMultipart *multipart; int i, n; multipart = (GMimeMultipart *) mime_part; if (GMIME_IS_MULTIPART_SIGNED(multipart) || GMIME_IS_MULTIPART_ENCRYPTED(multipart)) { /* must not modify these parts as they must be treated as opaque */ return; } n = g_mime_multipart_get_count(multipart); for (i = 0; i < n; i++) { subpart = g_mime_multipart_get_part(multipart, i); sign_prepare(subpart); } } else if (GMIME_IS_MESSAGE_PART(mime_part)) { subpart = GMIME_MESSAGE_PART(mime_part)->message->mime_part; sign_prepare(subpart); } else { encoding = g_mime_part_get_content_encoding(GMIME_PART(mime_part)); if ((encoding != GMIME_CONTENT_ENCODING_BASE64) && (encoding != GMIME_CONTENT_ENCODING_7BIT)) g_mime_part_set_content_encoding(GMIME_PART(mime_part), GMIME_CONTENT_ENCODING_QUOTEDPRINTABLE); } }
static void interpret_att(GSList** stack, gchar** args) { GMimePart* pt = g_mime_part_new_with_type(args[1], args[2]); g_mime_part_set_filename(pt, args[0]); g_mime_part_set_content_encoding(pt, GMIME_CONTENT_ENCODING_BASE64); g_mime_object_set_content_id(GMIME_OBJECT(pt), args[0]); add_content(GMIME_CONTENT_ENCODING_BASE64, args[0], pt); add_part(stack, GMIME_OBJECT(pt)); }
static void interpret_text(GSList** stack, gchar** args) { GMimePart* pt = g_mime_part_new(); g_mime_part_set_content_encoding(pt, GMIME_CONTENT_ENCODING_QUOTEDPRINTABLE); g_mime_object_set_content_disposition( GMIME_OBJECT(pt), g_mime_content_disposition_new_from_string(GMIME_DISPOSITION_INLINE)); add_content(GMIME_CONTENT_ENCODING_QUOTEDPRINTABLE, args[0], pt); add_part(stack, GMIME_OBJECT(pt)); }
static void mime_part_encode (GMimeObject *object, GMimeEncodingConstraint constraint) { GMimePart *part = (GMimePart *) object; GMimeContentEncoding encoding; GMimeStream *stream, *null; GMimeFilter *filter; switch (part->encoding) { case GMIME_CONTENT_ENCODING_DEFAULT: /* Unspecified encoding, we need to figure out the * best encoding no matter what */ break; case GMIME_CONTENT_ENCODING_7BIT: /* This encoding is always safe. */ return; case GMIME_CONTENT_ENCODING_8BIT: /* This encoding is safe unless the constraint is 7bit. */ if (constraint != GMIME_ENCODING_CONSTRAINT_7BIT) return; break; case GMIME_CONTENT_ENCODING_BINARY: /* This encoding is only safe if the constraint is binary. */ if (constraint == GMIME_ENCODING_CONSTRAINT_BINARY) return; break; case GMIME_CONTENT_ENCODING_BASE64: case GMIME_CONTENT_ENCODING_QUOTEDPRINTABLE: case GMIME_CONTENT_ENCODING_UUENCODE: /* These encodings are always safe. */ return; } filter = g_mime_filter_best_new (GMIME_FILTER_BEST_ENCODING); null = g_mime_stream_null_new (); stream = g_mime_stream_filter_new (null); g_mime_stream_filter_add ((GMimeStreamFilter *) stream, filter); g_object_unref (null); g_mime_object_write_to_stream (object, stream); g_object_unref (stream); encoding = g_mime_filter_best_encoding ((GMimeFilterBest *) filter, constraint); g_mime_part_set_content_encoding (part, encoding); g_object_unref (filter); }
gboolean g_mime_gpgme_mps_sign(GMimeMultipartSigned * mps, GMimeObject * content, const gchar * userid, gpgme_protocol_t protocol, GtkWindow * parent, GError ** err) { GMimeStream *stream; GMimeStream *filtered; GMimeStream *sigstream; GMimeFilter *filter; GMimeContentType *content_type; GMimeDataWrapper *wrapper; GMimeParser *parser; GMimePart *signature; gchar *micalg; const gchar *proto_type; const gchar *sig_subtype; gpgme_hash_algo_t hash_algo; g_return_val_if_fail(GMIME_IS_MULTIPART_SIGNED(mps), FALSE); g_return_val_if_fail(GMIME_IS_OBJECT(content), FALSE); /* Prepare all the parts for signing... */ sign_prepare(content); /* get the cleartext */ stream = g_mime_stream_mem_new(); filtered = g_mime_stream_filter_new(stream); /* Note: see rfc3156, section 3 - second note */ filter = g_mime_filter_from_new(GMIME_FILTER_FROM_MODE_ARMOR); g_mime_stream_filter_add(GMIME_STREAM_FILTER(filtered), filter); g_object_unref(filter); /* Note: see rfc3156, section 5.4 (this is the main difference between rfc2015 and rfc3156) */ filter = g_mime_filter_strip_new(); g_mime_stream_filter_add(GMIME_STREAM_FILTER(filtered), filter); g_object_unref(filter); g_mime_object_write_to_stream(content, filtered); g_mime_stream_flush(filtered); g_object_unref(filtered); g_mime_stream_reset(stream); /* Note: see rfc2015 or rfc3156, section 5.1 */ filtered = g_mime_stream_filter_new(stream); filter = g_mime_filter_crlf_new(TRUE, FALSE); g_mime_stream_filter_add(GMIME_STREAM_FILTER(filtered), filter); g_object_unref(filter); /* construct the signature stream */ sigstream = g_mime_stream_mem_new(); /* sign the content stream */ hash_algo = libbalsa_gpgme_sign(userid, filtered, sigstream, protocol, FALSE, parent, err); g_object_unref(filtered); if (hash_algo == GPGME_MD_NONE) { g_object_unref(sigstream); g_object_unref(stream); return FALSE; } g_mime_stream_reset(sigstream); g_mime_stream_reset(stream); /* set the multipart/signed protocol and micalg */ content_type = g_mime_object_get_content_type(GMIME_OBJECT(mps)); if (protocol == GPGME_PROTOCOL_OpenPGP) { micalg = g_strdup_printf("PGP-%s", gpgme_hash_algo_name(hash_algo)); proto_type = "application/pgp-signature"; sig_subtype = "pgp-signature"; } else { micalg = g_strdup(gpgme_hash_algo_name(hash_algo)); proto_type = "application/pkcs7-signature"; sig_subtype = "pkcs7-signature"; } g_mime_content_type_set_parameter(content_type, "micalg", micalg); g_free(micalg); g_mime_content_type_set_parameter(content_type, "protocol", proto_type); g_mime_multipart_set_boundary(GMIME_MULTIPART(mps), NULL); /* construct the content part */ parser = g_mime_parser_new_with_stream(stream); content = g_mime_parser_construct_part(parser); g_object_unref(stream); g_object_unref(parser); /* construct the signature part */ signature = g_mime_part_new_with_type("application", sig_subtype); wrapper = g_mime_data_wrapper_new(); g_mime_data_wrapper_set_stream(wrapper, sigstream); g_mime_part_set_content_object(signature, wrapper); g_object_unref(sigstream); g_object_unref(wrapper); /* FIXME: temporary hack, this info should probably be set in * the CipherContext class - maybe ::sign can take/output a * GMimePart instead. */ if (protocol == GPGME_PROTOCOL_CMS) { g_mime_part_set_content_encoding(signature, GMIME_CONTENT_ENCODING_BASE64); g_mime_part_set_filename(signature, "smime.p7m"); } /* save the content and signature parts */ /* FIXME: make sure there aren't any other parts?? */ g_mime_multipart_add(GMIME_MULTIPART(mps), content); g_mime_multipart_add(GMIME_MULTIPART(mps), (GMimeObject *) signature); g_object_unref(signature); g_object_unref(content); return TRUE; }
gboolean g_mime_gpgme_mpe_encrypt(GMimeMultipartEncrypted * mpe, GMimeObject * content, GPtrArray * recipients, gboolean trust_all, GtkWindow * parent, GError ** err) { GMimeStream *filtered_stream; GMimeStream *ciphertext; GMimeStream *stream; GMimePart *version_part; GMimePart *encrypted_part; GMimeDataWrapper *wrapper; GMimeFilter *crlf_filter; g_return_val_if_fail(GMIME_IS_MULTIPART_ENCRYPTED(mpe), FALSE); g_return_val_if_fail(GMIME_IS_OBJECT(content), FALSE); /* get the cleartext */ stream = g_mime_stream_mem_new(); filtered_stream = g_mime_stream_filter_new(stream); crlf_filter = g_mime_filter_crlf_new(TRUE, FALSE); g_mime_stream_filter_add(GMIME_STREAM_FILTER(filtered_stream), crlf_filter); g_object_unref(crlf_filter); g_mime_object_write_to_stream(content, filtered_stream); g_mime_stream_flush(filtered_stream); g_object_unref(filtered_stream); /* reset the content stream */ g_mime_stream_reset(stream); /* encrypt the content stream */ ciphertext = g_mime_stream_mem_new(); if (!libbalsa_gpgme_encrypt (recipients, NULL, stream, ciphertext, GPGME_PROTOCOL_OpenPGP, FALSE, trust_all, parent, err)) { g_object_unref(ciphertext); g_object_unref(stream); return FALSE; } g_object_unref(stream); g_mime_stream_reset(ciphertext); /* construct the version part */ version_part = g_mime_part_new_with_type("application", "pgp-encrypted"); g_mime_part_set_content_encoding(version_part, GMIME_CONTENT_ENCODING_7BIT); stream = g_mime_stream_mem_new_with_buffer("Version: 1\n", strlen("Version: 1\n")); wrapper = g_mime_data_wrapper_new_with_stream(stream, GMIME_CONTENT_ENCODING_7BIT); g_mime_part_set_content_object(version_part, wrapper); g_object_unref(wrapper); g_object_unref(stream); /* construct the encrypted mime part */ encrypted_part = g_mime_part_new_with_type("application", "octet-stream"); g_mime_part_set_content_encoding(encrypted_part, GMIME_CONTENT_ENCODING_7BIT); wrapper = g_mime_data_wrapper_new_with_stream(ciphertext, GMIME_CONTENT_ENCODING_7BIT); g_mime_part_set_content_object(encrypted_part, wrapper); g_object_unref(ciphertext); g_object_unref(wrapper); /* save the version and encrypted parts */ /* FIXME: make sure there aren't any other parts?? */ g_mime_multipart_add(GMIME_MULTIPART(mpe), GMIME_OBJECT(version_part)); g_mime_multipart_add(GMIME_MULTIPART(mpe), GMIME_OBJECT(encrypted_part)); g_object_unref(encrypted_part); g_object_unref(version_part); /* set the content-type params for this multipart/encrypted part */ g_mime_object_set_content_type_parameter(GMIME_OBJECT(mpe), "protocol", "application/pgp-encrypted"); g_mime_multipart_set_boundary(GMIME_MULTIPART(mpe), NULL); return TRUE; }