Synchronize pkg_install with HEAD:

- Add pkg_updating,
- Remove pkg_sign,
- Support for 8-CURRENT,
- Style cleanup (__P use),
- ... and much more.
This commit is contained in:
flz 2008-04-07 11:32:01 +00:00
parent 788ab66c9b
commit 657a605681
36 changed files with 206 additions and 2747 deletions

View File

@ -1,9 +1,7 @@
# $FreeBSD$
SUBDIR= lib add create delete info ${_sign} version
.include <bsd.own.mk>
.if !defined(NO_CRYPT) && !defined(NO_OPENSSL)
_sign= sign
.endif
SUBDIR= lib add create delete info updating version
.include <bsd.subdir.mk>

View File

@ -31,6 +31,7 @@ extern Boolean NoInstall;
extern Boolean NoRecord;
extern Boolean FailOnAlreadyInstalled;
extern Boolean KeepPackage;
extern Boolean IgnoreDeps;
extern char *Mode;
extern char *Owner;
extern char *Group;

View File

@ -27,7 +27,7 @@ __FBSDID("$FreeBSD$");
#include "lib.h"
#include "add.h"
static char Options[] = "hvIRfFnrp:P:SMt:C:K";
static char Options[] = "hviIRfFnrp:P:SMt:C:K";
char *Prefix = NULL;
Boolean PrefixRecursive = FALSE;
@ -37,6 +37,7 @@ Boolean NoRecord = FALSE;
Boolean Remote = FALSE;
Boolean KeepPackage = FALSE;
Boolean FailOnAlreadyInstalled = TRUE;
Boolean IgnoreDeps = FALSE;
char *Mode = NULL;
char *Owner = NULL;
@ -77,11 +78,14 @@ struct {
{ 601000, 601099, "/packages-6.1-release" },
{ 602000, 602099, "/packages-6.2-release" },
{ 603000, 603099, "/packages-6.3-release" },
{ 700000, 700099, "/packages-7.0-release" },
{ 300000, 399000, "/packages-3-stable" },
{ 400000, 499000, "/packages-4-stable" },
{ 502100, 502128, "/packages-5-current" },
{ 503100, 599000, "/packages-5-stable" },
{ 600100, 699000, "/packages-6-stable" },
{ 700100, 799000, "/packages-7-stable" },
{ 800000, 899000, "/packages-8-current" },
{ 0, 9999999, "/packages-current" },
{ 0, 0, NULL }
};
@ -89,7 +93,7 @@ struct {
static char *getpackagesite(void);
int getosreldate(void);
static void usage __P((void));
static void usage(void);
int
main(int argc, char **argv)
@ -109,7 +113,7 @@ main(int argc, char **argv)
while ((ch = getopt(argc, argv, Options)) != -1) {
switch(ch) {
case 'v':
Verbose = TRUE;
Verbose++;
break;
case 'p':
@ -166,6 +170,9 @@ main(int argc, char **argv)
case 'C':
Chroot = optarg;
break;
case 'i':
IgnoreDeps = TRUE;
break;
case 'h':
case '?':
@ -178,7 +185,7 @@ main(int argc, char **argv)
argv += optind;
if (AddMode != SLAVE) {
pkgs = (char **)malloc((argc + 1) * sizeof(char *));
pkgs = (char **)malloc((argc+1) * sizeof(char *));
for (ch = 0; ch <= argc; pkgs[ch++] = NULL) ;
/* Get all the remaining package names, if any */
@ -321,7 +328,7 @@ static void
usage()
{
fprintf(stderr, "%s\n%s\n",
"usage: pkg_add [-vInrfRMSK] [-t template] [-p prefix] [-P prefix] [-C chrootdir]",
"usage: pkg_add [-viInfFrRMSK] [-t template] [-p prefix] [-P prefix] [-C chrootdir]",
" pkg-name [pkg-name ...]");
exit(1);
}

View File

@ -252,6 +252,7 @@ pkg_do(char *pkg)
}
/* Now check the packing list for conflicts */
if (!IgnoreDeps){
for (p = Plist.head; p != NULL; p = p->next) {
if (p->type == PLIST_CONFLICTS) {
int i;
@ -368,6 +369,7 @@ pkg_do(char *pkg)
else if (Verbose)
printf(" - already installed.\n");
}
} /* if (!IgnoreDeps) */
if (code != 0)
goto bomb;
@ -514,6 +516,7 @@ pkg_do(char *pkg)
depnames[0] = p->name;
depnames[1] = NULL;
}
if(!IgnoreDeps){
for (i = 0; depnames[i] != NULL; i++) {
sprintf(contents, "%s/%s/%s", LOG_DIR, depnames[i],
REQUIRED_BY_FNAME);
@ -531,6 +534,7 @@ pkg_do(char *pkg)
}
}
}
}
if (Verbose)
printf("Package %s registered in %s\n", Plist.name, LogDir);
}

View File

