[Rt-commit] rt branch, 4.2/smime-v2, updated. rt-4.0.4-555-gd60801c

Kevin Falcone falcone at bestpractical.com
Thu Oct 25 18:59:12 EDT 2012


The branch, 4.2/smime-v2 has been updated
       via  d60801c786c92e5d18fb80ae4828ba79eee3ed7b (commit)
       via  4c1c529e4e3ebe7316469530499ed83185404e91 (commit)
       via  ea25753a1be2621ba62f849949aa00c7ae5eb556 (commit)
       via  28e586a11fdb9678f62ac5c2ef4c7af2d2f43508 (commit)
       via  340b8bd6e1b5937b683531fe50ff03aaf18b4b2f (commit)
       via  571084f5850e524c71392cb5b34bdfba6c1d3dfa (commit)
       via  df8482be85182e54dcf31581e9e24ea63c465d61 (commit)
       via  e6fc42016afb57211d143520434cbdf42da2e2a4 (commit)
       via  86995855afc52805f913897d42fafdcb806f741a (commit)
       via  e47938fdd51996c3133aa1939012da380c71b719 (commit)
       via  5308d42099e1b2545d14d48e3a9d4918e3bd2f9c (commit)
       via  d0726f702207676c525b5058b0f776e5f0f9a8d0 (commit)
       via  9c0209d22150b19dec5efecbd798afb23b86fcbb (commit)
       via  6c916bb49e77eccfb00eeb3525e7980203e48c05 (commit)
       via  1fa2b694d7ceab13f74be9dd767de103eb1311fa (commit)
       via  cc6637fbf0bb7563642f68b3f1926c34cba54b23 (commit)
       via  f604a25c6cee379ff810c79944c6790f8a8867ab (commit)
      from  19c26e9111264d9ce8d1c0203827131f7edc86c3 (commit)

Summary of changes:
 lib/RT/Action/SendEmail.pm                      | 54 +++++++++----------------
 lib/RT/Crypt/GnuPG.pm                           | 12 +++++-
 lib/RT/Crypt/SMIME.pm                           |  8 ++++
 lib/RT/Interface/Email.pm                       | 52 ++++++++++++++++--------
 lib/RT/Interface/Email/Auth/Crypt.pm            |  8 ++--
 lib/RT/Interface/Web.pm                         |  5 +--
 lib/RT/Queue.pm                                 | 40 ++++++++++++++----
 lib/RT/User.pm                                  |  1 +
 share/html/Admin/Articles/Elements/Topics       |  2 +-
 share/html/Admin/CustomFields/Modify.html       |  4 +-
 share/html/Admin/Queues/Modify.html             |  6 ++-
 share/html/Admin/Users/GnuPG.html               | 15 +++++--
 share/html/Approvals/Elements/PendingMyApproval |  4 +-
 share/html/Elements/CreateTicket                |  2 +-
 share/html/Elements/Crypt/SignEncryptWidget     | 10 +++--
 share/html/Elements/Footer                      |  4 +-
 share/html/Install/DatabaseType.html            |  2 +-
 share/html/Install/Finish.html                  |  2 +-
 share/html/Search/Chart.html                    |  2 +-
 share/html/Search/Simple.html                   | 10 ++---
 share/html/l                                    |  2 +-
 share/html/{l => l_unsafe}                      |  0
 share/html/m/_elements/footer                   |  2 +-
 t/crypt/no-signer-address.t                     |  2 +-
 24 files changed, 153 insertions(+), 96 deletions(-)
 copy share/html/{l => l_unsafe} (100%)

- Log -----------------------------------------------------------------
commit f604a25c6cee379ff810c79944c6790f8a8867ab
Author: Alex Vandiver <alexmv at bestpractical.com>
Date:   Mon Aug 27 19:59:54 2012 -0400

    Fix a typo, preventing emails from setting internal encryption header
    
    X-RT-Incoming-Encryption, along with a number of other headers, is
    removed from all parts of incoming emails because they are used to
    annotate GPG-related properties of the message.  Fix a typo, which
    allowed the properly-spelled header to pass through under specific
    circumstances.

