summaryrefslogtreecommitdiff
path: root/usr.bin
diff options
context:
space:
mode:
authormarius eriksen <marius@cvs.openbsd.org>2005-05-28 01:57:31 +0000
committermarius eriksen <marius@cvs.openbsd.org>2005-05-28 01:57:31 +0000
commit010931b7acab26046e0adaef4808f43f0a87050f (patch)
tree73441fc9a82db0aca0b0acfbf728d3aff9cc136b /usr.bin
parent25f01a945904da779dc25261b49b8e79b32b6fb9 (diff)
import gzsig by Dug Song.
a bunch of lumberjack work, zapped support for keynote and SSH1 and added support for SSH2 keys. ok millert@ deraadt@
Diffstat (limited to 'usr.bin')
-rw-r--r--usr.bin/gzsig/Makefile10
-rw-r--r--usr.bin/gzsig/extern.h45
-rw-r--r--usr.bin/gzsig/gzip.h107
-rw-r--r--usr.bin/gzsig/gzsig.1113
-rw-r--r--usr.bin/gzsig/gzsig.c64
-rw-r--r--usr.bin/gzsig/key.c216
-rw-r--r--usr.bin/gzsig/key.h57
-rw-r--r--usr.bin/gzsig/sign.c306
-rw-r--r--usr.bin/gzsig/ssh2.c221
-rw-r--r--usr.bin/gzsig/ssh2.h29
-rw-r--r--usr.bin/gzsig/util.c77
-rw-r--r--usr.bin/gzsig/util.h39
-rw-r--r--usr.bin/gzsig/verify.c212
-rw-r--r--usr.bin/gzsig/x509.c137
-rw-r--r--usr.bin/gzsig/x509.h40
15 files changed, 1673 insertions, 0 deletions
diff --git a/usr.bin/gzsig/Makefile b/usr.bin/gzsig/Makefile
new file mode 100644
index 00000000000..8b6f0cb7db1
--- /dev/null
+++ b/usr.bin/gzsig/Makefile
@@ -0,0 +1,10 @@
+# $OpenBSD: Makefile,v 1.1 2005/05/28 01:57:30 marius Exp $
+
+PROG = gzsig
+SRCS = gzsig.c key.c sign.c ssh2.c util.c verify.c x509.c
+
+LDADD = -lcrypto -lm
+
+CLEANFILES += TAGS *~
+
+.include <bsd.prog.mk>
diff --git a/usr.bin/gzsig/extern.h b/usr.bin/gzsig/extern.h
new file mode 100644
index 00000000000..eb43b1e1c3e
--- /dev/null
+++ b/usr.bin/gzsig/extern.h
@@ -0,0 +1,45 @@
+/*
+ * extern.h
+ *
+ * Copyright (c) 2001 Dug Song <dugsong@arbor.net>
+ * Copyright (c) 2001 Arbor Networks, Inc.
+ *
+ * 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. The names of the copyright holders may not be used to endorse or
+ * promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED ``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 AUTHOR 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.
+ *
+ * $Id: extern.h,v 1.1 2005/05/28 01:57:30 marius Exp $
+ */
+
+#ifndef EXTERN_H
+#define EXTERN_H
+
+void sign(int argc, char *argv[]);
+void verify(int argc, char *argv[]);
+
+int sign_passwd_cb(char *buf, int size, int rwflag, void *u);
+
+void sign_usage(void);
+void verify_usage(void);
+
+#endif /* EXTERN_H */
diff --git a/usr.bin/gzsig/gzip.h b/usr.bin/gzsig/gzip.h
new file mode 100644
index 00000000000..11f0b2c65bb
--- /dev/null
+++ b/usr.bin/gzsig/gzip.h
@@ -0,0 +1,107 @@
+/*
+ * gzip.h
+ *
+ * Copyright (c) 2001 Dug Song <dugsong@arbor.net>
+ * Copyright (c) 2001 Arbor Networks, Inc.
+ *
+ * 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. The names of the copyright holders may not be used to endorse or
+ * promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED ``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 AUTHOR 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.
+ *
+ * $Id: gzip.h,v 1.1 2005/05/28 01:57:30 marius Exp $
+ */
+
+#ifndef GZIP_H
+#define GZIP_H
+
+/* RFC 1952 is b0rked! This is from gzip-1.2.4's algorithm.doc... */
+
+/* Magic header */
+#define GZIP_MAGIC "\037\213"
+
+/* Compression methods */
+#define GZIP_MSTORED 0
+#define GZIP_MCOMPRESS 1
+#define GZIP_MPACKED 2
+#define GZIP_MLZHED 3
+#define GZIP_MDEFLATE 8
+
+/* Flags */
+#define GZIP_FTEXT 0x01
+#define GZIP_FCONT 0x02 /* never set by gzip-1.2.4 */
+#define GZIP_FEXTRA 0x04
+#define GZIP_FNAME 0x08
+#define GZIP_FCOMMENT 0x10
+#define GZIP_FENCRYPT 0x20
+#define GZIP_FRESERVED 0xC0
+
+#define GZIP_FENCRYPT_LEN 12
+
+#define GZSIG_ID "GS"
+#define GZSIG_VERSION 1
+
+struct gzsig_data {
+ u_char version;
+#ifdef COMMENT_ONLY
+ u_char signature[];
+#endif
+};
+
+/*
+ * Note: all number fields below are in little-endian byte order.
+ */
+
+struct gzip_xfield {
+ u_short len;
+ struct gzip_subfield {
+ u_char id[2];
+ u_short len;
+#ifdef COMMENT_ONLY
+ u_char data[];
+#endif
+ } subfield;
+};
+
+struct gzip_header {
+ u_char magic[2];
+ u_char method;
+ u_char flags;
+ u_char mtime[4];
+ u_char xflags;
+ u_char os;
+#if COMMENT_ONLY
+ /* Optional fields */
+ u_char part[2]; /* flags & GZIP_FCONT */
+ struct gzip_xfield xfield; /* flags & GZIP_FEXTRA */
+ char filename[]; /* flags & GZIP_FNAME */
+ char comment[]; /* flags & GZIP_FCOMMENT */
+ u_char encrypt_hdr[12]; /* flags & GZIP_FENCRYPT */
+#endif
+};
+
+struct gzip_trailer {
+ u_int32_t crc32[4];
+ u_int32_t size[4];
+};
+
+#endif /* GZIP_H */
diff --git a/usr.bin/gzsig/gzsig.1 b/usr.bin/gzsig/gzsig.1
new file mode 100644
index 00000000000..56a29f76d2d
--- /dev/null
+++ b/usr.bin/gzsig/gzsig.1
@@ -0,0 +1,113 @@
+.\" $OpenBSD: gzsig.1,v 1.1 2005/05/28 01:57:30 marius Exp $
+.\" $Id: gzsig.1,v 1.1 2005/05/28 01:57:30 marius Exp $
+.\"
+.\" Copyright (c) 2001 Dug Song <dugsong@arbor.net>
+.\" Copyright (c) 2001 Arbor Networks, Inc.
+.\"
+.\" 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. The names of the copyright holders may not be used to endorse or
+.\" promote products derived from this software without specific
+.\" prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED ``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 AUTHOR 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 July 6, 2001
+.Dt GZSIG 1
+.Sh NAME
+.Nm gzsig
+.Nd gzip signing utility
+.Sh SYNOPSIS
+.Nm gzsig sign
+.Op Fl v
+.Ar privkey
+.Op Ar
+.Pp
+.Nm gzsig verify
+.Op Fl v
+.Ar pubkey
+.Op Ar
+.Sh DESCRIPTION
+.Nm
+embeds or verifies RSA PKCS #1 v2.0 or DSA SHA1 signatures in
+.Xr gzip 1
+compressed files using SSH2 identity keys or X509 certificates.
+.Pp
+The
+.Ar file
+operands are processed in command-line order. If
+.Ar file
+is a single dash
+.Pq Sq \&-
+or absent,
+.Nm
+reads from the standard input.
+.Pp
+The options are as follows:
+.Bl -tag -width Ds
+.It Nm sign
+Sign the input using the private key in
+.Ar privkey .
+.It Nm verify
+Verify the signature using the public key in
+.Ar pubkey .
+.It Fl v
+Enable verbose mode.
+.It Fl p
+Supply a passphrase for decrypting private keys when signing.
+.El
+.Pp
+The
+.Nm
+utility exits 0 on success or >0 if an error occured.
+.Sh EXAMPLES
+.Cm gzsign sign ~/.ssh/id_rsa file1 file2
+.Pp
+Sign
+.Ar file1
+and
+.Ar file2
+with the SSH2 identity key in
+.Ar ~/.ssh/id_rsa .
+.Pp
+.Cm gzsign sign ~/.ssh/id_rsa < file1 > file2
+.Pp
+Sign
+.Ar file1
+with the SSH2 identity key, saving the signed file in
+.Ar file2 .
+.Pp
+.Cm gzsign verify /etc/ssl/server.crt < file1
+.Pp
+Verify the signature on
+.Ar file1
+using the SSL certificate in
+.Ar /etc/ssl/server.crt .
+.Pp
+.Sh SEE ALSO
+.Xr gzip 1 ,
+.Xr ssh-keygen 1 ,
+.Xr ssl 8
+.Sh AUTHORS
+Dug Song
+.Aq dugsong@arbor.net
+.Pp
+SSH2 support by
+Marius Eriksen
+.Aq marius@openbsd.org
diff --git a/usr.bin/gzsig/gzsig.c b/usr.bin/gzsig/gzsig.c
new file mode 100644
index 00000000000..0ebf4c34584
--- /dev/null
+++ b/usr.bin/gzsig/gzsig.c
@@ -0,0 +1,64 @@
+/* $OpenBSD: gzsig.c,v 1.1 2005/05/28 01:57:30 marius Exp $ */
+
+/*
+ * gzsig.c
+ *
+ * Copyright (c) 2001 Dug Song <dugsong@arbor.net>
+ * Copyright (c) 2001 Arbor Networks, Inc.
+ *
+ * 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. The names of the copyright holders may not be used to endorse or
+ * promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED ``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 AUTHOR 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.
+ *
+ * $Id: gzsig.c,v 1.1 2005/05/28 01:57:30 marius Exp $
+ */
+
+#include <stdio.h>
+#include <string.h>
+
+#include "extern.h"
+
+static void
+usage(void)
+{
+ sign_usage();
+ verify_usage();
+ exit(1);
+}
+
+int
+main(int argc, char *argv[])
+{
+ if (argc < 2)
+ usage();
+
+ if (strcmp(argv[1], "sign") == 0) {
+ sign(argc - 1, argv + 1);
+ } else if (strcmp(argv[1], "verify") == 0) {
+ verify(argc - 1, argv + 1);
+ } else {
+ usage();
+ }
+
+ exit(0);
+}
diff --git a/usr.bin/gzsig/key.c b/usr.bin/gzsig/key.c
new file mode 100644
index 00000000000..b7909384e88
--- /dev/null
+++ b/usr.bin/gzsig/key.c
@@ -0,0 +1,216 @@
+/* $OpenBSD: key.c,v 1.1 2005/05/28 01:57:30 marius Exp $ */
+
+/*
+ * key.c
+ *
+ * Copyright (c) 2001 Dug Song <dugsong@arbor.net>
+ * Copyright (c) 2001 Arbor Networks, Inc.
+ *
+ * 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. The names of the copyright holders may not be used to endorse or
+ * promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED ``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 AUTHOR 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.
+ *
+ * $Id: key.c,v 1.1 2005/05/28 01:57:30 marius Exp $
+ */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/uio.h>
+
+#include <openssl/ssl.h>
+
+#include <errno.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#include "key.h"
+#include "ssh2.h"
+#include "util.h"
+#include "x509.h"
+
+typedef int (*key_loader)(struct key *, struct iovec *);
+
+static key_loader pubkey_loaders[] = {
+ ssh2_load_public,
+ x509_load_public,
+ NULL
+};
+
+static key_loader privkey_loaders[] = {
+ x509_load_private,
+ NULL
+};
+
+static int
+load_file(struct iovec *iov, char *filename)
+{
+ struct stat st;
+ int fd;
+
+ if ((fd = open(filename, O_RDONLY)) < 0)
+ return (-1);
+
+ if (fstat(fd, &st) < 0)
+ return (-1);
+
+ if (st.st_size == 0) {
+ errno = EINVAL;
+ return (-1);
+ }
+ if ((iov->iov_base = malloc(st.st_size + 1)) == NULL)
+ return (-1);
+
+ iov->iov_len = st.st_size;
+ ((u_char *)iov->iov_base)[iov->iov_len] = '\0';
+
+ if (read(fd, iov->iov_base, iov->iov_len) != iov->iov_len) {
+ free(iov->iov_base);
+ return (-1);
+ }
+ close(fd);
+
+ return (0);
+}
+
+struct key *
+key_new(void)
+{
+ struct key *k;
+
+ if ((k = calloc(sizeof(*k), 1)) == NULL)
+ return (NULL);
+
+ return (k);
+}
+
+int
+key_load_private(struct key *k, char *filename)
+{
+ struct iovec iov;
+ int i;
+
+ if (load_file(&iov, filename) < 0)
+ return (-1);
+
+ for (i = 0; privkey_loaders[i] != NULL; i++) {
+ if (privkey_loaders[i](k, &iov) == 0)
+ return (0);
+ }
+ return (-1);
+}
+
+int
+key_load_public(struct key *k, char *filename)
+{
+ struct iovec iov;
+ int i;
+
+ if (load_file(&iov, filename) < 0)
+ return (-1);
+
+ for (i = 0; pubkey_loaders[i] != NULL; i++) {
+ if (pubkey_loaders[i](k, &iov) == 0)
+ return (0);
+ }
+ return (-1);
+}
+
+int
+key_sign(struct key *k, u_char *msg, int mlen, u_char *sig, int slen)
+{
+ switch (k->type) {
+ case KEY_RSA:
+ if (RSA_size((RSA *)k->data) > slen) {
+ fprintf(stderr, "RSA modulus too large: %d bits\n",
+ RSA_size((RSA *)k->data));
+ return (-1);
+ }
+ if (RSA_sign(NID_sha1, msg, mlen, sig, &slen,
+ (RSA *)k->data) <= 0) {
+ fprintf(stderr, "RSA signing failed\n");
+ return (-1);
+ }
+ break;
+
+ case KEY_DSA:
+ if (DSA_size((DSA *)k->data) > slen) {
+ fprintf(stderr, "DSA signature size too large: "
+ "%d bits\n", DSA_size((DSA *)k->data));
+ return (-1);
+ }
+ if (DSA_sign(NID_sha1, msg, mlen, sig, &slen,
+ (DSA *)k->data) <= 0) {
+ fprintf(stderr, "DSA signing failed\n");
+ return (-1);
+ }
+ break;
+
+ default:
+ fprintf(stderr, "Unknown key type: %d\n", k->type);
+ return (-1);
+ }
+ return (slen);
+}
+
+int
+key_verify(struct key *k, u_char *msg, int mlen, u_char *sig, int slen)
+{
+ switch (k->type) {
+
+ case KEY_RSA:
+ if (RSA_verify(NID_sha1, msg, mlen,
+ sig, slen, (RSA *)k->data) <= 0) {
+ fprintf(stderr, "RSA verification failed\n");
+ return (-1);
+ }
+ break;
+
+ case KEY_DSA:
+ if (DSA_verify(NID_sha1, msg, mlen,
+ sig, slen, (DSA *)k->data) <= 0) {
+ fprintf(stderr, "DSA verification failed\n");
+ return (-1);
+ }
+ break;
+
+ default:
+ fprintf(stderr, "Unknown key type: %d\n", k->type);
+ return (-1);
+ }
+ return (slen);
+}
+
+void
+key_free(struct key *k)
+{
+ if (k->type == KEY_RSA)
+ RSA_free((RSA *)k->data);
+ else if (k->type == KEY_DSA)
+ DSA_free((DSA *)k->data);
+ else if (k->data != NULL)
+ free(k->data);
+
+ free(k);
+}
diff --git a/usr.bin/gzsig/key.h b/usr.bin/gzsig/key.h
new file mode 100644
index 00000000000..7aac3ad8bb8
--- /dev/null
+++ b/usr.bin/gzsig/key.h
@@ -0,0 +1,57 @@
+/*
+ * key.h
+ *
+ * Copyright (c) 2001 Dug Song <dugsong@arbor.net>
+ * Copyright (c) 2001 Arbor Networks, Inc.
+ *
+ * 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. The names of the copyright holders may not be used to endorse or
+ * promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED ``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 AUTHOR 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.
+ *
+ * $Id: key.h,v 1.1 2005/05/28 01:57:30 marius Exp $
+ */
+
+#ifndef KEY_H
+#define KEY_H
+
+enum key_type {
+ KEY_UNSPEC,
+ KEY_RSA,
+ KEY_DSA
+};
+
+struct key {
+ int type;
+ void *data;
+};
+
+struct key *key_new(void);
+int key_load_public(struct key *k, char *filename);
+int key_load_private(struct key *k, char *filename);
+int key_sign(struct key *k, u_char *msg, int mlen,
+ u_char *sig, int slen);
+int key_verify(struct key *k, u_char *msg, int mlen,
+ u_char *sig, int slen);
+void key_free(struct key *k);
+
+#endif /* KEY_H */
diff --git a/usr.bin/gzsig/sign.c b/usr.bin/gzsig/sign.c
new file mode 100644
index 00000000000..a10e5c28d98
--- /dev/null
+++ b/usr.bin/gzsig/sign.c
@@ -0,0 +1,306 @@
+/* $OpenBSD: sign.c,v 1.1 2005/05/28 01:57:30 marius Exp $ */
+
+/*
+ * sign.c
+ *
+ * Copyright (c) 2001 Dug Song <dugsong@arbor.net>
+ * Copyright (c) 2001 Arbor Networks, Inc.
+ *
+ * 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. The names of the copyright holders may not be used to endorse or
+ * promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED ``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 AUTHOR 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.
+ *
+ * $Id: sign.c,v 1.1 2005/05/28 01:57:30 marius Exp $
+ */
+
+#include <sys/param.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include <openssl/ssl.h>
+#include <openssl/evp.h>
+#include <openssl/sha.h>
+
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "extern.h"
+#include "gzip.h"
+#include "key.h"
+#include "util.h"
+
+static char *passphrase = NULL;
+
+static int
+embed_signature(struct key *key, FILE *fin, FILE *fout)
+{
+ struct gzip_header gh;
+ struct gzip_xfield *gx;
+ struct gzsig_data *gd;
+ u_char *sig, digest[20], buf[8192];
+ SHA_CTX ctx;
+ int i, siglen;
+ long offset;
+
+ /* Read gzip header. */
+ if (fread((u_char *)&gh, 1, sizeof(gh), fin) != sizeof(gh)) {
+ fprintf(stderr, "Error reading gzip header: %s\n",
+ strerror(errno));
+ return (-1);
+ }
+ /* Verify gzip header. */
+ if (memcmp(gh.magic, GZIP_MAGIC, sizeof(gh.magic)) != 0) {
+ fprintf(stderr, "Invalid gzip file\n");
+ return (-1);
+ }
+ if (gh.flags & GZIP_FCONT) {
+ fprintf(stderr, "Multi-part gzip files not supported\n");
+ return (-1);
+ }
+ /* Skip over any existing signature. */
+ if (gh.flags & GZIP_FEXTRA) {
+ gx = (struct gzip_xfield *)buf;
+ gd = (struct gzsig_data *)(gx + 1);
+
+ if (fread((u_char *)gx, 1, sizeof(*gx), fin) != sizeof(*gx)) {
+ fprintf(stderr, "Error reading extra field: %s\n",
+ strerror(errno));
+ return (-1);
+ }
+ if (memcmp(gx->subfield.id, GZSIG_ID, 2) != 0) {
+ fprintf(stderr, "Unknown extra field\n");
+ return (-1);
+ }
+ gx->subfield.len = letoh16(gx->subfield.len);
+
+ if (gx->subfield.len < sizeof(*gd) ||
+ gx->subfield.len > sizeof(buf) - sizeof(*gx)) {
+ fprintf(stderr, "Invalid signature length\n");
+ return (-1);
+ }
+ if (fread((u_char *)gd, 1, gx->subfield.len, fin) !=
+ gx->subfield.len) {
+ fprintf(stderr, "Error reading signature: %s\n",
+ strerror(errno));
+ return (-1);
+ }
+ fprintf(stderr, "Overwriting existing signature\n");
+ }
+ /* Skip over any options. */
+ offset = ftell(fin);
+
+ if (gh.flags & GZIP_FNAME) {
+ while (getc(fin) != '\0')
+ ;
+ }
+ if (gh.flags & GZIP_FCOMMENT) {
+ while (getc(fin) != '\0')
+ ;
+ }
+ if (gh.flags & GZIP_FENCRYPT) {
+ if (fread(buf, 1, GZIP_FENCRYPT_LEN, fin) != GZIP_FENCRYPT_LEN)
+ return (-1);
+ }
+ /* Compute checksum over compressed data and trailer. */
+ SHA1_Init(&ctx);
+
+ while ((i = fread(buf, 1, sizeof(buf), fin)) > 0) {
+ SHA1_Update(&ctx, buf, i);
+ }
+ SHA1_Final(digest, &ctx);
+
+ /* Generate signature. */
+ gx = (struct gzip_xfield *)buf;
+ gd = (struct gzsig_data *)(gx + 1);
+ sig = (u_char *)(gd + 1);
+
+ siglen = key_sign(key, digest, sizeof(digest), sig,
+ sizeof(buf) - (sig - buf));
+
+ if (siglen < 0) {
+ fprintf(stderr, "Error signing checksum\n");
+ return (-1);
+ }
+ i = sizeof(*gd) + siglen;
+ gx->subfield.len = htole16(i);
+ gx->len = htole16(sizeof(gx->subfield) + i);
+ memcpy(gx->subfield.id, GZSIG_ID, sizeof(gx->subfield.id));
+ gd->version = GZSIG_VERSION;
+
+ /* Write out gzip header. */
+ gh.flags |= GZIP_FEXTRA;
+
+ if (fwrite((u_char *)&gh, 1, sizeof(gh), fout) != sizeof(gh)) {
+ fprintf(stderr, "Error writing output: %s\n", strerror(errno));
+ return (-1);
+ }
+ /* Write out signature. */
+ if (fwrite(buf, 1, sizeof(*gx) + i, fout) != sizeof(*gx) + i) {
+ fprintf(stderr, "Error writing output: %s\n", strerror(errno));
+ return (-1);
+ }
+ /* Write out options, compressed data, and trailer. */
+ if (fseek(fin, offset, SEEK_SET) < 0) {
+ fprintf(stderr, "Error writing output: %s\n", strerror(errno));
+ return (-1);
+ }
+ while ((i = fread(buf, 1, sizeof(buf), fin)) > 0) {
+ if (fwrite(buf, 1, i, fout) != i) {
+ fprintf(stderr, "Error writing output: %s\n",
+ strerror(errno));
+ return (-1);
+ }
+ }
+ if (ferror(fin)) {
+ fprintf(stderr, "Error reading input: %s\n", strerror(errno));
+ return (-1);
+ }
+ return (0);
+}
+
+void
+sign_usage(void)
+{
+ fprintf(stderr, "Usage: gzsig sign [-v] privkey [file ...]\n");
+}
+
+int
+sign_passwd_cb(char *buf, int size, int rwflag, void *u)
+{
+ char *p;
+
+ if (passphrase != NULL) {
+ if (strlcpy(buf, passphrase, size) >= size)
+ errx(1, "Passphrase too long");
+ } else {
+ p = getpass("Enter passphrase: ");
+ if (strlcpy(buf, p, size) >= size)
+ errx(1, "Passphrase too long");
+ memset(p, 0, strlen(p));
+ }
+
+ return (strlen(buf));
+}
+
+void
+sign(int argc, char *argv[])
+{
+ struct key *key;
+ char *gzipfile, tmpfile[MAXPATHLEN];
+ FILE *fin, *fout;
+ int i, fd, error, vflag;
+
+ vflag = 0;
+
+ while ((i = getopt(argc, argv, "vh?p:")) != -1) {
+ switch (i) {
+ case 'v':
+ vflag = 1;
+ break;
+ case 'p':
+ passphrase = optarg;
+ break;
+ default:
+ sign_usage();
+ exit(1);
+ }
+ }
+ argc -= optind;
+ argv += optind;
+
+ if (argc < 1) {
+ sign_usage();
+ exit(1);
+ }
+ OpenSSL_add_all_algorithms();
+
+ if ((key = key_new()) == NULL)
+ fatal(1, "Couldn't initialize private key");
+
+ if (key_load_private(key, argv[0]) < 0)
+ fatal(1, "Couldn't load private key");
+
+ if (argc == 1 || *argv[1] == '-') {
+ argc = 0;
+
+ if (embed_signature(key, stdin, stdout) == 0) {
+ if (vflag)
+ fprintf(stderr, "Signed input\n");
+ } else
+ fatal(1, "Couldn't sign input");
+ }
+ for (i = 1; i < argc; i++) {
+ gzipfile = argv[i];
+
+ if ((fin = fopen(gzipfile, "r+")) == NULL) {
+ fprintf(stderr, "Error opening %s: %s\n",
+ gzipfile, strerror(errno));
+ continue;
+ }
+ snprintf(tmpfile, sizeof(tmpfile), "%s.XXXXXX", gzipfile);
+
+ if ((fd = mkstemp(tmpfile)) < 0) {
+ fprintf(stderr, "Error creating %s: %s\n",
+ tmpfile, strerror(errno));
+ fclose(fin);
+ continue;
+ }
+ if ((fout = fdopen(fd, "w")) == NULL) {
+ fprintf(stderr, "Error opening %s: %s\n",
+ tmpfile, strerror(errno));
+ fclose(fin);
+ close(fd);
+ continue;
+ }
+ if (copy_permissions(gzipfile, tmpfile) < 0) {
+ fprintf(stderr, "Error initializing %s: %s\n",
+ tmpfile, strerror(errno));
+ fclose(fin);
+ fclose(fout);
+ continue;
+ }
+ error = embed_signature(key, fin, fout);
+
+ fclose(fin);
+ fclose(fout);
+
+ if (!error) {
+ if (rename(tmpfile, gzipfile) < 0) {
+ unlink(tmpfile);
+ fatal(1, "Couldn't sign %s", gzipfile);
+ }
+ if (vflag)
+ fprintf(stderr, "Signed %s\n", gzipfile);
+ } else {
+ unlink(tmpfile);
+ fatal(1, "Couldn't sign %s", gzipfile);
+ }
+ }
+ key_free(key);
+
+ if (passphrase != NULL)
+ memset(passphrase, 0, strlen(passphrase));
+}
diff --git a/usr.bin/gzsig/ssh2.c b/usr.bin/gzsig/ssh2.c
new file mode 100644
index 00000000000..f508058ca00
--- /dev/null
+++ b/usr.bin/gzsig/ssh2.c
@@ -0,0 +1,221 @@
+/* $OpenBSD: ssh2.c,v 1.1 2005/05/28 01:57:30 marius Exp $ */
+/*
+ * ssh2.c
+ *
+ * Copyright (c) 2005 Marius Eriksen <marius@openbsd.org>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <sys/types.h>
+#include <sys/uio.h>
+
+#include <arpa/nameser.h>
+#include <openssl/ssl.h>
+#include <openssl/des.h>
+#include <openssl/md5.h>
+
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <err.h>
+
+#include "key.h"
+#include "ssh2.h"
+
+#define GET_32BIT(cp) (((u_long)(u_char)(cp)[0] << 24) | \
+ ((u_long)(u_char)(cp)[1] << 16) | \
+ ((u_long)(u_char)(cp)[2] << 8) | \
+ ((u_long)(u_char)(cp)[3]))
+
+/* From OpenSSH */
+static int
+_uudecode(const char *src, u_char *target, size_t targsize)
+{
+ int len;
+ char *encoded, *p;
+
+ /* copy the 'readonly' source */
+ if ((encoded = strdup(src)) == NULL)
+ err(1, "");
+ /* skip whitespace and data */
+ for (p = encoded; *p == ' ' || *p == '\t'; p++)
+ ;
+ for (; *p != '\0' && *p != ' ' && *p != '\t'; p++)
+ ;
+ /* and remove trailing whitespace because __b64_pton needs this */
+ *p = '\0';
+ len = __b64_pton(encoded, target, targsize);
+
+ free(encoded);
+
+ return len;
+}
+
+/*
+ * Small compatibility layer for the OpenSSH buffers. Only what we
+ * need here.
+ */
+
+static int
+_keyfromstr(char *str, int len)
+{
+ if (strncmp(str, "rsa", len) == 0 ||
+ strncmp(str, "ssh-rsa", len) == 0)
+ return KEY_RSA;
+ else if (strncmp(str, "dsa", len) == 0 ||
+ strncmp(str, "ssh-dss", len) == 0)
+ return KEY_DSA;
+
+ return (-1);
+}
+
+static int
+_read_int(struct iovec *iov, int *ival)
+{
+ iov->iov_len -= 4;
+ if (iov->iov_len < 0)
+ return (-1);
+ *ival = GET_32BIT((u_char *)iov->iov_base);
+ (u_char*)iov->iov_base += 4;
+
+ return (0);
+}
+
+static int
+_read_opaque(struct iovec *iov, u_char **buf, int *len)
+{
+ if (_read_int(iov, len) < 0 || *len < 0)
+ return (-1);
+
+ iov->iov_len -= *len;
+ if (iov->iov_len < 0)
+ return (-1);
+
+ *buf = iov->iov_base;
+ (u_char*)iov->iov_base += *len;
+
+ return (0);
+}
+
+static int
+_read_bignum(struct iovec *iov, BIGNUM *bn)
+{
+ u_char *bp;
+ int blen;
+
+ if (_read_opaque(iov, &bp, &blen) < 0)
+ return (-1);
+
+ if ((blen > 0 && bp[0] & 0x80) || /* No negative values */
+ (blen > 8*1024)) /* Too large */
+ return (-1);
+
+ BN_bin2bn(bp, blen, bn);
+
+ return (0);
+}
+
+int
+ssh2_load_public(struct key *k, struct iovec *iovp)
+{
+ int len, keytype, error = 0, blen;
+ u_char *bp;
+ struct iovec iov;
+ /* iov->iov_base is NULL terminated */
+ char *cp0, *savep = NULL, *cp = iovp->iov_base;
+
+ if ((cp0 = strchr(cp, ' ')) == NULL)
+ return (-1);
+
+ len = cp0 - cp;
+
+ if ((keytype = _keyfromstr(cp, len)) < 0)
+ return (-1);
+
+ /* cp0 is a space (' '), so we have at least one more */
+ cp = cp0 + 1;
+
+ len = 2*strlen(cp);
+ if ((savep = iov.iov_base = malloc(len)) == NULL)
+ err(1, "");
+ iov.iov_len = _uudecode(cp, iov.iov_base, len);
+
+ if (_read_opaque(&iov, &bp, &len) < 0 ||
+ keytype != _keyfromstr(bp, len)) {
+ error = -1;
+ goto out;
+ }
+
+ k->type = keytype;
+ switch (keytype) {
+ case KEY_RSA: {
+ RSA *rsa;
+
+ if ((rsa = RSA_new()) == NULL ||
+ (rsa->e = BN_new()) == NULL ||
+ (rsa->n = BN_new()) == NULL)
+ errx(1, "");
+
+ if (_read_bignum(&iov, rsa->e) < 0 ||
+ _read_bignum(&iov, rsa->n) < 0) {
+ error = -1;
+ RSA_free(rsa);
+ goto out;
+ }
+
+ k->data = (void *)rsa;
+
+ break;
+ }
+ case KEY_DSA: {
+ DSA *dsa;
+
+ if ((dsa = DSA_new()) == NULL ||
+ (dsa->p = BN_new()) == NULL ||
+ (dsa->q = BN_new()) == NULL ||
+ (dsa->g = BN_new()) == NULL ||
+ (dsa->pub_key = BN_new()) == NULL)
+ errx(1, "");
+
+ if (_read_bignum(&iov, dsa->p) < 0 ||
+ _read_bignum(&iov, dsa->q) < 0 ||
+ _read_bignum(&iov, dsa->g) < 0 ||
+ _read_bignum(&iov, dsa->pub_key) < 0) {
+ error = -1;
+ DSA_free(dsa);
+ goto out;
+ }
+
+ k->data = (void *)dsa;
+
+ break;
+ }
+ default:
+ error = -1;
+ }
+
+#if 0
+ if (iov->iov_len != 0)
+ /* Sanity check. */
+ return (-1);
+#endif
+
+
+out:
+ if (savep != NULL)
+ free(savep);
+ return (error);
+}
diff --git a/usr.bin/gzsig/ssh2.h b/usr.bin/gzsig/ssh2.h
new file mode 100644
index 00000000000..d70382284ad
--- /dev/null
+++ b/usr.bin/gzsig/ssh2.h
@@ -0,0 +1,29 @@
+/* $OpenBSD: ssh2.h,v 1.1.1.1 2005/05/28 01:57:30 marius Exp $ */
+/*
+ * ssh2.h
+ *
+ * Copyright (c) 2005 Marius Eriksen <marius@openbsd.org>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef SSH2_H
+#define SSH2_H
+
+int ssh2_load_public(struct key *k, struct iovec *iovp);
+
+#endif /* SSH2_H */
+
+
+
+
diff --git a/usr.bin/gzsig/util.c b/usr.bin/gzsig/util.c
new file mode 100644
index 00000000000..84270a1fe87
--- /dev/null
+++ b/usr.bin/gzsig/util.c
@@ -0,0 +1,77 @@
+/* $OpenBSD: util.c,v 1.1 2005/05/28 01:57:30 marius Exp $ */
+
+/*
+ * util.c
+ *
+ * Copyright (c) 2001 Dug Song <dugsong@arbor.net>
+ * Copyright (c) 2001 Arbor Networks, Inc.
+ *
+ * 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. The names of the copyright holders may not be used to endorse or
+ * promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED ``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 AUTHOR 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.
+ *
+ * $Id: util.c,v 1.1 2005/05/28 01:57:30 marius Exp $
+ */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "util.h"
+
+int
+copy_permissions(char *srcfile, char *dstfile)
+{
+ struct stat st;
+
+ if (stat(srcfile, &st) < 0)
+ return (-1);
+
+ if (chmod(dstfile, st.st_mode) < 0)
+ return (-1);
+
+ if (chown(dstfile, st.st_uid, st.st_gid) < 0)
+ return (-1);
+
+ return (0);
+}
+
+void
+fatal(int status, const char *fmt, ...)
+{
+ va_list ap;
+
+ va_start(ap, fmt);
+ vfprintf(stderr, fmt, ap);
+ va_end(ap);
+
+ fprintf(stderr, "\n");
+
+ exit(status);
+}
diff --git a/usr.bin/gzsig/util.h b/usr.bin/gzsig/util.h
new file mode 100644
index 00000000000..c98c2264b08
--- /dev/null
+++ b/usr.bin/gzsig/util.h
@@ -0,0 +1,39 @@
+/*
+ * util.h
+ *
+ * Copyright (c) 2001 Dug Song <dugsong@arbor.net>
+ * Copyright (c) 2001 Arbor Networks, Inc.
+ *
+ * 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. The names of the copyright holders may not be used to endorse or
+ * promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED ``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 AUTHOR 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.
+ *
+ * $Id: util.h,v 1.1 2005/05/28 01:57:30 marius Exp $
+ */
+
+#ifndef UTIL_H
+
+int copy_permissions(char *srcfile, char *dstfile);
+void fatal(int status, const char *fmt, ...);
+
+#endif /* UTIL_H */
diff --git a/usr.bin/gzsig/verify.c b/usr.bin/gzsig/verify.c
new file mode 100644
index 00000000000..bdef51f460c
--- /dev/null
+++ b/usr.bin/gzsig/verify.c
@@ -0,0 +1,212 @@
+/* $OpenBSD: verify.c,v 1.1 2005/05/28 01:57:30 marius Exp $ */
+
+/*
+ * verify.c
+ *
+ * Copyright (c) 2001 Dug Song <dugsong@arbor.net>
+ * Copyright (c) 2001 Arbor Networks, Inc.
+ *
+ * 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. The names of the copyright holders may not be used to endorse or
+ * promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED ``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 AUTHOR 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.
+ *
+ * $Id: verify.c,v 1.1 2005/05/28 01:57:30 marius Exp $
+ */
+
+#include <sys/types.h>
+
+#include <openssl/ssl.h>
+#include <openssl/evp.h>
+#include <openssl/sha.h>
+
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "extern.h"
+#include "gzip.h"
+#include "key.h"
+#include "util.h"
+
+static int
+verify_signature(struct key *key, FILE *fin)
+{
+ struct gzip_header gh;
+ struct gzip_xfield *gx;
+ struct gzsig_data *gd;
+ u_char *sig, digest[20], buf[8192], sbuf[4096];
+ SHA_CTX ctx;
+ int i, siglen;
+
+ /* Read gzip header. */
+ if ((i = fread((u_char *)&gh, 1, sizeof(gh), fin)) != sizeof(gh)) {
+ fprintf(stderr, "Error reading gzip header: %s\n",
+ strerror(errno));
+ return (-1);
+ }
+ /* Verify gzip header. */
+ if (memcmp(gh.magic, GZIP_MAGIC, sizeof(gh.magic)) != 0) {
+ fprintf(stderr, "Invalid gzip file\n");
+ return (-1);
+ } else if (gh.flags & GZIP_FCONT){
+ fprintf(stderr, "Multi-part gzip files not supported\n");
+ return (-1);
+ } else if ((gh.flags & GZIP_FEXTRA) == 0) {
+ fprintf(stderr, "No gzip signature found\n");
+ return (-1);
+ }
+ /* Read signature. */
+ gx = (struct gzip_xfield *)buf;
+
+ if ((i = fread((u_char *)gx, 1, sizeof(*gx), fin)) != sizeof(*gx)) {
+ fprintf(stderr, "Error reading extra field: %s\n",
+ strerror(errno));
+ return (-1);
+ }
+ if (memcmp(gx->subfield.id, GZSIG_ID, sizeof(gx->subfield.id)) != 0) {
+ fprintf(stderr, "Unknown extra field\n");
+ return (-1);
+ }
+ gx->subfield.len = letoh16(gx->subfield.len);
+
+ if (gx->subfield.len <= 0 || gx->subfield.len > sizeof(sbuf)) {
+ fprintf(stderr, "Invalid signature length\n");
+ return (-1);
+ }
+ gd = (struct gzsig_data *)sbuf;
+
+ if ((i = fread((u_char *)gd, 1, gx->subfield.len, fin)) !=
+ gx->subfield.len) {
+ fprintf(stderr, "Error reading signature: %s\n",
+ strerror(errno));
+ return (-1);
+ }
+ /* Skip over any options. */
+ if (gh.flags & GZIP_FNAME) {
+ while (getc(fin) != '\0')
+ ;
+ }
+ if (gh.flags & GZIP_FCOMMENT) {
+ while (getc(fin) != '\0')
+ ;
+ }
+ if (gh.flags & GZIP_FENCRYPT &&
+ fread(buf, 1, GZIP_FENCRYPT_LEN, fin) != GZIP_FENCRYPT_LEN)
+ return (-1);
+
+ /* Check signature version. */
+ if (gd->version != GZSIG_VERSION) {
+ fprintf(stderr, "Unknown signature version: %d\n",
+ gd->version);
+ return (-1);
+ }
+ /* Compute SHA1 checksum over compressed data and trailer. */
+ sig = (u_char *)(gd + 1);
+ siglen = gx->subfield.len - sizeof(*gd);
+
+ SHA1_Init(&ctx);
+
+ while ((i = fread(buf, 1, sizeof(buf), fin)) > 0) {
+ SHA1_Update(&ctx, buf, i);
+ }
+ SHA1_Final(digest, &ctx);
+
+ /* Verify signature. */
+ if (key_verify(key, digest, sizeof(digest), sig, siglen) < 0) {
+ fprintf(stderr, "Error verifying signature\n");
+ return (-1);
+ }
+ return (0);
+}
+
+void
+verify_usage(void)
+{
+ fprintf(stderr, "Usage: gzsig verify [-v] pubkey [file ...]\n");
+}
+
+void
+verify(int argc, char *argv[])
+{
+ struct key *key;
+ char *gzipfile;
+ FILE *fin;
+ int i, error, vflag;
+
+ vflag = 0;
+
+ while ((i = getopt(argc, argv, "vh?")) != -1) {
+ switch (i) {
+ case 'v':
+ vflag = 1;
+ break;
+ default:
+ verify_usage();
+ exit(1);
+ }
+ }
+ argc -= optind;
+ argv += optind;
+
+ if (argc < 1) {
+ verify_usage();
+ exit(1);
+ }
+ OpenSSL_add_all_algorithms();
+
+ if ((key = key_new()) == NULL)
+ fatal(1, "Can't initialize public key");
+
+ if (key_load_public(key, argv[0]) < 0)
+ fatal(1, "Can't load public key");
+
+ if (argc == 1 || *argv[1] == '-') {
+ argc = 0;
+
+ if (verify_signature(key, stdin) == 0) {
+ if (vflag)
+ fprintf(stderr, "Verified input\n");
+ } else
+ fatal(1, "Couldn't verify input");
+ }
+ for (i = 1; i < argc; i++) {
+ gzipfile = argv[i];
+
+ if ((fin = fopen(gzipfile, "r")) < 0) {
+ fprintf(stderr, "Couldn't open %s: %s\n",
+ gzipfile, strerror(errno));
+ continue;
+ }
+ error = verify_signature(key, fin);
+ fclose(fin);
+
+ if (!error) {
+ if (vflag)
+ fprintf(stderr, "Verified %s\n", gzipfile);
+ } else
+ fatal(1, "Couldn't verify %s", gzipfile);
+ }
+ key_free(key);
+}
diff --git a/usr.bin/gzsig/x509.c b/usr.bin/gzsig/x509.c
new file mode 100644
index 00000000000..acb80f2f8b8
--- /dev/null
+++ b/usr.bin/gzsig/x509.c
@@ -0,0 +1,137 @@
+/* $OpenBSD: x509.c,v 1.1 2005/05/28 01:57:30 marius Exp $ */
+
+/*
+ * x509.c
+ *
+ * Copyright (c) 2001 Dug Song <dugsong@arbor.net>
+ * Copyright (c) 2001 Arbor Networks, Inc.
+ *
+ * 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. The names of the copyright holders may not be used to endorse or
+ * promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED ``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 AUTHOR 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.
+ *
+ * $Id: x509.c,v 1.1 2005/05/28 01:57:30 marius Exp $
+ */
+
+#include <sys/types.h>
+#include <sys/uio.h>
+
+#include <openssl/ssl.h>
+
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "key.h"
+#include "extern.h"
+#include "x509.h"
+
+#define X509_CERT_MAGIC "-----BEGIN CERTIFICATE-----"
+#define X509_RSA_MAGIC "-----BEGIN RSA PRIVATE KEY-----"
+#define X509_DSA_MAGIC "-----BEGIN DSA PRIVATE KEY-----"
+
+int
+x509_load_public(struct key *k, struct iovec *iov)
+{
+ BIO *bio;
+ X509 *cert;
+ EVP_PKEY *evp;
+
+ if (strncmp((char *)iov->iov_base, X509_CERT_MAGIC,
+ strlen(X509_CERT_MAGIC)) != 0)
+ return (-1);
+
+ if ((bio = BIO_new(BIO_s_mem())) == NULL)
+ return (-1);
+
+ if (BIO_write(bio, iov->iov_base, iov->iov_len + 1) <= 0) {
+ BIO_free(bio);
+ return (-1);
+ }
+ cert = PEM_read_bio_X509(bio, NULL, NULL, NULL);
+ BIO_free(bio);
+
+ if (cert == NULL)
+ return (-1);
+
+ evp = X509_get_pubkey(cert);
+
+ if (evp->type == EVP_PKEY_RSA) {
+ k->type = KEY_RSA;
+ k->data = (void *)RSAPublicKey_dup(evp->pkey.rsa);
+ } else if (evp->type == EVP_PKEY_DSA) {
+ k->type = KEY_DSA;
+ k->data = (void *)evp->pkey.dsa;
+ evp->pkey.dsa = NULL; /* XXX */
+ } else {
+ X509_free(cert);
+ return (-1);
+ }
+ X509_free(cert);
+
+ return (0);
+}
+
+int
+x509_load_private(struct key *k, struct iovec *iov)
+{
+ BIO *bio;
+ EVP_PKEY *evp;
+
+ if (strncmp((char *)iov->iov_base, X509_RSA_MAGIC,
+ strlen(X509_RSA_MAGIC)) != 0 &&
+ strncmp((char *)iov->iov_base, X509_DSA_MAGIC,
+ strlen(X509_DSA_MAGIC)) != 0) {
+ return (-1);
+ }
+ if ((bio = BIO_new(BIO_s_mem())) == NULL)
+ return (-1);
+
+ if (BIO_write(bio, iov->iov_base, iov->iov_len + 1) <= 0) {
+ BIO_free(bio);
+ return (-1);
+ }
+
+ evp = PEM_read_bio_PrivateKey(bio, NULL, sign_passwd_cb, NULL);
+
+ BIO_free(bio);
+
+ if (evp == NULL)
+ return (-1);
+
+ if (evp->type == EVP_PKEY_RSA) {
+ k->type = KEY_RSA;
+ k->data = (void *)evp->pkey.rsa;
+ evp->pkey.rsa = NULL; /* XXX */
+ } else if (evp->type == EVP_PKEY_DSA) {
+ k->type = KEY_DSA;
+ k->data = (void *)evp->pkey.dsa;
+ evp->pkey.dsa = NULL; /* XXX */
+ } else {
+ EVP_PKEY_free(evp);
+ return (-1);
+ }
+ EVP_PKEY_free(evp);
+
+ return (0);
+}
diff --git a/usr.bin/gzsig/x509.h b/usr.bin/gzsig/x509.h
new file mode 100644
index 00000000000..7a12da9b56c
--- /dev/null
+++ b/usr.bin/gzsig/x509.h
@@ -0,0 +1,40 @@
+/*
+ * x509.h
+ *
+ * Copyright (c) 2001 Dug Song <dugsong@arbor.net>
+ * Copyright (c) 2001 Arbor Networks, Inc.
+ *
+ * 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. The names of the copyright holders may not be used to endorse or
+ * promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED ``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 AUTHOR 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.
+ *
+ * $Id: x509.h,v 1.1 2005/05/28 01:57:30 marius Exp $
+ */
+
+#ifndef X509_H
+#define X509_H
+
+int x509_load_public(struct key *k, struct iovec *iov);
+int x509_load_private(struct key *k, struct iovec *iov);
+
+#endif /* X509_H */