Annotation of src/usr.bin/gzsig/ssh2.c, Revision 1.1
1.1 ! marius 1: /* $OpenBSD$ */
! 2: /*
! 3: * ssh2.c
! 4: *
! 5: * Copyright (c) 2005 Marius Eriksen <marius@openbsd.org>
! 6: *
! 7: * Permission to use, copy, modify, and distribute this software for any
! 8: * purpose with or without fee is hereby granted, provided that the above
! 9: * copyright notice and this permission notice appear in all copies.
! 10: *
! 11: * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
! 12: * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
! 13: * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
! 14: * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
! 15: * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
! 16: * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
! 17: * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
! 18: */
! 19:
! 20: #include <sys/types.h>
! 21: #include <sys/uio.h>
! 22:
! 23: #include <arpa/nameser.h>
! 24: #include <openssl/ssl.h>
! 25: #include <openssl/des.h>
! 26: #include <openssl/md5.h>
! 27:
! 28: #include <errno.h>
! 29: #include <stdio.h>
! 30: #include <stdlib.h>
! 31: #include <string.h>
! 32: #include <unistd.h>
! 33: #include <err.h>
! 34:
! 35: #include "key.h"
! 36: #include "ssh2.h"
! 37:
! 38: #define GET_32BIT(cp) (((u_long)(u_char)(cp)[0] << 24) | \
! 39: ((u_long)(u_char)(cp)[1] << 16) | \
! 40: ((u_long)(u_char)(cp)[2] << 8) | \
! 41: ((u_long)(u_char)(cp)[3]))
! 42:
! 43: /* From OpenSSH */
! 44: static int
! 45: _uudecode(const char *src, u_char *target, size_t targsize)
! 46: {
! 47: int len;
! 48: char *encoded, *p;
! 49:
! 50: /* copy the 'readonly' source */
! 51: if ((encoded = strdup(src)) == NULL)
! 52: err(1, "");
! 53: /* skip whitespace and data */
! 54: for (p = encoded; *p == ' ' || *p == '\t'; p++)
! 55: ;
! 56: for (; *p != '\0' && *p != ' ' && *p != '\t'; p++)
! 57: ;
! 58: /* and remove trailing whitespace because __b64_pton needs this */
! 59: *p = '\0';
! 60: len = __b64_pton(encoded, target, targsize);
! 61:
! 62: free(encoded);
! 63:
! 64: return len;
! 65: }
! 66:
! 67: /*
! 68: * Small compatibility layer for the OpenSSH buffers. Only what we
! 69: * need here.
! 70: */
! 71:
! 72: static int
! 73: _keyfromstr(char *str, int len)
! 74: {
! 75: if (strncmp(str, "rsa", len) == 0 ||
! 76: strncmp(str, "ssh-rsa", len) == 0)
! 77: return KEY_RSA;
! 78: else if (strncmp(str, "dsa", len) == 0 ||
! 79: strncmp(str, "ssh-dss", len) == 0)
! 80: return KEY_DSA;
! 81:
! 82: return (-1);
! 83: }
! 84:
! 85: static int
! 86: _read_int(struct iovec *iov, int *ival)
! 87: {
! 88: iov->iov_len -= 4;
! 89: if (iov->iov_len < 0)
! 90: return (-1);
! 91: *ival = GET_32BIT((u_char *)iov->iov_base);
! 92: (u_char*)iov->iov_base += 4;
! 93:
! 94: return (0);
! 95: }
! 96:
! 97: static int
! 98: _read_opaque(struct iovec *iov, u_char **buf, int *len)
! 99: {
! 100: if (_read_int(iov, len) < 0 || *len < 0)
! 101: return (-1);
! 102:
! 103: iov->iov_len -= *len;
! 104: if (iov->iov_len < 0)
! 105: return (-1);
! 106:
! 107: *buf = iov->iov_base;
! 108: (u_char*)iov->iov_base += *len;
! 109:
! 110: return (0);
! 111: }
! 112:
! 113: static int
! 114: _read_bignum(struct iovec *iov, BIGNUM *bn)
! 115: {
! 116: u_char *bp;
! 117: int blen;
! 118:
! 119: if (_read_opaque(iov, &bp, &blen) < 0)
! 120: return (-1);
! 121:
! 122: if ((blen > 0 && bp[0] & 0x80) || /* No negative values */
! 123: (blen > 8*1024)) /* Too large */
! 124: return (-1);
! 125:
! 126: BN_bin2bn(bp, blen, bn);
! 127:
! 128: return (0);
! 129: }
! 130:
! 131: int
! 132: ssh2_load_public(struct key *k, struct iovec *iovp)
! 133: {
! 134: int len, keytype, error = 0, blen;
! 135: u_char *bp;
! 136: struct iovec iov;
! 137: /* iov->iov_base is NULL terminated */
! 138: char *cp0, *savep = NULL, *cp = iovp->iov_base;
! 139:
! 140: if ((cp0 = strchr(cp, ' ')) == NULL)
! 141: return (-1);
! 142:
! 143: len = cp0 - cp;
! 144:
! 145: if ((keytype = _keyfromstr(cp, len)) < 0)
! 146: return (-1);
! 147:
! 148: /* cp0 is a space (' '), so we have at least one more */
! 149: cp = cp0 + 1;
! 150:
! 151: len = 2*strlen(cp);
! 152: if ((savep = iov.iov_base = malloc(len)) == NULL)
! 153: err(1, "");
! 154: iov.iov_len = _uudecode(cp, iov.iov_base, len);
! 155:
! 156: if (_read_opaque(&iov, &bp, &len) < 0 ||
! 157: keytype != _keyfromstr(bp, len)) {
! 158: error = -1;
! 159: goto out;
! 160: }
! 161:
! 162: k->type = keytype;
! 163: switch (keytype) {
! 164: case KEY_RSA: {
! 165: RSA *rsa;
! 166:
! 167: if ((rsa = RSA_new()) == NULL ||
! 168: (rsa->e = BN_new()) == NULL ||
! 169: (rsa->n = BN_new()) == NULL)
! 170: errx(1, "");
! 171:
! 172: if (_read_bignum(&iov, rsa->e) < 0 ||
! 173: _read_bignum(&iov, rsa->n) < 0) {
! 174: error = -1;
! 175: RSA_free(rsa);
! 176: goto out;
! 177: }
! 178:
! 179: k->data = (void *)rsa;
! 180:
! 181: break;
! 182: }
! 183: case KEY_DSA: {
! 184: DSA *dsa;
! 185:
! 186: if ((dsa = DSA_new()) == NULL ||
! 187: (dsa->p = BN_new()) == NULL ||
! 188: (dsa->q = BN_new()) == NULL ||
! 189: (dsa->g = BN_new()) == NULL ||
! 190: (dsa->pub_key = BN_new()) == NULL)
! 191: errx(1, "");
! 192:
! 193: if (_read_bignum(&iov, dsa->p) < 0 ||
! 194: _read_bignum(&iov, dsa->q) < 0 ||
! 195: _read_bignum(&iov, dsa->g) < 0 ||
! 196: _read_bignum(&iov, dsa->pub_key) < 0) {
! 197: error = -1;
! 198: DSA_free(dsa);
! 199: goto out;
! 200: }
! 201:
! 202: k->data = (void *)dsa;
! 203:
! 204: break;
! 205: }
! 206: default:
! 207: error = -1;
! 208: }
! 209:
! 210: #if 0
! 211: if (iov->iov_len != 0)
! 212: /* Sanity check. */
! 213: return (-1);
! 214: #endif
! 215:
! 216:
! 217: out:
! 218: if (savep != NULL)
! 219: free(savep);
! 220: return (error);
! 221: }