diff --git a/lib/RT/Interface/Email/Auth/Crypt.pm b/lib/RT/Interface/Email/Auth/Crypt.pm
index 3c9c957..13b6b61 100644
--- a/lib/RT/Interface/Email/Auth/Crypt.pm
+++ b/lib/RT/Interface/Email/Auth/Crypt.pm
@@ -114,7 +114,7 @@ sub GetCurrentUser {
     # we clean all possible headers
     my @headers =
         qw(
-            X-RT-Incoming-Encrypton
+            X-RT-Incoming-Encryption
             X-RT-Incoming-Signature
             X-RT-Privacy
         ),

commit cc6637fbf0bb7563642f68b3f1926c34cba54b23
Author: Alex Vandiver <alexmv at bestpractical.com>
Date:   Mon Aug 27 21:24:25 2012 -0400

    Remove internal signing and encryption hints from incoming mail
    
    RT uses the existance of the X-RT-Sign and X-RT-Encrypt headers to
    decide if the outgoing mails it sends as a result of the transaction
    should be signed and/or encrypted.  It standardly inserts these headers
    based on checkboxes visable in the web UI; however, it fails to remove
    them from incoming mails, allowing external users to create nearly
    arbitrary messages signed by the queue's key.

diff --git a/lib/RT/Interface/Email/Auth/Crypt.pm b/lib/RT/Interface/Email/Auth/Crypt.pm
index 13b6b61..625abeb 100644
--- a/lib/RT/Interface/Email/Auth/Crypt.pm
+++ b/lib/RT/Interface/Email/Auth/Crypt.pm
@@ -117,6 +117,8 @@ sub GetCurrentUser {
             X-RT-Incoming-Encryption
             X-RT-Incoming-Signature
             X-RT-Privacy
+            X-RT-Sign
+            X-RT-Encrypt
         ),
         map "X-RT-$_-Status", RT::Crypt->Protocols;
     foreach my $p ( $args{'Message'}->parts_DFS ) {

commit 1fa2b694d7ceab13f74be9dd767de103eb1311fa
Author: Alex Vandiver <alexmv at bestpractical.com>
Date:   Thu Aug 30 17:16:41 2012 -0400

    Restrict users to only signing with queue or their own personal keys
    
    While the UI only presents two options for signing, the underlying form
    accepted any key ID or email address, and dutifully signed the mail with
    the appropriate secret key.  Restrict the accepted values of SignUsing
    to the two values that we displayed.
    (cherry picked from commit aeaeb9cf58240603bb8a7d6d951518d32e8512a6)
    
    Conflicts:
    
    	share/html/Elements/Crypt/SignEncryptWidget

diff --git a/share/html/Elements/Crypt/SignEncryptWidget b/share/html/Elements/Crypt/SignEncryptWidget
index d3be307..c5742d9 100644
--- a/share/html/Elements/Crypt/SignEncryptWidget
+++ b/share/html/Elements/Crypt/SignEncryptWidget
@@ -136,12 +136,16 @@ if ( $self->{'Sign'} ) {
     $QueueObj ||= $TicketObj->QueueObj
         if $TicketObj;
 
-    my $address = $self->{'SignUsing'};
-    $address ||= ($self->{'UpdateType'} && $self->{'UpdateType'} eq "private")
+    my $private = $session{'CurrentUser'}->UserObj->PrivateKey || '';
+    my $queue = ($self->{'UpdateType'} && $self->{'UpdateType'} eq "private")
         ? ( $QueueObj->CommentAddress || RT->Config->Get('CommentAddress') )
         : ( $QueueObj->CorrespondAddress || RT->Config->Get('CorrespondAddress') );
 
-    unless ( RT::Crypt->DrySign( Signer => $address ) ) {
+    my $address = $self->{'SignUsing'} || $queue;
+    if ($address ne $private and $address ne $queue) {
+        push @{ $self->{'GnuPGCanNotSignAs'} ||= [] }, $address;
+        $checks_failure = 1;
+    } elsif ( not RT::Crypt->DrySign( Signer => $address ) ) {
         push @{ $self->{'GnuPGCanNotSignAs'} ||= [] }, $address;
         $checks_failure = 1;
     } else {

commit 6c916bb49e77eccfb00eeb3525e7980203e48c05
Author: Alex Vandiver <alexmv at bestpractical.com>
Date:   Thu Aug 30 18:42:55 2012 -0400

    Don't propose any secret keys to users with no email address
    
    GetKeysForSigning, when called with 'force', returns all keys if no
    email address is provided.  This caused users with no email address to
    have all secret keys offered to them.  Remove the 'force' to ensure that
    empty email address are shown an empty list.
    (cherry picked from commit 10e4a18a61b07b505bae8e9ffff65708a97fc659)
    
    Conflicts:
    
    	share/html/Admin/Users/GnuPG.html

diff --git a/share/html/Admin/Users/GnuPG.html b/share/html/Admin/Users/GnuPG.html
index b97e0a0..60f0797 100644
--- a/share/html/Admin/Users/GnuPG.html
+++ b/share/html/Admin/Users/GnuPG.html
@@ -64,7 +64,7 @@
 <& /Widgets/Form/Select,
     Name         => 'PrivateKey',
     Description  => loc('Private Key'),
-    Values       => [ map $_->{'Key'}, @{ $keys_meta{'info'} } ],
+    Values       => \@potential_keys,
     CurrentValue => $UserObj->PrivateKey,
     DefaultLabel => loc('No private key'),
 &>
@@ -91,7 +91,8 @@ unless ( $UserObj->id ) {
 $id = $ARGS{'id'} = $UserObj->id;
 
 my $email = $UserObj->EmailAddress;
-my %keys_meta = RT::Crypt->GetKeysForSigning( $email, Force => 1 );
+my %keys_meta = RT::Crypt->GetKeysForSigning( $email );
+my @potential_keys = map $_->{'Key'}, @{ $keys_meta{'info'} || [] };
 
 $ARGS{'PrivateKey'} = $m->comp('/Widgets/Form/Select:Process',
     Name      => 'PrivateKey',

commit 9c0209d22150b19dec5efecbd798afb23b86fcbb
Author: Alex Vandiver <alexmv at bestpractical.com>
Date:   Thu Aug 30 22:42:22 2012 -0400

    Explicitly restrict private keys to ones offered
    (cherry picked from commit b32d9f5ffe7b60816942c91a6b7cb62992910369)

diff --git a/share/html/Admin/Users/GnuPG.html b/share/html/Admin/Users/GnuPG.html
index 60f0797..af46f0c 100644
--- a/share/html/Admin/Users/GnuPG.html
+++ b/share/html/Admin/Users/GnuPG.html
@@ -101,8 +101,12 @@ $ARGS{'PrivateKey'} = $m->comp('/Widgets/Form/Select:Process',
 );
 
 if ( $Update ) {
-    my ($status, $msg) = $UserObj->SetPrivateKey( $ARGS{'PrivateKey'} );
-    push @results, $msg;
+    if (not $ARGS{'PrivateKey'} or grep {$_ eq $ARGS{'PrivateKey'}} @potential_keys) {
+        my ($status, $msg) = $UserObj->SetPrivateKey( $ARGS{'PrivateKey'} );
+        push @results, $msg;
+    } else {
+        push @results, loc("Invalid key [_1] for address '[_2]'", $ARGS{'PrivateKey'}, $email);
+    }
 }
 
 my $title = loc("[_1]'s GnuPG keys",$UserObj->Name);

commit d0726f702207676c525b5058b0f776e5f0f9a8d0
Author: Alex Vandiver <alexmv at bestpractical.com>
Date:   Thu Aug 30 22:46:32 2012 -0400

    Avoid spurious update and warning messages on key update
    
    This avoids an ominous-looking warning about failure to remove the key,
    when no key was previously set but no key was newly selected.
    (cherry picked from commit cd0235bda39972fabecd837d982dd9f1619296c4)

diff --git a/share/html/Admin/Users/GnuPG.html b/share/html/Admin/Users/GnuPG.html
index af46f0c..a28621b 100644
--- a/share/html/Admin/Users/GnuPG.html
+++ b/share/html/Admin/Users/GnuPG.html
@@ -102,8 +102,10 @@ $ARGS{'PrivateKey'} = $m->comp('/Widgets/Form/Select:Process',
 
 if ( $Update ) {
     if (not $ARGS{'PrivateKey'} or grep {$_ eq $ARGS{'PrivateKey'}} @potential_keys) {
-        my ($status, $msg) = $UserObj->SetPrivateKey( $ARGS{'PrivateKey'} );
-        push @results, $msg;
+        if (($ARGS{'PrivateKey'}||'') ne ($UserObj->PrivateKey||'')) {
+            my ($status, $msg) = $UserObj->SetPrivateKey( $ARGS{'PrivateKey'} );
+            push @results, $msg;
+        }
     } else {
         push @results, loc("Invalid key [_1] for address '[_2]'", $ARGS{'PrivateKey'}, $email);
     }

commit 5308d42099e1b2545d14d48e3a9d4918e3bd2f9c
Author: Alex Vandiver <alexmv at bestpractical.com>
Date:   Thu Aug 30 23:58:40 2012 -0400

    Require AdminUser to set PGP private key IDs, not merely ModifySelf
    
    Be explicit that modification of the PrivateKey pseudo-column requires
    admin rights -- namely, AdminUser, not just ModifySelf.  While the page
    that controlls that property is in /Admin/Users/GnuPG.html, accessing
    that page requires only the ShowConfigTab right, and modifying the
    property on yourself required only ModifySelf.  Combined with the
    ability (also granted by ModifySelf) for users to change their own email
    addresses, this opened the possibility for users to claim arbitrary
    private keys as their own, for use in signing.
    (cherry picked from commit 8ce033b38ced865622a2823aa266ae9bbc251811)

diff --git a/lib/RT/User.pm b/lib/RT/User.pm
index ff91ded..4bc75ea 100644
--- a/lib/RT/User.pm
+++ b/lib/RT/User.pm
@@ -102,6 +102,7 @@ sub _OverlayAccessible {
           AuthSystem            => { public => 1,  admin => 1 },
           Gecos                 => { public => 1,  admin => 1 },
           PGPKey                => { public => 1,  admin => 1 },
+          PrivateKey            => {               admin => 1 },
 
     }
 }

commit e47938fdd51996c3133aa1939012da380c71b719
Author: Alex Vandiver <alexmv at bestpractical.com>
Date:   Fri Aug 31 00:17:08 2012 -0400

    Ensure that no --arguments can be snuck to GPG commands as arguments
    
    GnuPG::Interface 0.46 adds code to prefix command_args with a "--" if it
    doesn't have one already.  Rather than bump the dependency, explicitly
    add the "--" in the two places that we pass in command_args.
    (cherry picked from commit 1f213d6989e646e0163c901b0567ba1c94a311a8)
    
    Conflicts:
    
    	lib/RT/Crypt/GnuPG.pm

diff --git a/lib/RT/Crypt/GnuPG.pm b/lib/RT/Crypt/GnuPG.pm
index e6b74ea..b9ab40b 100644
--- a/lib/RT/Crypt/GnuPG.pm
+++ b/lib/RT/Crypt/GnuPG.pm
@@ -1765,7 +1765,7 @@ sub GetKeysInfo {
             'fixed-list-mode' => undef, # don't merge uid with keys
         },
         Command     => $method,
-        ( $email ? (CommandArgs => [$email]) : () ),
+        ( $email ? (CommandArgs => ["--",$email]) : () ),
         Output      => \@info,
     );
     return %res if $res{'message'};
@@ -1915,7 +1915,7 @@ sub DeleteKey {
 
     return $self->CallGnuPG(
         Command     => "--delete-secret-and-public-key",
-        CommandArgs => [$key],
+        CommandArgs => ["--",$key],
         Callback    => sub {
             my %handle = @_;
             while ( my $str = readline $handle{'status'} ) {

commit 86995855afc52805f913897d42fafdcb806f741a
Author: Alex Vandiver <alexmv at bestpractical.com>
Date:   Fri Aug 31 21:12:02 2012 -0400

    Refactor shared code controlling if a message will be encrypted or signed
    (cherry picked from commit 8f242072bb196e155ec9a5fbbf06bc8a2d3c2813)
    
    Conflicts:
    
    	lib/RT/Interface/Email.pm

diff --git a/lib/RT/Action/SendEmail.pm b/lib/RT/Action/SendEmail.pm
index ad1136f..a9fff28 100644
--- a/lib/RT/Action/SendEmail.pm
+++ b/lib/RT/Action/SendEmail.pm
@@ -106,23 +106,10 @@ sub Commit {
     if (   RT->Config->Get('RecordOutgoingEmail')
         && RT->Config->Get('GnuPG')->{'Enable'} )
     {
-
-        # it's hacky, but we should know if we're going to crypt things
-        my $attachment = $self->TransactionObj->Attachments->First;
-
-        my %crypt;
-        foreach my $argument (qw(Sign Encrypt)) {
-            if ( $attachment
-                && defined $attachment->GetHeader("X-RT-$argument") )
-            {
-                $crypt{$argument} = $attachment->GetHeader("X-RT-$argument");
-            } else {
-                $crypt{$argument} = $self->TicketObj->QueueObj->$argument();
-            }
-        }
-        if ( $crypt{'Sign'} || $crypt{'Encrypt'} ) {
-            $orig_message = $message->dup;
-        }
+        $orig_message = $message->dup if RT::Interface::Email::WillSignEncrypt(
+            Attachment => $self->TransactionObj->Attachments->First,
+            Ticket     => $self->TicketObj,
+        );
     }
 
     my ($ret) = $self->SendMessage($message);
diff --git a/lib/RT/Interface/Email.pm b/lib/RT/Interface/Email.pm
index cfb7395..edaaec6 100644
--- a/lib/RT/Interface/Email.pm
+++ b/lib/RT/Interface/Email.pm
@@ -317,6 +317,24 @@ header field then it's value is used
 
 =cut
 
+sub WillSignEncrypt {
+    my %args = @_;
+    my $attachment = delete $args{Attachment};
+    my $ticket     = delete $args{Ticket};
+
+    for my $argument ( qw(Sign Encrypt) ) {
+        next if defined $args{ $argument };
+
+        if ( $attachment and defined $attachment->GetHeader("X-RT-$argument") ) {
+            $args{$argument} = $attachment->GetHeader("X-RT-$argument");
+        } elsif ( $ticket ) {
+            $args{$argument} = $ticket->QueueObj->$argument();
+        }
+    }
+
+    return wantarray ? %args : ($args{Sign} || $args{Encrypt});
+}
+
 sub SendEmail {
     my (%args) = (
         Entity => undef,
@@ -365,23 +383,12 @@ sub SendEmail {
     }
 
     if ( RT->Config->Get('Crypt')->{'Enable'} ) {
-        my %crypt;
-
-        my $attachment;
-        $attachment = $TransactionObj->Attachments->First
-            if $TransactionObj;
-
-        foreach my $argument ( qw(Sign Encrypt) ) {
-            next if defined $args{ $argument };
-
-            if ( $attachment && defined $attachment->GetHeader("X-RT-$argument") ) {
-                $crypt{$argument} = $attachment->GetHeader("X-RT-$argument");
-            } elsif ( $TicketObj ) {
-                $crypt{$argument} = $TicketObj->QueueObj->$argument();
-            }
-        }
-
-        my $res = SignEncrypt( %args, %crypt );
+        %args = WillSignEncrypt(
+            %args,
+            Attachment => $TransactionObj ? $TransactionObj->Attachments->First : undef,
+            Ticket     => $TicketObj,
+        );
+        my $res = SignEncrypt( %args );
         return $res unless $res > 0;
     }
 

commit e6fc42016afb57211d143520434cbdf42da2e2a4
Author: Alex Vandiver <alexmv at bestpractical.com>
Date:   Fri Aug 31 21:15:26 2012 -0400

    Refactor RT::Action::SendEmail->Commit to consolidate RecordOutgoingEmail path
    
    Instead of interweaving the logic around the case where
    RecordOutgoingEmail is disabled, resolve that simple case first.
    (cherry picked from commit 08555f51ff8a4105aaaf34725d6b8df356203a86)

diff --git a/lib/RT/Action/SendEmail.pm b/lib/RT/Action/SendEmail.pm
index a9fff28..4a35920 100644
--- a/lib/RT/Action/SendEmail.pm
+++ b/lib/RT/Action/SendEmail.pm
@@ -99,34 +99,31 @@ activated in the config.
 sub Commit {
     my $self = shift;
 
-    $self->DeferDigestRecipients() if RT->Config->Get('RecordOutgoingEmail');
+    return abs $self->SendMessage( $self->TemplateObj->MIMEObj )
+        unless RT->Config->Get('RecordOutgoingEmail');
+
+    $self->DeferDigestRecipients();
     my $message = $self->TemplateObj->MIMEObj;
 
     my $orig_message;
-    if (   RT->Config->Get('RecordOutgoingEmail')
-        && RT->Config->Get('GnuPG')->{'Enable'} )
-    {
-        $orig_message = $message->dup if RT::Interface::Email::WillSignEncrypt(
-            Attachment => $self->TransactionObj->Attachments->First,
-            Ticket     => $self->TicketObj,
-        );
-    }
+    $orig_message = $message->dup if RT::Interface::Email::WillSignEncrypt(
+        Attachment => $self->TransactionObj->Attachments->First,
+        Ticket     => $self->TicketObj,
+    );
 
     my ($ret) = $self->SendMessage($message);
-    if ( $ret > 0 && RT->Config->Get('RecordOutgoingEmail') ) {
-        if ($orig_message) {
-            $message->attach(
-                Type        => 'application/x-rt-original-message',
-                Disposition => 'inline',
-                Data        => $orig_message->as_string,
-            );
-        }
-        $self->RecordOutgoingMailTransaction($message);
-        $self->RecordDeferredRecipients();
-    }
-
+    return abs( $ret ) if $ret <= 0;
 
-    return ( abs $ret );
+    if ($orig_message) {
+        $message->attach(
+            Type        => 'application/x-rt-original-message',
+            Disposition => 'inline',
+            Data        => $orig_message->as_string,
+        );
+    }
+    $self->RecordOutgoingMailTransaction($message);
+    $self->RecordDeferredRecipients();
+    return 1;
 }
 
 =head2 Prepare
diff --git a/lib/RT/Interface/Email.pm b/lib/RT/Interface/Email.pm
index edaaec6..1ada952 100644
--- a/lib/RT/Interface/Email.pm
+++ b/lib/RT/Interface/Email.pm
@@ -322,6 +322,11 @@ sub WillSignEncrypt {
     my $attachment = delete $args{Attachment};
     my $ticket     = delete $args{Ticket};
 
+    if ( not RT->Config->Get('Crypt')->{'Enable'} ) {
+        $args{Sign} = $args{Encrypt} = 0;
+        return wantarray ? %args : 0;
+    }
+
     for my $argument ( qw(Sign Encrypt) ) {
         next if defined $args{ $argument };
 

commit df8482be85182e54dcf31581e9e24ea63c465d61
Author: Alex Vandiver <alexmv at bestpractical.com>
Date:   Fri Aug 31 23:25:27 2012 -0400

    When creating tickets via the UI, always set signing/encryption headers
    (cherry picked from commit e50f6496cfd15a3b9e1e24b67c9b1b721107d6a5)

diff --git a/lib/RT/Interface/Web.pm b/lib/RT/Interface/Web.pm
index 450e801..ca5c6c3 100644
--- a/lib/RT/Interface/Web.pm
+++ b/lib/RT/Interface/Web.pm
@@ -1352,9 +1352,8 @@ sub CreateTicket {
         }
     }
 
-    foreach my $argument (qw(Encrypt Sign)) {
-        $MIMEObj->head->replace( "X-RT-$argument" => $ARGS{$argument} ? 1 : 0 )
-          if defined $ARGS{$argument};
+    for my $argument (qw(Encrypt Sign)) {
+        $MIMEObj->head->replace( "X-RT-$argument" => $ARGS{$argument} ? 1 : 0 );
     }
 
     my %create_args = (

commit 571084f5850e524c71392cb5b34bdfba6c1d3dfa
Author: Thomas Sibley <trs at bestpractical.com>
Date:   Tue Mar 27 17:36:41 2012 -0400

    Escape all arguments passed to /l
    
    Escaping arguments prevents one of the easiest ways to accidentally
    write XSS vectors.  For /l calls which pass HTML in their arguments,
    /l_unsafe is provided which preserves the previous behaviour.  Note that
    the text to be localized itself is not escaped, only the placeholder
    values.  Hopefully seeing "unsafe" in the name will also make folks
    pause and consider what they're doing.
    
    Partially resolves CVE-2011-2083.
    (cherry picked from commit a2a50999aa214fa01bb824d2b6fcec197ec2a8e9)

diff --git a/share/html/Admin/Articles/Elements/Topics b/share/html/Admin/Articles/Elements/Topics
index 96ddaf0..43ca956 100644
--- a/share/html/Admin/Articles/Elements/Topics
+++ b/share/html/Admin/Articles/Elements/Topics
@@ -105,7 +105,7 @@ $topic
 % }
 % if ($Action) {
 % unless ($Action eq "Move" and grep {$_->getNodeValue->Id == $Modify} $Element->getAllChildren) {
-<li><input type="submit" name="<%$Prefix%>-<%$topic eq "root" ? 0 : $topic->Id%>" value="<&|/l&><%$Action%> here</&>" /></li>
+<li><input type="submit" name="<%$Prefix%>-<%$topic eq "root" ? 0 : $topic->Id%>" value="<% $Action eq 'Move' ? loc('Move here') : loc('Add here') %>" /></li>
 % }
 % }
 </ul>
diff --git a/share/html/Admin/CustomFields/Modify.html b/share/html/Admin/CustomFields/Modify.html
index 8d5a46a..0110b7d 100644
--- a/share/html/Admin/CustomFields/Modify.html
+++ b/share/html/Admin/CustomFields/Modify.html
@@ -105,7 +105,7 @@
 <div class="hints">
 <&|/l&>RT can make this custom field's values into hyperlinks to another service.</&>
 <&|/l&>Fill in this field with a URL.</&>
-<&|/l, '<tt>__id__</tt>', '<tt>__CustomField__</tt>' &>RT will replace [_1] and [_2] with the record's id and the custom field's value, respectively.</&>
+<&|/l_unsafe, '<tt>__id__</tt>', '<tt>__CustomField__</tt>' &>RT will replace [_1] and [_2] with the record's id and the custom field's value, respectively.</&>
 </div></td></tr>
 
 <tr><td class="label"><&|/l&>Include page</&></td><td>
@@ -113,7 +113,7 @@
 <div class="hints">
 <&|/l&>RT can include content from another web service when showing this custom field.</&>
 <&|/l&>Fill in this field with a URL.</&>
-<&|/l, '<tt>__id__</tt>', '<tt>__CustomField__</tt>' &>RT will replace [_1] and [_2] with the record's id and the custom field's value, respectively.</&>
+<&|/l_unsafe, '<tt>__id__</tt>', '<tt>__CustomField__</tt>' &>RT will replace [_1] and [_2] with the record's id and the custom field's value, respectively.</&>
 <i><&|/l&>Some browsers may only load content from the same domain as your RT server.</&></i>
 </div></td></tr>
 
diff --git a/share/html/Approvals/Elements/PendingMyApproval b/share/html/Approvals/Elements/PendingMyApproval
index 75ad5e1a..d2061da 100755
--- a/share/html/Approvals/Elements/PendingMyApproval
+++ b/share/html/Approvals/Elements/PendingMyApproval
@@ -63,9 +63,9 @@
 <input type="checkbox" class="checkbox" value="1" name="ShowRejected" <% defined($ARGS{'ShowRejected'}) && $ARGS{'ShowRejected'} && qq[checked="checked"] |n%> /> <&|/l&>Show denied requests</&><br />
 <input type="checkbox" class="checkbox" value="1" name="ShowDependent" <% defined($ARGS{'ShowDependent'}) && $ARGS{'ShowDependent'} && qq[checked="checked"] |n%> /> <&|/l&>Show requests awaiting other approvals</&><br />
 
-<&|/l, qq{<input size='15' class="ui-datepicker" value='}.($created_before->Unix > 0 &&$created_before->ISO(Timezone => 'user'))."' name='CreatedBefore' id='CreatedBefore' />"&>Only show approvals for requests created before [_1]</&><br />
+<&|/l_unsafe, qq{<input size='15' class="ui-datepicker" value='}.($created_before->Unix > 0 &&$created_before->ISO(Timezone => 'user'))."' name='CreatedBefore' id='CreatedBefore' />"&>Only show approvals for requests created before [_1]</&><br />
 
-<&|/l, qq{<input size='15' class="ui-datepicker" value='}.( $created_after->Unix >0 && $created_after->ISO(Timezone => 'user'))."' name='CreatedAfter' id='CreatedAfter' />"&>Only show approvals for requests created after [_1]</&>
+<&|/l_unsafe, qq{<input size='15' class="ui-datepicker" value='}.( $created_after->Unix >0 && $created_after->ISO(Timezone => 'user'))."' name='CreatedAfter' id='CreatedAfter' />"&>Only show approvals for requests created after [_1]</&>
 </&>
 
 <%init>
diff --git a/share/html/Elements/CreateTicket b/share/html/Elements/CreateTicket
index 6e541db..6702abc 100755
--- a/share/html/Elements/CreateTicket
+++ b/share/html/Elements/CreateTicket
@@ -51,7 +51,7 @@
 % my $button_start = '<input type="submit" class="button" value="';
 % my $button_end = '" />';
 % my $queue_selector = $m->scomp('/Elements/SelectNewTicketQueue', OnChange => 'document.CreateTicketInQueue.submit()', SendTo => $SendTo );
-<&|/l, $button_start, $button_end, $queue_selector &>[_1]New ticket in[_2] [_3]</&>
+<&|/l_unsafe, $button_start, $button_end, $queue_selector &>[_1]New ticket in[_2] [_3]</&>
 % $m->callback(CallbackName => 'BeforeFormEnd');
 </form>
 <%ARGS>
diff --git a/share/html/Elements/Footer b/share/html/Elements/Footer
index cbe8a0e..433a691 100755
--- a/share/html/Elements/Footer
+++ b/share/html/Elements/Footer
@@ -53,10 +53,10 @@
 % if ($m->{'rt_base_time'}) {
   <p id="time"><span><&|/l&>Time to display</&>: <%Time::HiRes::tv_interval( $m->{'rt_base_time'} )%></span></p>
 %}
-  <p id="bpscredits"><span><&|/l,     '»|«', $RT::VERSION, '2012', '<a href="http://www.bestpractical.com?rt='.$RT::VERSION.'">Best Practical Solutions, LLC</a>', &>[_1] RT [_2] Copyright 1996-[_3] [_4].</&>
+  <p id="bpscredits"><span><&|/l_unsafe,     '»|«', $RT::VERSION, '2012', '<a href="http://www.bestpractical.com?rt='.$RT::VERSION.'">Best Practical Solutions, LLC</a>', &>[_1] RT [_2] Copyright 1996-[_3] [_4].</&>
 </span></p>
 % if (!$Menu) {
-  <p id="legal"><&|/l, '<a href="http://www.gnu.org/licenses/gpl-2.0.html">', '</a>' &>Distributed under [_1]version 2 of the GNU GPL[_2].</&><br /><&|/l, '<a href="mailto:sales at bestpractical.com">sales at bestpractical.com</a>' &>To inquire about support, training, custom development or licensing, please contact [_1].</&><br /></p>
+  <p id="legal"><&|/l_unsafe, '<a href="http://www.gnu.org/licenses/gpl-2.0.html">', '</a>' &>Distributed under [_1]version 2 of the GNU GPL[_2].</&><br /><&|/l_unsafe, '<a href="mailto:sales at bestpractical.com">sales at bestpractical.com</a>' &>To inquire about support, training, custom development or licensing, please contact [_1].</&><br /></p>
 % }
 </div>
 % if ($Debug >= 2 ) {
diff --git a/share/html/Install/DatabaseType.html b/share/html/Install/DatabaseType.html
index 3312b57..68f8a67 100644
--- a/share/html/Install/DatabaseType.html
+++ b/share/html/Install/DatabaseType.html
@@ -58,7 +58,7 @@
 <&|/l&>SQLite is a database that doesn't need a server or any configuration whatsoever. RT's authors recommend it for testing, demoing and development, but it's not quite right for a high-volume production RT server.</&>
 </b></p>
 <p>
-<&|/l, '<a href="http://search.cpan.org" target="_new">CPAN</a>' &>If your preferred database isn't listed in the dropdown below, that means RT couldn't find a <i>database driver</i> for it installed locally. You may be able to remedy this by using [_1] to download and install DBD::MySQL, DBD::Oracle or DBD::Pg.</&>
+<&|/l_unsafe, '<a href="http://search.cpan.org" target="_new">CPAN</a>' &>If your preferred database isn't listed in the dropdown below, that means RT couldn't find a <i>database driver</i> for it installed locally. You may be able to remedy this by using [_1] to download and install DBD::MySQL, DBD::Oracle or DBD::Pg.</&>
 </p>
 </div>
 
diff --git a/share/html/Install/Finish.html b/share/html/Install/Finish.html
index ee81e70..24ac0ff 100644
--- a/share/html/Install/Finish.html
+++ b/share/html/Install/Finish.html
@@ -53,7 +53,7 @@
 </p>
 
 <p>
-<&|/l, '<tt>root</tt>' &>You should be taken directly to a login page. You'll be able to log in with username of [_1] and the password you set earlier.</&>
+<&|/l_unsafe, '<tt>root</tt>' &>You should be taken directly to a login page. You'll be able to log in with username of [_1] and the password you set earlier.</&>
 </p>
 
 <p>
diff --git a/share/html/Search/Chart.html b/share/html/Search/Chart.html
index 884d183..070ce7c 100644
--- a/share/html/Search/Chart.html
+++ b/share/html/Search/Chart.html
@@ -124,7 +124,7 @@ my %query;
 <input type="hidden" class="hidden" name="Query" value="<% $ARGS{Query} %>" />
 <input type="hidden" class="hidden" name="SavedChartSearchId" value="<% $saved_search->{SearchId} || 'new' %>" />
 
-<&|/l, $m->scomp('Elements/SelectChartType', Name => 'ChartStyle', Default => $ChartStyle), $m->scomp('Elements/SelectGroupBy', Name => 'PrimaryGroupBy', Query => $ARGS{Query}, Default => $PrimaryGroupBy) 
+<&|/l_unsafe, $m->scomp('Elements/SelectChartType', Name => 'ChartStyle', Default => $ChartStyle), $m->scomp('Elements/SelectGroupBy', Name => 'PrimaryGroupBy', Query => $ARGS{Query}, Default => $PrimaryGroupBy) 
 &>[_1] chart by [_2]</&><input type="submit" class="button" value="<%loc('Update Chart')%>" />
 </form>
 </&>
diff --git a/share/html/Search/Simple.html b/share/html/Search/Simple.html
index 07bd2f4..4d7b1e3 100644
--- a/share/html/Search/Simple.html
+++ b/share/html/Search/Simple.html
@@ -60,7 +60,7 @@
 
 % my @strong = qw(<strong> </strong>);
 
-<p><&|/l, @strong &>Search for tickets by entering [_1]id[_2] numbers, subject words [_1]"in quotes"[_2], [_1]queues[_2] by name, Owners by [_1]username[_2], Requestors by [_1]email address[_2], and ticket [_1]statuses[_2].</&></p>
+<p><&|/l_unsafe, @strong &>Search for tickets by entering [_1]id[_2] numbers, subject words [_1]"in quotes"[_2], [_1]queues[_2] by name, Owners by [_1]username[_2], Requestors by [_1]email address[_2], and ticket [_1]statuses[_2].</&></p>
 
 <p><&|/l&>Any word not recognized by RT is searched for in ticket subjects.</&></p>
 
@@ -74,7 +74,7 @@
 % }
 % }
 
-<p><&|/l, map { "<strong>$_</strong>" } qw(initial active inactive any) &>Entering [_1], [_2], [_3], or [_4] limits results to tickets with one of the respective types of statuses.  Any individual status name limits results to just the statuses named.</&>
+<p><&|/l_unsafe, map { "<strong>$_</strong>" } qw(initial active inactive any) &>Entering [_1], [_2], [_3], or [_4] limits results to tickets with one of the respective types of statuses.  Any individual status name limits results to just the statuses named.</&>
 
 % if (RT->Config->Get('OnlySearchActiveTicketsInSimpleSearch', $session{'CurrentUser'})) {
 % my $status_str  = join ', ', map { loc($_) } RT::Queue->ActiveStatusArray;
@@ -82,13 +82,13 @@
 % }
 </p>
 
-<p><&|/l, map { "<strong>$_</strong>" } 'queue:"Example Queue"', 'owner:email at example.com' &>Start the search term with the name of a supported field followed by a colon, as in [_1] and [_2], to explicitly specify the search type.</&></p>
+<p><&|/l_unsafe, map { "<strong>$_</strong>" } 'queue:"Example Queue"', 'owner:email at example.com' &>Start the search term with the name of a supported field followed by a colon, as in [_1] and [_2], to explicitly specify the search type.</&></p>
 
-<p><&|/l, '<strong>cf.Name:value</strong>' &>CFs may be searched using a similar syntax as above with [_1].</&></p>
+<p><&|/l_unsafe, '<strong>cf.Name:value</strong>' &>CFs may be searched using a similar syntax as above with [_1].</&></p>
 
 % my $link_start  = '<a href="' . RT->Config->Get('WebPath') . '/Search/Build.html">';
 % my $link_end    = '</a>';
-<p><&|/l, $link_start, $link_end &>For the full power of RT's searches, please visit the [_1]search builder interface[_2].</&></p>
+<p><&|/l_unsafe, $link_start, $link_end &>For the full power of RT's searches, please visit the [_1]search builder interface[_2].</&></p>
 
 </form>
 
diff --git a/share/html/l b/share/html/l
index 6396bc6..9f1b343 100755
--- a/share/html/l
+++ b/share/html/l
@@ -47,6 +47,6 @@
 %# END BPS TAGGED BLOCK }}}
 <%init>
  my $hand = ($session{'CurrentUser'} ||= RT::CurrentUser->new)->LanguageHandle;
- $m->print($hand->maketext($m->content, at _));
+ $m->print($hand->maketext($m->content,map { $m->interp->apply_escapes($_, 'h') } @_));
  return(1);
 </%init>
diff --git a/share/html/l b/share/html/l_unsafe
similarity index 100%
copy from share/html/l
copy to share/html/l_unsafe
diff --git a/share/html/m/_elements/footer b/share/html/m/_elements/footer
index aad0020..0d160c2 100644
--- a/share/html/m/_elements/footer
+++ b/share/html/m/_elements/footer
@@ -48,7 +48,7 @@
   <& /Elements/Logo, ShowName => 1, OnlyCustom => 1 &>
   <div id="bpscredits">
     <div id="copyright">
-<&|/l,     '', '', '2012', '<a href="http://www.bestpractical.com?rt='.$RT::VERSION.'">Best Practical Solutions, LLC</a>', &>[_1] RT [_2] Copyright 1996-[_3] [_4].</&>
+<&|/l_unsafe,     '', '', '2012', '<a href="http://www.bestpractical.com?rt='.$RT::VERSION.'">Best Practical Solutions, LLC</a>', &>[_1] RT [_2] Copyright 1996-[_3] [_4].</&>
 </div>
 </div>
 </body>

commit 340b8bd6e1b5937b683531fe50ff03aaf18b4b2f
Author: Alex Vandiver <alexmv at bestpractical.com>
Date:   Fri Aug 31 23:27:10 2012 -0400

    Differentiate "always sign" from "default to signing when composing"
    
    Signing incorporates two related but distinct concepts: first,
    verification that the message was transmitted without corruption
    (integrity), and second, proof that the message was indeed sent by the
    sender (authentication).
    
    When the "Sign by default" queue option is disabled, the only messages
    which are signed are those triggered by an action where the sender has
    explicitly checked the "Sign" option.  Consequently, messages which are
    not generated via the web UI, such as auto-replies, or requestors'
    messages which are forwarded to owners, are not signed.  In this
    configuration, the signing conveys authenticity, but does not provide
    integrity for all messages..
    
    When the "Sign by default" queue option is enabled, all messages default
    to being signed, even ones generated automatically.  Thus, emails from
    the requestor (which may have arbitrary content!) will be signed by the
    queue's key when redistributed to owners and AdminCcs.  In this
    configuration, the signing ensures integrity, but (because signing
    happens automatically) means that no authenticity should be attached to
    messages thus signed.
    
    Because the simple configuration option fundamentally changed the
    meaning of the signature, exchanging integrity for authenticity, with no
    warning, alter it to instead provide an additional option ("Sign
    auto-generated messages") which takes the burden of this change in
    meaning.  Degrade the "Sign by default" option to describing the default
    state of the checkbox on the ticket create or reply page.
    (cherry picked from commit e3c2880e6526f9c78079df2097483fea30ba910e)

diff --git a/lib/RT/Interface/Email.pm b/lib/RT/Interface/Email.pm
index 1ada952..9abb61e 100644
--- a/lib/RT/Interface/Email.pm
+++ b/lib/RT/Interface/Email.pm
@@ -332,8 +332,14 @@ sub WillSignEncrypt {
 
         if ( $attachment and defined $attachment->GetHeader("X-RT-$argument") ) {
             $args{$argument} = $attachment->GetHeader("X-RT-$argument");
-        } elsif ( $ticket ) {
-            $args{$argument} = $ticket->QueueObj->$argument();
+        } elsif ( $ticket and $argument eq "Encrypt" ) {
+            $args{Encrypt} = $ticket->QueueObj->Encrypt();
+        } elsif ( $ticket and $argument eq "Sign" ) {
+            # Note that $queue->Sign is UI-only, and that all
+            # UI-generated messages explicitly set the X-RT-Crypt header
+            # to 0 or 1; thus this path is only taken for messages
+            # generated _not_ via the web UI.
+            $args{Sign} = $ticket->QueueObj->SignAuto();
         }
     }
 
diff --git a/lib/RT/Queue.pm b/lib/RT/Queue.pm
index 84e2621..59bb56b 100644
--- a/lib/RT/Queue.pm
+++ b/lib/RT/Queue.pm
@@ -391,6 +391,7 @@ sub Create {
         FinalPriority     => 0,
         DefaultDueIn      => 0,
         Sign              => undef,
+        SignAuto          => undef,
         Encrypt           => undef,
         _RecordTransaction => 1,
         @_
@@ -433,14 +434,11 @@ sub Create {
     }
     $RT::Handle->Commit;
 
-    if ( defined $args{'Sign'} ) {
-        my ($status, $msg) = $self->SetSign( $args{'Sign'} );
-        $RT::Logger->error("Couldn't set attribute 'Sign': $msg")
-            unless $status;
-    }
-    if ( defined $args{'Encrypt'} ) {
-        my ($status, $msg) = $self->SetEncrypt( $args{'Encrypt'} );
-        $RT::Logger->error("Couldn't set attribute 'Encrypt': $msg")
+    for my $attr (qw/Sign SignAuto Encrypt/) {
+        next unless defined $args{$attr};
+        my $set = "Set" . $attr;
+        my ($status, $msg) = $self->$set( $args{$attr} );
+        $RT::Logger->error("Couldn't set attribute '$attr': $msg")
             unless $status;
     }
 
@@ -592,6 +590,32 @@ sub SetSign {
     return ($status, $self->loc('Signing disabled'));
 }
 
+sub SignAuto {
+    my $self = shift;
+    my $value = shift;
+
+    return undef unless $self->CurrentUserHasRight('SeeQueue');
+    my $attr = $self->FirstAttribute('SignAuto') or return 0;
+    return $attr->Content;
+}
+
+sub SetSignAuto {
+    my $self = shift;
+    my $value = shift;
+
+    return ( 0, $self->loc('Permission Denied') )
+        unless $self->CurrentUserHasRight('AdminQueue');
+
+    my ($status, $msg) = $self->SetAttribute(
+        Name        => 'SignAuto',
+        Description => 'Sign auto-generated outgoing messages',
+        Content     => $value,
+    );
+    return ($status, $msg) unless $status;
+    return ($status, $self->loc('Signing enabled')) if $value;
+    return ($status, $self->loc('Signing disabled'));
+}
+
 sub Encrypt {
     my $self = shift;
     my $value = shift;
diff --git a/share/html/Admin/Queues/Modify.html b/share/html/Admin/Queues/Modify.html
index be7909b..409b713 100755
--- a/share/html/Admin/Queues/Modify.html
+++ b/share/html/Admin/Queues/Modify.html
@@ -119,6 +119,8 @@
 <td align="right"><input type="checkbox" class="checkbox" name="Encrypt" value="1" <% $QueueObj->Encrypt? 'checked="checked"': '' |n%> /></td>
 <td><&|/l&>Encrypt by default</&></td>
 </tr>
+<tr><td align="right"><input type="checkbox" class="checkbox" name="SignAuto" value="1" <% $QueueObj->SignAuto? 'checked="checked"': '' |n%> /></td>
+<td colspan="3"><&|/l_unsafe, "<b>","</b>","<i>","</i>"&>Sign all auto-generated mail.  [_1]Caution[_2]: Enabling this option alters the signature from providing [_3]authentication[_4] to providing [_3]integrity[_4].</&></td></tr>
 % }
 
 <tr><td align="right"><input type="checkbox" class="checkbox" name="Enabled" value="1" <%$EnabledChecked|n%> /></td>
@@ -181,13 +183,13 @@ unless ($Create) {
 if ( $QueueObj->Id ) {
     $title = loc('Configuration for queue [_1]', $QueueObj->Name );
     my @attribs= qw(Description CorrespondAddress CommentAddress Name
-        InitialPriority FinalPriority DefaultDueIn Sign Encrypt Lifecycle SubjectTag Disabled);
+        InitialPriority FinalPriority DefaultDueIn Sign SignAuto Encrypt Lifecycle SubjectTag Disabled);
 
     # we're asking about enabled on the web page but really care about disabled
     if ( $SetEnabled ) {
         $Disabled = $ARGS{'Disabled'} = $Enabled? 0: 1;
         $ARGS{$_} = 0 foreach grep !defined $ARGS{$_} || !length $ARGS{$_},
-            qw(Sign Encrypt Disabled);
+            qw(Sign SignAuto Encrypt Disabled);
     }
 
     $m->callback(

commit 28e586a11fdb9678f62ac5c2ef4c7af2d2f43508
Author: Kevin Falcone <falcone at bestpractical.com>
Date:   Sat Sep 29 00:04:29 2012 -0400

    The "Always Sign, even redistributed email" option is now called SignAuto

diff --git a/t/crypt/no-signer-address.t b/t/crypt/no-signer-address.t
index 57c2591..16f0ebe 100644
--- a/t/crypt/no-signer-address.t
+++ b/t/crypt/no-signer-address.t
@@ -13,7 +13,7 @@ my $queue;
 {
     $queue = RT::Test->load_or_create_queue(
         Name => 'Regression',
-        Sign => 1,
+        SignAuto => 1,
     );
     ok $queue && $queue->id, 'loaded or created queue';
     ok !$queue->CorrespondAddress, 'address not set';

commit ea25753a1be2621ba62f849949aa00c7ae5eb556
Author: Kevin Falcone <falcone at bestpractical.com>
Date:   Tue Oct 2 19:49:50 2012 -0400

    Stop looking for things in the GnuPG configuration
    
    This restores the behavior that if mail comes in which is "invalid" in
    some way that we want to reject, we'll stop gpg/smime processing the
    mail after notifying external users of the failure (basically skip the
    parts that update X-RT-Incoming-(Signature|Encryption) to record
    success).  I'm not sure if that's actually the optimal behavior, but
    it's the back-compat behavior.

diff --git a/lib/RT/Interface/Email/Auth/Crypt.pm b/lib/RT/Interface/Email/Auth/Crypt.pm
index 625abeb..af490f0 100644
--- a/lib/RT/Interface/Email/Auth/Crypt.pm
+++ b/lib/RT/Interface/Email/Auth/Crypt.pm
@@ -216,13 +216,13 @@ sub HandleErrors {
         unless ( $sent_once{'NoPrivateKey'} ) {
             unless ( CheckNoPrivateKey( Message => $args{'Message'}, Status => \@status ) ) {
                 $sent_once{'NoPrivateKey'}++;
-                $reject = 1 if RT->Config->Get('GnuPG')->{'RejectOnMissingPrivateKey'};
+                $reject = 1 if RT->Config->Get('Crypt')->{'RejectOnMissingPrivateKey'};
             }
         }
         unless ( $sent_once{'BadData'} ) {
             unless ( CheckBadData( Message => $args{'Message'}, Status => \@status ) ) {
                 $sent_once{'BadData'}++;
-                $reject = 1 if RT->Config->Get('GnuPG')->{'RejectOnBadData'};
+                $reject = 1 if RT->Config->Get('Crypt')->{'RejectOnBadData'};
             }
         }
     }

commit 4c1c529e4e3ebe7316469530499ed83185404e91
Author: Thomas Sibley <trs at bestpractical.com>
Date:   Thu Oct 4 21:59:42 2012 -0700

    Let MIME::Head modify the crypt status headers to handle continuations
    
    X-RT-GnuPG-Status and X-RT-SMIME-Status are set to a many-line string
    and previously continuations weren't handled properly.
    
    Temporarily letting the inserted headers be modified fixes the known
    problem.  If instead we marked the entire entity as modifiable early
    after parsing and left it that way, the possibility of unforeseen
    breakage would be too high for a stable release series.  It would also
    lead to even further deviation of RT's stored message from the original
    source message.
    
    Forward ported from commit e6c6ae922252e36b510264472820ea8df72e4b7e.

diff --git a/lib/RT/Crypt/GnuPG.pm b/lib/RT/Crypt/GnuPG.pm
index b9ab40b..4755be6 100644
--- a/lib/RT/Crypt/GnuPG.pm
+++ b/lib/RT/Crypt/GnuPG.pm
@@ -1026,9 +1026,13 @@ sub VerifyDecrypt {
         }
         if ( $args{'SetStatus'} || $args{'AddStatus'} ) {
             my $method = $args{'AddStatus'} ? 'add' : 'set';
+            # Let the header be modified so continuations are handled
+            my $modify = $status_on->head->modify;
+            $status_on->head->modify(1);
             $status_on->head->$method(
                 'X-RT-GnuPG-Status' => $res{'status'}
             );
+            $status_on->head->modify($modify);
         }
     } elsif ( $item->{'Type'} eq 'encrypted' ) {
         my $status_on;
@@ -1046,9 +1050,13 @@ sub VerifyDecrypt {
         }
         if ( $args{'SetStatus'} || $args{'AddStatus'} ) {
             my $method = $args{'AddStatus'} ? 'add' : 'set';
+            # Let the header be modified so continuations are handled
+            my $modify = $status_on->head->modify;
+            $status_on->head->modify(1);
             $status_on->head->$method(
                 'X-RT-GnuPG-Status' => $res{'status'}
             );
+            $status_on->head->modify($modify);
         }
     } else {
         die "Unknow type '". $item->{'Type'} ."' of protected item";
diff --git a/lib/RT/Crypt/SMIME.pm b/lib/RT/Crypt/SMIME.pm
index 0dda369..a0d8774 100644
--- a/lib/RT/Crypt/SMIME.pm
+++ b/lib/RT/Crypt/SMIME.pm
@@ -293,17 +293,25 @@ sub VerifyDecrypt {
         }
         if ( $args{'SetStatus'} || $args{'AddStatus'} ) {
             my $method = $args{'AddStatus'} ? 'add' : 'set';
+            # Let the header be modified so continuations are handled
+            my $modify = $status_on->head->modify;
+            $status_on->head->modify(1);
             $status_on->head->$method(
                 'X-RT-SMIME-Status' => $res{'status'}
             );
+            $status_on->head->modify($modify);
         }
     } elsif ( $item->{'Type'} eq 'encrypted' ) {
         %res = $self->DecryptRFC3851( %args, %$item );
         if ( $args{'SetStatus'} || $args{'AddStatus'} ) {
             my $method = $args{'AddStatus'} ? 'add' : 'set';
+            # Let the header be modified so continuations are handled
+            my $modify = $item->{'Data'}->head->modify;
+            $item->{'Data'}->head->modify(1);
             $item->{'Data'}->head->$method(
                 'X-RT-SMIME-Status' => $res{'status'}
             );
+            $item->{'Data'}->head->modify($modify);
         }
     } else {
         die "Unknow type '". $item->{'Type'} ."' of protected item";

commit d60801c786c92e5d18fb80ae4828ba79eee3ed7b
Merge: 19c26e9 4c1c529
Author: Kevin Falcone <falcone at bestpractical.com>
Date:   Thu Oct 25 18:58:37 2012 -0400

    Merge branch 'security/4.2/signing' into 4.2/smime-v2


-----------------------------------------------------------------------


More information about the Rt-commit mailing list