[tor-commits] [trac-email/master] Moving key verification to python script. Managing Trust

hiro at torproject.org hiro at torproject.org
Tue Dec 13 12:14:58 UTC 2016


commit 7dd2971aeebb64f2974949691a8325cb6b701b59
Author: hiromipaw <hiro at torproject.org>
Date:   Tue Dec 13 13:14:52 2016 +0100

    Moving key verification to python script. Managing Trust
---
 mailverify.pl | 192 ----------------------------------------------------------
 notify.py     |  38 +++++++-----
 procmailrc    |  28 ++-------
 3 files changed, 29 insertions(+), 229 deletions(-)

diff --git a/mailverify.pl b/mailverify.pl
deleted file mode 100644
index aa523b9..0000000
--- a/mailverify.pl
+++ /dev/null
@@ -1,192 +0,0 @@
-#!/usr/bin/env perl
-# File Name: mailverify
-# Maintainer: Moshe Kaminsky <kaminsky at math.huji.ac.il>
-# Original Date: September 30, 2003
-# Last Update: September 30, 2003
-# http://mirror.hamakor.org.il/archives/linux-il/att-5615/mailverify
-###########################################################
-
-use warnings;
-use integer;
-
-BEGIN {
-    our $VERSION = 0.1;
-
-    # analyze command line
-    use Getopt::Long qw(:config gnu_getopt);
-    use Pod::Usage;
-
-    our $opt_help;
-    our $opt_man;
-    our $opt_version;
-    our $Gpg;
-    our $Tolerant;
-    GetOptions('gpg=s' => \$Gpg,
-               'tolerant!' => \$Tolerant,
-               'help', 'version', 'man');
-    pod2usage(1) if $opt_help;
-    pod2usage(-verbose => 2) if $opt_man;
-    print "$0 version $VERSION\n" and exit if $opt_version;
-    $Gpg = '/usr/bin/gpg --batch --verify' unless $Gpg;
-}
-
-use File::Temp qw( tempfile );
-
-my $PrevField = '';
-
-# process the header
-while (<>) {
-    next if /^From /o;
-    last if /^$/o;
-    if (/^([\w-]+): (.*)$/o) {
-        $Header{$1} = $2;
-        $PrevField = $1;
-    } else {
-        $Header{$PrevField} .= $_;
-    }
-}
-
-# check that the message is signed
-$Str = $Header{'Content-Type'};
- at Parts = split /;\s+/, $Str if $Str;
-if (not $Str or $Parts[0] ne 'multipart/signed' ) {
-    # the message is not multipart/signed, but might still be cleartext
-    # signed. Depending on --tolerant, we may pass the rest of the message to
-    # gpg directly
-    print "Message not signed\n" and exit -1 unless $Tolerant;
-    open GPG, "|$Gpg" or die "Can't open pipe to gpg ($Gpg): $!";
-    print GPG <>;
-    close GPG;
-    exit $? >> 8;
-}
-
-# the boundary string signals the boundary between two attachments
-$Boundary = $1 if $Parts[3] =~ /^boundary="(.*)"$/o;
-# go to the start of the message
-while (<>) {
-    last if $_ eq "--$Boundary\n";
-}
-
-# read the message, excluding the last (empty) line
-while (<>) {
-    last if $_ eq "--$Boundary\n";
-    push @Message, $_;
-}
-pop @Message;
-# read the sig
-while (<>) {
-    last if /^-----BEGIN PGP SIGNATURE-----$/o;
-}
-{
-do {
-    push @Sig, $_;
-    last if /^-----END PGP SIGNATURE-----$/o;
-} while (<>);
-};
-
-# here comes the funny part: replace \n by \r\n
-$_ = join '', @Message;
-s/(?<!\r)\n/\r\n/g;
-
-# write everything to files
-my ($MsgFH, $MsgFile) = tempfile;
-print $MsgFH $_;
-my $SigFile = "$MsgFile.asc";
-open SIGFH, ">$SigFile" or die "can't open $SigFile: $!";
-print SIGFH @Sig;
-close $MsgFH;
-close SIGFH;
-
-# run gpg
-print `$Gpg $SigFile`;
-
-# clean up
-unlink $MsgFile, $SigFile;
-
-# exit with the status of gpg
-exit $? >> 8;
-
-__DATA__
-
-# start of POD
-
-=head1 NAME
-
-mailverify - verify the pgp signature of a mime signed mail message
-
-=head1 SYNOPSIS
-
-B<mailverify> B<--help>|B<--man>|B<--version>
-
-B<mailverify> [B<--gpg=I<gpg command>>] [B<--(no)tolerant>] [I<mail file>]
-
-=head1 OPTIONS
-
-=over 4
-
-=item B<--gpg=I<gpg command>>
-
-The command to run to do the actual checking. The default is
-S<C</usr/local/bin/gpg --batch --verify>>. It is called with one argument,
-which is the name of the file containing the signature. If B<--tolerant> is
-used, it may also be called with the whole message on the standard input.
-
-=item B<--(no)tolerant>
-
-Normally (with B<--notolerant>), if the Content-Type is not
-C<multipart/signed>, B<mailverify> decides that the message is not signed,
-and exits with status -1. With this switch, the message is passed to I<gpg>
-(or whatever was specified with the B<--gpg> option) as is. This way,
-clearsigned messages can be verified with the same command.
-
-=item B<--help>
-
-Give a short usage message and exit with status 1
-
-=item B<--man>
-
-Give the full description and exit with status 1
-
-=item B<--version>
-
-Print a line with the program name and exit with status 0
-
-=back
-
-=head1 ARGUMENTS
-
-If an argument is given, it is treated a file containing an e-mail message to
-verify, but more common is to read the message from stdin.
-
-=head1 DESCRIPTION
-
-This script verifies the pgp signature of files whose signature appears as an
-attachment (Content-Type C<multipart/signed>). If B<--tolerant> is used, it
-will also verify clearsigned messages. The usage is basically to pipe the
-mail to this program.
-
-=head1 EXIT STATUS
-
-If the message is not of type C<multipart/signed>, and B<--tolerant> is not
-given, the exit status is -1. In any other case, it is the exit status of the
-I<gpg> command.
-
-=head1 SEE ALSO
-
-I<gpg(1)>
-
-=head1 BUGS
-
-Probably plenty, since I don't read any RFCs. Works with all cases I checked,
-though.
-
-=head1 AUTHOR
-
-Moshe Kaminsky <kaminsky at math.huji.ac.il> - Copyright (c) 2003
-
-=head1 LICENSE
-
-This program is free software. You may copy or
-redistribute it under the same terms as Perl itself.
-
-=cut
diff --git a/notify.py b/notify.py
index f0f384e..189ca12 100755
--- a/notify.py
+++ b/notify.py
@@ -1,19 +1,23 @@
 import sys
 import email
 import re
