signify support
authorespie <espie@openbsd.org>
Tue, 31 Dec 2013 11:21:10 +0000 (11:21 +0000)
committerespie <espie@openbsd.org>
Tue, 31 Dec 2013 11:21:10 +0000 (11:21 +0000)
usr.sbin/pkg_add/Makefile
usr.sbin/pkg_add/OpenBSD/PackingElement.pm
usr.sbin/pkg_add/OpenBSD/PackingList.pm
usr.sbin/pkg_add/OpenBSD/Paths.pm
usr.sbin/pkg_add/OpenBSD/PkgCreate.pm
usr.sbin/pkg_add/OpenBSD/signify.pm [new file with mode: 0644]

index 69c22f3..11ac046 100644 (file)
@@ -1,4 +1,4 @@
-# $OpenBSD: Makefile,v 1.76 2012/08/06 00:00:28 fgsch Exp $
+# $OpenBSD: Makefile,v 1.77 2013/12/31 11:21:10 espie Exp $
 
 .include <bsd.own.mk>
 
@@ -66,6 +66,7 @@ PACKAGES= \
     OpenBSD/Ustar.pm \
     OpenBSD/Vstat.pm \
     OpenBSD/md5.pm \
+    OpenBSD/signify.pm \
     OpenBSD/x509.pm
 
 PACKAGEDIRS=OpenBSD  OpenBSD/PackageRepository OpenBSD/ProgressMeter \
index 3258adb..66b90e3 100644 (file)
@@ -1,5 +1,5 @@
 # ex:ts=8 sw=4:
-# $OpenBSD: PackingElement.pm,v 1.214 2013/12/30 09:14:49 espie Exp $
+# $OpenBSD: PackingElement.pm,v 1.215 2013/12/31 11:21:10 espie Exp $
 #
 # Copyright (c) 2003-2010 Marc Espie <espie@openbsd.org>
 #
@@ -1805,13 +1805,12 @@ sub new
                $class;
 }
 
-sub new_x509
+sub blank
 {
-       my ($class) = @_;
-       bless { key => 'x509', timestamp => time, b64sig => '' }, $class;
+       my ($class, $type) = @_;
+       bless { key => $type, timestamp => time, b64sig => '' }, $class;
 }
 
-
 sub stringize
 {
        my $self = shift;
index 1afa73e..a965fc0 100644 (file)
@@ -1,5 +1,5 @@
 # ex:ts=8 sw=4:
-# $OpenBSD: PackingList.pm,v 1.123 2013/12/30 09:14:49 espie Exp $
+# $OpenBSD: PackingList.pm,v 1.124 2013/12/31 11:21:10 espie Exp $
 #
 # Copyright (c) 2003-2010 Marc Espie <espie@openbsd.org>
 #
@@ -538,6 +538,9 @@ sub check_signature
        if ($sig->{key} eq 'x509') {
                require OpenBSD::x509;
                return OpenBSD::x509::check_signature($plist, $state);
+       } elsif ($sig->{key} eq 'signify') {
+               require OpenBSD::signify;
+               return OpenBSD::signify::check_signature($plist, $state);
        } else {
                $state->log("Error: unknown signature style $sig->{key}");
                return 0;
index 00a9cac..1d77913 100644 (file)
@@ -1,5 +1,5 @@
 # ex:ts=8 sw=4:
-# $OpenBSD: Paths.pm,v 1.21 2012/01/16 08:42:38 schwarze Exp $
+# $OpenBSD: Paths.pm,v 1.22 2013/12/31 11:21:10 espie Exp $
 #
 # Copyright (c) 2007 Marc Espie <espie@openbsd.org>
 #
@@ -32,6 +32,8 @@ sub groupadd() { '/usr/sbin/groupadd' }
 sub sysctl() { '/sbin/sysctl' }
 sub openssl() { '/usr/sbin/openssl' }
 sub pkgca() { '/etc/ssl/pkgca.pem' }
+sub signify() { '/usr/bin/signify' }
+sub signifykey() { '/etc/openbsd.pubkey' }
 sub pkg_add() { '/usr/sbin/pkg_add' }
 sub chmod() { '/bin/chmod' }   # external command is used for symbolic modes.
 sub gzip() { '/usr/bin/gzip' }
index 9e4443e..6be2407 100644 (file)
@@ -1,6 +1,6 @@
 #! /usr/bin/perl
 # ex:ts=8 sw=4:
-# $OpenBSD: PkgCreate.pm,v 1.75 2013/12/30 09:14:49 espie Exp $
+# $OpenBSD: PkgCreate.pm,v 1.76 2013/12/31 11:21:10 espie Exp $
 #
 # Copyright (c) 2003-2010 Marc Espie <espie@openbsd.org>
 #
@@ -23,13 +23,33 @@ use OpenBSD::AddCreateDelete;
 use OpenBSD::Dependencies;
 use OpenBSD::SharedLibs;
 
+package Signer;
+
+my $h = {
+       x509 => 'Signer::X509',
+       signify => 'Signer::SIGNIFY',
+};
+
+sub factory
+{
+       my ($class, $state) = @_;
+
+       my @p = @{$state->{signature_params}};
+
+       if (defined $h->{$p[0]}) {
+               return $h->{$p[0]}->new($state, @p);
+       } else {
+               $state->usage("Unknown signature scheme $p[0]");
+       }
+}
+
 package Signer::X509;
 sub new
 {
        my ($class, $state, @p) = @_;
 
        if (@p != 3 || !-f $p[1] || !-f $p[2]) {
-               $state->usage("x509 signature wants -s cert -s privkey");
+               $state->usage("$p[0] signature wants -s cert -s privkey");
        }
        bless {cert => $p[1], privkey => $p[2]}, $class;
 }
@@ -37,7 +57,7 @@ sub new
 sub new_sig
 {
        require OpenBSD::x509;
-       return OpenBSD::PackingElement::DigitalSignature->new_x509;
+       return OpenBSD::PackingElement::DigitalSignature->blank('x509');
 }
 
 sub compute_signature
@@ -47,6 +67,30 @@ sub compute_signature
            $self->{privkey});
 }
 
