[Author Prev][Author Next][Thread Prev][Thread Next][Author Index][Thread Index]
[tor-commits] [trac-email/master] Add perl script to verify gpg and notify python script
commit 7ca90ee60f156f87b4cc8be76191ef830824eda8
Author: hiromipaw <hiro@xxxxxxxxxxxxxx>
Date: Mon Dec 12 21:48:15 2016 +0100
Add perl script to verify gpg and notify python script
---
mailverify.pl | 192 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
notify.py | 71 ++++++++++++++++++++++
2 files changed, 263 insertions(+)
diff --git a/mailverify.pl b/mailverify.pl
new file mode 100644
index 0000000..aa523b9
--- /dev/null
+++ b/mailverify.pl
@@ -0,0 +1,192 @@
+#!/usr/bin/env perl
+# File Name: mailverify
+# Maintainer: Moshe Kaminsky <kaminsky@xxxxxxxxxxxxxxx>
+# 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 (<>) {
+ 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@xxxxxxxxxxxxxxx> - 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
new file mode 100755
index 0000000..f0f384e
--- /dev/null
+++ b/notify.py
@@ -0,0 +1,71 @@
+import sys
+import email
+import re
+from trac.env import Environment
+from trac.ticket.model import Ticket
+from trac.perm import IPermissionRequestor, PermissionCache, PermissionSystem
+
+def read_message:
+ full_msg = sys.stdin.read()
+ return email.message_from_string("".join(full_msg))
+
+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())
+
+ return body
+
+def verify_user_permissions(env, user, permission):
+ ps = PermissionSystem(env)
+ permissions_list = ps.get_user_permissions(user)
+ return permission_list[permission]
+
+def find_or_create_ticket(message, env):
+ # Find the ticket ID if exists
+ ticket_id = re.search('#(.+?) ', summary)
+
+ # Get the message body
+ body = get_message_body(message)
+ reporter = msg['From']
+
+ if ticket_id:
+ t_id = ticket_id.group(1)
+ tkt = Ticket(env, int(t_id))
+ if verify_user_permissions(env, reporter, 'TICKET_MODIFY'):
+ tkt.save_changes(comment=body)
+ else:
+ if verify_user_permissions(env, reporter, 'TICKET_CREATE'):
+ summary = msg['Subject']
+ cc_list = msg['Cc']
+ component = re.findall(r'\[(.*?)\]', summary)
+ tkt = Ticket(env)
+ tkt['reporter'] = reporter
+ tkt['summary'] = summary
+ tkt['cc'] = cc_list
+ tkt['componet'] = component
+ tkt['description'] = body
+ tkt['status'] = 'new'
+ 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
+
+# Verify user can create/reply to tickets
+
+# Find or create ticket
+find_or_create_ticket(msg, env)
+
+# Close log file
+f.close
_______________________________________________
tor-commits mailing list
tor-commits@xxxxxxxxxxxxxxxxxxxx
https://lists.torproject.org/cgi-bin/mailman/listinfo/tor-commits