commit 7dd2971aeebb64f2974949691a8325cb6b701b59 Author: hiromipaw hiro@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@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'}; -@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 (<>) {
-} 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@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
tor-commits@lists.torproject.org