+package Signer::SIGNIFY;
+sub new
+{
+       my ($class, $state, @p) = @_;
+       if (@p != 2 || !-f $p[1]) {
+               $state->usage("$p[0] signature wants -s privkey");
+       }
+
+       bless {privkey => $p[1]}, $class;
+}
+
+sub new_sig
+{
+       require OpenBSD::signify;
+       return OpenBSD::PackingElement::DigitalSignature->blank('signify');
+}
+
+sub compute_signature
+{
+       my ($self, $state, $plist) = @_;
+       return OpenBSD::signify::compute_signature($plist, $state, 
+           $self->{privkey});
+}
+
 package OpenBSD::PkgCreate::State;
 our @ISA = qw(OpenBSD::AddCreateDelete::State);
 
@@ -146,7 +190,7 @@ sub handle_options
        $state->SUPER::handle_options('p:f:d:M:U:s:A:B:P:W:qQo:S:',
            '[-nQqvx] [-A arches] [-B pkg-destdir] [-D name[=value]]',
            '[-L localbase] [-M displayfile] [-P pkg-dependency]',
-           '[-s [x509|sos] -s cert -s priv] [-o dir] [-S source]',
+           '[-s [x509 -s cert|signify] -s priv] [-o dir] [-S source]',
            '[-U undisplayfile] [-W wantedlib]',
            '[-d desc -D COMMENT=value -f packinglist -p prefix]',
            'pkg-name...');
@@ -219,6 +263,15 @@ sub verify_checksum
 {
 }
 
+sub register_forbidden
+{
+       my ($self, $state) = @_;
+       if ($self->is_forbidden) {
+               push(@{$state->{forbidden}}, $self);
+       }
+}
+
+sub is_forbidden() { 0 }
 sub resolve_link
 {
        my ($filename, $base, $level) = @_;
@@ -413,7 +466,6 @@ sub verify_checksum
 {
 }
 
-
 package OpenBSD::PackingElement::Cwd;
 sub archive
 {
@@ -654,6 +706,12 @@ sub find_every_library
        push(@{$h->{$l[0]}{dynamic}}, $self);
 }
 
+package OpenBSD::PackingElement::DigitalSignature;
+sub is_forbidden() { 1 }
+
+package OpenBSD::PackingElement::Url;
+sub is_forbidden() { 1 }
+
 package OpenBSD::PackingElement::Fragment;
 our @ISA=qw(OpenBSD::PackingElement);
 
@@ -671,7 +729,6 @@ sub stringize
        return '!%%'.shift->{name}.'%%';
 }
 
-
 # put together file and filename, in order to handle fragments simply
 package MyFile;
 sub new
