summaryrefslogtreecommitdiff
path: root/usr.sbin/pkg_install
diff options
context:
space:
mode:
Diffstat (limited to 'usr.sbin/pkg_install')
-rw-r--r--usr.sbin/pkg_install/sign/INSTALL4
-rw-r--r--usr.sbin/pkg_install/sign/Makefile1
-rw-r--r--usr.sbin/pkg_install/sign/README31
-rw-r--r--usr.sbin/pkg_install/sign/check.c198
-rw-r--r--usr.sbin/pkg_install/sign/common.c89
-rw-r--r--usr.sbin/pkg_install/sign/extern.h53
-rw-r--r--usr.sbin/pkg_install/sign/gzip.c317
-rw-r--r--usr.sbin/pkg_install/sign/gzip.h50
-rw-r--r--usr.sbin/pkg_install/sign/main.c41
-rw-r--r--usr.sbin/pkg_install/sign/pgp.h23
-rw-r--r--usr.sbin/pkg_install/sign/pgp_check.c193
-rw-r--r--usr.sbin/pkg_install/sign/pgp_sign.c266
-rw-r--r--usr.sbin/pkg_install/sign/pkg_sign.173
-rw-r--r--usr.sbin/pkg_install/sign/sha1.c212
-rw-r--r--usr.sbin/pkg_install/sign/sign.c110
-rw-r--r--usr.sbin/pkg_install/sign/simple_check.c72
-rw-r--r--usr.sbin/pkg_install/sign/stand.c54
-rw-r--r--usr.sbin/pkg_install/sign/stand.h13
18 files changed, 1337 insertions, 463 deletions
diff --git a/usr.sbin/pkg_install/sign/INSTALL b/usr.sbin/pkg_install/sign/INSTALL
index 1577272fc8c..bc0a530fcee 100644
--- a/usr.sbin/pkg_install/sign/INSTALL
+++ b/usr.sbin/pkg_install/sign/INSTALL
@@ -4,8 +4,8 @@ Normally, `make' should be enough to build these tools.
A simpler version can be built by using `make check_sign'
(does not depend on the existence of getpass())
-You should define PGP and GZCAT in the Makefile if the defaults
-(/usr/local/bin/pgp and /usr/bin/gzcat) don't apply.
+You should define PGP in the Makefile if the default
+(/usr/local/bin/pgp) doesn't apply.
There is no install target, just copy pkg_sign and/or check_sign where
you want, along with the manpage.
diff --git a/usr.sbin/pkg_install/sign/Makefile b/usr.sbin/pkg_install/sign/Makefile
index b3adf4d287d..72b2e5c506c 100644
--- a/usr.sbin/pkg_install/sign/Makefile
+++ b/usr.sbin/pkg_install/sign/Makefile
@@ -1,5 +1,4 @@
# define PGP to be the path to pgp (default: /usr/local/bin/pgp)
-# and GZCAT to be the path to gzcat (default: /usr/bin/gzcat)
# Use the check_sign target if your system can't handle pipes or getpass
all: pkg_sign
diff --git a/usr.sbin/pkg_install/sign/README b/usr.sbin/pkg_install/sign/README
index 57a6656c8a4..952dec5a40a 100644
--- a/usr.sbin/pkg_install/sign/README
+++ b/usr.sbin/pkg_install/sign/README
@@ -1,21 +1,36 @@
To sign packages in a transparent way:
-gzip files can handle an EXTRA_FIELD at the beginning that
+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 put a specific cookie `S, i, g, P, G, P, length'
-at the beginning of the extra-field, so that eventually we can put
-more information in that field (like several signatures),
-followed by the signature output by PGP.
+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.
-The checker just needs to extract the signature, pass it off to PGP,
-followed by the uncompressed archive.
+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 that just look like normal .tar.gz files,
+* 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 $
diff --git a/usr.sbin/pkg_install/sign/check.c b/usr.sbin/pkg_install/sign/check.c
index 1799b438ff3..435a03026d7 100644
--- a/usr.sbin/pkg_install/sign/check.c
+++ b/usr.sbin/pkg_install/sign/check.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: check.c,v 1.1 1999/09/27 21:40:03 espie Exp $ */
+/* $OpenBSD: check.c,v 1.2 1999/10/04 21:46:27 espie Exp $ */
/*-
* Copyright (c) 1999 Marc Espie.
*
@@ -32,77 +32,20 @@
#include <sys/types.h>
#include <sys/wait.h>
#include <stdlib.h>
-#include <unistd.h>
#include <stdio.h>
-#include <fcntl.h>
-#include <paths.h>
-#include <errno.h>
#include "stand.h"
#include "pgp.h"
#include "gzip.h"
#include "extern.h"
-#ifndef _PATH_DEVNULL
-#define _PATH_DEVNULL "/dev/null"
-#endif
-
-typedef /*@observer@*/char *pchar;
-
-static void
-gzcat(fdin, fdout, envp)
- int fdin, fdout;
- char *envp[];
-{
- pchar argv[2];
-
- argv[0] = GZCAT;
- argv[1] = NULL;
- if (dup2(fdin, fileno(stdin)) == -1 ||
- dup2(fdout, fileno(stdout)) == -1 ||
- execve(GZCAT, argv, envp) == -1)
- exit(errno);
-}
-
-static void
-pgpcheck(fd, userid, envp)
- int fd;
- const char *userid;
- char *envp[];
-{
- int fdnull;
- pchar argv[6];
-
- argv[0] = PGP;
- argv[1] = "+batchmode";
- argv[2] = "-f";
-
- if (userid) {
- argv[3] = "-u";
- argv[4] = (char *)userid;
- argv[5] = NULL;
- } else
- argv[3] = NULL;
-
- fdnull = open(_PATH_DEVNULL, O_RDWR);
- if (fdnull == -1 ||
- dup2(fd, fileno(stdin)) == -1 ||
- dup2(fdnull, fileno(stdout)) == -1 ||
- execve(PGP, argv, envp) == -1)
- exit(errno);
-}
-
-static int
-reap(pid)
- pid_t pid;
-{
- pid_t result;
- int pstat;
+struct checker {
+ void *context;
+ void (*add)(void *, const char *, size_t);
+ int (*get)(void *);
+ int status;
+};
- do {
- result = waitpid(pid, &pstat, 0);
- } while (result == -1 && errno == EINTR);
- return result == -1 ? -1 : pstat;
-}
+#define MAX_CHECKERS 20
int
check_signature(file, userid, envp, filename)
@@ -111,96 +54,53 @@ check_signature(file, userid, envp, filename)
char *envp[];
/*@observer@*/const char *filename;
{
- FILE *file2;
- int c;
- char sign[SIGNSIZE];
+ struct signature *sign;
struct mygzip_header h;
int status;
- int togzcat[2], topgpcheck[2];
- pid_t pgpid, gzcatid;
+ 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);
+ status = read_header_and_diagnose(file, &h, &sign, filename);
if (status != 1)
return PKG_UNSIGNED;
- if (pipe(topgpcheck) == -1) {
- fprintf(stderr, "Error creating pipe\n");
- return PKG_SIGERROR;
- }
- switch(pgpid = fork()) {
- case -1:
- fprintf(stderr, "Error creating pgp process\n");
- return PKG_SIGERROR;
- case 0:
- if (close(topgpcheck[1]) == -1)
- exit(errno);
- pgpcheck(topgpcheck[0], userid, envp);
- /*@notreached@*/
- break;
- default:
- (void)close(topgpcheck[0]);
- break;
- }
- if (write(topgpcheck[1], sign, sizeof(sign)) != sizeof(sign)) {
- fprintf(stderr, "Error writing to pgp pipe\n");
- (void)close(topgpcheck[1]);
- (void)reap(pgpid);
- return PKG_SIGERROR;
- }
- if (pipe(togzcat) == -1) {
- fprintf(stderr, "Error creating pipe\n");
- (void)close(topgpcheck[1]);
- (void)reap(pgpid);
- return PKG_SIGERROR;
- }
- switch (gzcatid=fork()) {
- case -1:
- fprintf(stderr, "Error creating gzcat process\n");
- (void)reap(pgpid);
- return PKG_SIGERROR;
- case 0:
- if (close(togzcat[1]) == -1)
- exit(errno);
- gzcat(togzcat[0], topgpcheck[1], envp);
- /*@notreached@*/
- break;
- default:
- (void)close(topgpcheck[1]);
- (void)close(togzcat[0]);
- }
-
- file2 = fdopen(togzcat[1], "w");
- if (file2 == NULL) {
- (void)close(togzcat[1]);
- (void)reap(gzcatid);
- (void)reap(pgpid);
- fprintf(stderr, "Error turning fd into FILE *\n");
- return PKG_SIGERROR;
- }
-
- if (gzip_write_header(file2, &h, NULL) != 1) {
- (void)fclose(file2);
- (void)reap(pgpid);
- (void)reap(gzcatid);
- fprintf(stderr, "Error writing gzip header\n");
- return PKG_SIGERROR;
- }
- while((c = fgetc(file)) != EOF) {
- if (fputc(c, file2) == EOF) {
- fprintf(stderr, "Problem writing to zcat\n");
- (void)fclose(file2);
- (void)reap(pgpid);
- (void)reap(gzcatid);
- return PKG_SIGERROR;
+ 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_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();
}
-
}
- status = PKG_GOODSIG;
- if (fclose(file2) != 0)
- status = PKG_SIGERROR;
- if (reap(gzcatid) != 0)
- status = PKG_SIGERROR;
- if (reap(pgpid) != 0)
- status = PKG_BADSIG;
- return status;
+ 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;
}
+
diff --git a/usr.sbin/pkg_install/sign/common.c b/usr.sbin/pkg_install/sign/common.c
index adc58b69565..d46629e57ff 100644
--- a/usr.sbin/pkg_install/sign/common.c
+++ b/usr.sbin/pkg_install/sign/common.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: common.c,v 1.1 1999/09/27 21:40:03 espie Exp $ */
+/* $OpenBSD: common.c,v 1.2 1999/10/04 21:46:27 espie Exp $ */
/*-
* Copyright (c) 1999 Marc Espie.
*
@@ -29,8 +29,11 @@
*/
#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"
@@ -41,7 +44,7 @@ int
read_header_and_diagnose(file, h, sign, filename)
FILE *file;
struct mygzip_header *h;
- char sign[];
+ struct signature **sign;
const char *filename;
{
switch(gzip_read_header(file, h, sign)) {
@@ -69,20 +72,82 @@ read_header_and_diagnose(file, h, sign, filename)
}
}
-/* Check command existence */
-int check_helpers()
+struct reg_fd {
+ int fd;
+ pid_t pid;
+ struct reg_fd *next;
+};
+
+static struct reg_fd *first = NULL;
+
+void
+register_pipe(fd, pid)
+ int fd;
+ pid_t pid;
{
- struct stat sbuf;
+ struct reg_fd *n;
- if (stat(GZCAT, &sbuf) == -1) {
- fprintf(stderr, "Tool %s does not exist\n", GZCAT);
- return 0;
+ n = malloc(sizeof *n);
+ if (n) {
+ n->fd = fd;
+ n->pid = pid;
+ n->next = first;
+ first = n;
}
- if (stat(PGP, &sbuf) == -1) {
- fprintf(stderr, "Tool %s does not exist\n", PGP);
- return 0;
+}
+
+void
+close_dangling_pipes()
+{
+ while (first) {
+ close(first->fd);
+ first = first->next;
}
- return 1;
}
+static struct reg_fd *
+retrieve_reg(fd)
+ int fd;
+{
+ struct reg_fd **i, *cur;
+
+ for (i = &first; *i ; i = &((*i)->next))
+ if ((*i)->fd == fd)
+ break;
+ cur = *i;
+ *i = cur->next;
+ return cur;
+}
+
+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;
+}
+
+/* kill process and reap status
+ */
+int
+terminate_pipe(fd)
+ int fd;
+{
+ pid_t result;
+ int close_result;
+ struct reg_fd *cur;
+
+ cur = retrieve_reg(fd);
+ if (!cur)
+ return -1;
+ close_result = close(cur->fd);
+ result = reap(cur->pid);
+ free(cur);
+ return close_result == -1 ? -1 : result;
+}
diff --git a/usr.sbin/pkg_install/sign/extern.h b/usr.sbin/pkg_install/sign/extern.h
index 7cc86239a6b..202f7c378bc 100644
--- a/usr.sbin/pkg_install/sign/extern.h
+++ b/usr.sbin/pkg_install/sign/extern.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: extern.h,v 1.1 1999/09/27 21:40:03 espie Exp $ */
+/* $OpenBSD: extern.h,v 1.2 1999/10/04 21:46:27 espie Exp $ */
/*-
* Copyright (c) 1999 Marc Espie.
*
@@ -28,23 +28,56 @@
* 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;
+
+/* 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));
-extern int read_header_and_diagnose
- __P((FILE *file, /*@out@*/struct mygzip_header *h, /*@null@*/char sign[], const char *filename));
-extern int check_helpers __P((void));
+extern int terminate_pipe __P((int fd));
+extern void close_dangling_pipes __P((void));
+extern void register_pipe __P((int fd, pid_t pid));
-extern int sign
- __P((/*@observer@*/const char *filename, /*@null@*/const char *userid, char *envp[]));
-extern int check_signature
- __P((/*@dependent@*/FILE *file, /*@null@*/const char *userid, char *envp[], /*@observer@*/const char *filename));
-extern void handle_passphrase __P((void));
+/* 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 simple_check __P((const char *pkg_name));
+extern int retrieve_sha1_marker __P((const char *filename, \
+ struct signature **sign, const char *userid));
diff --git a/usr.sbin/pkg_install/sign/gzip.c b/usr.sbin/pkg_install/sign/gzip.c
index 03132d83bf6..abebee5a767 100644
--- a/usr.sbin/pkg_install/sign/gzip.c
+++ b/usr.sbin/pkg_install/sign/gzip.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: gzip.c,v 1.2 1999/10/01 01:14:38 espie Exp $ */
+/* $OpenBSD: gzip.c,v 1.3 1999/10/04 21:46:28 espie Exp $ */
/*-
* Copyright (c) 1999 Marc Espie.
*
@@ -30,113 +30,284 @@
#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"
-/* For now, signatures follow a hardcoded format
+/* Signatures follow a simple format
(endianess was chosen to conform to gzip header format)
*/
-static char tagsign[] =
- {'S', 'i', 'g', 'P', 'G', 'P',
- (char)(SIGNSIZE /256), (char)(SIGNSIZE & 255) };
-/* retrieve a gzip header, including PGP signatures */
-int
-gzip_read_header(f, h, sign)
- FILE *f;
- struct mygzip_header *h;
- char sign[];
+SIGNTAG known_tags[KNOWN_TAGS] = {
+ {'S', 'I', 'G', 'P', 'G', 'P', 0, 0 },
+ {'C', 'K', 'S', 'H', 'A', '1', 0, 0 },
+ {'S', 'i', 'g', 'P', 'G', 'P', 0, 0 } /* old format */
+};
+
+void
+sign_fill_tag(sign)
+ struct signature *sign;
{
- {
- int c, d;
+ 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];
+}
- c = fgetc(f);
- d = fgetc(f);
- if ((unsigned char)c != (unsigned char)GZIP_MAGIC0
- || (unsigned char)d != (unsigned char)GZIP_MAGIC1)
- return GZIP_NOT_GZIP;
+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;
}
- {
- int method, flags;
-
- method = fgetc(f);
- flags = fgetc(f);
+ 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;
+}
- if (method == EOF || flags == EOF || fread(h->stamp, 1, 6, f) != 6)
- return GZIP_NOT_GZIP;
- h->method = (char)method;
- h->flags = (char)flags;
+
+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 GZIP_NOT_GZIP;
- if ((h->flags & EXTRA_FIELD) != 0) {
- char match[sizeof(tagsign)];
- unsigned int len;
+ 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_PGPSIGNED;
- len = (unsigned)c;
+ return GZIP_NOT_GZIP;
+ h->remaining = (unsigned)c;
c = fgetc(f);
if (c == EOF)
return GZIP_NOT_PGPSIGNED;
- len |= ((unsigned) c) << 8;
- if (len != sizeof(tagsign) + SIGNSIZE)
- return GZIP_NOT_PGPSIGNED;
- if (fread(match, 1, sizeof(match), f) != sizeof(match) ||
- memcmp(match, tagsign, sizeof(match)) != 0)
- return GZIP_NOT_PGPSIGNED;
- if (sign != NULL) {
- if (fread(sign, 1, SIGNSIZE, f) == SIGNSIZE)
- return GZIP_SIGNED;
- else
- return GZIP_NOT_PGPSIGNED;
- } else {
- if (fseek(f, SIGNSIZE, SEEK_CUR) != -1)
+ 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;
- else
- return GZIP_NOT_PGPSIGNED;
}
- } else
- return GZIP_UNSIGNED;
+ 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 PGP signature */
+/* write a gzip header, including signatures */
int
gzip_write_header(f, h, sign)
FILE *f;
const struct mygzip_header *h;
- const char sign[];
+ 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;
- flags = h->flags;
-
- if (sign != NULL)
- flags |= EXTRA_FIELD;
- else
- flags &= ~EXTRA_FIELD;
- if (fputc(GZIP_MAGIC0, f) == EOF ||
- fputc(GZIP_MAGIC1, f) == EOF ||
- fputc(h->method, f) == EOF ||
- fputc(flags, f) == EOF ||
- fwrite(h->stamp, 1, 6, f) != 6)
- return 0;
+ 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)
- if (fwrite(h->part, 1, 2, f) != 2)
- return 0;
- if (sign != NULL) {
- unsigned short len = sizeof(tagsign) + SIGNSIZE;
- if (fputc(len & 255, f) == EOF ||
- fputc(len/256, f) == EOF ||
- fwrite(tagsign, 1, sizeof(tagsign), f) != sizeof(tagsign) ||
- fwrite(sign, 1, SIGNSIZE, f) != SIGNSIZE)
- return 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;
+ }
+}
diff --git a/usr.sbin/pkg_install/sign/gzip.h b/usr.sbin/pkg_install/sign/gzip.h
index 13db86fa40d..dc3267ea5c8 100644
--- a/usr.sbin/pkg_install/sign/gzip.h
+++ b/usr.sbin/pkg_install/sign/gzip.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: gzip.h,v 1.1 1999/09/27 21:40:04 espie Exp $ */
+/* $OpenBSD: gzip.h,v 1.2 1999/10/04 21:46:28 espie Exp $ */
/*-
* Copyright (c) 1999 Marc Espie.
*
@@ -38,26 +38,52 @@
This structure should not be fiddled with outside of gzip_read_header
and gzip_write_header
*/
-struct mygzip_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@*/char sign[]));
+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@*/const char sign[]));
-
-#ifndef GZCAT
-#define GZCAT "/usr/bin/gzcat"
-#endif
+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 3
+#define TAG_PGP 0
+#define TAG_SHA1 1
+#define TAG_OLD 2
+#define TAG_ANY -1
+#define pgptag (known_tags[TAG_PGP])
+#define sha1tag (known_tags[TAG_SHA1])
+extern SIGNTAG known_tags[KNOWN_TAGS];
diff --git a/usr.sbin/pkg_install/sign/main.c b/usr.sbin/pkg_install/sign/main.c
index 2792f1ad816..bb444a9919c 100644
--- a/usr.sbin/pkg_install/sign/main.c
+++ b/usr.sbin/pkg_install/sign/main.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: main.c,v 1.1 1999/09/27 21:40:04 espie Exp $ */
+/* $OpenBSD: main.c,v 1.2 1999/10/04 21:46:28 espie Exp $ */
/*-
* Copyright (c) 1999 Marc Espie.
*
@@ -29,12 +29,14 @@
*/
#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__
@@ -56,9 +58,11 @@ usage()
#define SIGN 0
#define CHECK 1
+/* wrapper for the check_signature function (open file if needed) */
static int
-check(filename, userid, envp)
+check(filename, type, userid, envp)
/*@observer@*/const char *filename;
+ int type;
/*@null@*/const char *userid;
char *envp[];
{
@@ -73,9 +77,12 @@ check(filename, userid, envp)
return 0;
}
result = check_signature(file, userid, envp, filename);
- if (fclose(file) == 0)
- return result;
- else
+ if (fclose(file) == 0) {
+ if (result == PKG_BADSIG || result == PKG_SIGERROR)
+ return 0;
+ else
+ return 1;
+ } else
return 0;
}
@@ -90,7 +97,11 @@ main(argc, argv, envp)
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
@@ -106,10 +117,16 @@ main(argc, argv, envp)
mode = CHECK;
#endif
- if (check_helpers() == 0)
- exit(EXIT_FAILURE);
- while ((ch = getopt(argc, argv, "u:sc")) != -1) {
+ while ((ch = getopt(argc, argv, "u:t:sc")) != -1) {
switch(ch) {
+ case 't':
+ if (strcmp(optarg, "pgp") == 0)
+ type = TAG_PGP;
+ else if (strcmp(optarg, "sha1") == 0)
+ type = TAG_SHA1;
+ else
+ usage();
+ break;
case 'u':
userid = strdup(optarg);
break;
@@ -135,10 +152,12 @@ main(argc, argv, envp)
}
#ifndef CHECKER_ONLY
- if (mode == SIGN)
- handle_passphrase();
+ 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], userid, envp);
+ success &= (mode == SIGN ? sign : check)(argv[i], type, userid, envp);
exit(success == 1 ? EXIT_SUCCESS : EXIT_FAILURE);
}
diff --git a/usr.sbin/pkg_install/sign/pgp.h b/usr.sbin/pkg_install/sign/pgp.h
index cf91474e1c9..4487ce413aa 100644
--- a/usr.sbin/pkg_install/sign/pgp.h
+++ b/usr.sbin/pkg_install/sign/pgp.h
@@ -1,7 +1,24 @@
-/* $OpenBSD: pgp.h,v 1.1 1999/09/27 21:40:04 espie Exp $ */
-/* Hardcode size of a pgp signature */
-#define SIGNSIZE 168
+/* $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[]));
diff --git a/usr.sbin/pkg_install/sign/pgp_check.c b/usr.sbin/pkg_install/sign/pgp_check.c
new file mode 100644
index 00000000000..7615615a162
--- /dev/null
+++ b/usr.sbin/pkg_install/sign/pgp_check.c
@@ -0,0 +1,193 @@
+/* $OpenBSD: pgp_check.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 <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;
+
+ close_dangling_pipes();
+ setsid();
+ 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];
+ pid_t pgpid;
+
+ 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(pgpid = 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];
+ register_pipe(n->fdout, pgpid);
+#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 (terminate_pipe(n->fdout) != 0)
+ status = PKG_BADSIG;
+ free(n);
+ return status;
+}
diff --git a/usr.sbin/pkg_install/sign/pgp_sign.c b/usr.sbin/pkg_install/sign/pgp_sign.c
new file mode 100644
index 00000000000..8997769450a
--- /dev/null
+++ b/usr.sbin/pkg_install/sign/pgp_sign.c
@@ -0,0 +1,266 @@
+/* $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/types.h>
+#include <stdlib.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";
+
+ 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;
+
+ /* 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.
+ */
+ for(;;) {
+ char c = '\n';
+ (void)write(fd[1], p, strlen(p));
+ (void)write(fd[1], &c, 1);
+ }
+ }
+ default:
+ {
+ char buf[10];
+
+ (void)close(fd[1]);
+ (void)sprintf(buf, "%d", fd[0]);
+ (void)setenv("PGPPASSFD", buf, 1);
+ }
+ }
+}
+
diff --git a/usr.sbin/pkg_install/sign/pkg_sign.1 b/usr.sbin/pkg_install/sign/pkg_sign.1
index 2f46b9ca094..a3b19eae961 100644
--- a/usr.sbin/pkg_install/sign/pkg_sign.1
+++ b/usr.sbin/pkg_install/sign/pkg_sign.1
@@ -1,4 +1,4 @@
-.\" $OpenBSD: pkg_sign.1,v 1.1 1999/09/27 21:40:04 espie Exp $
+.\" $OpenBSD: pkg_sign.1,v 1.2 1999/10/04 21:46:29 espie Exp $
.\" Copyright (c) 1999 Marc Espie.
.\"
.\" Redistribution and use in source and binary forms, with or without
@@ -36,28 +36,44 @@
.Sh SYNOPSIS
.Nm pkg_sign
.Op Fl sc
-.Op Fl u Ar userid
+.Op Fl t Ar type
+.Op Fl u Ar id
.Op Ar
.Nm pkg_check
.Op Fl sc
-.Op Fl u Ar userid
+.Op Fl u Ar id
.Op Ar
.Sh DESCRIPTION
.Nm pkg_sign
-embeds a cryptographic signature (currently PGP) within a gzip file
+embeds a cryptographic signature within a gzip file
.Ar file .
-It will always prompt you for a passphrase to unlock your private pgp key,
-even if you don't use a passphrase (which is a bad idea, anyway).
-.Nm pkg_check
-cheks that cryptographic signature.
+.Ar type
+can be
+.Li pgp
+(default) or
+.Li
+sha1 .
+If
+.Ar type
+is
+.Li pgp ,
+it will always prompt you for a passphrase to unlock your private
+pgp key, even if you don't use a passphrase (which is a bad idea, anyway).
+If
+.Ar type
+is
+.Li sha1 ,
+you must supply an
+.Ar id,
+which will be recorded as the name of the package, and printed as the
+SHA1 checksum.
.Pp
-This 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 OpenBSD signing scheme uses `SigPGP\\0\\xa8'
-as a magic number for its signature (this marker is conveniently 8 bytes
-long, and the `\\0\\xa8' is the length of the pgp signature proper).
+.Nm pkg_check
+checks that cryptographic signature. It currently disregards
+.Ar type
+and checks only the topmost signature. For 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
@@ -65,8 +81,8 @@ and
.Fl c
can be used to force package signing or signature checking mode.
.Pp
-The
-.Ar userid
+For pgp, the
+.Ar id
to use to sign the package or verify the signature can be forced with
.Fl u .
.Pp
@@ -77,6 +93,15 @@ is a single dash
or absent,
.Nm check_sign
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 OpenBSD signing scheme uses eight bytes markers such `SIGPGP' \+ length
+or `CKSHA1' \+ length for its signatures (those markers are conveniently
+eight bytes long).
.Sh RESULTS
.Nm pkg_sign
and
@@ -99,6 +124,9 @@ This is an unsigned package.
The program couldn't 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 BUGS
.Xr pgp 1
@@ -116,8 +144,7 @@ that pgp expects on the fly.
Paths to
.Nm pgp
and
-.Nm gzcat
-are hard-coded to avoid tampering and hinder flexibility.
+the checksum file are hard-coded to avoid tampering and hinder flexibility.
.Sh FILES
.Bl -tag -width "/usr/local/bin/pgp" -compact
.It Pa file.sign
@@ -128,11 +155,11 @@ from
.It Pa /usr/local/bin/pgp
Default path to
.Xr pgp 1 .
-.It Pa /usr/bin/gzcat
-Default path to
-.Xr gzcat 1 .
+.It Pa /var/db/pkgs/SHA1
+Recorded checksums.
.El
.Sh SEE ALSO
+.Xr gzip 1 ,
.Xr pgp 1 ,
.Xr pkg_add 1 ,
-.Xr gzip 1
+.Xr sha1 1
diff --git a/usr.sbin/pkg_install/sign/sha1.c b/usr.sbin/pkg_install/sign/sha1.c
new file mode 100644
index 00000000000..796b8cce664
--- /dev/null
+++ b/usr.sbin/pkg_install/sign/sha1.c
@@ -0,0 +1,212 @@
+/* $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/types.h>
+#include <sys/wait.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <assert.h>
+#include <sha1.h>
+#include "stand.h"
+#include "gzip.h"
+#include "extern.h"
+
+
+/* private context for sha1 signature checker */
+struct sha1_checker {
+ SHA1_CTX context;
+ const char *id;
+ const char *filename;
+};
+
+
+#define SHA1_TEMPLATE "SHA1 (%s) = "
+#define BUFSIZE (MAXID+sizeof(SHA1_TEMPLATE)+2*SHA1_DIGESTSIZE+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;
+
+ sprintf(result, "SHA1 (%s) = ", n->id);
+ length = strlen(result);
+ SHA1End(&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;
+ }
+ SHA1Init(&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;
+ SHA1Update(&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;
+ struct sha1_checker *checker;
+ struct signature *old;
+
+ *sign = NULL;
+ if (userid == NULL)
+ return 0;
+
+ n = malloc(sizeof *n);
+ if (n == NULL)
+ return 0;
+ n->data = (char *)userid;
+ n->length = strlen(n->data)+1;
+ n->type = TAG_SHA1;
+ memcpy(n->tag, sha1tag, sizeof sha1tag);
+ sign_fill_tag(n);
+
+ 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;
+
+ checker = new_sha1_checker(&h, *sign, NULL, NULL, filename);
+ 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;
+}
+
diff --git a/usr.sbin/pkg_install/sign/sign.c b/usr.sbin/pkg_install/sign/sign.c
index 953dd5e867e..ea1cf554971 100644
--- a/usr.sbin/pkg_install/sign/sign.c
+++ b/usr.sbin/pkg_install/sign/sign.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: sign.c,v 1.2 1999/09/28 21:31:23 espie Exp $ */
+/* $OpenBSD: sign.c,v 1.3 1999/10/04 21:46:29 espie Exp $ */
/*-
* Copyright (c) 1999 Marc Espie.
*
@@ -31,60 +31,28 @@
#include <stdlib.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 SIGN_TEMPLATE "%s %s | %s +batchmode +compress=off -f -s"
-#define SIGN2_TEMPLATE "%s %s | %s +batchmode +compress=off -f -u %s -s"
#define COPY_TEMPLATE "%s.sign"
-static int
-retrieve_signature(filename, sign, userid)
- const char *filename;
- char sign[];
- const char *userid;
-{
- char *buffer;
- FILE *cmd;
-
- if (userid) {
- buffer = malloc(strlen(GZCAT) + strlen(filename) +
- strlen(PGP) + strlen(userid) + sizeof(SIGN2_TEMPLATE));
- if (!buffer)
- return 0;
- sprintf(buffer, SIGN2_TEMPLATE, GZCAT, filename, PGP, userid);
- } else {
- buffer = malloc(strlen(GZCAT) + strlen(filename) +
- strlen(PGP) + sizeof(SIGN_TEMPLATE));
- if (!buffer)
- return 0;
- sprintf(buffer, SIGN_TEMPLATE, GZCAT, filename, PGP);
- }
- cmd = popen(buffer, "r");
- free(buffer);
- if (!cmd)
- return 0;
- if (fread(sign, 1, SIGNSIZE, cmd) != SIGNSIZE)
- return 0;
- (void)pclose(cmd);
- return 1;
-}
-
static int
embed_signature_FILE(orig, dest, sign, filename)
/*@temp@*/FILE *orig;
/*@temp@*/FILE *dest;
- const char sign[];
+ struct signature *sign;
const char *filename;
{
struct mygzip_header h;
int c;
- if (read_header_and_diagnose(orig, &h, NULL, filename) == 0)
+ if (gzip_read_header(orig, &h, NULL) == GZIP_NOT_GZIP)
return 0;
if (gzip_write_header(dest, &h, sign) == 0)
@@ -100,7 +68,7 @@ static int
embed_signature(filename, copy, sign)
const char *filename;
const char *copy;
- const char sign[];
+ struct signature *sign;
{
FILE *orig, *dest;
int success;
@@ -121,22 +89,35 @@ embed_signature(filename, copy, sign)
}
int
-sign(filename, userid, envp)
+sign(filename, type, userid, envp)
const char *filename;
const char *userid;
- /*@unused@*/char *envp[] __attribute__((unused));
+ int type;
+ char *envp[];
{
- char sign[SIGNSIZE];
char *copy;
int result;
+ struct signature *sign;
+ int success;
+
+ 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;
+ }
- if (retrieve_signature(filename, sign, userid) == 0) {
+ 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);
@@ -151,50 +132,7 @@ sign(filename, userid, envp)
result = 0;
}
free(copy);
+ free_signature(sign);
return result;
}
-void
-handle_passphrase()
-{
- pid_t pid;
- int fd[2];
- char *p;
-
- /* 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.
- */
- for(;;) {
- char c = '\n';
- (void)write(fd[1], p, strlen(p));
- (void)write(fd[1], &c, 1);
- }
- }
- default:
- {
- char buf[10];
-
- (void)close(fd[1]);
- (void)sprintf(buf, "%d", fd[0]);
- (void)setenv("PGPPASSFD", buf, 1);
- }
- }
-}
-
diff --git a/usr.sbin/pkg_install/sign/simple_check.c b/usr.sbin/pkg_install/sign/simple_check.c
deleted file mode 100644
index 4156042701f..00000000000
--- a/usr.sbin/pkg_install/sign/simple_check.c
+++ /dev/null
@@ -1,72 +0,0 @@
-/* $OpenBSD: simple_check.c,v 1.1 1999/09/27 21:40:04 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 <stdio.h>
-#include <stdlib.h>
-#include <libgen.h>
-#include "extern.h"
-
-#define CHECKER_STRING "/usr/bin/fgrep \"`cd %s && /bin/sha1 %s`\" /var/db/pkg/SHA1"
-#define CHECKER2_STRING "/usr/bin/fgrep \\(%s\\) /var/db/pkg/SHA1"
-
-int
-simple_check(pkg_name)
- const char *pkg_name;
-{
- int result;
- char *buffer;
- char *dir, *file;
-
- dir = dirname(pkg_name);
- file = basename(pkg_name);
- if (dir == NULL || file == NULL)
- return PKG_SIGERROR;
-
- buffer = malloc(sizeof(CHECKER_STRING)+strlen(dir)+strlen(file));
- if (!buffer)
- return PKG_SIGERROR;
- sprintf(buffer, CHECKER_STRING, dir, file);
- result = system(buffer);
- free(buffer);
- if (result == 0)
- return PKG_GOODSIG;
- buffer = malloc(sizeof(CHECKER2_STRING)+strlen(file));
- if (!buffer)
- return PKG_SIGERROR;
- sprintf(buffer, CHECKER2_STRING, file);
- result = system(buffer);
- free(buffer);
- if (result == 0)
- return PKG_BADSIG;
- else
- return PKG_UNSIGNED;
-}
-
-
diff --git a/usr.sbin/pkg_install/sign/stand.c b/usr.sbin/pkg_install/sign/stand.c
new file mode 100644
index 00000000000..4788a79ced3
--- /dev/null
+++ b/usr.sbin/pkg_install/sign/stand.c
@@ -0,0 +1,54 @@
+#include "stand.h"
+
+#ifdef 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
diff --git a/usr.sbin/pkg_install/sign/stand.h b/usr.sbin/pkg_install/sign/stand.h
index f90d9e53477..c411ad3d2ef 100644
--- a/usr.sbin/pkg_install/sign/stand.h
+++ b/usr.sbin/pkg_install/sign/stand.h
@@ -1,7 +1,11 @@
-/* $OpenBSD: stand.h,v 1.1 1999/09/27 21:40:04 espie Exp $ */
+/* $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
@@ -10,6 +14,13 @@
#endif
#endif
+#if defined(BSD4_4)
+#include <err.h>
+#else
+extern void set_program_name __P((const char * name));
+extern void warn __P((const char *fmt, ...));
+extern void warnx __P((const char *fmt, ...));
+#endif
#ifndef __GNUC__
#define __attribute__(x)