PkgSign.pm (c07cf433) PkgSign.pm (039cbdaa)
1#! /usr/bin/perl
2# ex:ts=8 sw=4:
1#! /usr/bin/perl
2# ex:ts=8 sw=4:
3# $OpenBSD: PkgSign.pm,v 1.17 2019/07/08 10:55:39 espie Exp $
3# $OpenBSD: PkgSign.pm,v 1.18 2023/06/13 09:07:17 espie Exp $
4#
5# Copyright (c) 2003-2014 Marc Espie <espie@openbsd.org>
6#
7# Permission to use, copy, modify, and distribute this software for any
8# purpose with or without fee is hereby granted, provided that the above
9# copyright notice and this permission notice appear in all copies.
10#
11# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18
4#
5# Copyright (c) 2003-2014 Marc Espie <espie@openbsd.org>
6#
7# Permission to use, copy, modify, and distribute this software for any
8# purpose with or without fee is hereby granted, provided that the above
9# copyright notice and this permission notice appear in all copies.
10#
11# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18
19use strict;
20use warnings;
19use v5.36;
21
22use OpenBSD::AddCreateDelete;
23use OpenBSD::Signer;
24
25package OpenBSD::PkgSign::State;
26our @ISA = qw(OpenBSD::CreateSign::State);
27
20
21use OpenBSD::AddCreateDelete;
22use OpenBSD::Signer;
23
24package OpenBSD::PkgSign::State;
25our @ISA = qw(OpenBSD::CreateSign::State);
26
28sub handle_options
27sub handle_options($state)
29{
28{
30 my $state = shift;
31
32 $state->{extra_stats} = 0;
33 $state->{opt} = {
34 'o' =>
29 $state->{extra_stats} = 0;
30 $state->{opt} = {
31 'o' =>
35 sub {
36 $state->{output_dir} = shift;
32 sub($opt) {
33 $state->{output_dir} = $opt;
37 },
38 'S' =>
34 },
35 'S' =>
39 sub {
40 $state->{source} = shift;
36 sub($opt) {
37 $state->{source} = $opt;
41 },
42 's' =>
38 },
39 's' =>
43 sub {
44 push(@{$state->{signature_params}}, shift);
40 sub($opt) {
41 push(@{$state->{signature_params}}, $opt);
45 },
46 'V' =>
42 },
43 'V' =>
47 sub {
44 sub() {
48 $state->{extra_stats}++;
49 },
50 };
51 $state->{signature_style} = 'unsigned';
52
53 $state->SUPER::handle_options('Cij:o:S:s:V',
54 '[-CvV] [-D name[=value]] -s signify2 -s priv',
55 '[-o dir] [-S source] [pkg-name...]');

--- 12 unchanged lines hidden (view full) ---

68 $state->{wantntogo} = $state->{extra_stats};
69}
70
71package OpenBSD::PkgSign;
72use OpenBSD::Temp;
73use OpenBSD::PackingList;
74use OpenBSD::PackageInfo;
75
45 $state->{extra_stats}++;
46 },
47 };
48 $state->{signature_style} = 'unsigned';
49
50 $state->SUPER::handle_options('Cij:o:S:s:V',
51 '[-CvV] [-D name[=value]] -s signify2 -s priv',
52 '[-o dir] [-S source] [pkg-name...]');

--- 12 unchanged lines hidden (view full) ---

65 $state->{wantntogo} = $state->{extra_stats};
66}
67
68package OpenBSD::PkgSign;
69use OpenBSD::Temp;
70use OpenBSD::PackingList;
71use OpenBSD::PackageInfo;
72
76sub sign_existing_package
73sub sign_existing_package($self, $state, $pkg)
77{
74{
78 my ($self, $state, $pkg) = @_;
79 my $output = $state->{output_dir};
80 my $dest = $output.'/'.$pkg->name.".tgz";
81 if ($state->opt('i')) {
82 if (-f $dest) {
83 return;
84 }
85 }
86 my (undef, $tmp) = OpenBSD::Temp::permanent_file($output, "pkg") or
87 die $state->fatal(OpenBSD::Temp->last_error);
88 $state->{signer}->sign($pkg, $state, $tmp);
89
90 chmod((0666 & ~umask), $tmp);
91 rename($tmp, $dest) or
92 $state->fatal("Can't create final signed package: #1", $!);
93 if ($state->opt('C')) {
75 my $output = $state->{output_dir};
76 my $dest = $output.'/'.$pkg->name.".tgz";
77 if ($state->opt('i')) {
78 if (-f $dest) {
79 return;
80 }
81 }
82 my (undef, $tmp) = OpenBSD::Temp::permanent_file($output, "pkg") or
83 die $state->fatal(OpenBSD::Temp->last_error);
84 $state->{signer}->sign($pkg, $state, $tmp);
85
86 chmod((0666 & ~umask), $tmp);
87 rename($tmp, $dest) or
88 $state->fatal("Can't create final signed package: #1", $!);
89 if ($state->opt('C')) {
94 $state->system(sub {
95 chdir($output);
96 open(STDOUT, '>>', 'SHA256');
90 $state->system(
91 sub() {
92 chdir($output);
93 open(STDOUT, '>>', 'SHA256');
97 },
98 OpenBSD::Paths->sha256, '-b', $pkg->name.".tgz");
99 }
100}
101
94 },
95 OpenBSD::Paths->sha256, '-b', $pkg->name.".tgz");
96 }
97}
98
102sub sign_list
99sub sign_list($self, $l, $repo, $maxjobs, $state)
103{
100{
104 my ($self, $l, $repo, $maxjobs, $state) = @_;
105 $state->{total} = scalar @$l;
106 $maxjobs //= 1;
101 $state->{total} = scalar @$l;
102 $maxjobs //= 1;
107 my $code = sub {
108 my $name = shift;
103 my $code = sub($name) {
109 my $pkg = $repo->find($name);
110 if (!defined $pkg) {
111 $state->errsay("#1 not found", $name);
112 } else {
113 $self->sign_existing_package($state, $pkg);
114 }
115 };
116 my $display = $state->verbose ?
104 my $pkg = $repo->find($name);
105 if (!defined $pkg) {
106 $state->errsay("#1 not found", $name);
107 } else {
108 $self->sign_existing_package($state, $pkg);
109 }
110 };
111 my $display = $state->verbose ?
117 sub {
118 $state->progress->set_header("Signed ".shift);
112 sub($name) {
113 $state->progress->set_header("Signed ".$name);
119 $state->{done}++;
120 $state->progress->next($state->ntogo);
121 } :
114 $state->{done}++;
115 $state->progress->next($state->ntogo);
116 } :
122 sub {
117 sub($) {
123 };
124 if ($maxjobs > 1) {
125 my $jobs = {};
126 my $n = 0;
118 };
119 if ($maxjobs > 1) {
120 my $jobs = {};
121 my $n = 0;
127 my $reap_job = sub {
122 my $reap_job = sub() {
128 my $pid = wait;
129 if (!defined $jobs->{$pid}) {
130 $state->fatal("Wait returned #1: unknown process", $pid);
131 }
132 if ($? != 0) {
133 $state->fatal("Signature of #1 failed\n",
134 $jobs->{$pid});
135 }

--- 10 unchanged lines hidden (view full) ---

146 $repo->reinitialize;
147 &$code($name);
148 exit(0);
149 } else {
150 $jobs->{$pid} = $name;
151 $n++;
152 }
153 if ($n >= $maxjobs) {
123 my $pid = wait;
124 if (!defined $jobs->{$pid}) {
125 $state->fatal("Wait returned #1: unknown process", $pid);
126 }
127 if ($? != 0) {
128 $state->fatal("Signature of #1 failed\n",
129 $jobs->{$pid});
130 }

--- 10 unchanged lines hidden (view full) ---

141 $repo->reinitialize;
142 &$code($name);
143 exit(0);
144 } else {
145 $jobs->{$pid} = $name;
146 $n++;
147 }
148 if ($n >= $maxjobs) {
154 &$reap_job;
149 &$reap_job();
155 }
156 }
157 while ($n != 0) {
150 }
151 }
152 while ($n != 0) {
158 &$reap_job;
153 &$reap_job();
159 }
160 } else {
161 for my $name (@$l) {
162 &$code($name);
163 &$display($name);
164 delete $state->{signer}{pubkey};
165 }
166 }
167 if ($state->opt('C')) {
154 }
155 } else {
156 for my $name (@$l) {
157 &$code($name);
158 &$display($name);
159 delete $state->{signer}{pubkey};
160 }
161 }
162 if ($state->opt('C')) {
168 $state->system(sub {
169 chdir($state->{output_dir});
170 open(STDOUT, '>', 'SHA256.new');
163 $state->system(
164 sub() {
165 chdir($state->{output_dir});
166 open(STDOUT, '>', 'SHA256.new');
171 }, 'sort', 'SHA256');
172 rename($state->{output_dir}.'/SHA256.new',
173 $state->{output_dir}.'/SHA256');
174 }
175}
176
167 }, 'sort', 'SHA256');
168 rename($state->{output_dir}.'/SHA256.new',
169 $state->{output_dir}.'/SHA256');
170 }
171}
172
177sub sign_existing_repository
173sub sign_existing_repository($self, $state, $source)
178{
174{
179 my ($self, $state, $source) = @_;
180 require OpenBSD::PackageRepository;
181 my $repo = OpenBSD::PackageRepository->new($source, $state);
182 if ($state->{signer}->want_local && !$repo->is_local_file) {
183 $state->fatal("Signing distant source is not supported");
184 }
185 my @list = sort @{$repo->list};
186 if (@list == 0) {
187 $state->errsay('Source repository "#1" is empty', $source);
188 }
189 $self->sign_list(\@list, $repo, $state->opt('j'), $state);
190}
191
192
175 require OpenBSD::PackageRepository;
176 my $repo = OpenBSD::PackageRepository->new($source, $state);
177 if ($state->{signer}->want_local && !$repo->is_local_file) {
178 $state->fatal("Signing distant source is not supported");
179 }
180 my @list = sort @{$repo->list};
181 if (@list == 0) {
182 $state->errsay('Source repository "#1" is empty', $source);
183 }
184 $self->sign_list(\@list, $repo, $state->opt('j'), $state);
185}
186
187
193sub parse_and_run
188sub parse_and_run($self, $cmd)
194{
189{
195 my ($self, $cmd) = @_;
196 my $state = OpenBSD::PkgSign::State->new($cmd);
197 $state->handle_options;
198 if (!defined $state->{source} && @ARGV == 0) {
199 $state->usage("Nothing to sign");
200 }
201 if (defined $state->{source}) {
202 $self->sign_existing_repository($state,
203 $state->{source});
204 }
205 $self->sign_list(\@ARGV, $state->repo, $state->opt('j'),
206 $state);
207 return 0;
208}
209
190 my $state = OpenBSD::PkgSign::State->new($cmd);
191 $state->handle_options;
192 if (!defined $state->{source} && @ARGV == 0) {
193 $state->usage("Nothing to sign");
194 }
195 if (defined $state->{source}) {
196 $self->sign_existing_repository($state,
197 $state->{source});
198 }
199 $self->sign_list(\@ARGV, $state->repo, $state->opt('j'),
200 $state);
201 return 0;
202}
203