+import gnupg
 from trac.env import Environment
 from trac.ticket.model import Ticket
 from trac.perm import IPermissionRequestor, PermissionCache, PermissionSystem
 
-def read_message:
+def read_message():
     full_msg = sys.stdin.read()
     return email.message_from_string("".join(full_msg))
 
+def verify_email_signature(message):
+    gpg = gnupg.GPG(gnupghome='/home/tracadm/.gnupg')
+    return gpg.verify(message)
+
 def get_message_body(message):
     body = ""
     if message.is_multipart():
         for payload in message.get_payload():
-            # if payload.is_multipart(): ...
             body.join(payload.get_payload())
     else:
         body.join(message.get_payload())
@@ -23,15 +27,14 @@ def get_message_body(message):
 def verify_user_permissions(env, user, permission):
     ps = PermissionSystem(env)
     permissions_list = ps.get_user_permissions(user)
-    return permission_list[permission]
+    return permissions_list[permission]
 
-def find_or_create_ticket(message, env):
+def find_or_create_ticket(message, body, env):
     # Find the ticket ID if exists
+    summary = message['Subject']
     ticket_id = re.search('#(.+?) ', summary)
 
-    # Get the message body
-    body = get_message_body(message)
-    reporter = msg['From']
+    reporter = message['From']
 
     if ticket_id:
         t_id = ticket_id.group(1)
@@ -40,32 +43,37 @@ def find_or_create_ticket(message, env):
             tkt.save_changes(comment=body)
     else:
         if verify_user_permissions(env, reporter, 'TICKET_CREATE'):
-            summary = msg['Subject']
-            cc_list = msg['Cc']
+            summary = message['Subject']
+            cc_list = message['Cc']
             component = re.findall(r'\[(.*?)\]', summary)
             tkt = Ticket(env)
             tkt['reporter'] = reporter
             tkt['summary'] = summary
-            tkt['cc'] = cc_list
+            tkt['cc'] = str(cc_list)
             tkt['componet'] = component
             tkt['description'] = body
             tkt['status'] = 'new'
+            tkt['priority'] = 'medium'
             tkt.insert()
 
 # Open logs file
 f = open('/home/tracadm/log/test.log', 'w')
-f.write('PGP verified\n')
 
 # Define the current trac environment
 env = Environment('/current')
 
 # Build email message
-msg = read_message
+msg = read_message()
+
+# Get the message body
+body = msg.get_payload()
+
+verified = verify_email_signature(body)
 
-# Verify user can create/reply to tickets
+if verified.trust_level is not None and verified.trust_level >= verified.TRUST_FULLY:
 
-# Find or create ticket
-find_or_create_ticket(msg, env)
+    # Find or create ticket
+    find_or_create_ticket(msg, body, env)
 
 # Close log file
 f.close
diff --git a/procmailrc b/procmailrc
index 43d36e8..4c0b518 100644
--- a/procmailrc
+++ b/procmailrc
@@ -1,31 +1,15 @@
 ##########################################################################
-# whitelist
+#
+# whitelist pgp verify
+#
+
 SHELL=/bin/sh
 MAILDIR=$HOME/Maildir
 LOGFILE=$HOME/log/pm.log
 LOGABSTRACT="all"
 VERBOSE="on"
 DEFAULT=$HOME/Maildir/
-PGP_WHITELIST=$HOME/pgp-whitelist
-
-#looking from spam, but blessing sender from my white list
-# by setting a X-Whitelist header
-
-# First, removing fake headers
-:0 fwh
-* ^X-Whitelist
-| formail -IX-Whitelist
 
 # checking for people with a trusted PGP key
-FROM=`formail -XFrom: | formail -r -xTo: | tr -d ' '`
-PGP_OK=`$HOME/bin/mailverify --tolerant 1>/dev/null && echo 1`
-:0
-* ? egrep -q "$FROM" $PGP_WHITELIST
-{
-   :0Wc
-   * ? test -n "$PGP_OK"
-   {
-    :0Wc
-      | /usr/bin/python $HOME/bin/notify
-   }
-}
+:0Wc
+  | /usr/bin/python $HOME/bin/notify



More information about the tor-commits mailing list