Module-Signature
view release on metacpan or search on metacpan
[Changes for 0.71 - Tue Jun 4 18:24:10 CST 2013]
* Constrain the user-specified digest name to /^\w+\d+$/.
* Avoid loading Digest::* from relative paths in @INC.
Contributed by: Florian Weimer (CVE-2013-2145)
[Changes for 0.70 - Thu Nov 29 01:45:54 CST 2012]
* Don't check gpg version if gpg does not exist.
This avoids unnecessary warnings during installation
when gpg executable is not installed.
Contributed by: Kenichi Ishigaki
[Changes for 0.69 - Fri Nov 2 23:04:19 CST 2012]
* Support for gpg under these alternate names:
gpg gpg2 gnupg gnupg2
Contributed by: Michael Schwern
[Changes for 0.68 - Fri, 13 May 2011 11:51:50 +0200]
* Fix breakage introduced by 0.67 (Andreas König).
[Changes for 0.67 - Sun, 17 Apr 2011 16:29:23 +0200]
* Better handling of \r (Andreas König, Zefram) (Closes RT#46339).
* Don't ask user to install Crypt::OpenPGP if she does not have a
C compiler anyway.
* ExtUtils::Manifest 1.38 does not support good enough skips even
for Makefile.PL, sigh.
[Changes for 0.33 - 2003-08-12]
* William Wentworth-Sheilds points out that META.yml is dynamic,
which makes SIGNATURE incorrect for people without either "diff"
or "gpg". Fixed.
[Changes for 0.32 - 2003-08-11]
* Take Schwern's patch to only set _maniskip for legacy EU::Manifest.
* Remove ::TieOut since we are not using it anymore.
* Reduce noise for untrusted signatures to two lines.
[Changes for 0.31 - 2003-08-10]
* Ken Williams noted that M::B now works on 5.005.
[Changes for 0.22 - 2003-05-15]
* Move Signature.pm to lib/Module/Signature.pm.
* Switch to the Module::Install framework.
* Updates TODO to reflect correspondence with andk.
* Matt Southall mentioned that, if somebody has never run gpg before,
we need to initialize it once before running test.
* Warn about potential 'Makefile' exploit as pointed out by Tels.
Document pending.
* Bugfix for incorrect 'MALFORMED' response to signatures made from
older versions of GnuPG, as reported by Tels.
[Changes for 0.18 - 2002-11-04]
Makefile.PL view on Meta::CPAN
if ( can_cc() ) {
$requires{'Digest::SHA'} = 0;
} else {
$requires{'Digest::SHA::PurePerl'} = 0;
}
}
# Is openpgp currently installed
if ( can_use ('Crypt::OpenPGP') ) {
# Crypt::OpenPGP installed/available, continue on...
} elsif ( my $gpg = locate_gpg() ) {
# We SHOULD have gpg, double-check formally
requires_external_bin ($gpg);
} elsif ( can_cc() and $ENV{AUTOMATED_TESTING} ) {
# Dive headlong into a full Crypt::OpenPGP install.
$requires{'Crypt::OpenPGP'} = 0;
} else {
# Ask the user what to do
ask_user();
}
unless ( can_run('diff') ) {
# We know Text::Diff fails on Cygwin (for now)
if ( $^O ne 'Cygwin' ) {
$requires{'Algorithm::Diff'} = 0;
$requires{'Text::Diff'} = 0;
}
}
#####################################################################
# Support Functions
sub locate_gpg {
print "Looking for GNU Privacy Guard (gpg), a cryptographic signature tool...\n";
my ($gpg, $gpg_path);
for my $gpg_bin ('gpg', 'gpg2', 'gnupg', 'gnupg2') {
$gpg_path = can_run($gpg_bin);
next unless $gpg_path;
next unless `$gpg_bin --version` =~ /GnuPG/;
next unless defined `$gpg_bin --list-public-keys`;
$gpg = $gpg_bin;
last;
}
unless ( $gpg ) {
print "gpg not found.\n";
return;
}
print "GnuPG found ($gpg_path).\n";
return 1 if grep { /^--installdeps/} @ARGV;
if ( prompt("Import PAUSE and author keys to GnuPG?", 'y' ) =~ /^y/i) {
print 'Importing... ';
system $gpg, '--quiet', '--import', qw[ AUDREYT2018.pub ANDK2020.pub PAUSE2022.pub NIKLASHOLM2018.pub TIMLEGGE2024.pub ];
print "done.\n";
}
return $gpg;
}
sub ask_user {
# Defined the prompt messages
my $message1 = <<'END_MESSAGE';
Could not auto-detect a signature utility on your system.
What do you want me to do?
Makefile.PL view on Meta::CPAN
END_MESSAGE
my $choice;
foreach ( 1 .. 3 ) {
$choice = prompt("Your choice:", 3) || 3;
last if $choice =~ /^[123]$/;
print "Sorry, I cannot understand '$choice'.\n"
}
if ( $choice == 1 ) {
# They claim to have installed gpg
requires_external_bin ('gpg');
} elsif ( $choice == 2 and $option3 == 3 ) {
# They want to install Crypt::OpenPGP
$requires{'Crypt::OpenPGP'} = 0;
} else {
# Forget about it...
print "Module::Signature is not wanted on this host.\n";
exit(0);
}
}
PAUSE2022.pub view on Meta::CPAN
gpg --export --armor 450F89EC
-----BEGIN PGP PUBLIC KEY BLOCK-----
mQGiBD4+cJARBACxOByY0SJBBuJoFrH2hoqRFny423gY6V3jq1uTgGY/PPaxP+Sq
r3RzxPct4vJcsoo48pwBsMHLrWfORq26zb6eKgmMq/CQo2gzaRbeRxCi3ke4KBmu
aREi6RjaZSU94yABtDmspUBrpYV8zfZMv5ZIQlg9W1Tu66BFOUrrNeDpKwCgosCp
9dtNAMhHkzxs8UJH5i3Uzb0D/0VLoAE8sOfUXqjc38rxiHuGBFSNC70Ih4mzGUCJ
MGT4z1X3K6uUawnXMoc8XqPaYnEgOzztMymydtr+urjUwcGnuXDSpV6nulE5irxh
zlikSTJy/42QzTMcrdRynffmJo9PRgymMI8GgWaYG5g3zzGAhi5BA6G8JKfC93IV
xiRPBACXJpLBYQljqJY9UDNJuq8nHhKiWHBXdZzrC3LM0FSF3PKuP/ugc+KBIKXm
clNPNFKla/SRbH6dMHsGIy8wnGPI5AtTS0roNQrttv3/ghRT7+OKXrGmBxZ/KHVr
lib/Module/Signature.pm view on Meta::CPAN
my $sock = IO::Socket::INET->new(
Timeout => $Timeout,
PeerAddr => "$KeyServer:$KeyServerPort",
);
$CanKeyRetrieve = ($sock ? 1 : 0);
$sock->shutdown(2) if $sock;
}
$AutoKeyRetrieve = $CanKeyRetrieve;
}
if (my $version = _has_gpg()) {
return _verify_gpg($sigtext, $plaintext, $version);
}
elsif (eval {require Crypt::OpenPGP; 1}) {
return _verify_crypt_openpgp($sigtext, $plaintext);
}
else {
warn "Cannot use GnuPG or Crypt::OpenPGP, please install either one first!\n";
return _compare($sigtext, $plaintext, CANNOT_VERIFY);
}
}
sub _has_gpg {
my $gpg = _which_gpg() or return;
`$gpg --version` =~ /GnuPG.*?(\S+)\s*$/m or return;
return $1;
}
sub _fullcheck {
my $skip = shift;
my @extra;
local $^W;
local $ExtUtils::Manifest::Quiet = 1;
lib/Module/Signature.pm view on Meta::CPAN
sub _default_skip {
local $_ = shift;
return 1 if /\bRCS\b/ or /\bCVS\b/ or /\B\.svn\b/ or /,v$/
or /^MANIFEST\.bak/ or /^Makefile$/ or /^blib\//
or /^MakeMaker-\d/ or /^pm_to_blib/ or /^blibdirs/
or /^_build\// or /^Build$/ or /^pmfiles\.dat/
or /^MYMETA\./
or /~$/ or /\.old$/ or /\#$/ or /^\.#/;
}
my $which_gpg;
sub _which_gpg {
# Cache it so we don't need to keep checking.
return $which_gpg if $which_gpg;
for my $gpg_bin ('gpg', 'gpg2', 'gnupg', 'gnupg2') {
my $version = `$gpg_bin --version 2>&1`;
if( $version && $version =~ /GnuPG/ ) {
$which_gpg = $gpg_bin;
return $which_gpg;
}
}
}
sub _verify_gpg {
my ($sigtext, $plaintext, $version) = @_;
local $SIGNATURE = Win32::GetShortPathName($SIGNATURE)
if defined &Win32::GetShortPathName and $SIGNATURE =~ /[^-\w.:~\\\/]/;
my $keyserver = _keyserver($version);
require File::Temp;
my $fh = File::Temp->new();
print $fh $sigtext || _read_sigfile($SIGNATURE);
close $fh;
my $gpg = _which_gpg();
my @quiet = $Verbose ? () : qw(-q --logger-fd=1);
my @cmd = (
$gpg, qw(--verify --batch --no-tty), @quiet, ($KeyServer ? (
"--keyserver=$keyserver",
($AutoKeyRetrieve and $version ge '1.0.7')
? '--keyserver-options=auto-key-retrieve'
: ()
) : ()), $fh->filename
);
my $output = '';
if( $Verbose ) {
warn "Executing @cmd\n";
lib/Module/Signature.pm view on Meta::CPAN
warn "==> MISMATCHED content between MANIFEST and the distribution! <==\n";
warn "==> Please correct your MANIFEST file and/or delete extra files. <==\n";
}
if (!$overwrite and -e $SIGNATURE and IO::Interactive::is_interactive()) {
local $/ = "\n";
print "$SIGNATURE already exists; overwrite [y/N]? ";
return unless <STDIN> =~ /[Yy]/;
}
if (my $version = _has_gpg()) {
_sign_gpg($SIGNATURE, $plaintext, $version);
}
elsif (eval {require Crypt::OpenPGP; 1}) {
_sign_crypt_openpgp($SIGNATURE, $plaintext);
}
else {
die 'Cannot use GnuPG or Crypt::OpenPGP, please install either one first!';
}
warn "==> SIGNATURE file created successfully. <==\n";
return SIGNATURE_OK;
}
sub _sign_gpg {
my ($sigfile, $plaintext, $version) = @_;
die "Could not write to $sigfile"
if -e $sigfile and (-d $sigfile or not -w $sigfile);
my $gpg = _which_gpg();
my $gpg_fh;
my $set_key = '';
$set_key = qq{--default-key "$AUTHOR"} if($AUTHOR);
open ($gpg_fh, '|-', "$gpg $set_key --clearsign --openpgp --personal-digest-preferences RIPEMD160 >> $sigfile.tmp")
or die "Could not call $gpg: $!";
print $gpg_fh $plaintext;
close $gpg_fh;
(-e "$sigfile.tmp" and -s "$sigfile.tmp") or do {
unlink "$sigfile.tmp";
die "Cannot find $sigfile.tmp, signing aborted.\n";
};
my $sigfile_tmp_fh;
open ($sigfile_tmp_fh, '<', "$sigfile.tmp") or die "Cannot open $sigfile.tmp: $!";
my $sigfile_fh;
lib/Module/Signature.pm view on Meta::CPAN
print $sigfile_fh $Preamble;
print $sigfile_fh (<$sigfile_tmp_fh>);
close $sigfile_fh;
close $sigfile_tmp_fh;
unlink("$sigfile.tmp");
my $key_id;
my $key_name;
my @verify = `$gpg --batch --logger-fd 1 --verify $SIGNATURE`;
foreach (@verify) {
if (/key(?: ID)? ([0-9A-F]+)$/) {
$key_id = $1;
} elsif (/signature from "(.+)"(?: \[[a-z]+\])?$/) {
$key_name = $1;
}
}
my $found_name;
my $found_key;
if (defined $key_id && defined $key_name) {
my $keyserver = _keyserver($version);
foreach (`$gpg --output - --keyserver=$keyserver --recv-key '$key_id' 2>&1`) {
if (/^\(\d+\)/) {
$found_name = 0;
} elsif ($key_id) {
my $short_key_id = substr($key_id, (length($key_id) - 16));
if (/key \Q$short_key_id\E/) {
$found_key = 1;
last;
}
}
lib/Module/Signature.pm view on Meta::CPAN
=head1 VARIABLES
No package variables are exported by default.
=over 4
=item $Verbose
If true, Module::Signature will give information during processing including
gpg output. If false, Module::Signature will be as quiet as possible as
long as everything is working ok. Defaults to false.
=item $SIGNATURE
The filename for a distribution's signature file. Defaults to
C<SIGNATURE>.
=item $AUTHOR
The key ID used for signature. If empty/null/0, C<gpg>'s configured default ID,
or the most recently added key within the secret keyring for C<Crypt::OpenPGP>,
will be used for the signature.
=item $KeyServer
The OpenPGP key server for fetching the author's public key
(currently only implemented on C<gpg>, not C<Crypt::OpenPGP>).
May be set to a false value to prevent this module from
fetching public keys.
=item $KeyServerPort
The OpenPGP key server port, defaults to C<11371>.
=item $Timeout
Maximum time to wait to try to establish a link to the key server.
maint/Makefile_header.PL view on Meta::CPAN
if ( can_cc() ) {
$requires{'Digest::SHA'} = 0;
} else {
$requires{'Digest::SHA::PurePerl'} = 0;
}
}
# Is openpgp currently installed
if ( can_use ('Crypt::OpenPGP') ) {
# Crypt::OpenPGP installed/available, continue on...
} elsif ( my $gpg = locate_gpg() ) {
# We SHOULD have gpg, double-check formally
requires_external_bin ($gpg);
} elsif ( can_cc() and $ENV{AUTOMATED_TESTING} ) {
# Dive headlong into a full Crypt::OpenPGP install.
$requires{'Crypt::OpenPGP'} = 0;
} else {
# Ask the user what to do
ask_user();
}
unless ( can_run('diff') ) {
# We know Text::Diff fails on Cygwin (for now)
if ( $^O ne 'Cygwin' ) {
$requires{'Algorithm::Diff'} = 0;
$requires{'Text::Diff'} = 0;
}
}
#####################################################################
# Support Functions
sub locate_gpg {
print "Looking for GNU Privacy Guard (gpg), a cryptographic signature tool...\n";
my ($gpg, $gpg_path);
for my $gpg_bin ('gpg', 'gpg2', 'gnupg', 'gnupg2') {
$gpg_path = can_run($gpg_bin);
next unless $gpg_path;
next unless `$gpg_bin --version` =~ /GnuPG/;
next unless defined `$gpg_bin --list-public-keys`;
$gpg = $gpg_bin;
last;
}
unless ( $gpg ) {
print "gpg not found.\n";
return;
}
print "GnuPG found ($gpg_path).\n";
return 1 if grep { /^--installdeps/} @ARGV;
if ( prompt("Import PAUSE and author keys to GnuPG?", 'y' ) =~ /^y/i) {
print 'Importing... ';
system $gpg, '--quiet', '--import', qw[ AUDREYT2018.pub ANDK2020.pub PAUSE2022.pub NIKLASHOLM2018.pub TIMLEGGE2024.pub ];
print "done.\n";
}
return $gpg;
}
sub ask_user {
# Defined the prompt messages
my $message1 = <<'END_MESSAGE';
Could not auto-detect a signature utility on your system.
What do you want me to do?
maint/Makefile_header.PL view on Meta::CPAN
END_MESSAGE
my $choice;
foreach ( 1 .. 3 ) {
$choice = prompt("Your choice:", 3) || 3;
last if $choice =~ /^[123]$/;
print "Sorry, I cannot understand '$choice'.\n"
}
if ( $choice == 1 ) {
# They claim to have installed gpg
requires_external_bin ('gpg');
} elsif ( $choice == 2 and $option3 == 3 ) {
# They want to install Crypt::OpenPGP
$requires{'Crypt::OpenPGP'} = 0;
} else {
# Forget about it...
print "Module::Signature is not wanted on this host.\n";
exit(0);
}
}
t/2-cygwin.t view on Meta::CPAN
use Module::Signature;
use Test::More;
if ($^O ne 'cygwin') {
plan skip_all => "Cygwin only tests";
}
elsif (! $ENV{TEST_CYGWIN_GNUPG} ) {
plan skip_all => 'Set the environment variable TEST_CYGWIN_GNUPG to enable this test';
}
elsif (! -x '/usr/local/bin/gpg') {
plan skip_all => '/usr/local/bin/gpg not found';
}
plan tests => 1;
my $version = Module::Signature::_has_gpg();
like($version, qr/^\d+\.\d+\.\d+$/, "gpg version detected");
( run in 0.627 second using v1.01-cache-2.11-cpan-df04353d9ac )