summaryrefslogtreecommitdiff
path: root/usr.bin/gzsig/ssh2.c
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/gzsig/ssh2.c
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/gzsig/ssh2.c')
-rw-r--r--usr.bin/gzsig/ssh2.c221
1 files changed, 221 insertions, 0 deletions
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);
+}