Example #1
0
/**
 * 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);
    }
}
Example #2
0
void remove_multipart(GMimeMultipart *multipart) {
  int i=0;

  while (i < g_mime_multipart_get_count(multipart)) {
    int removed = remove_part((GMimeObject*)multipart, g_mime_multipart_get_part(multipart, i));
    if (!removed)
      i++;
  }
}
Example #3
0
static void
multipart_encode (GMimeObject *object, GMimeEncodingConstraint constraint)
{
	GMimeMultipart *multipart = (GMimeMultipart *) object;
	GMimeObject *subpart;
	int i;
	
	for (i = 0; i < g_mime_multipart_get_count (multipart); i++) {
		subpart = g_mime_multipart_get_part (multipart, i);
		g_mime_object_encode (subpart, constraint);
	}
}
Example #4
0
static gboolean
handle_encrypted_part (MuMsg *msg, GMimeMultipartEncrypted *part,
		       MuMsgOptions opts, unsigned *index,
		       MuMsgPartForeachFunc func, gpointer user_data)
{
	GError *err;
	gboolean rv;
	GMimeObject *dec;
	MuMsgPartPasswordFunc pw_func;

	if (opts & MU_MSG_OPTION_CONSOLE_PASSWORD)
		pw_func = (MuMsgPartPasswordFunc)get_console_pw;
	else
		pw_func = NULL;


	err = NULL;
	dec = mu_msg_crypto_decrypt_part (part, opts, pw_func, NULL, &err);
	if (err) {
		g_warning ("error decrypting part: %s", err->message);
		g_clear_error (&err);
	}

	if (dec) {
		rv = handle_mime_object (msg, dec, (GMimeObject *) part,
		                         opts, index, TRUE, func, user_data);
		g_object_unref (dec);
	} else {
		/* On failure to decrypt, list the encrypted part as
		 * an attachment
		 */
		GMimeObject *encrypted;

		encrypted = g_mime_multipart_get_part (
			GMIME_MULTIPART (part), 1);

		g_return_val_if_fail (GMIME_IS_PART(encrypted), FALSE);

		rv = handle_mime_object (msg, encrypted, (GMimeObject *) part,
		                         opts, index, FALSE, func, user_data);
	}

	return rv;
}
Example #5
0
static void
print_body (GMimeMessage *msg)
{
	GMimeObject		*body;
	GMimeDataWrapper	*wrapper;
	GMimeStream		*stream;

	body = g_mime_message_get_body (msg);

	if (GMIME_IS_MULTIPART(body))
		body = g_mime_multipart_get_part (GMIME_MULTIPART(body), 0);

	if (!GMIME_IS_PART(body))
		return;

	wrapper = g_mime_part_get_content_object (GMIME_PART(body));
	if (!GMIME_IS_DATA_WRAPPER(wrapper))
		return;

	stream = g_mime_data_wrapper_get_stream (wrapper);
	if (!GMIME_IS_STREAM(stream))
		return;

	do {
		char	buf[512];
		ssize_t	len;

		len = g_mime_stream_read (stream, buf, sizeof(buf));
		if (len == -1)
			break;

		if (write (fileno(stdout), buf, len) == -1)
			break;

		if (len < (int)sizeof(buf))
			break;

	} while (1);
}
Example #6
0
static void
print_mime_struct (GMimeStream *stream, GMimeObject *part, int depth)
{
	GMimeMultipart *multipart;
	GMimeMessagePart *mpart;
	GMimeContentType *type;
	GMimeObject *subpart;
	GMimeObject *body;
	GMimeMessage *msg;
	int i, n;
	
	print_depth (stream, depth);
	
	type = g_mime_object_get_content_type (part);
	
	g_mime_stream_printf (stream, "Content-Type: %s/%s\n",
			      g_mime_content_type_get_media_type (type),
			      g_mime_content_type_get_media_subtype (type));
	
	if (GMIME_IS_MULTIPART (part)) {
		multipart = (GMimeMultipart *) part;
		
		n = g_mime_multipart_get_count (multipart);
		for (i = 0; i < n; i++) {
			subpart = g_mime_multipart_get_part (multipart, i);
			print_mime_struct (stream, subpart, depth + 1);
		}
	} else if (GMIME_IS_MESSAGE_PART (part)) {
		mpart = (GMimeMessagePart *) part;
		msg = g_mime_message_part_get_message (mpart);
		
		if (msg != NULL) {
			body = g_mime_message_get_mime_part (msg);
			
			print_mime_struct (stream, body, depth + 1);
		}
	}
}
Example #7
0
GMimeObject *
g_mime_gpgme_mpe_decrypt(GMimeMultipartEncrypted * mpe,
			 GMimeGpgmeSigstat ** signature,
			 GtkWindow * parent, GError ** err)
{
    GMimeObject *decrypted, *version, *encrypted;
    GMimeStream *stream, *ciphertext;
    GMimeStream *filtered_stream;
    GMimeContentType *mime_type;
    GMimeGpgmeSigstat *sigstat;
    GMimeDataWrapper *wrapper;
    GMimeFilter *crlf_filter;
    GMimeParser *parser;
    const char *protocol;
    char *content_type;

    g_return_val_if_fail(GMIME_IS_MULTIPART_ENCRYPTED(mpe), NULL);

    if (signature && *signature) {
	g_object_unref(G_OBJECT(*signature));
	*signature = NULL;
    }

    protocol =
	g_mime_object_get_content_type_parameter(GMIME_OBJECT(mpe),
						 "protocol");

    /* make sure the protocol is present and matches the cipher encrypt protocol */
    if (!protocol
	|| g_ascii_strcasecmp("application/pgp-encrypted",
			      protocol) != 0) {
	g_set_error(err, GMIME_ERROR, GMIME_ERROR_PROTOCOL_ERROR,
		    _
		    ("Cannot decrypt multipart/encrypted part: unsupported encryption protocol ā€œ%sā€."),
		    protocol ? protocol : _("(none)"));
	return NULL;
    }

    version =
	g_mime_multipart_get_part(GMIME_MULTIPART(mpe),
				  GMIME_MULTIPART_ENCRYPTED_VERSION);

    /* 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, GMIME_ERROR_PROTOCOL_ERROR, "%s",
		    _
		    ("Cannot decrypt multipart/encrypted part: content-type does not match protocol."));
	g_free(content_type);
	return NULL;
    }
    g_free(content_type);

    /* get the encrypted part and check that it is of type application/octet-stream */
    encrypted =
	g_mime_multipart_get_part(GMIME_MULTIPART(mpe),
				  GMIME_MULTIPART_ENCRYPTED_CONTENT);
    mime_type = g_mime_object_get_content_type(encrypted);
    if (!g_mime_content_type_is_type
	(mime_type, "application", "octet-stream")) {
	g_set_error(err, GMIME_ERROR, GMIME_ERROR_PROTOCOL_ERROR, "%s",
		    _
		    ("Cannot decrypt multipart/encrypted part: unexpected content type"));
	return NULL;
    }

    /* get the ciphertext stream */
    wrapper = g_mime_part_get_content_object(GMIME_PART(encrypted));
    ciphertext = g_mime_data_wrapper_get_decoded_stream(wrapper);
    g_mime_stream_reset(ciphertext);

    stream = g_mime_stream_mem_new();
    filtered_stream = g_mime_stream_filter_new(stream);
    crlf_filter = g_mime_filter_crlf_new(FALSE, FALSE);
    g_mime_stream_filter_add(GMIME_STREAM_FILTER(filtered_stream),
			     crlf_filter);
    g_object_unref(crlf_filter);

    /* get the cleartext */
    sigstat =
	libbalsa_gpgme_decrypt(ciphertext, filtered_stream,
			       GPGME_PROTOCOL_OpenPGP, parent, err);
    if (!sigstat) {
	g_object_unref(filtered_stream);
	g_object_unref(ciphertext);
	g_object_unref(stream);
	return NULL;
    }

    g_mime_stream_flush(filtered_stream);
    g_object_unref(filtered_stream);
    g_object_unref(ciphertext);

    g_mime_stream_reset(stream);
    parser = g_mime_parser_new();
    g_mime_parser_init_with_stream(parser, stream);
    g_object_unref(stream);

    decrypted = g_mime_parser_construct_part(parser);
    g_object_unref(parser);

    if (!decrypted) {
	g_set_error(err, GMIME_ERROR, GMIME_ERROR_PARSE_ERROR, "%s",
		    _
		    ("Cannot decrypt multipart/encrypted part: failed to parse decrypted content"));
	g_object_unref(G_OBJECT(sigstat));
	return NULL;
    }


    /* cache the decrypted part */
    if (signature) {
	if (sigstat->status != GPG_ERR_NOT_SIGNED)
	    *signature = sigstat;
	else
	    g_object_unref(G_OBJECT(sigstat));
    }

    return decrypted;
}
Example #8
0
GMimeGpgmeSigstat *
g_mime_gpgme_mps_verify(GMimeMultipartSigned * mps, GError ** error)
{
    const gchar *protocol;
    gpgme_protocol_t crypto_prot;
    gchar *content_type;
    GMimeObject *content;
    GMimeObject *signature;
    GMimeStream *stream;
    GMimeStream *filtered_stream;
    GMimeFilter *crlf_filter;
    GMimeDataWrapper *wrapper;
    GMimeStream *sigstream;
    GMimeGpgmeSigstat *result;

    g_return_val_if_fail(GMIME_IS_MULTIPART_SIGNED(mps), NULL);

    if (g_mime_multipart_get_count(GMIME_MULTIPART(mps)) < 2) {
	g_set_error(error, GMIME_ERROR, GMIME_ERROR_PARSE_ERROR, "%s",
		    _
		    ("Cannot verify multipart/signed part due to missing subparts."));
	return NULL;
    }

    /* grab the protocol so we can configure the GpgME context */
    protocol =
	g_mime_object_get_content_type_parameter(GMIME_OBJECT(mps),
						 "protocol");
    if (protocol) {
	if (g_ascii_strcasecmp("application/pgp-signature", protocol) == 0)
	    crypto_prot = GPGME_PROTOCOL_OpenPGP;
	else if (g_ascii_strcasecmp
		 ("application/pkcs7-signature", protocol) == 0
		 || g_ascii_strcasecmp("application/x-pkcs7-signature",
				       protocol) == 0)
	    crypto_prot = GPGME_PROTOCOL_CMS;
	else
	    crypto_prot = GPGME_PROTOCOL_UNKNOWN;
    } else
	crypto_prot = GPGME_PROTOCOL_UNKNOWN;

    /* eject on unknown protocols */
    if (crypto_prot == GPGME_PROTOCOL_UNKNOWN) {
	g_set_error(error, GPGME_ERROR_QUARK, GPG_ERR_INV_VALUE,
		    _("unsupported protocol ā€œ%sā€"), protocol);
	return NULL;
    }

    signature =
	g_mime_multipart_get_part(GMIME_MULTIPART(mps),
				  GMIME_MULTIPART_SIGNED_SIGNATURE);

    /* make sure the protocol matches the signature content-type */
    content_type = g_mime_content_type_to_string(signature->content_type);
    if (g_ascii_strcasecmp(content_type, protocol) != 0) {
	g_set_error(error, GMIME_ERROR, GMIME_ERROR_PARSE_ERROR, "%s",
		    _
		    ("Cannot verify multipart/signed part: signature content-type does not match protocol."));
	g_free(content_type);
	return NULL;
    }
    g_free(content_type);

    content =
	g_mime_multipart_get_part(GMIME_MULTIPART(mps),
				  GMIME_MULTIPART_SIGNED_CONTENT);

    /* get the content stream */
    stream = g_mime_stream_mem_new();
    filtered_stream = g_mime_stream_filter_new(stream);

    /* Note: see rfc2015 or rfc3156, section 5.1 */
    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);
    g_mime_stream_reset(stream);

    /* get the signature stream */
    wrapper = g_mime_part_get_content_object(GMIME_PART(signature));

    /* a s/mime signature is always encoded, a pgp signature shouldn't,
     * but there exist implementations which encode it... */
	sigstream = g_mime_stream_mem_new();
	g_mime_data_wrapper_write_to_stream(wrapper, sigstream);
    g_mime_stream_reset(sigstream);

    /* verify the signature */
    result =
	libbalsa_gpgme_verify(stream, sigstream, crypto_prot, FALSE,
			      error);
    g_object_unref(stream);
    g_object_unref(sigstream);

    return result;
}