@@ -1062,7 +1119,6 @@ sub add_signature
 {
        my ($self, $plist, $state) = @_;
 
-
        if ($plist->has('digital-signature')) {
                if ($state->defines('resign')) {
                        $state->errsay("Resigning #1", $plist->pkgname);
@@ -1222,18 +1278,25 @@ sub create_plist
                $pkgname = $1;
                $pkgname =~ s/\.tgz$//o;
        }
-       $plist->set_pkgname($pkgname);
        $state->say("Creating package #1", $pkgname)
            if !(defined $state->opt('q')) && $state->opt('v');
        if (!$state->opt('q')) {
                $plist->set_infodir(OpenBSD::Temp->dir);
        }
 
-       $self->add_elements($plist, $state);
        unless (defined $state->opt('q') && defined $state->opt('n')) {
                $state->set_status("reading plist");
        }
+       $plist->set_pkgname($pkgname);
+       $self->add_elements($plist, $state);
        $self->read_all_fragments($state, $plist);
+       $plist->register_forbidden($state);
+       if (defined $state->{forbidden}) {
+               for my $e (@{$state->{forbidden}}) {
+                       $state->errsay("Error: #1 can't be set explicitly", "\@".$e->keyword." ".$e->stringize);
+               }
+               $state->fatal("Can't continue");
+       }
        return $plist;
 }
 
@@ -1386,12 +1449,7 @@ sub parse_and_run
 
        try {
        if (defined $state->{signature_params}) {
-               my @p = @{$state->{signature_params}};
-               if ($p[0] eq 'x509') {
-                       $state->{signer} = Signer::X509->new($state, @p);
-               } else  {
-                       $state->usage("Unknown signature scheme $p[0]");
-               }
+               $state->{signer} = Signer->factory($state);
        }
        if (defined $state->opt('Q')) {
                $state->{opt}{q} = 1;
diff --git a/usr.sbin/pkg_add/OpenBSD/signify.pm b/usr.sbin/pkg_add/OpenBSD/signify.pm
new file mode 100644 (file)
index 0000000..e1ed4a4
--- /dev/null
@@ -0,0 +1,84 @@
+# ex:ts=8 sw=4:
+# $OpenBSD: signify.pm,v 1.1 2013/12/31 11:21:10 espie Exp $
+#
+# Copyright (c) 2013 Marc Espie <espie@openbsd.org>
+#
+# Permission to use, copy, modify, and distribute this software for any
+# purpose with or without fee is hereby granted, provided that the above
+# copyright notice and this permission notice appear in all copies.
+#
+# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+use strict;
+use warnings;
+
+package OpenBSD::signify;
+
+use OpenBSD::PackageInfo;
+use OpenBSD::Paths;
+use File::Temp qw/mkstemp/;
+
+my $header = "signify -- signature\n";
+my $cmd = OpenBSD::Paths->signify;
+my $defaultpubkey = OpenBSD::Paths->signifykey;
+my $suffix = ".sig";
+
+sub compute_signature
+{
+       my ($plist, $state, $key) = @_;
+
+       my $contents = $plist->infodir.CONTENTS;
+       my $sigfile = $contents.$suffix;
+
+       open my $fh, ">", $contents;
+       $plist->write_no_sig($fh);
+       close $fh;
+       $state->system($cmd, '-I', $contents, '-S', $key, '-V', 'sign')
+           == 0 or die "probleme generating signature";
+       open(my $sighandle, '<', $sigfile)
+               or die "problem reading signature";
+       my $header = <$sighandle>;
+       my $sig = <$sighandle>;
+       close($sighandle);
+       unlink($sigfile);
+       chomp $sig;
+       return $sig;
+}
+
+sub check_signature
+{
+       my ($plist, $state) = @_;
+       my $sig = $plist->get('digital-signature');
+       my ($fh, $fname) = mkstemp("/tmp/pkgcontent.XXXXXXXXX");
+       $plist->write_no_sig($fh);
+       open(my $fh2, ">", $fname.$suffix);
+       print $fh2 $header, $sig->{b64sig}, "\n";
+       close $fh;
+       close $fh2;
+       my $pubkey = $defaultpubkey;
+       if ($plist->has('vendor')) {
+               my $vendor = $plist->get('vendor')->name;
+               $pubkey = "/etc/signify/$vendor.pubkey";
+               if (!-f $pubkey) {
+                       $state->say("Unknown vendor #1", $vendor);
+                       return 0;
+               }
+       }
+       if ($state->system(sub { open STDERR, ">", "/dev/null";
+           open STDOUT, ">", "/dev/null";},
+           $cmd, '-I', $fname, '-P', $pubkey, '-V', 'verify') != 0) {
+               $state->log("Bad signature");
+               return 0;
+       }
+       unlink $fname;
+       unlink $fname.$suffix;
+       return 1;
+}
+
+1;