Skip to content
Commits on Source (5)
......@@ -19,7 +19,7 @@ Dependencies
Monkeysphere depends on:
* GnuPG >= 2.1.11
* GnuPG >= 2.1.17
* Perl
* Perl's Crypt::OpenSSL::RSA module
* lockfile-progs or procmail's lockfile
......
......@@ -27,9 +27,10 @@ be omitted, and \fBmonkeysphere\-host\fP will operate on it.
\fBmonkeysphere\-host\fP takes various subcommands:
.TP
.B import\-key FILE SCHEME://HOSTNAME[:PORT]
Import a PEM\-encoded host secret key from file FILE. If FILE is
`\-', then the key will be imported from stdin. Only RSA keys are
supported at the moment. SCHEME://HOSTNAME[:PORT] is used to specify
Import an SSH host secret key from file FILE. If FILE is
`\-', then the key will be imported from stdin, and must be an
RSA key in PEM\-encoded format.
SCHEME://HOSTNAME[:PORT] is used to specify
the scheme (e.g. ssh or https), fully\-qualified hostname (and port)
used in the user ID of the new OpenPGP key (e.g. ssh://example.net or
https://www.example.net). If PORT is not specified, then no port is
......
......@@ -871,147 +871,6 @@ sub getallprimarykeys {
}
}
sub adduserid {
my $instr = shift;
my $fpr = shift;
my $uid = shift;
my $args = shift;
if ((! defined $fpr) ||
(length($fpr) < 8)) {
die "We need at least 8 hex digits of fingerprint.\n";
}
$fpr = uc($fpr);
if (! defined $uid) {
die "No User ID defined.\n";
}
my $data = { target => { fpr => $fpr,
uid => $uid,
},
};
my $subs = { $packet_types->{seckey} => \&findkey,
$packet_types->{uid} => \&finduid,
$packet_types->{sig} => \&findsig,
};
packetwalk($instr, $subs, $data);
if ((! defined $data->{key}) ||
(! defined $data->{key}->{rsa}) ||
(! defined $data->{key}->{timestamp})) {
die "The key requested was not found.\n"
}
if (defined $data->{uid}->{$uid} &&
defined $data->{sigs} &&
scalar(@{$data->{sigs}}) > 0 ) {
die "The requested User ID '$uid' is already associated with this key.\n";
}
$args->{key_timestamp} = $data->{key}->{timestamp};
return
make_packet($packet_types->{pubkey}, make_rsa_pub_key_body($data->{key}->{rsa}, $data->{key}->{timestamp})).
make_packet($packet_types->{uid}, $uid).
makeselfsig($data->{key}->{rsa},
$uid,
$args);
}
sub revokeuserid {
my $instr = shift;
my $fpr = shift;
my $uid = shift;
my $sigtime = shift;
if ((! defined $fpr) ||
(length($fpr) < 8)) {
die "We need at least 8 hex digits of fingerprint.\n";
}
$fpr = uc($fpr);
if (! defined $uid) {
die "No User ID defined.\n";
}
my $data = { target => { fpr => $fpr,
uid => $uid,
},
};
my $subs = { $packet_types->{seckey} => \&findkey,
$packet_types->{uid} => \&finduid,
$packet_types->{sig} => \&findsig,
};
packetwalk($instr, $subs, $data);
if ((! defined $data->{uid}) ||
(! defined $data->{uid}->{$uid})) {
die "The User ID \"$uid\" is not associated with this key";
}
if ((! defined $data->{key}) ||
(! defined $data->{key}->{rsa}) ||
(! defined $data->{key}->{timestamp})) {
die "The key requested was not found."
}
my $revocation_reason = 'No longer using this hostname';
if (defined $data->{revocation_reason}) {
$revocation_reason = $data->{revocation_reason};
}
my $rev_reason_subpkt = prefixsubpacket(pack('CC',
$subpacket_types->{revocation_reason},
$revocation_reasons->{user_id_no_longer_valid}).
$revocation_reason);
if (! defined $sigtime) {
$sigtime = time();
}
# what does a signature like this look like?
my $args = { key_timestamp => $data->{key}->{timestamp},
sig_timestamp => $sigtime,
certification_type => $sig_types->{certification_revocation},
hashed_subpackets => $rev_reason_subpkt,
};
return
make_packet($packet_types->{pubkey}, make_rsa_pub_key_body($data->{key}->{rsa}, $data->{key}->{timestamp})).
make_packet($packet_types->{uid}, $uid).
join('', @{$data->{sigs}}).
gensig($data->{key}->{rsa}, $uid, $args);
}
# see 5.2.3.1 for tips on how to calculate the length of a subpacket:
sub prefixsubpacket {
my $subpacket = shift;
my $len = length($subpacket);
my $prefix;
use bytes;
if ($len < 192) {
# one byte:
$prefix = pack('C', $len);
} elsif ($len < 16576) {
my $in = $len - 192;
my $second = $in%256;
my $first = ($in - $second)>>8;
$prefix = pack('CC', $first + 192, $second)
} else {
$prefix = pack('CN', 255, $len);
}
return $prefix.$subpacket;
}
sub packetwalk {
my $instr = shift;
my $subs = shift;
......@@ -1172,30 +1031,7 @@ for (basename($0)) {
# UNDOCUMENTED, and WILL NOT BE MAINTAINED.
my $subcommand = shift;
for ($subcommand) {
if (/^revokeuserid$/) {
my $fpr = shift;
my $uid = shift;
my $instream;
open($instream,'-');
binmode($instream, ":bytes");
my $revcert = revokeuserid($instream, $fpr, $uid, $ENV{PEM2OPENPGP_TIMESTAMP});
print $revcert;
} elsif (/^adduserid$/) {
my $fpr = shift;
my $uid = shift;
my $instream;
open($instream,'-');
binmode($instream, ":bytes");
my $newuid = adduserid($instream, $fpr, $uid,
{ sig_timestamp => $ENV{PEM2OPENPGP_TIMESTAMP},
expiration => $ENV{PEM2OPENPGP_EXPIRATION},
usage_flags => $ENV{PEM2OPENPGP_USAGE_FLAGS},
});
print $newuid;
} elsif (/^listfprs$/) {
if (/^listfprs$/) {
my $instream;
open($instream,'-');
binmode($instream, ":bytes");
......@@ -1232,4 +1068,3 @@ for (basename($0)) {
die "Unrecognized keytrans call.\n";
}
}
......@@ -50,10 +50,7 @@ else
fi
# execute edit-key script
if gpg_host --export-secret-keys "$keyID" | \
PEM2OPENPGP_USAGE_FLAGS=authenticate \
"$SYSSHAREDIR/keytrans" adduserid "$keyID" "$serviceName" \
| gpg_host --import ; then
if gpg_host --quick-add-uid "$keyID" "$serviceName" ; then
gpg_host --check-trustdb
......
......@@ -18,7 +18,7 @@ local serviceName="$2"
# check that key file specified
if [ -z "$keyFile" ] ; then
failure "Must specify PEM-encoded key file to import, or specify '-' for stdin."
failure "Must specify key file to import, or specify '-' for PEM-encoded RSA key on stdin."
fi
# fail if hostname not specified
......@@ -37,16 +37,84 @@ mkdir -p "${MHDATADIR}"
mkdir -p "${GNUPGHOME_HOST}"
chmod 700 "${GNUPGHOME_HOST}"
# import pem-encoded key to an OpenPGP private key
key_type_from_file() {
# translates from OpenSSH's pubkey format string to GnuPG's
# Key-Type parameter:
local keyType
if keyType=$(ssh-keygen -y -f "$keyFile" | awk '{ print $1 }'); then
case "$keyType" in
ssh-dss)
echo DSA
;;
ecdsa-sha2-nistp256)
echo ECDSA
;;
ssh-ed25519)
echo EDDSA
;;
ssh-rsa)
echo RSA
;;
*)
log error "unknown key type '$keyType' from file '$keyFile'"
return 1
;;
esac
else
log error "ssh-keygen could not interpret '$keyFile'"
return 1
fi
return 0
}
if [ "$keyFile" = '-' ] ; then
log verbose "importing key from stdin..."
# import PEM-encoded RSA stdin to an OpenPGP private key
log verbose "importing PEM-encoded RSA key from stdin..."
PEM2OPENPGP_USAGE_FLAGS=authenticate pem2openpgp "$serviceName" \
| gpg_host --import
else
log verbose "importing key from file '$keyFile'..."
PEM2OPENPGP_USAGE_FLAGS=authenticate pem2openpgp "$serviceName" \
<"$keyFile" \
| gpg_host --import
# import some sort of file that OpenSSH's keygen can handle
if keyType=$(key_type_from_file "$keyFile"); then
# we lock to avoid concurrent interactions with gpg-agent and
# the sshcontrol file would be dubious
lock create "$GNUPGHOME_HOST/importlock"
if test -e "$GNUPGHOME_HOST/sshcontrol" && grep -q '^[0-9A-F]' "$GNUPGHOME_HOST/sshcontrol"; then
backupSshControl=$(mktemp "$GNUPGHOME_HOST/sshcontrol.XXXXXXXX")
log error "$GNUPGHOME_HOST/sshcontrol already contained a key, backing up to $backupSshControl"
mv -f "$GNUPGHOME_HOST/sshcontrol" "$backupSshControl"
fi
log verbose "importing $keyType key from file '$keyFile'..."
if ! { test -e "$GNUPGHOME_HOST/gpg-agent.conf" && grep -Fxq batch "$GNUPGHOME_HOST/gpg-agent.conf" ; }; then
echo batch >> "$GNUPGHOME_HOST/gpg-agent.conf"
GNUPGHOME="$GNUPGHOME_HOST" gpgconf --reload gpg-agent
GNUPGHOME="$GNUPGHOME_HOST" gpgconf --launch gpg-agent
fi
SSH_AUTH_SOCK=$(GNUPGHOME="$GNUPGHOME_HOST" gpgconf --list-dirs agent-ssh-socket) ssh-add "$keyFile"
if keyGrip=$(awk '/^[0-9A-F]/{print $1}' < "$GNUPGHOME_HOST/sshcontrol") &&
test -n "$keyGrip" && [ $(wc -l <<<"$keyGrip") -eq 1 ] ; then
gpg_host --batch --full-generate-key <<EOF
Key-Type: $keyType
Key-Grip: $keyGrip
Key-Usage: auth
Name-Real: $serviceName
%no-protection
%commit
EOF
else
rm -f "$GNUPGHOME_HOST/sshcontrol"
lock remove "$GNUPGHOME_HOST/importlock"
failure "did not find a single keygrip in $GNUPGHOME_HOST/sshcontrol during import"
fi
rm -f "$GNUPGHOME_HOST/sshcontrol"
lock remove "$GNUPGHOME_HOST/importlock"
else
log error "falling back to pem2openpgp (which will probably still fail)..."
PEM2OPENPGP_USAGE_FLAGS=authenticate pem2openpgp "$serviceName" \
<"$keyFile" \
| gpg_host --import
fi
fi
# export to OpenPGP public key to file
......
......@@ -46,15 +46,7 @@ else
fi
# actually revoke:
# the gpg secring might not contain the host key we are trying to
# revoke (let alone any selfsig over that host key), but the plain
# --export won't contain the secret key. "keytrans revokeuserid"
# needs access to both pieces, so we feed it both of them.
if gpg_host --export-secret-keys "$keyID" \
| "$SYSSHAREDIR/keytrans" revokeuserid "$keyID" "$serviceName" \
| gpg_host --import ; then
if gpg_host --quick-revoke-uid "$keyID" "$serviceName" ; then
gpg_host --check-trustdb
......
......@@ -275,7 +275,7 @@ fi
echo
echo "##################################################"
echo "### import host key..."
ssh-keygen -m PEM -b 3072 -t rsa -N '' -f "$TEMPDIR"/ssh_host_rsa_key
ssh-keygen -b 3072 -t rsa -N '' -f "$TEMPDIR"/ssh_host_rsa_key
monkeysphere-host import-key "$TEMPDIR"/ssh_host_rsa_key ssh://testhost.example
echo
......
......@@ -136,57 +136,6 @@ gpg --check-trustdb
gpg --list-keys
echo "##################################################"
echo "### test User ID addition..."
gpg --export-secret-keys | \
PEM2OPENPGP_TIMESTAMP="$timestamp" \
PEM2OPENPGP_USAGE_FLAGS=sign,certify \
keytrans adduserid "$KEYID" "monkeymonkey" | gpg --import
gpg --check-trustdb
gpg --list-keys
cat >"$TEMPDIR"/expectedout <<EOF
pub:u:3072:1:$KEYID:$timestamp:::u:::scSC
uid:u::::$timestamp::E90EC72E68C6C2A0751DADC70F54F60D27B88C3D::monkeymonkey
sig:!::1:$KEYID:$timestamp::::monkeymonkey:13x::$KEYFPR:::8
uid:u::::$timestamp::8200BD0425CC70C7D698DF3FE412044EAAB83F94::testtest
sig:!::1:$KEYID:$timestamp::::monkeymonkey:13x::$KEYFPR:::8
EOF
diff -u "$TEMPDIR"/expectedout <(gpg --check-sigs --with-colons | grep -vE '^(tru|fpr):' | cut -d: -f1-16 | sed 's/:*$//')
echo "##################################################"
echo "### sleeping to avoid test suite breakage on fast"
echo "### processors (see https://bugs.debian.org/591118)"
sleep 2
echo "##################################################"
echo "### test User ID revocation ... "
revtime=$(($timestamp + 1))
gpg --export-secret-keys | \
PEM2OPENPGP_TIMESTAMP="$revtime" \
keytrans revokeuserid "$KEYID" "testtest" | gpg --import
gpg --check-trustdb
gpg --list-keys
cat >"$TEMPDIR"/expectedout <<EOF
pub:u:3072:1:$KEYID:$timestamp:::u:::scSC
uid:u::::$timestamp::E90EC72E68C6C2A0751DADC70F54F60D27B88C3D::monkeymonkey
sig:!::1:$KEYID:$timestamp::::monkeymonkey:13x::$KEYFPR:::8
uid:r::::::8200BD0425CC70C7D698DF3FE412044EAAB83F94::testtest
sig:!::1:$KEYID:$timestamp::::monkeymonkey:13x::$KEYFPR:::8
rev:!::1:$KEYID:$revtime::::monkeymonkey:30x,20::$KEYFPR:::8
EOF
diff -u "$TEMPDIR"/expectedout <(gpg --check-sigs --with-colons | grep -vE '^(tru|fpr):' | cut -d: -f1-16 | sed 's/:*$//')
echo "##################################################"
echo "### test working with two primary keys ... "
......@@ -201,19 +150,14 @@ NEWKEYID=$( printf "%s" "$NEWKEYFPR" | cut -b25-40)
< "$TEMPDIR"/newkey.gpg gpg --import
gpg --export-secret-keys | \
PEM2OPENPGP_TIMESTAMP="$timestamp" \
keytrans adduserid "$KEYID" "baz" | gpg --import
gpg --batch --no-tty --faked-system-time "$timestamp" --quick-add-uid "$KEYID" baz
cat >"$TEMPDIR"/expectedout <<EOF
pub:u:3072:1:$KEYID:$timestamp:::u:::scSC
uid:u::::$timestamp::E90EC72E68C6C2A0751DADC70F54F60D27B88C3D::monkeymonkey
sig:!::1:$KEYID:$timestamp::::monkeymonkey:13x::$KEYFPR:::8
uid:r::::::8200BD0425CC70C7D698DF3FE412044EAAB83F94::testtest
sig:!::1:$KEYID:$timestamp::::monkeymonkey:13x::$KEYFPR:::8
rev:!::1:$KEYID:$revtime::::monkeymonkey:30x,20::$KEYFPR:::8
uid:u::::$timestamp::8200BD0425CC70C7D698DF3FE412044EAAB83F94::testtest
sig:!::1:$KEYID:$timestamp::::testtest:13x::$KEYFPR:::8
uid:u::::$timestamp::EDDC32D783E7F4C7B6982D9AE5DC4A61000648BA::baz
sig:!::1:$KEYID:$timestamp::::monkeymonkey:13x::$KEYFPR:::8
sig:!::1:$KEYID:$timestamp::::testtest:13x::$KEYFPR:::8
pub:-:3072:1:$NEWKEYID:$(($timestamp + 1)):::-:::caCA
uid:-::::$(($timestamp + 1))::A0D708F51CC257DEFC01AEDE1E0A5F329DFD8F16::fubar
sig:!::1:$NEWKEYID:$(($timestamp + 1))::::fubar:13x::$NEWKEYFPR:::8
......
......@@ -11,7 +11,7 @@
* create debian-specific version tag:
git tag -s -m "Tagging Monkeysphere $version-1" monkeysphere_$version-1 debian
git tag -s -m "Tagging Monkeysphere $version-1" monkeysphere_$version-1 debian/master
* make releasenote
......