@ -15,7 +15,7 @@
.\"
.\" $FreeBSD$
.\"
.Dd January 16, 2006
.Dd November 29, 2007
.Dt PKG_ADD 1
.Os
.Sh NAME
@ -23,7 +23,7 @@
.Nd a utility for installing software package distributions
.Sh SYNOPSIS
.Nm
.Op Fl vInfFrRMSK
.Op Fl viInfFrRMSK
.Op Fl t Ar template
.Op Fl p Ar prefix
.Op Fl P Ar prefix
@ -87,6 +87,9 @@ Turn on verbose output.
Keep any downloaded package in
.Ev PKGDIR
if it is defined or in current directory by default.
.It Fl i
Install the package without fetching and installing
dependencies.
.It Fl I
If any installation scripts (pre-install or post-install) exist for a given
package, do not execute them.
@ -134,11 +137,12 @@ modes (see the
.Fl M
and
.Fl S
options). If the
options).
If the
.Fl p
flag appears after any
.Fl P
flag on the command line, it overrides it's effect, causing
flag on the command line, it overrides its effect, causing
.Nm
not to use the given
.Ar prefix
@ -148,11 +152,12 @@ Does the same as the
.Fl p
option, except that the given
.Ar prefix
is also used recursively for the dependency packages, if any. If the
is also used recursively for the dependency packages, if any.
If the
.Fl P
flag appears after any
.Fl p
flag on the command line, it overrides it's effect, causing
flag on the command line, it overrides its effect, causing
.Nm
to use the given
.Ar prefix
@ -279,8 +284,11 @@ ftp.
.Sh TECHNICAL DETAILS
The
.Nm
utility extracts each package's "packing list" into a special staging
directory in /tmp (or $PKG_TMPDIR if set), parses it, and then runs
utility extracts each package's
.Dq "packing list"
into a special staging directory (see
.Sx ENVIRONMENT ) ,
parses it, and then runs
through the following sequence to fully extract the contents of the package:
.Bl -enum
.It
@ -288,14 +296,14 @@ A check is made to determine if the package is already recorded as installed.
If it is, installation is terminated.
.It
A check is made to determine if the package conflicts (from
.Cm @conflicts
.Ic @conflicts
directives, see
.Xr pkg_create 1 )
with an already-installed package.
with an already installed package.
If it is, installation is terminated.
.It
Scan all the package dependencies (from
.Cm @pkgdep
.Ic @pkgdep
directives, see
.Xr pkg_create 1 )
are read from the packing list.
@ -305,54 +313,51 @@ if the missing package cannot be found or installed,
the installation is terminated.
.It
Search for any
.Cm @option
.Ic @option
directives which control how the package is added to the system.
At the time of this writing, the only currently implemented option is
.Cm @option extract-in-place
.Ic @option Cm extract-in-place
which will cause the package to be extracted directly into its
prefix directory without moving through a staging area in
.Pa /tmp .
prefix directory without moving through a staging area.
.It
If
.Cm @option extract-in-place
.Ic @option Cm extract-in-place
is enabled, the package is now extracted directly into its
final location, otherwise it is extracted into the staging area.
.It
If the package contains a
.Ar require
file (see
If a requirements script
.Pa +REQUIRE
exists for the package (see the
.Fl r
flag of
.Xr pkg_create 1 ) ,
then execute it with the following arguments:
.Bd -ragged -offset indent -compact
.Ar pkg-name
.Ar INSTALL
.Ed
.Pp
.D1 Ar pkg-name Li INSTALL
.Pp
where
.Ar pkg-name
is the name of the package in question and the
.Ar INSTALL
.Dq Li INSTALL
keyword denotes this as an installation requirements check (useful if
you want to have one script serving multiple functions).
.It
If a
.Ar pre-install
script exists for the package, it is then executed with the following
arguments:
.Bd -ragged -offset indent -compact
.Cm script
.Ar pkg-name
.Ar PRE-INSTALL
.Ed
If a pre-install script
.Pa +INSTALL
exists for the package,
it is then executed with the following arguments:
.Pp
.D1 Ar pkg-name Li PRE-INSTALL
.Pp
where
.Ar pkg-name
is the name of the package in question and
.Ar PRE-INSTALL
.Dq Li PRE-INSTALL
is a keyword denoting this as the preinstallation phase.
.Pp
.Sy Note :
The
.Ar PRE-INSTALL
.Dq Li PRE-INSTALL
keyword will not appear if separate scripts for pre-install and post-install
are given during package creation time (using the
.Fl i
@ -362,55 +367,51 @@ flags to
.Xr pkg_create 1 ) .
.It
If
.Cm @option extract-in-place
.Cm @option Cm extract-in-place
is not used, then the packing list (this is the
.Pa +CONTENTS
file) is now used as a guide for moving (or copying, as necessary) files from
the staging area into their final locations.
.It
If the package contains an
.Ar mtreefile
file (see
If an mtree file
.Pa +MTREE_DIRS
exists for the package (see the
.Fl m
flag of
.Xr pkg_create 1 ) ,
then mtree is invoked as:
.Bd -ragged -offset indent -compact
.Cm mtree
.Fl u
.Fl f
.Ar mtreefile
.Fl d
.Fl e
.Fl p
.Pa prefix
.Ed
then
.Xr mtree 8
is invoked as:
.Pp
.D1 Nm mtree Fl U f Pa +MTREE_DIRS Fl d e p Ar prefix
.Pp
where
.Pa prefix
.Ar prefix
is either the prefix specified with the
.Fl p
or
.Fl P
flag or,
if neither flag was specified, the name of the first directory named by a
.Cm @cwd
.Ic @cwd
directive within this package.
.It
If a
.Ar post-install
script exists for the package, it is then executed as
.Bd -ragged -offset indent -compact
.Cm script
.Ar pkg-name
.Ar POST-INSTALL
.Ed
If a post-install script
.Pa +POST-INSTALL
exists for the package,
it is then executed with the following arguments:
.Pp
.D1 Ar pkg-name Li POST-INSTALL
.Pp
where
.Ar pkg-name
is the name of the package in question and
.Ar POST-INSTALL
.Dq Li POST-INSTALL
is a keyword denoting this as the post-installation phase.
.Pp
.Sy Note :
The
.Ar POST-INSTALL
.Dq Li POST-INSTALL
keyword will not appear if separate scripts for pre-install and post-install
are given during package creation time (using the
.Fl i
@ -420,27 +421,50 @@ flags to
.Xr pkg_create 1 ) .
.Pp
Reasoning behind passing keywords such as
.Ar POST-INSTALL
.Dq Li POST-INSTALL
and
.Ar PRE-INSTALL
.Dq Li PRE-INSTALL
is that this allows you to write a single
.Ar install
install
script that does both
.Dq before and after
.Dq before
and
.Dq after
actions.
But, separating the
functionality is more advantageous and easier from a maintenance viewpoint.
.It
After installation is complete, a copy of the packing list,
.Ar deinstall
script, description, and display files are copied into
.Pa /var/db/pkg/<pkg-name>
After installation is complete, a copy of the
description
.Pq Pa +DESC ,
comment
.Pq Pa +COMMENT ,
pre-install script
.Pq Pa +INSTALL ,
post-install script
.Pq Pa +POST-INSTALL ,
deinstall script
.Pq Pa +DEINSTALL ,
post-deinstall script
.Pq Pa +POST-DEINSTALL ,
requirements script
.Pq Pa +REQUIRE ,
display
.Pq Pa +DISPLAY ,
mtree
.Pq Pa +MTREE_DIRS ,
and packing list
.Pq Pa +CONTENTS
files are copied into
.Pa /var/db/pkg/ Ns Aq Ar pkg-name
for subsequent possible use by
.Xr pkg_delete 1 .
Any package dependencies are recorded in the other packages'
.Pa /var/db/pkg/<other-pkg>/+REQUIRED_BY
.Pa /var/db/pkg/ Ns Ao Ar other-pkg Ac Ns Pa /+REQUIRED_BY
file
(if the environment variable PKG_DBDIR is set, this overrides the
(if the environment variable
.Ev PKG_DBDIR
is set, this overrides the
.Pa /var/db/pkg/
path shown above).
.It
@ -461,7 +485,7 @@ is installed, even if the user might change it with the
or
.Fl P
flags to
.Cm pkg_add .
.Nm .
.Sh ENVIRONMENT
The value of the
.Ev PKG_PATH

View File

@ -42,13 +42,13 @@ int Dereference = FALSE;
int PlistOnly = FALSE;
int Recursive = FALSE;
#if defined(__FreeBSD_version) && __FreeBSD_version >= 500039
enum zipper Zipper = BZIP2;
enum zipper Zipper = BZIP2;
#else
enum zipper Zipper = GZIP;
enum zipper Zipper = GZIP;
#endif
static void usage __P((void));
static void usage(void);
int
main(int argc, char **argv)
@ -60,7 +60,7 @@ main(int argc, char **argv)
while ((ch = getopt(argc, argv, Options)) != -1)
switch(ch) {
case 'v':
Verbose = TRUE;
Verbose++;
break;
case 'x':
@ -228,12 +228,12 @@ static void
usage()
{
fprintf(stderr, "%s\n%s\n%s\n%s\n%s\n%s\n%s\n",
"usage: pkg_create [-YNOhvyz] [-P pkgs] [-C conflicts] [-p prefix] ",
" [-i iscript] [-I piscript] [-k dscript] [-K pdscript] ",
" [-r rscript] [-t template] [-X excludefile] ",
" [-D displayfile] [-m mtreefile] [-o origin] ",
" [-s srcdir] [-S basedir] ",
"usage: pkg_create [-YNOhjvyz] [-C conflicts] [-P pkgs] [-p prefix]",
" [-i iscript] [-I piscript] [-k dscript] [-K pdscript]",
" [-r rscript] [-s srcdir] [-S basedir]",
" [-t template] [-X excludefile]",
" [-D displayfile] [-m mtreefile] [-o originpath]",
" -c comment -d description -f packlist pkg-filename",
" pkg_create [-EGYNhvxyzR] -b pkg-name [pkg-filename]");
" pkg_create [-EGYNRhvxy] -b pkg-name [pkg-filename]");
exit(1);
}

View File

@ -37,7 +37,7 @@ Boolean NoDeInstall = FALSE;
Boolean Recursive = FALSE;
match_t MatchType = MATCH_GLOB;
static void usage __P((void));
static void usage(void);
int
main(int argc, char **argv)
@ -52,7 +52,7 @@ main(int argc, char **argv)
while ((ch = getopt(argc, argv, Options)) != -1)
switch(ch) {
case 'v':
Verbose = TRUE;
Verbose++;
break;
case 'f':

View File

@ -266,7 +266,7 @@ pkg_do(char *pkg)
for (p = Plist.head; p ; p = p->next) {
if (p->type != PLIST_PKGDEP)
continue;
deporigin = (p->next->type == PLIST_DEPORIGIN) ? p->next->name :
deporigin = (p->next != NULL && p->next->type == PLIST_DEPORIGIN) ? p->next->name :
NULL;
if (Verbose) {
printf("Trying to remove dependency on package '%s'", p->name);

View File

@ -39,7 +39,7 @@ char *LookUpOrigin = NULL;
Boolean KeepPackage = FALSE;
struct which_head *whead;
static void usage __P((void));
static void usage(void);
int
main(int argc, char **argv)
@ -69,7 +69,7 @@ main(int argc, char **argv)
break;
case 'v':
Verbose = TRUE;
Verbose++;
/* Reasonable definition of 'everything' */
Flags = SHOW_COMMENT | SHOW_DESC | SHOW_PLIST | SHOW_INSTALL |
SHOW_DEINSTALL | SHOW_REQUIRE | SHOW_DISPLAY | SHOW_MTREE;

View File

@ -17,7 +17,7 @@
.\" @(#)pkg_info.1
.\" $FreeBSD$
.\"
.Dd January 16, 2006
.Dd January 9, 2006
.Dt PKG_INFO 1
.Os
.Sh NAME
@ -25,7 +25,7 @@
.Nd a utility for displaying information on software packages
.Sh SYNOPSIS
.Nm
.Op Fl bcdDEfgGijIkKLmopPqQrRsvVxX
.Op Fl bcdDEfgGiIjkKLmopPqQrRsvVxX
.Op Fl e Ar package
.Op Fl l Ar prefix
.Op Fl t Ar template
@ -56,19 +56,23 @@ A package name may either be the name of
an installed package, the pathname to a package distribution file or a
URL to an FTP available package.
Package version numbers can also be matched in a relational manner using the
.Pa \*[Ge], \*[Le], \*[Gt]
.Pa >= , <= , >
and
.Pa \*[Lt]
.Pa <
operators.
For example,
.Pa pkg_info 'portupgrade\*[Ge]20030723'
.Pp
.Dl "pkg_info 'portupgrade>=20030723'"
.Pp
will match versions 20030723 and later of the
.Pa portupgrade
package.
.It Fl a
Show all currently installed packages.
.It Fl b
Use the BLOCKSIZE environment variable for output even when the
Use the
.Ev BLOCKSIZE
environment variable for output even when the
.Fl q
or
.Fl Q
@ -111,11 +115,15 @@ Keep any downloaded package in
.Ev PKGDIR
if it is defined or in current directory by default.
.It Fl r
Show the list of packages on which each package depends.
For each of the specified packages,
show the list of packages on which it depends.
.It Fl R
Show the list of installed packages which require each package.
For each of the specified packages,
show the list of installed packages which require it.
.It Fl m
Show the mtree file (if any) for each package.
Show the
.Xr mtree 8
file (if any) for each package.
.It Fl L
Show the files within each package.
This is different from just
@ -127,11 +135,10 @@ Show the total size occupied by files installed within each package.
Show the
.Dq origin
path recorded on package generation.
This path
intended to give an idea as to where the underlying port, from which
package was generated, is located in the
This path is the directory name in the
.Fx
.Em "Ports Collection" .
.Em "Ports Collection"
of the underlying port from which the package was generated.
.It Fl G
Do not try to expand shell glob patterns in the
.Ar pkg-name
@ -139,19 +146,19 @@ when selecting packages to be displayed (by default
.Nm
automatically expands shell glob patterns in the
.Ar pkg-name ) .
.It Fl W
.It Fl W Ar filename
For the specified
.Ar filename
argument show which package it belongs to.
If the file is not in the
current directory, and does not have an absolute path, then the
directories specified in the environment variable
.Ev PATH
is searched using
are searched using
.Xr which 1 .
.It Fl O
For the specified
.Ar origin
argument list all packages having this origin.
.It Fl O Ar origin
List all packages having the specified
.Ar origin .
.It Fl x
Treat the
.Ar pkg-name
@ -168,9 +175,9 @@ Like
but treats the
.Ar pkg-name
as an extended regular expression.
.It Fl e Ar pkg-name
.It Fl e Ar package
If the package identified by
.Ar pkg-name
.Ar package
is currently installed, return 0, otherwise return 1.
This option
allows you to easily test for the presence of another (perhaps
@ -180,21 +187,21 @@ Show only matching package names.
This option takes
precedence over all other package formatting options.
If any packages match, return 0, otherwise return 1.
.It Fl l Ar str
.It Fl l Ar prefix
Prefix each information category header (see
.Fl q )
shown with
.Ar str .
This is primarily of use to front-end programs who want to request a
.Ar prefix .
This is primarily of use to front-end programs that want to request a
lot of different information fields at once for a package, but do not
necessary want the output intermingled in such a way that they cannot
necessarily want the output intermingled in such a way that they cannot
organize it.
This lets you add a special token to the start of
each field.
.It Fl t Ar template
Use
.Ar template
as the input to
as the argument to
.Xr mktemp 3
when creating a
.Dq staging area .
@ -204,8 +211,9 @@ but it may be necessary to override it in the situation where
space in your
.Pa /tmp
directory is limited.
Be sure to leave some number of `X' characters
for
Be sure to leave some number of
.Ql X
characters for
.Xr mktemp 3
to fill in with a unique ID.
.Bd -ragged -offset indent -compact
@ -227,7 +235,7 @@ command line, or from already installed package information
in
.Pa /var/db/pkg/ Ns Aq Ar pkg-name .
.Sh ENVIRONMENT
.Bl -tag -width PKG_TMPDIR
.Bl -tag -width ".Ev PKG_TMPDIR"
.It Ev BLOCKSIZE
If the environment variable
.Ev BLOCKSIZE
@ -250,7 +258,7 @@ found.
Specifies an alternative location to save downloaded packages to.
.El
.Sh FILES
.Bl -tag -width /var/db/pkg -compact
.Bl -tag -width ".Pa /var/db/pkg" -compact
.It Pa /var/tmp
Used if the environment variables
.Ev PKG_TMPDIR

View File

@ -68,8 +68,8 @@ vpipe(const char *fmt, ...)
rp = malloc(MAXPATHLEN);
if (!rp) {
warnx("vpipe can't alloc buffer space");
return NULL;
warnx("vpipe can't alloc buffer space");
return NULL;
}
maxargs = sysconf(_SC_ARG_MAX);
maxargs -= 32; /* some slop for the sh -c */

View File

@ -26,7 +26,7 @@ __FBSDID("$FreeBSD$");
/* These are global for all utils */
Boolean Quiet = FALSE;
Boolean Verbose = FALSE;
Boolean Fake = FALSE;
Boolean Force = FALSE;
int AutoAnswer = FALSE;
int Verbose = 0; /* Allow multiple levels of verbose. */

View File

@ -57,6 +57,13 @@
/* Usually "rm", but often "echo" during debugging! */
#define RMDIR_CMD "/bin/rmdir"
/* Where the ports lives by default */
#define DEF_PORTS_DIR "/usr/ports"
/* just in case we change the environment variable name */
#define PORTSDIR "PORTSDIR"
/* macro to get name of directory where the ports lives */
#define PORTS_DIR (getenv(PORTSDIR) ? getenv(PORTSDIR) : DEF_PORTS_DIR)
/* Where we put logging information by default, else ${PKG_DBDIR} if set */
#define DEF_LOG_DIR "/var/db/pkg"
/* just in case we change the environment variable name */
@ -77,7 +84,9 @@
#define DISPLAY_FNAME "+DISPLAY"
#define MTREE_FNAME "+MTREE_DIRS"
#if defined(__FreeBSD_version) && __FreeBSD_version >= 700000
#if defined(__FreeBSD_version) && __FreeBSD_version >= 800000
#define INDEX_FNAME "INDEX-8"
#elif defined(__FreeBSD_version) && __FreeBSD_version >= 700000
#define INDEX_FNAME "INDEX-7"
#elif defined(__FreeBSD_version) && __FreeBSD_version >= 600000
#define INDEX_FNAME "INDEX-6"
@ -170,7 +179,7 @@ Boolean fexists(const char *);
Boolean isdir(const char *);
Boolean isemptydir(const char *fname);
Boolean isemptyfile(const char *fname);
Boolean isfile(const char *);
Boolean isfile(const char *);
Boolean isempty(const char *);
Boolean issymlink(const char *);
Boolean isURL(const char *);
@ -230,9 +239,9 @@ int version_cmp(const char *, const char *);
/* Externs */
extern Boolean Quiet;
extern Boolean Verbose;
extern Boolean Fake;
extern Boolean Force;
extern int AutoAnswer;
extern int Verbose;
#endif /* _INST_LIB_LIB_H_ */

View File

@ -480,7 +480,7 @@ delete_package(Boolean ign_err, Boolean nukedirs, Package *pkg)
/* Mismatch? */
if (strcmp(cp, p->next->name + 4)) {
warnx("'%s' fails original MD5 checksum - %s",
tmp, Force ? "deleted anyway." : "not deleted.");
tmp, Force ? "deleted anyway." : "not deleted.");
if (!Force) {
fail = FAIL;
continue;

View File

@ -38,8 +38,8 @@ fileGetURL(const char *base, const char *spec, int keep_package)
char *cp, *rp, *tmp;
char fname[FILENAME_MAX];
char pen[FILENAME_MAX];
char buf[8192];
char pkg[FILENAME_MAX];
char buf[8192];
FILE *ftp;
pid_t tpid;
int pfd[2], pstat, r, w = 0;
@ -98,18 +98,18 @@ fileGetURL(const char *base, const char *spec, int keep_package)
else
strcpy(fname, spec);
if (keep_package) {
tmp = getenv("PKGDIR");
if (keep_package) {
tmp = getenv("PKGDIR");
strlcpy(pkg, tmp ? tmp : ".", sizeof(pkg));
tmp = basename(fname);
strlcat(pkg, "/", sizeof(pkg));
strlcat(pkg, tmp, sizeof(pkg));
if ((pkgfd = open(pkg, O_WRONLY|O_CREAT|O_TRUNC, 0644)) == -1) {
printf("Error: Unable to open %s\n", pkg);
if ((pkgfd = open(pkg, O_WRONLY|O_CREAT|O_TRUNC, 0644)) == -1) {
printf("Error: Unable to open %s\n", pkg);
perror("open");
return NULL;
}
}
}
fetchDebug = (Verbose > 0);
if ((ftp = fetchGetURL(fname, Verbose ? "v" : NULL)) == NULL) {
@ -142,9 +142,9 @@ fileGetURL(const char *base, const char *spec, int keep_package)
close(fd);
execl("/usr/bin/tar", "tar",
#if defined(__FreeBSD_version) && __FreeBSD_version >= 500039
Verbose ? "-xjvf" : "-xjf",
Verbose ? "-xpjvf" : "-xpjf",
#else
Verbose ? "-xzvf" : "-xzf",
Verbose ? "-xpzvf" : "-xpzf",
#endif
"-", (char *)0);
_exit(2);

View File

@ -1,16 +0,0 @@
# $FreeBSD$
# $OpenBSD: Makefile.bsd-wrapper,v 1.2 1999/10/07 16:30:32 espie Exp $
PROG= pkg_sign
LINKS= ${BINDIR}/pkg_sign ${BINDIR}/pkg_check
MLINKS= pkg_sign.1 pkg_check.1
SRCS= main.c check.c common.c gzip.c pgp_check.c pgp_sign.c \
sha1.c sign.c stand.c x509.c
CFLAGS+= -I${.CURDIR}/../lib
DPADD= ${LIBINSTALL} ${LIBMD} ${LIBCRYPTO}
LDADD= ${LIBINSTALL} -lmd -lcrypto
.include <bsd.prog.mk>

View File

@ -1,55 +0,0 @@
To sign packages in a transparent way:
gzip files can handle an extra field at the beginning that
stores anything we wish.
So it's just a question to choose a format for the signature, and to
embed it there.
We use the extra field to store signatures. Each signature consists
of a 6 bytes type marker, a 2 bytes length, followed by the signature
itself. We can potentially stack signatures: resign a signed archive
by just prepending the new signature to the extra field.
To check the first signature, the checker just needs to extract it, pass it
off to the checking protocol (e.g. PGP), followed by the unsigned archive
(e.g., regenerate the gzip header without the first signature, then put
the gzip data).
* Signed archives just look like normal .tar.gz files, except for programs
that use the extra field for their own purpose,
* Possibility to grab the files off the net and extract stuff/verify
signatures on the fly (just need to wedge the checker as an intermediate
pipe)
* Pretty simple, small portable code to be able to check signatures
everywhere (the signer itself needs getpass and corresponding functionality)
The scheme should be extensible to any compressed format which allows for
extended headers.
Thanks to Angelos D. Keromytis for pointing out I did not need to
uncompress the archive to sign it, and to other members of the OpenBSD
project for various reasons.
--
Marc Espie, 1999
$OpenBSD: README,v 1.2 1999/10/04 21:46:27 espie Exp $
--
X.509 notes:
I added the ability to sign a package with an X.509 key, and to check
against a stack of X.509 certificates. This allows a "vendor" to
distribute a system with one or more certificates pre-installed, and
to add certificates in a signed package by appending them to the
default certficiate stack.
The X.509 signatures are stored in the gzip header in the same manner
as other signatures. This is known to compile against OpenSSL
libraries on OpenBSD 2.7 and FreeBSD 5.0, your mileage may vary.
--
Wes Peters, Dec 2000
$FreeBSD$

View File

@ -1,119 +0,0 @@
/* $OpenBSD: check.c,v 1.2 1999/10/04 21:46:27 espie Exp $ */
/*-
* Copyright (c) 1999 Marc Espie.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by Marc Espie for the OpenBSD
* Project.
*
* THIS SOFTWARE IS PROVIDED BY THE OPENBSD PROJECT AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OPENBSD
* PROJECT OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
/* Simple code for a stand-alone package checker */
#include <sys/types.h>
#include <sys/wait.h>
#include <stdlib.h>
#include <stdio.h>
#include "stand.h"
#include "pgp.h"
#include "gzip.h"
#include "extern.h"
struct checker {
void *context;
void (*add)(void *, const char *, size_t);
int (*get)(void *);
int status;
};
#define MAX_CHECKERS 20
int
check_signature(file, userid, envp, filename)
/*@dependent@*/FILE *file;
const char *userid;
char *envp[];
/*@observer@*/const char *filename;
{
struct signature *sign;
struct mygzip_header h;
int status;
char buffer[1024];
size_t length;
struct checker checker[MAX_CHECKERS];
struct signature *sweep;
int i, j;
status = read_header_and_diagnose(file, &h, &sign, filename);
if (status != 1)
return PKG_UNSIGNED;
for (sweep = sign, i = 0;
sweep != NULL && i < MAX_CHECKERS;
sweep=sweep->next, i++) {
switch(sweep->type) {
case TAG_OLD:
fprintf(stderr, "File %s uses old signatures, no longer supported\n",
filename);
checker[i].context = NULL;
break;
case TAG_X509:
checker[i].context = new_x509_checker(&h, sweep, userid, envp, filename);
checker[i].add = x509_add;
checker[i].get = x509_sign_ok;
break;
case TAG_SHA1:
checker[i].context = new_sha1_checker(&h, sweep, userid, envp, filename);
checker[i].add = sha1_add;
checker[i].get = sha1_sign_ok;
break;
case TAG_PGP:
checker[i].context = new_pgp_checker(&h, sweep, userid, envp, filename);
checker[i].add = pgp_add;
checker[i].get = pgp_sign_ok;
break;
default:
abort();
}
}
while ((length = fread(buffer, 1, sizeof buffer, file)) > 0) {
for (j = 0; j < i; j++) {
if (checker[j].context) {
(*checker[j].add)(checker[j].context, buffer, length);
}
}
}
// for (j = i-1; j >= 0; j--)
for (j = 0; j < i; j++) {
if (checker[j].context) {
checker[j].status = (*checker[j].get)(checker[j].context);
} else {
checker[j].status = PKG_SIGERROR;
}
}
free_signature(sign);
return checker[0].status;
}

View File

@ -1,90 +0,0 @@
/* $OpenBSD: common.c,v 1.3 1999/10/07 16:30:32 espie Exp $ */
/*-
* Copyright (c) 1999 Marc Espie.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by Marc Espie for the OpenBSD
* Project.
*
* THIS SOFTWARE IS PROVIDED BY THE OPENBSD PROJECT AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OPENBSD
* PROJECT OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/stat.h>
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include "stand.h"
#include "gzip.h"
#include "pgp.h"
#include "extern.h"
/* Ensure consistent diagnostics */
int
read_header_and_diagnose(file, h, sign, filename)
FILE *file;
struct mygzip_header *h;
struct signature **sign;
const char *filename;
{
switch(gzip_read_header(file, h, sign)) {
case GZIP_SIGNED:
if (sign == NULL) {
fprintf(stderr, "File %s is already signed\n", filename);
return 0;
} else
return 1;
case GZIP_UNSIGNED:
if (sign != NULL) {
fprintf(stderr, "File %s is not a signed gzip file\n", filename);
return 0;
} else
return 1;
case GZIP_NOT_GZIP:
fprintf(stderr, "File %s is not a gzip file\n", filename);
return 0;
case GZIP_NOT_PGPSIGNED:
fprintf(stderr, "File %s contains an unknown extension\n", filename);
return 0;
default:
/* this should not happen */
abort();
}
}
int
reap(pid)
pid_t pid;
{
int pstat;
pid_t result;
do {
result = waitpid(pid, &pstat, 0);
} while (result == -1 && errno == EINTR);
return result == -1 ? -1 : pstat;
}

View File

@ -1,100 +0,0 @@
/* $FreeBSD$ */
/* $OpenBSD: extern.h,v 1.3 1999/10/07 16:30:32 espie Exp $ */
/*-
* Copyright (c) 1999 Marc Espie.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by Marc Espie for the OpenBSD
* Project.
*
* THIS SOFTWARE IS PROVIDED BY THE OPENBSD PROJECT AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OPENBSD
* PROJECT OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*
* Convention: all functions that operate on a FILE * also take a filename
* for diagnostic purposes. The file can be connected to a pipe, so
* - don't rewind
* - don't reopen from filename.
*/
struct mygzip_header;
struct signature;
/* main.c */
extern int verbose;
extern int quiet;
extern char *userkey;
/* common.c */
extern int read_header_and_diagnose __P((FILE *file, \
/*@out@*/struct mygzip_header *h, /*@null@*/struct signature **sign, \
const char *filename));
extern int reap __P((pid_t pid));
/* sign.c */
extern int sign __P((/*@observer@*/const char *filename, int type, \
/*@null@*/const char *userid, char *envp[]));
/* check.c */
extern int check_signature __P((/*@dependent@*/FILE *file, \
/*@null@*/const char *userid, char *envp[], \
/*@observer@*/const char *filename));
#define PKG_BADSIG 0
#define PKG_GOODSIG 1
#define PKG_UNSIGNED 2
#define PKG_SIGNED 4
#define PKG_SIGERROR 8
#define PKG_SIGUNKNOWN 16
typedef /*@observer@*/char *pchar;
#define MAXID 512
/* sha1.c */
#define SHA1_DB_NAME "/var/db/pkg/SHA1"
extern void *new_sha1_checker __P((struct mygzip_header *h, \
struct signature *sign, const char *userid, char *envp[], \
const char *filename));
extern void sha1_add __P((void *arg, const char *buffer, \
size_t length));
extern int sha1_sign_ok __P((void *arg));
extern int retrieve_sha1_marker __P((const char *filename, \
struct signature **sign, const char *userid));
/* x509.c */
#define X509_DB_NAME "/var/db/pkg/X509"
extern void *new_x509_checker __P((struct mygzip_header *h, \
struct signature *sign, const char *userid, char *envp[], \
const char *filename));
extern void x509_add __P((void *arg, const char *buffer, \
size_t length));
extern int x509_sign_ok __P((void *arg));
extern int retrieve_x509_marker __P((const char *filename, \
struct signature **sign, const char *userid));

View File

@ -1,319 +0,0 @@
/* $OpenBSD: gzip.c,v 1.3 1999/10/04 21:46:28 espie Exp $ */
/*-
* Copyright (c) 1999 Marc Espie.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by Marc Espie for the OpenBSD
* Project.
*
* THIS SOFTWARE IS PROVIDED BY THE OPENBSD PROJECT AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OPENBSD
* PROJECT OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <sys/types.h>
#include <sys/wait.h>
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <string.h>
#include "stand.h"
#include "gzip.h"
#include "pgp.h"
/*
* Signatures follow a simple format
* (endianess was chosen to conform to gzip header format)
*/
SIGNTAG known_tags[KNOWN_TAGS] = {
{'S', 'I', 'G', 'P', 'G', 'P', 0, 0 },
{'C', 'K', 'S', 'H', 'A', '1', 0, 0 },
{'C', 'R', 'X', '5', '0', '9', 0, 0 },
{'S', 'i', 'g', 'P', 'G', 'P', 0, 0 } /* old format */
};
void
sign_fill_tag(sign)
struct signature *sign;
{
sign->tag[6] = sign->length % 256;
sign->tag[7] = sign->length / 256;
}
void
sign_fill_length(sign)
struct signature *sign;
{
sign->length = sign->tag[6] + 256 * sign->tag[7];
}
static size_t
stack_sign(match, t, f, sign)
SIGNTAG match;
int t;
FILE *f;
struct signature **sign;
{
struct signature *new_sign;
size_t length;
new_sign = malloc(sizeof *new_sign);
if (new_sign == NULL)
return 0;
new_sign->type = t;
new_sign->next = NULL;
memcpy(new_sign->tag, match, sizeof(SIGNTAG));
sign_fill_length(new_sign);
new_sign->data = malloc(new_sign->length);
if (new_sign->data == NULL ||
fread(new_sign->data, 1, new_sign->length, f) != new_sign->length) {
free_signature(new_sign);
return 0;
}
length = new_sign->length;
if (sign != NULL) {
if (!*sign)
*sign = new_sign;
else {
while ((*sign)->next != NULL)
sign = &((*sign)->next);
(*sign)->next = new_sign;
}
} else
free_signature(new_sign);
return length;
}
static int
add_sign(f, sign)
FILE *f;
struct signature **sign;
{
SIGNTAG match;
int i;
if (fread(match, 1, sizeof(SIGNTAG), f) != sizeof(SIGNTAG))
return -1;
for (i = 0; i < KNOWN_TAGS; i++) {
if (memcmp(match, known_tags[i], TAGCHECK) == 0) {
unsigned int sign_length = stack_sign(match, i, f, sign);
if (sign_length > 0)
return sign_length + sizeof(SIGNTAG);
else
return -1;
}
}
return 0;
}
static int
gzip_magic(f)
FILE *f;
{
int c, d;
c = fgetc(f);
d = fgetc(f);
if ((unsigned char)c != (unsigned char)GZIP_MAGIC0
|| (unsigned char)d != (unsigned char)GZIP_MAGIC1)
return 0;
else
return 1;
}
static int
fill_gzip_fields(f, h)
FILE *f;
struct mygzip_header *h;
{
int method, flags;
method = fgetc(f);
flags = fgetc(f);
if (method == EOF || flags == EOF || fread(h->stamp, 1, 6, f) != 6)
return 0;
h->method = (char)method;
h->flags = (char)flags;
if ((h->flags & CONTINUATION) != 0)
if (fread(h->part, 1, 2, f) != 2)
return 0;
return 1;
}
/* retrieve a gzip header, including signatures */
int
gzip_read_header(f, h, sign)
FILE *f;
struct mygzip_header *h;
struct signature **sign;
{
if (sign != NULL)
*sign = NULL;
if (!gzip_magic(f) || !fill_gzip_fields(f, h))
return GZIP_NOT_GZIP;
if ((h->flags & EXTRA_FIELD) == 0) {
h->remaining = 0;
return GZIP_UNSIGNED;
}
else {
int c;
c = fgetc(f);
if (c == EOF)
return GZIP_NOT_GZIP;
h->remaining = (unsigned)c;
c = fgetc(f);
if (c == EOF)
return GZIP_NOT_PGPSIGNED;
h->remaining += ((unsigned) c) << 8;
while (h->remaining >= sizeof(SIGNTAG)) {
int sign_length = add_sign(f, sign);
if (sign_length > 0)
h->remaining -= sign_length;
if (sign_length < 0)
return GZIP_NOT_GZIP;
if (sign_length == 0)
return GZIP_SIGNED;
}
return GZIP_SIGNED;
}
}
static unsigned
sign_length(sign)
struct signature *sign;
{
unsigned total = 0;
while (sign != NULL) {
total += sizeof(SIGNTAG) + sign->length;
sign = sign->next;
}
return total;
}
struct mydata {
FILE *file;
int ok;
};
static void myadd(arg, buffer, size)
void *arg;
const char *buffer;
size_t size;
{
struct mydata *d = arg;
if (fwrite(buffer, 1, size, d->file) == size)
d->ok = 1;
else
d->ok = 0;
}
/* write a gzip header, including signatures */
int
gzip_write_header(f, h, sign)
FILE *f;
const struct mygzip_header *h;
struct signature *sign;
{
struct mydata d;
d.file = f;
if (gzip_copy_header(h, sign, myadd, &d) == 0)
return 0;
return d.ok;
}
int
gzip_copy_header(h, sign, add, data)
const struct mygzip_header *h;
struct signature *sign;
void (*add)(void *, const char *, size_t);
void *data;
{
char flags;
size_t length;
size_t buflength;
size_t i;
char *buffer;
length = h->remaining + sign_length(sign);
if (length) {
buflength = length + 2;
flags = h->flags | EXTRA_FIELD;
} else {
flags = h->flags & ~EXTRA_FIELD;
buflength = 0;
}
buflength += 10;
if ((h->flags & CONTINUATION) != 0)
buflength += 2;
buffer = malloc(buflength);
if (buffer == NULL)
return 0;
i = 0;
buffer[i++] = GZIP_MAGIC0;
buffer[i++] = GZIP_MAGIC1;
buffer[i++] = h->method;
buffer[i++] = flags;
memcpy(buffer+i, h->stamp, 6);
i += 6;
if ((flags & CONTINUATION) != 0) {
memcpy(buffer+i, h->part, 2);
i += 2;
}
if (length) {
buffer[i++] = (char)(length % 256);
buffer[i++] = (char)(length / 256);
while (sign != NULL) {
memcpy(buffer+i, sign->tag, sizeof(SIGNTAG));
i += sizeof(SIGNTAG);
memcpy(buffer+i, sign->data, sign->length);
i += sign->length;
sign = sign->next;
}
}
(*add)(data, buffer, buflength);
free(buffer);
return 1;
}
void
free_signature(sign)
struct signature *sign;
{
struct signature *next;
while (sign != NULL) {
next = sign->next;
free(sign->data);
free(sign);
sign = next;
}
}

View File

@ -1,95 +0,0 @@
/* $FreeBSD$ */
/* $OpenBSD: gzip.h,v 1.2 1999/10/04 21:46:28 espie Exp $ */
/*-
* Copyright (c) 1999 Marc Espie.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by Marc Espie for the OpenBSD
* Project.
*
* THIS SOFTWARE IS PROVIDED BY THE OPENBSD PROJECT AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OPENBSD
* PROJECT OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#define GZIP_MAGIC0 '\037'
#define GZIP_MAGIC1 '\213'
/* flags values */
#define CONTINUATION 0x02
#define EXTRA_FIELD 0x04
/*
* Meaningful fields in a gzip header, see gzip proper for details.
* This structure should not be fiddled with outside of gzip_read_header
* and gzip_write_header
*/
struct mygzip_header {
char method;
char flags;
char stamp[6];
char part[2];
/* remaining extra, after know signs have been read */
unsigned int remaining;
};
#define TAGSIZE 8
#define TAGCHECK 6
typedef unsigned char SIGNTAG[8];
/* stack of signatures */
struct signature {
SIGNTAG tag;
int type;
int length;
char *data;
struct signature *next;
};
/* returns from gzip_read_header */
#define GZIP_UNSIGNED 0 /* gzip file, no signature */
#define GZIP_SIGNED 1 /* gzip file, signature parsed ok */
#define GZIP_NOT_GZIP 2 /* not a proper gzip file */
#define GZIP_NOT_PGPSIGNED 3 /* gzip file, unknown extension */
extern int gzip_read_header __P((FILE *f, /*@out@*/struct mygzip_header *h, \
/*@null@*/struct signature **sign));
/* gzip_write_header returns 1 for success */
extern int gzip_write_header __P((FILE *f, const struct mygzip_header *h, \
/*@null@*/struct signature *sign));
/*
* Writing header to memory. Returns size needed, or 0 if buffer too small
* buffer must be at least 14 characters
*/
extern int gzip_copy_header __P((const struct mygzip_header *h, \
/*@null@*/struct signature *sign, \
void (*add)(void *, const char *, size_t), void *data));
extern void free_signature __P((/*@null@*/struct signature *sign));
extern void sign_fill_tag __P((struct signature *sign));
#define KNOWN_TAGS 4
#define TAG_PGP 0
#define TAG_SHA1 1
#define TAG_X509 2
#define TAG_OLD 3
#define TAG_ANY -1
#define pgptag (known_tags[TAG_PGP])
#define sha1tag (known_tags[TAG_SHA1])
#define x509tag (known_tags[TAG_X509])
extern SIGNTAG known_tags[KNOWN_TAGS];

View File

@ -1,185 +0,0 @@
/* $OpenBSD: main.c,v 1.2 1999/10/04 21:46:28 espie Exp $ */
/*-
* Copyright (c) 1999 Marc Espie.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by Marc Espie for the OpenBSD
* Project.
*
* THIS SOFTWARE IS PROVIDED BY THE OPENBSD PROJECT AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OPENBSD
* PROJECT OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <sys/types.h>
#include <sys/wait.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include "stand.h"
#include "gzip.h"
#include "pgp.h"
#include "extern.h"
#ifdef __OpenBSD__
extern char *__progname;
#define argv0 __progname
#else
static char *argv0;
#endif
#define NM_SIGN "pkg_sign"
int verbose = 0;
int quiet = 0;
char *userkey = NULL;
static void
usage()
{
fprintf(stderr, "usage: %s [-sc] [-t type] [-u userid] [-k keyfile] pkg1 ...\n", argv0);
exit(EXIT_FAILURE);
}
#define SIGN 0
#define CHECK 1
/* wrapper for the check_signature function (open file if needed) */
static int
check(filename, type, userid, envp)
/*@observer@*/const char *filename;
int type;
/*@null@*/const char *userid;
char *envp[];
{
int result;
FILE *file;
if (strcmp(filename, "-") == 0)
return check_signature(stdin, userid, envp, "stdin");
file = fopen(filename, "r");
if (file == NULL) {
fprintf(stderr, "Can't open %s\n", filename);
return 0;
}
result = check_signature(file, userid, envp, filename);
if (fclose(file) == 0) {
if (result == PKG_BADSIG || result == PKG_SIGERROR)
return 0;
else
return 1;
} else
return 0;
}
int
main(argc, argv, envp)
int argc;
char *argv[];
char *envp[];
{
int success = 1;
int ch;
char *userid = NULL;
int mode;
int i;
int type = TAG_ANY;
#ifndef BSD4_4
set_program_name(argv[0]);
#endif
#ifdef CHECKER_ONLY
mode = CHECK;
#else
#ifndef __OpenBSD__
if ((argv0 = strrchr(argv[0], '/')) != NULL)
argv0++;
else
argv0 = argv[0];
#endif
if (strcmp(argv0, NM_SIGN) == 0)
mode = SIGN;
else
mode = CHECK;
#endif
while ((ch = getopt(argc, argv, "t:u:k:qscv")) != -1) {
switch(ch) {
case 't':
if (strcmp(optarg, "pgp") == 0)
type = TAG_PGP;
else if (strcmp(optarg, "sha1") == 0)
type = TAG_SHA1;
else if (strcmp(optarg, "x509") == 0)
type = TAG_X509;
else
usage();
break;
case 'u':
userid = strdup(optarg);
break;
case 'k':
userkey = optarg;
break;
case 'q':
quiet = 1;
break;
#ifndef CHECKER_ONLY
case 's':
mode = SIGN;
break;
#endif
case 'c':
mode = CHECK;
break;
case 'v':
verbose = 1;
break;
default:
usage();
}
}
argc -= optind;
argv += optind;
if (argc == 0) {
if (mode == CHECK)
success &= check("-", 0, userid, envp);
else
usage();
}
#ifndef CHECKER_ONLY
if (mode == SIGN && type == TAG_ANY)
type = TAG_PGP;
if (mode == SIGN && type == TAG_PGP)
handle_pgp_passphrase();
#endif
for (i = 0; i < argc; i++)
success &= (mode == SIGN ? sign : check)(argv[i], type, userid, envp);
exit(success == 1 ? EXIT_SUCCESS : EXIT_FAILURE);
}

View File

@ -1,25 +0,0 @@
/* $FreeBSD$ */
/* $OpenBSD: pgp.h,v 1.2 1999/10/04 21:46:28 espie Exp $ */
/* Estimate size of pgp signature */
#define MAXPGPSIGNSIZE 1024
#ifndef PGP
#define PGP "/usr/local/bin/pgp"
#endif
struct mygzip_header;
struct signature;
extern void *new_pgp_checker __P((struct mygzip_header *h, \
struct signature *sign, const char *userid, char *envp[], \
const char *filename));
extern void pgp_add __P((void *arg, const char *buffer, \
size_t length));
extern int pgp_sign_ok __P((void *arg));
extern void handle_pgp_passphrase __P((void));
extern int retrieve_pgp_signature __P((const char *filename, \
struct signature **sign, const char *userid, char *envp[]));

View File

@ -1,196 +0,0 @@
/* $OpenBSD: pgp_check.c,v 1.2 1999/10/07 16:30:32 espie Exp $ */
/*-
* Copyright (c) 1999 Marc Espie.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by Marc Espie for the OpenBSD
* Project.
*
* THIS SOFTWARE IS PROVIDED BY THE OPENBSD PROJECT AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OPENBSD
* PROJECT OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <stdio.h>
#include <errno.h>
#include <assert.h>
#include <unistd.h>
#include <fcntl.h>
#include <paths.h>
#include <stdlib.h>
#include <sys/stat.h>
#include "stand.h"
#include "pgp.h"
#include "gzip.h"
#include "extern.h"
#ifndef _PATH_DEVNULL
#define _PATH_DEVNULL "/dev/null"
#endif
/* transform current process into pgp signature checker -u userid <fd */
static void
pgpcheck(fd, userid, envp)
int fd;
const char *userid;
char *envp[];
{
int fdnull;
pchar argv[6];
int argc = 0;
argv[argc++] = PGP;
argv[argc++] = "+batchmode";
argv[argc++] = "-f";
if (userid) {
argv[argc++] = "-u";
argv[argc++] = (char *)userid;
}
argv[argc++] = NULL;
assert(argc <= sizeof argv / sizeof(pchar));
fdnull = open(_PATH_DEVNULL, O_RDWR);
if (fdnull == -1 ||
dup2(fd, fileno(stdin)) == -1 ||
dup2(fdnull, fileno(stdout)) == -1 ||
close(fdnull) == -1 || close(fd) == -1 ||
execve(PGP, argv, envp) == -1)
perror("launching pgp");
exit(errno);
}
struct pgp_checker {
pid_t id;
int fdout;
int status;
#ifdef DEBUG_DUMP
FILE *out;
#endif
};
void *
new_pgp_checker(h, sign, userid, envp, filename)
struct mygzip_header *h;
struct signature *sign;
const char *userid;
char *envp[];
/*@observer@*/const char *filename;
{
struct pgp_checker *n;
int topgpcheck[2];
assert(sign->type == TAG_PGP);
n = malloc(sizeof *n);
{
struct stat sbuf;
if (stat(PGP, &sbuf) == -1) {
warnx("%s does not exist", PGP);
return NULL;
}
}
if (n == NULL) {
warnx("Can't allocate pgp_checker");
return NULL;
}
if (pipe(topgpcheck) == -1) {
warn("Pgp checker pipe");
free(n);
return NULL;
}
switch(n->id = fork()) {
case -1:
warn("Pgp checker process");
free(n);
return NULL;
case 0:
if (close(topgpcheck[1]) == -1)
exit(errno);
pgpcheck(topgpcheck[0], userid, envp);
/*@notreached@*/
break;
default:
(void)close(topgpcheck[0]);
break;
}
n->fdout = topgpcheck[1];
/* so that subsequent fork() won't duplicate it inadvertently */
(void)fcntl(n->fdout, F_SETFD, FD_CLOEXEC);
#ifdef DEBUG_DUMP
n->out = fopen("compare", "w");
#endif
n->status = PKG_GOODSIG;
pgp_add(n, sign->data, sign->length);
if (gzip_copy_header(h, sign->next, pgp_add, n) == 0) {
warnx("Unexpected header in %s", filename);
n->status = PKG_SIGERROR;
}
return n;
}
void
pgp_add(arg, buffer, length)
void *arg;
const char *buffer;
size_t length;
{
struct pgp_checker *n = arg;
if (n->status == PKG_GOODSIG) {
#ifdef DEBUG_DUMP
fwrite(buffer, 1, length, n->out);
#endif
while (length > 0) {
ssize_t l = write(n->fdout, buffer, length);
if (l == -1) {
n->status = PKG_SIGERROR;
break;
}
length -= l;
buffer += l;
}
}
}
int
pgp_sign_ok(arg)
void *arg;
{
struct pgp_checker *n = arg;
int status = n->status;
#ifdef DEBUG_DUMP
fclose(n->out);
#endif
if (close(n->fdout) != 0)
status = PKG_SIGERROR;
if (reap(n->id) != 0)
status = PKG_BADSIG;
free(n);
return status;
}

View File

@ -1,281 +0,0 @@
/* $OpenBSD: pgp_sign.c,v 1.1 1999/10/04 21:46:29 espie Exp $ */
/*-
* Copyright (c) 1999 Marc Espie.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by Marc Espie for the OpenBSD
* Project.
*
* THIS SOFTWARE IS PROVIDED BY THE OPENBSD PROJECT AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OPENBSD
* PROJECT OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <sys/types.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <stdio.h>
#include <errno.h>
#include <signal.h>
#include <pwd.h>
#include <assert.h>
#include "stand.h"
#include "pgp.h"
#include "gzip.h"
#include "extern.h"
static void
pgpsign(fdin, fdout, userid, envp)
int fdin, fdout;
const char *userid;
char *envp[];
{
pchar argv[10];
int argc = 0;
argv[argc++] = PGP;
argv[argc++] = "+batchmode";
argv[argc++] = "+compress=off";
argv[argc++] = "-f";
argv[argc++] = "-s";
argv[argc++] = "-zAthlon";
if (userid) {
argv[argc++] = "-u";
argv[argc++] = (char *)userid;
}
argv[argc++] = NULL;
assert(argc <= sizeof argv / sizeof(pchar));
if (dup2(fdin, fileno(stdin)) == -1 ||
dup2(fdout, fileno(stdout)) == -1 ||
execve(PGP, argv, envp) == -1)
exit(errno);
}
static struct signature *
new_pgpsignature(old)
struct signature *old;
{
struct signature *n;
n = malloc(sizeof(*n));
if (n != NULL) {
n->data = malloc(MAXPGPSIGNSIZE);
if (n->data == NULL) {
free(n);
return NULL;
}
n->length = 0;
n->next = old;
n->type = TAG_PGP;
memcpy(n->tag, pgptag, sizeof pgptag);
}
return n;
}
int
retrieve_pgp_signature(filename, sign, userid, envp)
const char *filename;
struct signature **sign;
const char *userid;
char *envp[];
{
int topgp[2], frompgp[2];
pid_t pgpid;
struct mygzip_header h;
int success;
FILE *orig, *dest, *signin;
struct signature *old;
orig = fopen(filename, "r");
if (orig == NULL)
return 0;
if (gzip_read_header(orig, &h, &old) == GZIP_NOT_GZIP) {
warnx("File %s is not a gzip file\n", filename);
fclose(orig);
return 0;
}
if (pipe(topgp) == -1) {
fclose(orig);
return 0;
}
if (pipe(frompgp) == -1) {
fclose(orig);
(void)close(topgp[0]);
(void)close(topgp[1]);
return 0;
}
switch(pgpid = fork()) {
case 0:
(void)close(topgp[1]);
(void)close(frompgp[0]);
pgpsign(topgp[0], frompgp[1], userid, envp);
/*NOT REACHED */
case -1:
(void)close(topgp[0]);
(void)close(topgp[1]);
(void)close(frompgp[0]);
(void)close(frompgp[1]);
fclose(orig);
return 0;
default:
(void)close(topgp[0]);
(void)close(frompgp[1]);
}
dest = fdopen(topgp[1], "w");
if (dest == NULL) {
(void)close(topgp[1]);
(void)close(frompgp[0]);
(void)reap(pgpid);
return 0;
}
success = 1;
if (gzip_write_header(dest, &h, old) == 0)
success = 0;
else {
int c;
while ((c = fgetc(orig)) != EOF && fputc(c, dest) != EOF)
;
if (ferror(dest))
success = 0;
}
if (fclose(dest) != 0)
success = 0;
if (fclose(orig) != 0)
success = 0;
signin = fdopen(frompgp[0], "r");
if (signin == NULL) {
(void)close(frompgp[0]);
} else {
enum { NONE, FIRST, DONE, COPY} magic = NONE;
int c;
#ifdef DEBUG_DUMP
FILE *out = fopen("dump", "w");
#endif
if ((*sign = new_pgpsignature(old)) == NULL)
success = 0;
else {
while ((c = fgetc(signin)) != EOF && magic != DONE &&
(*sign)->length < MAXPGPSIGNSIZE) {
switch(magic) {
case NONE:
(*sign)->data[(*sign)->length++] = c;
if ((unsigned char)c == (unsigned char)GZIP_MAGIC0)
magic = FIRST;
break;
case FIRST:
(*sign)->data[(*sign)->length++] = c;
if ((unsigned char)c == (unsigned char)GZIP_MAGIC1)
#ifdef DEBUG_DUMP
magic = COPY;
#else
magic = DONE;
#endif
else if ((unsigned char)c != (unsigned char)GZIP_MAGIC0)
magic = NONE;
break;
case DONE:
case COPY:
break;
}
#ifdef DEBUG_DUMP
fputc(c, out);
#endif
}
if ((*sign)->length == MAXPGPSIGNSIZE)
success = 0;
(*sign)->length -= 2;
sign_fill_tag(*sign);
}
fclose(signin);
#ifdef DEBUG_DUMP
fclose(out);
#endif
reap(pgpid);
}
return success;
}
void
handle_pgp_passphrase()
{
pid_t pid;
int fd[2];
char *p;
printf("Short-circuiting %s\n", __func__);
return;
/* Retrieve the pgp passphrase */
p = getpass("Enter passphrase:");
/*
* Somewhat kludgy code to get the passphrase to pgp, see
* pgp documentation for the gore
*/
if (pipe(fd) != 0) {
perror("pkg_sign");
exit(EXIT_FAILURE);
}
switch(pid = fork()) {
case -1:
perror("pkg_sign");
exit(EXIT_FAILURE);
case 0:
{
(void)close(fd[0]);
/*
* The child fills the pipe with copies of the passphrase.
* Expect violent death when father exits.
*/
printf("Child process %d stuffing passphrase in pipe:\n", getpid());
for(;;) {
char c = '\n';
(void)write(fd[1], p, strlen(p));
(void)write(fd[1], &c, 1);
putchar('.'); fflush(stdout);
}
}
default:
{
char buf[10];
sleep(1);
(void)close(fd[1]);
(void)sprintf(buf, "%d", fd[0]);
(void)setenv("PGPPASSFD", buf, 1);
printf("Parent process PGPPASSFD=%d.\n", fd[0]);
}
}
}

View File

@ -1,211 +0,0 @@
.\" $FreeBSD$
.\" $OpenBSD: pkg_sign.1,v 1.6 2000/04/15 02:15:20 aaron Exp $
.\"
.\" Copyright (c) 1999 Marc Espie.
.\"
.\" Redistribution and use in source and binary forms, with or without
.\" modification, are permitted provided that the following conditions
.\" are met:
.\" 1. Redistributions of source code must retain the above copyright
.\" notice, this list of conditions and the following disclaimer.
.\" 2. Redistributions in binary form must reproduce the above copyright
.\" notice, this list of conditions and the following disclaimer in the
.\" documentation and/or other materials provided with the distribution.
.\" 3. All advertising materials mentioning features or use of this software
.\" must display the following acknowledgement:
.\" This product includes software developed by Marc Espie for the OpenBSD
.\" Project.
.\"
.\" THIS SOFTWARE IS PROVIDED BY THE OPENBSD PROJECT AND CONTRIBUTORS
.\" ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
.\" LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
.\" A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OPENBSD
.\" PROJECT OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
.\" SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
.\" LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
.\" DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
.\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
.\" OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
.Dd September 24, 1999
.Dt PKG_SIGN 1
.Os
.Sh NAME
.Nm pkg_sign ,
.Nm pkg_check
.Nd handle package signatures
.Sh SYNOPSIS
.Nm
.Op Fl sc
.Op Fl t Ar type
.Op Fl u Ar id
.Op Fl k Ar key
.Op Ar
.Nm pkg_check
.Op Fl sc
.Op Fl u Ar id
.Op Fl k Ar cert
.Op Ar
.Sh DESCRIPTION
The
.Nm
utility embeds a cryptographic signature within a gzip file
.Ar file .
.Ar type
can be
.Cm pgp
(default),
.Cm sha1 ,
or
.Cm x509 .
If
.Ar type
is
.Cm pgp ,
it will always prompt you for a passphrase to unlock your private
pgp key, even if you do not use a passphrase (which is a bad idea, anyway).
If
.Ar type
is
.Cm sha1 ,
you must supply an
.Ar id ,
which will be recorded as the name of the package, and printed as the
SHA1 checksum.
.Pp
The
.Nm pkg_check
utility checks that cryptographic signature.
It currently disregards
.Ar type
and checks only the topmost signature.
For
.Cm sha1 ,
it checksums the file
and verifies that the result matches the list of checksums recorded in
.Pa /var/db/pkg/SHA1 .
.Pp
Options
.Fl s
and
.Fl c
can be used to force package signing or signature checking mode.
.Pp
For
.Cm pgp ,
the
.Ar id
to use to sign the package or verify the signature can be forced with
.Fl u .
.Pp
For
.Cm x509 ,
the signing key or verification certificate may be
specified with the
.Fl k
option.
If not specified, packages are signed or verified with the
default keys and certificates documented below.
.Pp
If
.Ar file
is a single dash
.Pq Sq Fl
or absent,
.Nm
reads from the standard input.
.Pp
Package signing uses a feature of the gzip format, namely that one can
set a flag
.Dv EXTRA_FIELD
in the gzip header and store extra data between the gzip header and the
compressed file proper.
The
.Ox
signing scheme uses eight bytes markers such
.Sq Li SIGPGP
+ length or
.Sq CKSHA1
+ length for its signatures (those markers are conveniently
eight bytes long).
.Sh FILES
.Bl -tag -width "/usr/local/bin/pgp" -compact
.It Pa file.sign
Temporary file built by
.Nm
from
.Ar file .
.It Pa /usr/local/bin/pgp
Default path to
.Xr pgp 1 .
.It Pa /var/db/pkgs/SHA1
Recorded checksums.
.It Pa /etc/ssl/pkg.key
Default package signing key.
.It Pa /etc/ssl/pkg.crt
Default package verification certificate(s).
.El
.Sh EXIT STATUS
The
.Nm
and
.Nm pkg_check
utilities return with an exit code >0 if anything went wrong for any
.Ar file .
For
.Nm pkg_check ,
this usually indicates that the package is not signed, or that the
signature is forged.
.Sh DIAGNOSTICS
.Bl -diag
.It "File %s is already signed"
There is a signature embedded within the gzip file already.
The
.Nm
utility currently does not handle multiple signatures.
.It "File %s is not a signed gzip file"
This is an unsigned package.
.It "File %s is not a gzip file"
The program could not find a proper gzip header.
.It "File %s contains an unknown extension"
The extended area of the gzip file has been used for an unknown purpose.
.It "File %s uses old signatures, no longer supported"
The gzip file uses a very early version of package signing that was
substantially slower.
.El
.Sh SEE ALSO
.Xr gzip 1 ,
.Xr pgp 1 ,
.Xr pkg_add 1 ,
.Xr sha1 1
.Sh AUTHORS
.An -nosplit
A
.Nm
utility was created by
.An Marc Espie
for the
.Ox
Project.
X.509 signatures and
.Fx
support added by
.An Wes Peters Aq wes@softweyr.com .
.Sh BUGS
The
.Xr pgp 1
utility is an ill-designed program, which is hard to interface with.
For instance, the `separate signing scheme' it pretends to offer is
useless, as it cannot be used with pipes, so that
.Nm pgp_sign
needs to kludge it by knowing the length of a pgp signature, and invoking
pgp in `seamless' signature mode, without compression of the main file,
and just retrieving the signature.
.Pp
The checking scheme is little less convoluted, namely we rebuild the file
that pgp expects on the fly.
.Pp
Paths to
.Nm pgp
and
the checksum file are hard-coded to avoid tampering and hinder flexibility.

View File

@ -1,230 +0,0 @@
/* $OpenBSD: sha1.c,v 1.1 1999/10/04 21:46:29 espie Exp $ */
/*-
* Copyright (c) 1999 Marc Espie.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by Marc Espie for the OpenBSD
* Project.
*
* THIS SOFTWARE IS PROVIDED BY THE OPENBSD PROJECT AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OPENBSD
* PROJECT OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <sys/types.h>
#include <sys/wait.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <assert.h>
#include <sha.h>
#include "stand.h"
#include "gzip.h"
#include "extern.h"
/* private context for sha1 signature checker */
struct sha1_checker {
SHA_CTX context;
const char *id;
const char *filename;
};
#define SHA1_TEMPLATE "SHA1 (%s) = "
#define BUFSIZE (MAXID+sizeof(SHA1_TEMPLATE)+2*SHA_DIGEST_LENGTH+1)
/*
* Finalize SHA1 checksum for our sha1_context into result
* (size at least BUFSIZE). Returns the length of the checksum
* marker, e.g., SHA1 (id) = xxxxxxxxx
* ^here
* Return 0 for errors.
*/
size_t
sha1_build_checksum(result, n)
char *result;
struct sha1_checker *n;
{
size_t length;
snprintf(result, BUFSIZE-2*SHA_DIGEST_LENGTH-1, SHA1_TEMPLATE, n->id);
length = strlen(result);
SHA1_End(&n->context, result + length);
strcat(result, "\n");
free(n);
return length;
}
void *
new_sha1_checker(h, sign, userid, envp, filename)
struct mygzip_header *h;
struct signature *sign;
const char *userid;
char *envp[];
/*@observer@*/const char *filename;
{
struct sha1_checker *n;
assert(sign->type == TAG_SHA1);
/* make sure data conforms to what we can handle */
if (sign->length > MAXID || sign->data[sign->length-1] != '\0') {
warnx("Corrupted SHA1 header in %s", filename);
return 0;
}
n = malloc(sizeof *n);
if (n == NULL) {
warnx("Can't allocate sha1_checker");
return NULL;
}
SHA1_Init(&n->context);
n->id = sign->data;
n->filename = filename;
/* copy header, as this is a checksum, we don't strip our own marker */
if (gzip_copy_header(h, sign, sha1_add, n) == 0) {
warnx("Unexpected header in %s", filename);
free(n);
return 0;
}
return n;
}
void
sha1_add(arg, buffer, length)
void *arg;
const char *buffer;
size_t length;
{
struct sha1_checker *n = arg;
SHA1_Update(&n->context, buffer, length);
}
int
sha1_sign_ok(arg)
void *arg;
{
struct sha1_checker *n = arg;
char buffer[BUFSIZE];
char scan[BUFSIZE];
size_t length;
FILE *f;
int tag_found;
length = sha1_build_checksum(buffer, n);
f= fopen(SHA1_DB_NAME, "r");
tag_found = 0;
if (f == NULL) {
warn("Can't access checksum file %s", SHA1_DB_NAME);
return PKG_BADSIG;
}
while (fgets(scan, sizeof(scan), f) != NULL) {
if (strcmp(scan, buffer) == 0) {
fprintf(stderr, "Checksum ok\n");
return PKG_GOODSIG;
}
if (strncmp(scan, buffer, length) == 0)
tag_found = 1;
}
if (tag_found) {
warnx("Checksum incorrect for %s (%s)", n->filename, n->id);
return PKG_BADSIG;
} else {
warnx("No checksum found for %s (%s)", n->filename, n->id);
return PKG_SIGUNKNOWN;
}
}
int
retrieve_sha1_marker(filename, sign, userid)
const char *filename;
struct signature **sign;
const char *userid;
{
struct signature *n;
struct mygzip_header h;
FILE *f;
char buffer[1024];
char result[BUFSIZE];
ssize_t length = -1;
struct sha1_checker *checker;
*sign = NULL;
if (userid == NULL)
return 0;
/*
* Create a blank signature and fill it with the userid.
*/
n = malloc(sizeof *n);
if (n == NULL)
return 0;
n->length = strlen(userid)+1;
n->data = malloc(n->length);
if (n->data == NULL) {
free(n);
return 0;
}
memcpy(n->data, userid, n->length);
n->type = TAG_SHA1;
memcpy(n->tag, sha1tag, sizeof sha1tag);
sign_fill_tag(n);
/*
* Read the gzip header and add our "userid" signature to it.
*/
f = fopen(filename, "r");
if (f == NULL) {
free(n);
return 0;
}
if (gzip_read_header(f, &h, sign) == GZIP_NOT_GZIP) {
warnx("File %s is not a gzip file\n", filename);
fclose(f);
free(n);
return 0;
}
n->next = *sign;
*sign = n;
/*
* Calculate the SHA1 of the remaining data and write it to stderr.
*/
checker = new_sha1_checker(&h, *sign, NULL, NULL, filename);
if (checker)
while ((length = fread(buffer, 1, sizeof buffer, f)) > 0)
sha1_add(checker, buffer, length);
if (fclose(f) != 0 || length == -1) {
warn("Problem checksumming %s", filename);
*sign = n->next;
free(n);
return 0;
}
(void)sha1_build_checksum(result, checker);
fputs(result, stderr);
return 1;
}

View File

@ -1,150 +0,0 @@
/* $OpenBSD: sign.c,v 1.3 1999/10/04 21:46:29 espie Exp $ */
/*-
* Copyright (c) 1999 Marc Espie.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by Marc Espie for the OpenBSD
* Project.
*
* THIS SOFTWARE IS PROVIDED BY THE OPENBSD PROJECT AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OPENBSD
* PROJECT OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <sys/types.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <stdio.h>
#include <errno.h>
#include <signal.h>
#include <pwd.h>
#include <assert.h>
#include "stand.h"
#include "pgp.h"
#include "gzip.h"
#include "extern.h"
#define COPY_TEMPLATE "%s.sign"
static int
embed_signature_FILE(orig, dest, sign, filename)
/*@temp@*/FILE *orig;
/*@temp@*/FILE *dest;
struct signature *sign;
const char *filename;
{
struct mygzip_header h;
int c;
if (gzip_read_header(orig, &h, NULL) == GZIP_NOT_GZIP)
return 0;
if (gzip_write_header(dest, &h, sign) == 0)
return 0;
while ((c = fgetc(orig)) != EOF && fputc(c, dest) != EOF)
;
if (ferror(dest) != 0)
return 0;
return 1;
}
static int
embed_signature(filename, copy, sign)
const char *filename;
const char *copy;
struct signature *sign;
{
FILE *orig, *dest;
int success;
success = 0;
orig= fopen(filename, "r");
if (orig) {
dest = fopen(copy, "w");
if (dest) {
success = embed_signature_FILE(orig, dest, sign, filename);
if (fclose(dest) != 0)
success = 0;
}
if (fclose(orig) != 0)
success = 0;
}
return success;
}
int
sign(filename, type, userid, envp)
const char *filename;
const char *userid;
int type;
char *envp[];
{
char *copy;
int result;
struct signature *sign;
int success;
sign = NULL;
switch(type) {
case TAG_PGP:
success = retrieve_pgp_signature(filename, &sign, userid, envp);
break;
case TAG_SHA1:
success = retrieve_sha1_marker(filename, &sign, userid);
break;
case TAG_X509:
success = retrieve_x509_marker(filename, &sign, userid);
break;
default:
success = 0;
fprintf(stderr, "Unknown type %d\n", type);
}
if (!success) {
fprintf(stderr, "Problem signing %s\n", filename);
free_signature(sign);
return 0;
}
copy = malloc(strlen(filename)+sizeof(COPY_TEMPLATE));
if (copy == NULL) {
fprintf(stderr, "Can't allocate memory\n");
free_signature(sign);
return 0;
}
sprintf(copy, COPY_TEMPLATE, filename);
result = embed_signature(filename, copy, sign);
if (result == 0) {
fprintf(stderr, "Can't embed signature in %s\n", filename);
} else if (unlink(filename) != 0) {
fprintf(stderr, "Can't unlink original %s\n", filename);
result = 0;
} else if (rename(copy, filename) != 0) {
fprintf(stderr, "Can't rename new file %s\n", copy);
result = 0;
}
free(copy);
free_signature(sign);
return result;
}

View File

@ -1,57 +0,0 @@
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include "stand.h"
#ifndef BSD4_4
#include <string.h>
#include <stdio.h>
#include <errno.h>
#include <stdarg.h>
/* shortened version of warn */
static const char *program_name;
void
set_program_name(n)
const char *n;
{
if ((program_name = strrchr(n, '/')) != NULL)
program_name++;
else
program_name = n;
}
void
warn(const char *fmt, ...)
{
va_list ap;
int interrno;
va_start(ap, fmt);
interrno = errno;
(void)fprintf(stderr, "%s: ", program_name);
if (fmt != NULL) {
(void)vfprintf(stderr, fmt, ap);
(void)fprintf(stderr, ": ");
}
(void)fprintf(stderr, "%s\n", strerror(interrno));
va_end(ap);
}
void
warnx(const char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
(void)fprintf(stderr, "%s: ", program_name);
if (fmt != NULL)
(void)vfprintf(stderr, fmt, ap);
(void)fprintf(stderr, "\n");
va_end(ap);
}
#endif

View File

@ -1,28 +0,0 @@
/* $FreeBSD$ */
/* $OpenBSD: stand.h,v 1.2 1999/10/04 21:46:30 espie Exp $ */
/* provided to cater for BSD idiosyncrasies */
#if (defined(__unix__) || defined(unix)) && !defined(USG)
#include <sys/param.h>
#endif
#ifndef __P
#ifdef __STDC__
#define __P(x) x
#else
#define __P(x) ()
#endif
#endif
#if defined(BSD4_4)
#include <err.h>
#else
extern void warn __P((const char *fmt, ...));
extern void warnx __P((const char *fmt, ...));
#endif
extern void set_program_name __P((const char * name));
#ifndef __GNUC__
#define __attribute__(x)
#endif

View File

@ -1,428 +0,0 @@
/*-
* Copyright (c) 2000 Softweyr LLC, South Jordan, Utah, USA.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY Softweyr LLC ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL Softweyr LLC BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <sys/types.h>
#include <sys/wait.h>
#include <assert.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <libgen.h>
#include <openssl/rsa.h>
#include <openssl/evp.h>
#include <openssl/objects.h>
#include <openssl/x509.h>
#include <openssl/err.h>
#include <openssl/pem.h>
#include <openssl/ssl.h>
#include "stand.h"
#include "gzip.h"
#include "extern.h"
/*
* Default names for the signing key and certificate(s) for verification.
*/
#define CERTFILE "/etc/ssl/pkg.crt"
#define KEYFILE "/etc/ssl/pkg.key"
/*
* Private context for X.509 signature checker
*/
struct x509_checker
{
const char * id;
const char * filename;
struct signature * signature;
STACK_OF(X509) * certs;
EVP_MD_CTX rsa_ctx, dsa_ctx;
int has_rsa, has_dsa;
};
static void key_from_name(char *, const char *);
/*
* Initialize an X.509 "checker" context.
*/
void *
new_x509_checker(h, sign, userid, envp, filename)
struct mygzip_header *h;
struct signature *sign;
const char *userid;
char *envp[];
/*@observer@*/const char *filename;
{
FILE * fp;
struct x509_checker * me;
char certfile[PATH_MAX + 1] = CERTFILE;
X509 * x509;
assert(sign->type == TAG_X509);
/*
* Make sure data conforms to what we can handle. We do not write a
* trailing null onto the signature like some other types, because
* the X.509 signature is binary data.
*/
if (sign->length > MAXID) {
warnx("Corrupted X.509 header in %s", filename);
return 0;
}
me = malloc(sizeof *me);
if (me == NULL) {
warn("Cannot allocate x509_checker");
return 0;
}
me->id = sign->data;
me->filename = filename;
me->signature = sign;
me->has_rsa = 0;
me->has_dsa = 0;
key_from_name(certfile, userkey);
/*
* Load just the crypto library error strings.
*/
ERR_load_crypto_strings();
/*
* Load the stack of X.509 certs we will compare against.
*
* KLUDGE: this needs to be fleshed out a bit. We can do better
* than hard-coding the location of the cert key file.
*/
me->certs = sk_X509_new_null();
fp = fopen(certfile, "r");
if (fp == NULL) {
warnx("Cannot open public key %s", certfile);
return 0;
}
if (verbose)
printf("Loading certificates from %s:\n", certfile);
while ((x509 = PEM_read_X509(fp, NULL, NULL, 0))) {
sk_X509_push(me->certs, x509);
switch (EVP_PKEY_type(X509_get_pubkey(x509)->type))
{
case EVP_PKEY_RSA:
me->has_rsa = 1;
break;
case EVP_PKEY_DSA:
me->has_dsa = 1;
break;
default:
warnx("Unknown certificate type: %d", EVP_PKEY_type(X509_get_pubkey(x509)->type));
fclose(fp);
return 0;
}
/*
* By default, print the contents of the cert we matched so the
* user can decide if she is willing to accept a package from
* whoever signed this.
*/
if (!quiet)
X509_print_fp(stdout, x509);
}
fclose(fp);
/*
* Initialize the verification contexts for both RSA and DSA.
*/
if (me->has_rsa) EVP_VerifyInit(&me->rsa_ctx, EVP_sha1());
if (me->has_dsa) EVP_VerifyInit(&me->dsa_ctx, EVP_dss1());
return me;
}
/*
* "Add" another data block to an existing checker.
*/
void
x509_add(arg, buffer, length)
void *arg;
const char *buffer;
size_t length;
{
struct x509_checker * me = arg;
if (me->has_rsa) EVP_VerifyUpdate(&me->rsa_ctx, buffer, length);
if (me->has_dsa) EVP_VerifyUpdate(&me->dsa_ctx, buffer, length);
}
/*
* Finalize an existing checker and verify the signature matches one of the
* certs in our stack.
*/
int
x509_sign_ok(arg)
void *arg;
{
struct x509_checker * n = arg;
X509 * x509;
EVP_PKEY * pkey;
EVP_MD_CTX * md_ctx;
int status;
if (verbose)
printf("\n\n-------\n\nChecking package signature:\n");
while ((x509 = sk_X509_pop(n->certs)) != NULL) {
/*
* Get public key from cert.
*/
pkey = X509_get_pubkey(x509);
if (pkey == NULL) {
warnx("Getting public key:");
ERR_print_errors_fp(stderr);
continue;
}
if (verbose)
X509_print_fp(stdout, x509);
switch (EVP_PKEY_type(pkey->type))
{
case EVP_PKEY_RSA:
md_ctx = &n->rsa_ctx;
break;
case EVP_PKEY_DSA:
md_ctx = &n->dsa_ctx;
break;
default:
warnx("Unknown public key type: %d", EVP_PKEY_type(pkey->type));
md_ctx = NULL;
break;
}
status = (md_ctx == NULL) ? 0 : EVP_VerifyFinal(md_ctx,
n->signature->data,
n->signature->length,
pkey);
EVP_PKEY_free(pkey);
X509_free(x509);
if (status == 1) {
fprintf(stderr, "X.509 signature matched\n");
/*
* KLUDGE: Does this free the rest of the certs, or just the
* stack itself? Enquiring minds want to know.
*/
sk_X509_free(n->certs);
return PKG_GOODSIG;
}
}
warnx("Verifying signature:");
ERR_print_errors_fp(stderr);
sk_X509_free(n->certs);
return PKG_BADSIG;
}
/*
* Sign the specified filename into sign.
*/
int
retrieve_x509_marker(filename, sign, userid)
const char * filename;
struct signature ** sign;
const char * userid;
{
struct signature * n;
struct mygzip_header h;
FILE * f, * keyf;
char buffer[1024];
ssize_t length;
int err;
int sig_len = 4096;
unsigned char * sig_buf;
EVP_MD_CTX md_ctx;
const EVP_MD * md_type;
EVP_PKEY * pkey;
char keyfile[PATH_MAX + 1] = KEYFILE;
key_from_name(keyfile, userkey);
f = fopen(filename, "r");
if (f == NULL) {
return 0;
}
if (gzip_read_header(f, &h, sign) == GZIP_NOT_GZIP) {
warnx("File %s is not a gzip file\n", filename);
fclose(f);
return 0;
}
/*
* Sign the remaining data:
* Load just the crypto library error strings.
*/
ERR_load_crypto_strings();
/*
* Read private key.
*/
keyf = fopen(keyfile, "r");
if (keyf == NULL)
{
warnx("Cannot open private key %s.", keyfile);
fclose(f);
return 0;
}
pkey = PEM_read_PrivateKey(keyf, NULL, NULL, 0);
fclose(keyf);
if (pkey == NULL)
{
warnx("Reading private key %s:", keyfile);
ERR_print_errors_fp(stderr);
return 0;
}
/*
* Do the signature. The remaining bytes of the GZIP file are the
* compressed tar image, which is what we are signing.
*/
switch (EVP_PKEY_type(pkey->type))
{
case EVP_PKEY_RSA:
md_type = EVP_sha1();
break;
case EVP_PKEY_DSA:
md_type = EVP_dss1();
break;
default:
warnx("Unknown key type");
fclose(f);
return 0;
}
EVP_SignInit(&md_ctx, md_type);
while ((length = fread(buffer, 1, sizeof buffer, f)) > 0)
EVP_SignUpdate(&md_ctx, buffer, length);
fclose(f);
sig_buf = malloc(sig_len);
if (sig_buf == NULL) {
warnx("Cannot allocated %u bytes for signature buffer", sig_len);
return 0;
}
err = EVP_SignFinal(&md_ctx, sig_buf, &sig_len, pkey);
if (err != 1)
{
warnx("Creating signature:");
ERR_print_errors_fp(stderr);
return 0;
}
EVP_PKEY_free(pkey);
/*
* Stuff the signature onto the head of the chain of signatures in
* the package.
*/
n = malloc(sizeof *n);
if (n == NULL) {
warnx("Cannot allocate %u bytes for new signature", sizeof *n);
return 0;
}
n->data = sig_buf;
n->length = sig_len;
n->type = TAG_X509;
memcpy(n->tag, x509tag, sizeof x509tag);
sign_fill_tag(n);
n->next = *sign;
*sign = n;
/*
* Report our success.
*/
return 1;
}
static void
key_from_name(char * filename, const char * ident)
{
char * cp;
/*
* If an alternate keyfile was specified, treat it as the name of an
* alternate private key with which to sign or verify the package.
*/
if (ident) {
printf("Using alternate key/cert \"%s\".\n", ident);
if (strchr(ident, '/')) {
/*
* The user specified a path, take it verbatim.
*/
strncpy(filename, ident, PATH_MAX);
} else {
cp = dirname(filename);
if (cp == NULL) {
warnx("Key directory not correctly specified.");
return;
}
snprintf(filename, PATH_MAX, "%s/%s", cp, ident);
}
}
if (verbose)
printf("Key is \"%s\".\n", filename);
}

View File

@ -35,7 +35,7 @@ Boolean RegexExtended = FALSE;
Boolean UseINDEXOnly = FALSE;
Boolean ShowOrigin = FALSE;
static void usage __P((void));
static void usage(void);
int
main(int argc, char **argv)
@ -54,7 +54,7 @@ main(int argc, char **argv)
else while ((ch = getopt(argc, argv, Options)) != -1) {
switch(ch) {
case 'v':
Verbose = TRUE;
Verbose++;
break;
case 'I':
@ -77,9 +77,9 @@ main(int argc, char **argv)
MatchName = optarg;
break;
case 'O':
LookUpOrigin = optarg;
break;
case 'O':
LookUpOrigin = optarg;
break;
case 'o':
ShowOrigin = TRUE;

View File

@ -235,8 +235,8 @@ pkg_do(char *pkg)
show_version(plist, NULL, NULL);
else
show_version(plist, latest, "index");
}
}
}
if (latest != NULL)
free(latest);
free_plist(&plist);
@ -275,7 +275,7 @@ show_version(Package plist, const char *latest, const char *source)
if (Verbose)
printf(" Comparison failed");
printf("\n");
} else if (source == NULL && OUTPUT('?')) {
} else if (OUTPUT('?')) {
printf("%-34s ?", tmp);
if (Verbose)
printf(" orphaned: %s", plist.origin);

View File

@ -25,7 +25,7 @@
.\"
.\" $FreeBSD$
.\"
.Dd Jul 27, 2005
.Dd July 27, 2005
.Dt PKG_VERSION 1
.Os
.Sh NAME
@ -72,7 +72,7 @@ cannot be located,
.Nm
will search for the package in the ports collection index file
(typically
.Pa /usr/ports/INDEX-6 ) .
.Pa /usr/ports/INDEX-8 ) .
Any matching version number(s) there will be used to determine whether
the installed package is up-to-date or requires updating.
.Pp
@ -205,12 +205,12 @@ can be used here.
If no
.Ar index
file is specified on the command line,
.Pa /usr/ports/INDEX-6
.Pa /usr/ports/INDEX-8
is used.
.El
.Sh FILES
.Bl -tag -width /usr/ports/INDEX-6 -compact
.It Pa /usr/ports/INDEX-6
.Bl -tag -width /usr/ports/INDEX-8 -compact
.It Pa /usr/ports/INDEX-8
Default index file.
.El
.Sh EXAMPLES
@ -224,7 +224,7 @@ index file:
The command below generates a report against
the version numbers in the on-line ports collection:
.Pp
.Dl % pkg_version http://www.FreeBSD.org/ports/INDEX-6
.Dl % pkg_version http://www.FreeBSD.org/ports/INDEX-8
.Pp
The following command compares two package version strings:
.Pp

View File

@ -23,13 +23,6 @@
#ifndef _INST_VERSION_H_INCLUDE
#define _INST_VERSION_H_INCLUDE
/* Where the ports lives by default */
#define DEF_PORTS_DIR "/usr/ports"
/* just in case we change the environment variable name */
#define PORTSDIR "PORTSDIR"
/* macro to get name of directory where we put logging information */
#define PORTS_DIR (getenv(PORTSDIR) ? getenv(PORTSDIR) : DEF_PORTS_DIR)
struct index_entry {
SLIST_ENTRY(index_entry) next;
char *name;