Replace canlockcheck with canlockey.
- Rewrite. - Add functionalityx to create a Cancel-Key. - Update README. Signed-off-by: Thomas Hochstein <thh@thh.name>
This commit is contained in:
parent
fcf1faa41c
commit
5d910a9d76
3 changed files with 152 additions and 85 deletions
|
|
@ -2,9 +2,11 @@
|
||||||
|
|
||||||
This is a collection of tools around (managing) Netnews.
|
This is a collection of tools around (managing) Netnews.
|
||||||
|
|
||||||
## canlockcheck
|
## canlockey
|
||||||
|
|
||||||
`canlockcheck.pl` will check whether a given Cancel-Lock and Cancel-Key match.
|
`canlockey.pl` will create a Cancel-Key for a given Message-ID with
|
||||||
|
optional user, canlock-secret and hash (defaulting to `SHA1`) or
|
||||||
|
check whether a given Cancel-Lock and Cancel-Key match.
|
||||||
|
|
||||||
## mew
|
## mew
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,83 +0,0 @@
|
||||||
#! /usr/bin/perl -w
|
|
||||||
#
|
|
||||||
# canlockcheck.pl
|
|
||||||
#
|
|
||||||
# Check whether Cancel-Lock and Cancel-Key match.
|
|
||||||
#
|
|
||||||
# Copyright (c) 2023 Thomas Hochstein <thh@thh.name>
|
|
||||||
|
|
||||||
use MIME::Base64();
|
|
||||||
use Digest::SHA();
|
|
||||||
use Digest::MD5();
|
|
||||||
use Getopt::Long qw(GetOptions);
|
|
||||||
Getopt::Long::config ('bundling');
|
|
||||||
|
|
||||||
my $VERSION = "0.1";
|
|
||||||
|
|
||||||
# read commandline options ############
|
|
||||||
my ($OptCanLock,$OptCanKey);
|
|
||||||
GetOptions ('l|lock=s' => \$OptCanLock,
|
|
||||||
'k|key=s' => \$OptCanKey,
|
|
||||||
'V|version' => \&ShowVersion) or exit 1;
|
|
||||||
|
|
||||||
# subroutines #########################
|
|
||||||
|
|
||||||
### display version information and exit
|
|
||||||
sub ShowVersion {
|
|
||||||
print "canlockcheck v$VERSION\n";
|
|
||||||
print "Copyright (c) 2023 Thomas Hochstein <thh\@thh.name>\n";
|
|
||||||
print "This program is free software; you may redistribute it ".
|
|
||||||
"and/or modify it under the same terms as Perl itself.\n";
|
|
||||||
exit;
|
|
||||||
};
|
|
||||||
|
|
||||||
sub verify_cancel_key($$) {
|
|
||||||
my $cancel_lock = shift;
|
|
||||||
my $cancel_key = shift;
|
|
||||||
|
|
||||||
my %lock;
|
|
||||||
for my $l(split(/\s+/, $cancel_lock)) {
|
|
||||||
unless($l =~ m/^(sha512|sha256|sha1|md5):(\S+)/) {
|
|
||||||
printf ("Invalid Cancel-Lock syntax '%s'\n", $l);
|
|
||||||
next;
|
|
||||||
}
|
|
||||||
$lock{$2} = $1;
|
|
||||||
}
|
|
||||||
|
|
||||||
for my $k(split(/\s+/, $cancel_key)) {
|
|
||||||
unless($k =~ m/^(sha512|sha256|sha1|md5):(\S+)/) {
|
|
||||||
printf ("Invalid Cancel-Key syntax '%s'\n", $k);
|
|
||||||
next;
|
|
||||||
}
|
|
||||||
|
|
||||||
my $key;
|
|
||||||
if ($1 eq 'sha512') {
|
|
||||||
$key = Digest::SHA::sha512($2);
|
|
||||||
} elsif ($1 eq 'sha256') {
|
|
||||||
$key = Digest::SHA::sha256($2);
|
|
||||||
} elsif($1 eq 'sha1') {
|
|
||||||
$key = Digest::SHA::sha1($2);
|
|
||||||
} elsif ($1 eq 'md5') {
|
|
||||||
$key = Digest::MD5::md5($2);
|
|
||||||
}
|
|
||||||
$key = MIME::Base64::encode_base64($key, '');
|
|
||||||
|
|
||||||
if (exists($lock{$key})) {
|
|
||||||
return sprintf("Cancel-Key %s:%s matches Cancel-Lock %s:%s.", $1, $2, $lock{$key}, $key);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return 'No Cancel-Key matches any Cancel-Lock.';
|
|
||||||
}
|
|
||||||
|
|
||||||
# Main program ########################
|
|
||||||
|
|
||||||
if (!$OptCanLock or !$OptCanKey) {
|
|
||||||
print "canlockcheck -l <Cancel-Lock> -k <Cancel-Key>\n";
|
|
||||||
exit 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
my $result = &verify_cancel_key($OptCanLock, $OptCanKey);
|
|
||||||
|
|
||||||
printf ("%s\n", $result);
|
|
||||||
exit;
|
|
||||||
148
canlockey.pl
Normal file
148
canlockey.pl
Normal file
|
|
@ -0,0 +1,148 @@
|
||||||
|
#! /usr/bin/perl -w
|
||||||
|
#
|
||||||
|
# canlockey.pl
|
||||||
|
#
|
||||||
|
# Generate a Cancel-Key for a given Message-ID with a given INN-User
|
||||||
|
# and secret, or check if a given Cancel-Key matches the Cancel-Lock.
|
||||||
|
#
|
||||||
|
# Copyright (c) 2023, 2026 Thomas Hochstein <thh@thh.name>
|
||||||
|
|
||||||
|
use MIME::Base64();
|
||||||
|
use Digest::SHA();
|
||||||
|
use Digest::MD5 qw(md5);
|
||||||
|
use Digest::HMAC qw(hmac);
|
||||||
|
use Getopt::Long qw(GetOptions);
|
||||||
|
Getopt::Long::config ('bundling');
|
||||||
|
|
||||||
|
my $VERSION = "0.2";
|
||||||
|
|
||||||
|
# read commandline options ############
|
||||||
|
my ($OptCanLock,$OptCanKey);
|
||||||
|
GetOptions ('h|hash=s' => \$OptCanHash,
|
||||||
|
'k|key=s' => \$OptCanKey,
|
||||||
|
'l|lock=s' => \$OptCanLock,
|
||||||
|
'm|mid=s' => \$OptMID,
|
||||||
|
's|secret=s' => \$OptSecret,
|
||||||
|
'u|user=s' => \$OptUser,
|
||||||
|
'V|version' => \&ShowVersion) or exit 1;
|
||||||
|
|
||||||
|
# subroutines #########################
|
||||||
|
|
||||||
|
### display version information and exit
|
||||||
|
sub ShowVersion {
|
||||||
|
print "canlockey.pl v$VERSION\n";
|
||||||
|
print "Copyright (c) 2023, 2026 Thomas Hochstein <thh\@thh.name>\n";
|
||||||
|
print "This program is free software; you may redistribute it ".
|
||||||
|
"and/or modify it under the same terms as Perl itself.\n";
|
||||||
|
exit;
|
||||||
|
};
|
||||||
|
|
||||||
|
sub create_cancel_key($$$) {
|
||||||
|
my ( $message_id, $user, $secret, $hash ) = @_;
|
||||||
|
|
||||||
|
# create Cancel-Key
|
||||||
|
my $key;
|
||||||
|
if ($hash eq 'sha512') {
|
||||||
|
$key = Digest::SHA::hmac_sha512($message_id, $user . $secret);
|
||||||
|
} elsif ($hash eq 'sha256') {
|
||||||
|
$key = Digest::SHA::hmac_sha256($message_id, $user . $secret);
|
||||||
|
} elsif($hash eq 'sha1') {
|
||||||
|
$key = Digest::SHA::hmac_sha1($message_id, $user . $secret);
|
||||||
|
} elsif ($hash eq 'md5') {
|
||||||
|
$key = Digest::HMAC::hmac($message_id, $user . $secret);
|
||||||
|
}
|
||||||
|
$key = sprintf('%s:%s', $hash, MIME::Base64::encode_base64($key, ''));
|
||||||
|
return $key;
|
||||||
|
}
|
||||||
|
|
||||||
|
sub verify_cancel_key($$) {
|
||||||
|
my ( $cancel_lock, $cancel_key ) = @_;
|
||||||
|
|
||||||
|
# split Cancel-Locks in a hash
|
||||||
|
# key is Cancel-Lock, value is hash
|
||||||
|
my %lock;
|
||||||
|
for my $l(split(/\s+/, $cancel_lock)) {
|
||||||
|
unless($l =~ m/^(sha512|sha256|sha1|md5):(\S+)/) {
|
||||||
|
printf ("Invalid Cancel-Lock syntax '%s'\n", $l);
|
||||||
|
next;
|
||||||
|
}
|
||||||
|
$lock{$2} = $1;
|
||||||
|
}
|
||||||
|
|
||||||
|
# split Cancel-Keys and iterate about the result
|
||||||
|
# $1 is hash, $2 is Cancel-Key
|
||||||
|
for my $k(split(/\s+/, $cancel_key)) {
|
||||||
|
unless($k =~ m/^(sha512|sha256|sha1|md5):(\S+)/) {
|
||||||
|
printf ("Invalid Cancel-Key syntax '%s'\n", $k);
|
||||||
|
next;
|
||||||
|
}
|
||||||
|
|
||||||
|
# calculate Cancel-Lock from Cancel-Key
|
||||||
|
my $lock;
|
||||||
|
if ($1 eq 'sha512') {
|
||||||
|
$lock = Digest::SHA::sha512($2);
|
||||||
|
} elsif ($1 eq 'sha256') {
|
||||||
|
$lock = Digest::SHA::sha256($2);
|
||||||
|
} elsif($1 eq 'sha1') {
|
||||||
|
$lock = Digest::SHA::sha1($2);
|
||||||
|
} elsif ($1 eq 'md5') {
|
||||||
|
$lock = Digest::MD5::md5($2);
|
||||||
|
}
|
||||||
|
$lock = MIME::Base64::encode_base64($lock, '');
|
||||||
|
|
||||||
|
if (exists($lock{$lock})) {
|
||||||
|
return sprintf("Cancel-Key %s:%s matches Cancel-Lock %s:%s.", $1, $2, $lock{$lock}, $lock);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 'No Cancel-Key matches any Cancel-Lock.';
|
||||||
|
}
|
||||||
|
|
||||||
|
# Main program ########################
|
||||||
|
|
||||||
|
if ($OptCanLock && $OptCanKey) {
|
||||||
|
### compare -k to -l
|
||||||
|
|
||||||
|
print "Checking for Cancel-Key that matches Cancel-Lock ...\n";
|
||||||
|
printf("%s\n", &verify_cancel_key($OptCanLock, $OptCanKey));
|
||||||
|
|
||||||
|
} elsif ($OptMID) {
|
||||||
|
### create a Cancel-Key
|
||||||
|
|
||||||
|
# die if no (valid) Message-ID has been submitted
|
||||||
|
die sprintf("Invalid Message-ID: %s\n", $OptMID)
|
||||||
|
if $OptMID !~ /^<[^\@<>]+\@[^\@<>]+>$/;
|
||||||
|
|
||||||
|
# set defaults for options not given
|
||||||
|
$OptUser = '' if !$OptUser;
|
||||||
|
$OptSecret = '' if !$OptSecret;
|
||||||
|
$OptCanHash = 'sha1' if !$OptCanHash;
|
||||||
|
|
||||||
|
# die if no valid hash has been submitted
|
||||||
|
die sprintf("Invalid hash type: %s\n", $OptCanHash)
|
||||||
|
unless $OptCanHash =~ m/^(sha512|sha256|sha1|md5)$/;
|
||||||
|
|
||||||
|
printf("Creating a %s Cancel-Key for user '%s'%sagainst %s ...\n",
|
||||||
|
$OptCanHash, $OptUser, $OptSecret ? ' ' : ' without secret ', $OptMID);
|
||||||
|
|
||||||
|
my $cancel_key = &create_cancel_key($OptMID, $OptUser, $OptSecret, $OptCanHash);
|
||||||
|
|
||||||
|
printf("Cancel-Key: %s\n", $cancel_key);
|
||||||
|
|
||||||
|
if($OptCanLock) {
|
||||||
|
printf("%s\n", &verify_cancel_key($OptCanLock, $cancel_key));
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
### show usage
|
||||||
|
|
||||||
|
print "canlockey.pl v$VERSION\n";
|
||||||
|
print "Usage:\n";
|
||||||
|
print "1) Check for a matching Cancel-Key:\n";
|
||||||
|
print " canlockey -l <Cancel-Lock> -k <Cancel-Key>\n";
|
||||||
|
print "2) Create a Cancel-Key:\n";
|
||||||
|
print " canlockey -m <Message-ID> [-u <User>] [-s <secret>] [-h <hash>] [-l <Cancel-Lock>]\n";
|
||||||
|
exit 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
exit;
|
||||||
Loading…
Add table
Add a link
Reference in a new issue