Skip Menu |

This queue is for tickets about the Mail-GnuPG CPAN distribution.

Report information
The Basics
Id: 2718
Status: open
Priority: 0/
Queue: Mail-GnuPG

People
Owner: Nobody in particular
Requestors: joern [...] zyn.de
Cc:
AdminCc:

Bug Information
Severity: Normal
Broken in: (no value)
Fixed in: (no value)



To: bug-Mail-GnuPG [...] rt.cpan.org
From: Jörn Reder <joern [...] zyn.de>
Subject: verify() broken, conceptual problem with MIME::Entity
Date: Mon, 2 Jun 2003 00:09:52 +0200
Hiho, after some serious debugging trying to find out why some messages can not be verified succesfully with Mail::GnuPG, I found a serious conceptual problem with the module (it's not really a bug in Mail::GnuPG, but it makes wrong assumptions). MIME::Entity stores all data *decoded*, while the sender calculated the signature on the content-transfer *encoded* data. So when using Mail::GnuPG MIME::Parser first decodes the mail, then MIME::Entity->parts(0)->as_string - called by Mail::GnuPG - gives a re-encoded version, but probably with a different result (in particular with quoted-printable, which is a pretty ambigious encoding). It's not possible to reconstruct the original representation once the data was passed through MIME::Parser, and thus it's impossible to verify a signature reliably when using MIME::Entity as the data model (which is pretty comfortable and desirable). So I'm currently working on a patch, which enables handling encoded data with MIME::Parser, MIME::Entity and MIME::Body, which resolves this issue. Regards, Joern -- LINUX - Linux Is Not gnU linuX
Download (untitled)
application/pgp-signature 189b

Message body not shown because it is not plain text.

Show quoted text
> So I'm currently working on a patch, which enables handling encoded data > with MIME::Parser, MIME::Entity and MIME::Body, which resolves this > issue.
I really appreciate this. Thanks for looking into this. I did a bunch of testing before I released the initial version, but apparently I missed many edge cases. (At some point, I need to add a test suite.) I've release 0.05 with your patches. Thanks! -R
Subject: Re: verify() broken, conceptual problem with MIME::Entity
From: joern [...] zyn.de
[joern@zyn.de - Sun Jun 1 18:10:07 2003]: Show quoted text
> So I'm currently working on a patch, which enables handling encoded data > with MIME::Parser, MIME::Entity and MIME::Body, which resolves this > issue.
I created this patch and sent it to the maintainer of MIME-tools. He was not sure, if he accepts it, because it introduces a non-decoded mode, which changes the semantics signficantly resp. break some parts of the module (which are not relevant for our problem of making signature checking possible). Anyway I attach the patch here (for MIME-tools 5.411), because it's the only currently known way to make signature checking with Mail::GnuPG work ;) The patch adds a new method, which tells MIME::Parser to omit decoding: $parser->dont_decode_bodies(1); An entity created with this parser can be passed to Mail::GnuPG->verify. MIME::Entity->print_bodyhandle() gives the original encoded data, but you can't get decoded data from such an entity. You have to decode it yourself, if you need decoded data from it! Regards, Joern
diff -ur MIME-tools-5.411.orig/lib/MIME/Body.pm MIME-tools-5.411/lib/MIME/Body.pm --- MIME-tools-5.411.orig/lib/MIME/Body.pm 2000-11-04 20:54:46.000000000 +0100 +++ MIME-tools-5.411/lib/MIME/Body.pm 2003-06-02 00:37:39.000000000 +0200 @@ -239,6 +239,23 @@ #------------------------------ +=item is_encoded [ONOFF] + +I<Instance method.> +If set to yes, no decoding is applied on output. This flag is set +by MIME::Parser, if the parser runs in dont_decode(1) mode, so the +content is handled transparent and completely unmodified. + +=cut + +sub is_encoded { + my ($self, $yesno) = @_; + $self->{MB_IsEncoded} = $yesno if (@_ > 1); + $self->{MB_IsEncoded}; +} + +#------------------------------ + =item dup I<Instance method.> diff -ur MIME-tools-5.411.orig/lib/MIME/Entity.pm MIME-tools-5.411/lib/MIME/Entity.pm --- MIME-tools-5.411.orig/lib/MIME/Entity.pm 2000-11-06 12:58:53.000000000 +0100 +++ MIME-tools-5.411/lib/MIME/Entity.pm 2003-06-02 00:40:58.000000000 +0200 @@ -1846,14 +1846,21 @@ my ($self, $out) = @_; $out = wraphandle($out || select); ### get a printable output - ### Get the encoding, defaulting to "binary" if unsupported: - my $encoding = ($self->head->mime_encoding || 'binary'); - my $decoder = best MIME::Decoder $encoding; - $decoder->head($self->head); ### associate with head, if any - ### Output the body: my $IO = $self->open("r") || die "open body: $!"; - $decoder->encode($IO, $out) || return error "encoding failed"; + if ( $self->bodyhandle->is_encoded ) { + ### Transparent mode: data is already encoded, so no + ### need to encode it again + my $buf; + $out->print($buf) while ($IO->read($buf, 2048)); + } else { + ### Get the encoding, defaulting to "binary" if unsupported: + my $encoding = ($self->head->mime_encoding || 'binary'); + my $decoder = best MIME::Decoder $encoding; + $decoder->head($self->head); ### associate with head, if any + $decoder->encode($IO, $out) || return error "encoding failed"; + } + $IO->close; 1; } diff -ur MIME-tools-5.411.orig/lib/MIME/Parser.pm MIME-tools-5.411/lib/MIME/Parser.pm --- MIME-tools-5.411.orig/lib/MIME/Parser.pm 2000-11-12 06:55:11.000000000 +0100 +++ MIME-tools-5.411/lib/MIME/Parser.pm 2003-06-02 23:20:19.000000000 +0200 @@ -471,8 +471,37 @@ } +#------------------------------ + +=item dont_decode_bodies [YESNO] + +I<Instance method.> +Controls whether the parser should decode entity bodies or not. +If this is set to a true value (default is false), all entity bodies +will be kept as-is in the original content-transfer encoding. + +To prevent double encoding on the output side MIME::Body->is_encoded +is set, which tells MIME::Body not to encode the data agin, if encoded +data is requested. This is in particular useful, when it's importat that +the content B<must not> be modified, e.g. if you want to calculate +OpenPGP signatures from it. + +B<WARNING>: the semantics change significantly if you parse MIME +messages with this option set, because MIME::Entity resp. MIME::Body +*always* see encoded data now, while the default behaviour is +working with *decoded* data (and encoding it only if you request it). +You need to decode the data yourself, if you want to have it decoded. + +So use this option only if you exactly know, what you're doing, and +that you're sure, that you really need it ;) +=cut +sub dont_decode_bodies { + my ($self, $yesno) = @_; + $self->{MP5_DontDecodeBodies} = $yesno if (@_ > 1); + $self->{MP5_DontDecodeBodies}; +} #------------------------------ # @@ -781,6 +810,10 @@ $ENCODED->seek(0, 0); } + ### Open a new bodyhandle for outputting the data: + my $body = $self->new_body_for($head) || die "$ME: no body\n"; # gotta die + $body->binmode(1) unless textual_type($ent->effective_type); + ### Get a content-decoder to decode this part's encoding: my $encoding = $head->mime_encoding; my $decoder = new MIME::Decoder $encoding; @@ -790,41 +823,52 @@ "application/octet-stream."); ### as per RFC-2045 $ent->effective_type('application/octet-stream'); $decoder = new MIME::Decoder 'binary'; + $encoding = 'binary'; } - ### If desired, sidetrack to troll for UUENCODE: - $self->debug("extract uuencode? ", $self->extract_uuencode); - $self->debug("encoding? ", $encoding); - $self->debug("effective type? ", $ent->effective_type); - if ($self->extract_uuencode and - ($encoding =~ /^(7bit|8bit|binary)\Z/) and - ($ent->effective_type =~ m{^text/plain\Z})) { - - ### Hunt for it: - my $uu_ent = eval { $self->hunt_for_uuencode($ENCODED, $ent) }; - if ($uu_ent) { ### snark - %$ent = %$uu_ent; - return 1; - } - else { ### boojum - $self->whine("while hunting for uuencode: $@"); - $ENCODED->seek(0,0); - } + ### Data should be stored decoded? + if ( !$self->dont_decode_bodies ) { + + ### If desired, sidetrack to troll for UUENCODE: + $self->debug("extract uuencode? ", $self->extract_uuencode); + $self->debug("encoding? ", $encoding); + $self->debug("effective type? ", $ent->effective_type); + if ($self->extract_uuencode and + ($encoding =~ /^(7bit|8bit|binary)\Z/) and + ($ent->effective_type =~ m{^text/plain\Z})) { + + ### Hunt for it: + my $uu_ent = eval { $self->hunt_for_uuencode($ENCODED, $ent) }; + if ($uu_ent) { ### snark + %$ent = %$uu_ent; + return 1; + } + else { ### boojum + $self->whine("while hunting for uuencode: $@"); + $ENCODED->seek(0,0); + } + } + + ### Decode and save the body (using the decoder): + my $DECODED = $body->open("w") || die "$ME: body not opened: $!\n"; + + my $bm = benchmark { + eval { $decoder->decode($ENCODED, $DECODED); }; + $@ and $self->error($@); + }; + $self->debug("t decode: $bm"); + + $DECODED->close; + + } else { + ### No decoding, copy the data as is into the body object + my $HANDLE = $body->open("w") || die "$ME: body not opened: $!\n"; + my $buf; + $HANDLE->print($buf) while ($ENCODED->read($buf, 2048)); + $HANDLE->close; + $body->is_encoded(1); } - - ### Open a new bodyhandle for outputting the data: - my $body = $self->new_body_for($head) || die "$ME: no body\n"; # gotta die - $body->binmode(1) unless textual_type($ent->effective_type); - ### Decode and save the body (using the decoder): - my $DECODED = $body->open("w") || die "$ME: body not opened: $!\n"; - my $bm = benchmark { - eval { $decoder->decode($ENCODED, $DECODED); }; - $@ and $self->error($@); - }; - $self->debug("t decode: $bm"); - $DECODED->close; - ### Success! Remember where we put stuff: $ent->bodyhandle($body);
From: ntyni [...] iki.fi
On Sun Jun 22 16:43:35 2003, JRED wrote: Show quoted text
> [joern@zyn.de - Sun Jun 1 18:10:07 2003]: >
> > So I'm currently working on a patch, which enables handling encoded data > > with MIME::Parser, MIME::Entity and MIME::Body, which resolves this > > issue.
> > I created this patch and sent it to the maintainer of MIME-tools. He was > not sure, if he accepts it, because it introduces a non-decoded mode, > which changes the semantics signficantly resp. break some parts of the > module (which are not relevant for our problem of making signature > checking possible).
Hi, as a heads-up, this patch (or something equivalent) was included in MIME-tools 5.419, and verifying MIME-encoded messages with Mail::GnuPG is now working. For your convenience, I'm attaching a suggested modification to the Mail::GnuPG documentation to recommended this. Cheers, -- Niko Tyni ntyni@iki.fi
--- libmail-gnupg-perl-0.08.orig/GnuPG.pm +++ libmail-gnupg-perl-0.08/GnuPG.pm @@ -338,6 +338,12 @@ The message can either be in RFC compliant-ish multipart/signed format, or just a single part ascii armored message. + Note that MIME-encoded data should be supplied unmodified inside + the MIME::Entity input message, otherwise the signature will be + broken. Since MIME-tools version 5.419, this can be achieved with + the C<decode_bodies> method of MIME::Parser. See the MIME::Parser + documentation for more information. + Output: On error: Exit code of gpg. (0 on success)
I think we've done the best we can here; people need to use decode_bodies(0) option provided by recent versions of MIME::Parser. Feel free to re-open if you think there is more Mail::GnuPG can/should do here.
On Mon Dec 13 21:36:35 2010, DDB wrote: Show quoted text
> I think we've done the best we can here; people need to use > decode_bodies(0) option provided by recent versions of MIME::Parser. > > Feel free to re-open if you think there is more Mail::GnuPG can/should > do here.
Oops. My bad for checking the docs on Debian. It turns out this patch is not applied yet.