summaryrefslogtreecommitdiff
path: root/usr/src/cmd/ssh/libssh/common
diff options
context:
space:
mode:
authorRichard Lowe <richlowe@richlowe.net>2016-08-09 13:52:53 -0400
committerRichard Lowe <richlowe@richlowe.net>2016-08-22 10:51:23 -0400
commit0343317a7b3df0798d9facd6eb5a0e83abd23d83 (patch)
treefa4c21e47758ad53e9e82c4709593e9731baffb4 /usr/src/cmd/ssh/libssh/common
parent09c0accb630678e1a150310a8852806c5052b2ac (diff)
downloadillumos-gate-0343317a7b3df0798d9facd6eb5a0e83abd23d83.tar.gz
7293 Sun Secure Shell is neither
Reviewed by: Albert Lee <trisk@omniti.com> Reviewed by: Alex Wilson <alex.wilson@joyent.com> Reviewed by: Alexander Pyhalov <alp@rsu.ru> Reviewed by: Dan McDonald <danmcd@omniti.com> Reviewed by: Garrett D'Amore <garrett@damore.org> Reviewed by: Peter Tribble <peter.tribble@gmail.com>
Diffstat (limited to 'usr/src/cmd/ssh/libssh/common')
-rw-r--r--usr/src/cmd/ssh/libssh/common/addrmatch.c426
-rw-r--r--usr/src/cmd/ssh/libssh/common/atomicio.c118
-rw-r--r--usr/src/cmd/ssh/libssh/common/authfd.c631
-rw-r--r--usr/src/cmd/ssh/libssh/common/authfile.c624
-rw-r--r--usr/src/cmd/ssh/libssh/common/bufaux.c469
-rw-r--r--usr/src/cmd/ssh/libssh/common/buffer.c263
-rw-r--r--usr/src/cmd/ssh/libssh/common/canohost.c391
-rw-r--r--usr/src/cmd/ssh/libssh/common/channels.c3035
-rw-r--r--usr/src/cmd/ssh/libssh/common/cipher-ctr.c172
-rw-r--r--usr/src/cmd/ssh/libssh/common/cipher.c585
-rw-r--r--usr/src/cmd/ssh/libssh/common/compat.c260
-rw-r--r--usr/src/cmd/ssh/libssh/common/compress.c162
-rw-r--r--usr/src/cmd/ssh/libssh/common/crc32.c116
-rw-r--r--usr/src/cmd/ssh/libssh/common/deattack.c178
-rw-r--r--usr/src/cmd/ssh/libssh/common/dh.c289
-rw-r--r--usr/src/cmd/ssh/libssh/common/dispatch.c101
-rw-r--r--usr/src/cmd/ssh/libssh/common/engine.c118
-rw-r--r--usr/src/cmd/ssh/libssh/common/entropy.c156
-rw-r--r--usr/src/cmd/ssh/libssh/common/fatal.c42
-rw-r--r--usr/src/cmd/ssh/libssh/common/g11n.c964
-rw-r--r--usr/src/cmd/ssh/libssh/common/hostfile.c357
-rw-r--r--usr/src/cmd/ssh/libssh/common/kex.c711
-rw-r--r--usr/src/cmd/ssh/libssh/common/kexdh.c89
-rw-r--r--usr/src/cmd/ssh/libssh/common/kexdhc.c144
-rw-r--r--usr/src/cmd/ssh/libssh/common/kexdhs.c144
-rw-r--r--usr/src/cmd/ssh/libssh/common/kexgex.c100
-rw-r--r--usr/src/cmd/ssh/libssh/common/kexgexc.c195
-rw-r--r--usr/src/cmd/ssh/libssh/common/kexgexs.c191
-rw-r--r--usr/src/cmd/ssh/libssh/common/kexgssc.c325
-rw-r--r--usr/src/cmd/ssh/libssh/common/kexgsss.c252
-rw-r--r--usr/src/cmd/ssh/libssh/common/key.c876
-rw-r--r--usr/src/cmd/ssh/libssh/common/llib-lssh130
-rw-r--r--usr/src/cmd/ssh/libssh/common/log.c445
-rw-r--r--usr/src/cmd/ssh/libssh/common/mac.c164
-rw-r--r--usr/src/cmd/ssh/libssh/common/match.c271
-rw-r--r--usr/src/cmd/ssh/libssh/common/misc.c702
-rw-r--r--usr/src/cmd/ssh/libssh/common/mpaux.c48
-rw-r--r--usr/src/cmd/ssh/libssh/common/msg.c75
-rw-r--r--usr/src/cmd/ssh/libssh/common/nchan.c512
-rw-r--r--usr/src/cmd/ssh/libssh/common/packet.c1845
-rw-r--r--usr/src/cmd/ssh/libssh/common/progressmeter.c308
-rw-r--r--usr/src/cmd/ssh/libssh/common/proxy-io.c38
-rw-r--r--usr/src/cmd/ssh/libssh/common/radix.c160
-rw-r--r--usr/src/cmd/ssh/libssh/common/readconf.c1276
-rw-r--r--usr/src/cmd/ssh/libssh/common/readpass.c163
-rw-r--r--usr/src/cmd/ssh/libssh/common/rsa.c146
-rw-r--r--usr/src/cmd/ssh/libssh/common/sftp-common.c227
-rw-r--r--usr/src/cmd/ssh/libssh/common/ssh-dss.c183
-rw-r--r--usr/src/cmd/ssh/libssh/common/ssh-gss.c782
-rw-r--r--usr/src/cmd/ssh/libssh/common/ssh-rsa.c270
-rw-r--r--usr/src/cmd/ssh/libssh/common/tildexpand.c95
-rw-r--r--usr/src/cmd/ssh/libssh/common/ttymodes.c480
-rw-r--r--usr/src/cmd/ssh/libssh/common/uidswap.c257
-rw-r--r--usr/src/cmd/ssh/libssh/common/uuencode.c75
-rw-r--r--usr/src/cmd/ssh/libssh/common/xlist.c85
-rw-r--r--usr/src/cmd/ssh/libssh/common/xmalloc.c86
56 files changed, 0 insertions, 21307 deletions
diff --git a/usr/src/cmd/ssh/libssh/common/addrmatch.c b/usr/src/cmd/ssh/libssh/common/addrmatch.c
deleted file mode 100644
index 91aa1e7ac7..0000000000
--- a/usr/src/cmd/ssh/libssh/common/addrmatch.c
+++ /dev/null
@@ -1,426 +0,0 @@
-/* $OpenBSD: addrmatch.c,v 1.4 2008/12/10 03:55:20 stevesk Exp $ */
-
-/*
- * Copyright (c) 2004-2008 Damien Miller <djm@mindrot.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 "includes.h"
-
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
-
-#include <netdb.h>
-#include <string.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <stdarg.h>
-
-#include "match.h"
-#include "log.h"
-#include "xmalloc.h"
-
-struct xaddr {
- sa_family_t af;
- union {
- struct in_addr v4;
- struct in6_addr v6;
- u_int8_t addr8[16];
- u_int32_t addr32[4];
- } xa; /* 128-bit address */
- u_int32_t scope_id; /* iface scope id for v6 */
-#define v4 xa.v4
-#define v6 xa.v6
-#define addr8 xa.addr8
-#define addr32 xa.addr32
-};
-
-static int
-addr_unicast_masklen(int af)
-{
- switch (af) {
- case AF_INET:
- return 32;
- case AF_INET6:
- return 128;
- default:
- return -1;
- }
-}
-
-static inline int
-masklen_valid(int af, u_int masklen)
-{
- switch (af) {
- case AF_INET:
- return masklen <= 32 ? 0 : -1;
- case AF_INET6:
- return masklen <= 128 ? 0 : -1;
- default:
- return -1;
- }
-}
-
-/*
- * Convert struct sockaddr to struct xaddr
- * Returns 0 on success, -1 on failure.
- */
-static int
-addr_sa_to_xaddr(struct sockaddr *sa, socklen_t slen, struct xaddr *xa)
-{
- /* LINTED E_BAD_PTR_CAST_ALIGN */
- struct sockaddr_in *in4 = (struct sockaddr_in *)sa;
- /* LINTED E_BAD_PTR_CAST_ALIGN */
- struct sockaddr_in6 *in6 = (struct sockaddr_in6 *)sa;
-
- memset(xa, '\0', sizeof(*xa));
-
- switch (sa->sa_family) {
- case AF_INET:
- if (slen < sizeof(*in4))
- return -1;
- xa->af = AF_INET;
- memcpy(&xa->v4, &in4->sin_addr, sizeof(xa->v4));
- break;
- case AF_INET6:
- if (slen < sizeof(*in6))
- return -1;
- xa->af = AF_INET6;
- memcpy(&xa->v6, &in6->sin6_addr, sizeof(xa->v6));
-#ifdef HAVE_STRUCT_SOCKADDR_IN6_SIN6_SCOPE_ID
- xa->scope_id = in6->sin6_scope_id;
-#endif
- break;
- default:
- return -1;
- }
-
- return 0;
-}
-
-/*
- * Calculate a netmask of length 'l' for address family 'af' and
- * store it in 'n'.
- * Returns 0 on success, -1 on failure.
- */
-static int
-addr_netmask(int af, u_int l, struct xaddr *n)
-{
- int i;
-
- if (masklen_valid(af, l) != 0 || n == NULL)
- return -1;
-
- memset(n, '\0', sizeof(*n));
- switch (af) {
- case AF_INET:
- n->af = AF_INET;
- n->v4.s_addr = htonl((0xffffffff << (32 - l)) & 0xffffffff);
- return 0;
- case AF_INET6:
- n->af = AF_INET6;
- for (i = 0; i < 4 && l >= 32; i++, l -= 32)
- n->addr32[i] = 0xffffffffU;
- if (i < 4 && l != 0)
- n->addr32[i] = htonl((0xffffffff << (32 - l)) &
- 0xffffffff);
- return 0;
- default:
- return -1;
- }
-}
-
-/*
- * Perform logical AND of addresses 'a' and 'b', storing result in 'dst'.
- * Returns 0 on success, -1 on failure.
- */
-static int
-addr_and(struct xaddr *dst, const struct xaddr *a, const struct xaddr *b)
-{
- int i;
-
- if (dst == NULL || a == NULL || b == NULL || a->af != b->af)
- return -1;
-
- memcpy(dst, a, sizeof(*dst));
- switch (a->af) {
- case AF_INET:
- dst->v4.s_addr &= b->v4.s_addr;
- return 0;
- case AF_INET6:
- dst->scope_id = a->scope_id;
- for (i = 0; i < 4; i++)
- dst->addr32[i] &= b->addr32[i];
- return 0;
- default:
- return -1;
- }
-}
-
-/*
- * Compare addresses 'a' and 'b'
- * Return 0 if addresses are identical, -1 if (a < b) or 1 if (a > b)
- */
-static int
-addr_cmp(const struct xaddr *a, const struct xaddr *b)
-{
- int i;
-
- if (a->af != b->af)
- return a->af == AF_INET6 ? 1 : -1;
-
- switch (a->af) {
- case AF_INET:
- if (a->v4.s_addr == b->v4.s_addr)
- return 0;
- return ntohl(a->v4.s_addr) > ntohl(b->v4.s_addr) ? 1 : -1;
- case AF_INET6:
- for (i = 0; i < 16; i++)
- if (a->addr8[i] - b->addr8[i] != 0)
- return a->addr8[i] > b->addr8[i] ? 1 : -1;
- if (a->scope_id == b->scope_id)
- return 0;
- return a->scope_id > b->scope_id ? 1 : -1;
- default:
- return -1;
- }
-}
-
-/*
- * Parse string address 'p' into 'n'
- * Returns 0 on success, -1 on failure.
- */
-static int
-addr_pton(const char *p, struct xaddr *n)
-{
- struct addrinfo hints, *ai;
-
- memset(&hints, '\0', sizeof(hints));
- hints.ai_flags = AI_NUMERICHOST;
-
- if (p == NULL || getaddrinfo(p, NULL, &hints, &ai) != 0)
- return -1;
-
- if (ai == NULL || ai->ai_addr == NULL)
- return -1;
-
- if (n != NULL &&
- addr_sa_to_xaddr(ai->ai_addr, ai->ai_addrlen, n) == -1) {
- freeaddrinfo(ai);
- return -1;
- }
-
- freeaddrinfo(ai);
- return 0;
-}
-
-/*
- * Perform bitwise negation of address
- * Returns 0 on success, -1 on failure.
- */
-static int
-addr_invert(struct xaddr *n)
-{
- int i;
-
- if (n == NULL)
- return (-1);
-
- switch (n->af) {
- case AF_INET:
- n->v4.s_addr = ~n->v4.s_addr;
- return (0);
- case AF_INET6:
- for (i = 0; i < 4; i++)
- n->addr32[i] = ~n->addr32[i];
- return (0);
- default:
- return (-1);
- }
-}
-
-/*
- * Calculate a netmask of length 'l' for address family 'af' and
- * store it in 'n'.
- * Returns 0 on success, -1 on failure.
- */
-static int
-addr_hostmask(int af, u_int l, struct xaddr *n)
-{
- if (addr_netmask(af, l, n) == -1 || addr_invert(n) == -1)
- return (-1);
- return (0);
-}
-
-/*
- * Test whether address 'a' is all zeros (i.e. 0.0.0.0 or ::)
- * Returns 0 on if address is all-zeros, -1 if not all zeros or on failure.
- */
-static int
-addr_is_all0s(const struct xaddr *a)
-{
- int i;
-
- switch (a->af) {
- case AF_INET:
- return (a->v4.s_addr == 0 ? 0 : -1);
- case AF_INET6:;
- for (i = 0; i < 4; i++)
- if (a->addr32[i] != 0)
- return (-1);
- return (0);
- default:
- return (-1);
- }
-}
-
-/*
- * Test whether host portion of address 'a', as determined by 'masklen'
- * is all zeros.
- * Returns 0 on if host portion of address is all-zeros,
- * -1 if not all zeros or on failure.
- */
-static int
-addr_host_is_all0s(const struct xaddr *a, u_int masklen)
-{
- struct xaddr tmp_addr, tmp_mask, tmp_result;
-
- memcpy(&tmp_addr, a, sizeof(tmp_addr));
- if (addr_hostmask(a->af, masklen, &tmp_mask) == -1)
- return (-1);
- if (addr_and(&tmp_result, &tmp_addr, &tmp_mask) == -1)
- return (-1);
- return (addr_is_all0s(&tmp_result));
-}
-
-/*
- * Parse a CIDR address (x.x.x.x/y or xxxx:yyyy::/z).
- * Return -1 on parse error, -2 on inconsistency or 0 on success.
- */
-static int
-addr_pton_cidr(const char *p, struct xaddr *n, u_int *l)
-{
- struct xaddr tmp;
- long unsigned int masklen = 999;
- char addrbuf[64], *mp, *cp;
-
- /* Don't modify argument */
- if (p == NULL || strlcpy(addrbuf, p, sizeof(addrbuf)) > sizeof(addrbuf))
- return -1;
-
- if ((mp = strchr(addrbuf, '/')) != NULL) {
- *mp = '\0';
- mp++;
- masklen = strtoul(mp, &cp, 10);
- if (*mp == '\0' || *cp != '\0' || masklen > 128)
- return -1;
- }
-
- if (addr_pton(addrbuf, &tmp) == -1)
- return -1;
-
- if (mp == NULL)
- masklen = addr_unicast_masklen(tmp.af);
- if (masklen_valid(tmp.af, masklen) == -1)
- return -2;
- if (addr_host_is_all0s(&tmp, masklen) != 0)
- return -2;
-
- if (n != NULL)
- memcpy(n, &tmp, sizeof(*n));
- if (l != NULL)
- *l = masklen;
-
- return 0;
-}
-
-static int
-addr_netmatch(const struct xaddr *host, const struct xaddr *net, u_int masklen)
-{
- struct xaddr tmp_mask, tmp_result;
-
- if (host->af != net->af)
- return -1;
-
- if (addr_netmask(host->af, masklen, &tmp_mask) == -1)
- return -1;
- if (addr_and(&tmp_result, host, &tmp_mask) == -1)
- return -1;
- return addr_cmp(&tmp_result, net);
-}
-
-/*
- * Match "addr" against list pattern list "_list", which may contain a
- * mix of CIDR addresses and old-school wildcards.
- *
- * If addr is NULL, then no matching is performed, but _list is parsed
- * and checked for well-formedness.
- *
- * Returns 1 on match found (never returned when addr == NULL).
- * Returns 0 on if no match found, or no errors found when addr == NULL.
- * Returns -1 on negated match found (never returned when addr == NULL).
- * Returns -2 on invalid list entry.
- */
-int
-addr_match_list(const char *addr, const char *_list)
-{
- char *list, *cp, *o;
- struct xaddr try_addr, match_addr;
- u_int masklen, neg;
- int ret = 0, r;
-
- if (addr != NULL && addr_pton(addr, &try_addr) != 0) {
- debug2("%s: couldn't parse address %.100s", __func__, addr);
- return 0;
- }
- if ((o = list = strdup(_list)) == NULL)
- return -1;
- while ((cp = strsep(&list, ",")) != NULL) {
- neg = *cp == '!';
- if (neg)
- cp++;
- if (*cp == '\0') {
- ret = -2;
- break;
- }
- /* Prefer CIDR address matching */
- r = addr_pton_cidr(cp, &match_addr, &masklen);
- if (r == -2) {
- error("Inconsistent mask length for "
- "network \"%.100s\"", cp);
- ret = -2;
- break;
- } else if (r == 0) {
- if (addr != NULL && addr_netmatch(&try_addr,
- &match_addr, masklen) == 0) {
- foundit:
- if (neg) {
- ret = -1;
- break;
- }
- ret = 1;
- }
- continue;
- } else {
- /* If CIDR parse failed, try wildcard string match */
- if (addr != NULL && match_pattern(addr, cp) == 1)
- goto foundit;
- }
- }
- xfree(o);
-
- return ret;
-}
diff --git a/usr/src/cmd/ssh/libssh/common/atomicio.c b/usr/src/cmd/ssh/libssh/common/atomicio.c
deleted file mode 100644
index f4a7945702..0000000000
--- a/usr/src/cmd/ssh/libssh/common/atomicio.c
+++ /dev/null
@@ -1,118 +0,0 @@
-/*
- * Copyright (c) 2006 Damien Miller. All rights reserved.
- * Copyright (c) 2005 Anil Madhavapeddy. All rights reserved.
- * Copyright (c) 1995,1999 Theo de Raadt. All rights reserved.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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.
- */
-
-#include "includes.h"
-RCSID("$OpenBSD: atomicio.c,v 1.10 2001/05/08 22:48:07 markus Exp $");
-
-#pragma ident "%Z%%M% %I% %E% SMI"
-
-#include "atomicio.h"
-
-/*
- * ensure all of data on socket comes through. f==read || f==write
- */
-ssize_t
-atomicio(f, fd, _s, n)
- ssize_t (*f) ();
- int fd;
- void *_s;
- size_t n;
-{
- char *s = _s;
- ssize_t res, pos = 0;
-
- while (n > pos) {
- res = (f) (fd, s + pos, n - pos);
- switch (res) {
- case -1:
-#ifdef EWOULDBLOCK
- if (errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK)
-#else
- if (errno == EINTR || errno == EAGAIN)
-#endif
- continue;
- /* FALLTHROUGH */
- case 0:
- return (res);
- default:
- pos += res;
- }
- }
- return (pos);
-}
-
-/*
- * ensure all of data on socket comes through. f==readv || f==writev
- */
-size_t
-atomiciov(ssize_t (*f) (int, const struct iovec *, int), int fd,
- const struct iovec *_iov, int iovcnt)
-{
- size_t pos = 0, rem;
- ssize_t res;
- struct iovec iov_array[IOV_MAX], *iov = iov_array;
-
- if (iovcnt > IOV_MAX) {
- errno = EINVAL;
- return 0;
- }
- /* Make a copy of the iov array because we may modify it below */
- memcpy(iov, _iov, iovcnt * sizeof(*_iov));
-
- for (; iovcnt > 0 && iov[0].iov_len > 0;) {
- res = (f) (fd, iov, iovcnt);
- switch (res) {
- case -1:
- if (errno == EINTR || errno == EAGAIN)
- continue;
- return 0;
- case 0:
- errno = EPIPE;
- return pos;
- default:
- rem = (size_t)res;
- pos += rem;
- /* skip completed iov entries */
- while (iovcnt > 0 && rem >= iov[0].iov_len) {
- rem -= iov[0].iov_len;
- iov++;
- iovcnt--;
- }
- /* This shouldn't happen... */
- if (rem > 0 && (iovcnt <= 0 || rem > iov[0].iov_len)) {
- errno = EFAULT;
- return 0;
- }
- if (iovcnt == 0)
- break;
- /* update pointer in partially complete iov */
- iov[0].iov_base = ((char *)iov[0].iov_base) + rem;
- iov[0].iov_len -= rem;
- }
- }
- return pos;
-}
diff --git a/usr/src/cmd/ssh/libssh/common/authfd.c b/usr/src/cmd/ssh/libssh/common/authfd.c
deleted file mode 100644
index 43fbfbeb3c..0000000000
--- a/usr/src/cmd/ssh/libssh/common/authfd.c
+++ /dev/null
@@ -1,631 +0,0 @@
-/*
- * Author: Tatu Ylonen <ylo@cs.hut.fi>
- * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
- * All rights reserved
- * Functions for connecting the local authentication agent.
- *
- * As far as I am concerned, the code I have written for this software
- * can be used freely for any purpose. Any derived versions of this
- * software must be clearly marked as such, and if the derived work is
- * incompatible with the protocol description in the RFC file, it must be
- * called by a name other than "ssh" or "Secure Shell".
- *
- * SSH2 implementation,
- * Copyright (c) 2000 Markus Friedl. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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.
- */
-
-#include "includes.h"
-RCSID("$OpenBSD: authfd.c,v 1.57 2002/09/11 18:27:26 stevesk Exp $");
-
-#include <openssl/evp.h>
-
-#include "ssh.h"
-#include "rsa.h"
-#include "buffer.h"
-#include "bufaux.h"
-#include "xmalloc.h"
-#include "getput.h"
-#include "key.h"
-#include "authfd.h"
-#include "cipher.h"
-#include "kex.h"
-#include "compat.h"
-#include "log.h"
-#include "atomicio.h"
-
-static int agent_present = 0;
-
-/* helper */
-int decode_reply(int type);
-
-/* macro to check for "agent failure" message */
-#define agent_failed(x) \
- ((x == SSH_AGENT_FAILURE) || (x == SSH_COM_AGENT2_FAILURE) || \
- (x == SSH2_AGENT_FAILURE))
-
-int
-ssh_agent_present(void)
-{
- int authfd;
-
- if (agent_present)
- return 1;
- if ((authfd = ssh_get_authentication_socket()) == -1)
- return 0;
- else {
- ssh_close_authentication_socket(authfd);
- return 1;
- }
-}
-
-/* Returns the number of the authentication fd, or -1 if there is none. */
-
-int
-ssh_get_authentication_socket(void)
-{
- const char *authsocket;
- int sock;
- struct sockaddr_un sunaddr;
-
- authsocket = getenv(SSH_AUTHSOCKET_ENV_NAME);
- if (!authsocket)
- return -1;
-
- sunaddr.sun_family = AF_UNIX;
- strlcpy(sunaddr.sun_path, authsocket, sizeof(sunaddr.sun_path));
-
- sock = socket(AF_UNIX, SOCK_STREAM, 0);
- if (sock < 0)
- return -1;
-
- /* close on exec */
- if (fcntl(sock, F_SETFD, FD_CLOEXEC) == -1) {
- close(sock);
- return -1;
- }
- if (connect(sock, (struct sockaddr *) &sunaddr, sizeof sunaddr) < 0) {
- close(sock);
- return -1;
- }
- agent_present = 1;
- return sock;
-}
-
-static int
-ssh_request_reply(AuthenticationConnection *auth, Buffer *request, Buffer *reply)
-{
- int l, len;
- char buf[1024];
-
- /* Get the length of the message, and format it in the buffer. */
- len = buffer_len(request);
- PUT_32BIT(buf, len);
-
- /* Send the length and then the packet to the agent. */
- if (atomicio(write, auth->fd, buf, 4) != 4 ||
- atomicio(write, auth->fd, buffer_ptr(request),
- buffer_len(request)) != buffer_len(request)) {
- error("Error writing to authentication socket.");
- return 0;
- }
- /*
- * Wait for response from the agent. First read the length of the
- * response packet.
- */
- len = 4;
- while (len > 0) {
- l = read(auth->fd, buf + 4 - len, len);
- if (l == -1 && (errno == EAGAIN || errno == EINTR))
- continue;
- if (l <= 0) {
- error("Error reading response length from authentication socket.");
- return 0;
- }
- len -= l;
- }
-
- /* Extract the length, and check it for sanity. */
- len = GET_32BIT(buf);
- if (len > 256 * 1024)
- fatal("Authentication response too long: %d", len);
-
- /* Read the rest of the response in to the buffer. */
- buffer_clear(reply);
- while (len > 0) {
- l = len;
- if (l > sizeof(buf))
- l = sizeof(buf);
- l = read(auth->fd, buf, l);
- if (l == -1 && (errno == EAGAIN || errno == EINTR))
- continue;
- if (l <= 0) {
- error("Error reading response from authentication socket.");
- return 0;
- }
- buffer_append(reply, buf, l);
- len -= l;
- }
- return 1;
-}
-
-/*
- * Closes the agent socket if it should be closed (depends on how it was
- * obtained). The argument must have been returned by
- * ssh_get_authentication_socket().
- */
-
-void
-ssh_close_authentication_socket(int sock)
-{
- if (getenv(SSH_AUTHSOCKET_ENV_NAME))
- close(sock);
-}
-
-/*
- * Opens and connects a private socket for communication with the
- * authentication agent. Returns the file descriptor (which must be
- * shut down and closed by the caller when no longer needed).
- * Returns NULL if an error occurred and the connection could not be
- * opened.
- */
-
-AuthenticationConnection *
-ssh_get_authentication_connection(void)
-{
- AuthenticationConnection *auth;
- int sock;
-
- sock = ssh_get_authentication_socket();
-
- /*
- * Fail if we couldn't obtain a connection. This happens if we
- * exited due to a timeout.
- */
- if (sock < 0)
- return NULL;
-
- auth = xmalloc(sizeof(*auth));
- auth->fd = sock;
- buffer_init(&auth->identities);
- auth->howmany = 0;
-
- return auth;
-}
-
-/*
- * Closes the connection to the authentication agent and frees any associated
- * memory.
- */
-
-void
-ssh_close_authentication_connection(AuthenticationConnection *auth)
-{
- buffer_free(&auth->identities);
- close(auth->fd);
- xfree(auth);
-}
-
-/* Lock/unlock agent */
-int
-ssh_lock_agent(AuthenticationConnection *auth, int lock, const char *password)
-{
- int type;
- Buffer msg;
-
- buffer_init(&msg);
- buffer_put_char(&msg, lock ? SSH_AGENTC_LOCK : SSH_AGENTC_UNLOCK);
- buffer_put_cstring(&msg, password);
-
- if (ssh_request_reply(auth, &msg, &msg) == 0) {
- buffer_free(&msg);
- return 0;
- }
- type = buffer_get_char(&msg);
- buffer_free(&msg);
- return decode_reply(type);
-}
-
-/*
- * Returns the first authentication identity held by the agent.
- */
-
-int
-ssh_get_num_identities(AuthenticationConnection *auth, int version)
-{
- int type, code1 = 0, code2 = 0;
- Buffer request;
-
- switch (version) {
- case 1:
- code1 = SSH_AGENTC_REQUEST_RSA_IDENTITIES;
- code2 = SSH_AGENT_RSA_IDENTITIES_ANSWER;
- break;
- case 2:
- code1 = SSH2_AGENTC_REQUEST_IDENTITIES;
- code2 = SSH2_AGENT_IDENTITIES_ANSWER;
- break;
- default:
- return 0;
- }
-
- /*
- * Send a message to the agent requesting for a list of the
- * identities it can represent.
- */
- buffer_init(&request);
- buffer_put_char(&request, code1);
-
- buffer_clear(&auth->identities);
- if (ssh_request_reply(auth, &request, &auth->identities) == 0) {
- buffer_free(&request);
- return 0;
- }
- buffer_free(&request);
-
- /* Get message type, and verify that we got a proper answer. */
- type = buffer_get_char(&auth->identities);
- if (agent_failed(type)) {
- return 0;
- } else if (type != code2) {
- fatal("Bad authentication reply message type: %d", type);
- }
-
- /* Get the number of entries in the response and check it for sanity. */
- auth->howmany = buffer_get_int(&auth->identities);
- if (auth->howmany > 1024)
- fatal("Too many identities in authentication reply: %d",
- auth->howmany);
-
- return auth->howmany;
-}
-
-Key *
-ssh_get_first_identity(AuthenticationConnection *auth, char **comment, int version)
-{
- /* get number of identities and return the first entry (if any). */
- if (ssh_get_num_identities(auth, version) > 0)
- return ssh_get_next_identity(auth, comment, version);
- return NULL;
-}
-
-Key *
-ssh_get_next_identity(AuthenticationConnection *auth, char **comment, int version)
-{
- u_int bits;
- u_char *blob;
- u_int blen;
- Key *key = NULL;
-
- /* Return failure if no more entries. */
- if (auth->howmany <= 0)
- return NULL;
-
- /*
- * Get the next entry from the packet. These will abort with a fatal
- * error if the packet is too short or contains corrupt data.
- */
- switch (version) {
- case 1:
- key = key_new(KEY_RSA1);
- bits = buffer_get_int(&auth->identities);
- buffer_get_bignum(&auth->identities, key->rsa->e);
- buffer_get_bignum(&auth->identities, key->rsa->n);
- *comment = buffer_get_string(&auth->identities, NULL);
- if (bits != BN_num_bits(key->rsa->n))
- log("Warning: identity keysize mismatch: actual %d, announced %u",
- BN_num_bits(key->rsa->n), bits);
- break;
- case 2:
- blob = buffer_get_string(&auth->identities, &blen);
- *comment = buffer_get_string(&auth->identities, NULL);
- key = key_from_blob(blob, blen);
- xfree(blob);
- break;
- default:
- return NULL;
- break;
- }
- /* Decrement the number of remaining entries. */
- auth->howmany--;
- return key;
-}
-
-/*
- * Generates a random challenge, sends it to the agent, and waits for
- * response from the agent. Returns true (non-zero) if the agent gave the
- * correct answer, zero otherwise. Response type selects the style of
- * response desired, with 0 corresponding to protocol version 1.0 (no longer
- * supported) and 1 corresponding to protocol version 1.1.
- */
-
-int
-ssh_decrypt_challenge(AuthenticationConnection *auth,
- Key* key, BIGNUM *challenge,
- u_char session_id[16],
- u_int response_type,
- u_char response[16])
-{
- Buffer buffer;
- int success = 0;
- int i;
- int type;
-
- if (key->type != KEY_RSA1)
- return 0;
- if (response_type == 0) {
- log("Compatibility with ssh protocol version 1.0 no longer supported.");
- return 0;
- }
- buffer_init(&buffer);
- buffer_put_char(&buffer, SSH_AGENTC_RSA_CHALLENGE);
- buffer_put_int(&buffer, BN_num_bits(key->rsa->n));
- buffer_put_bignum(&buffer, key->rsa->e);
- buffer_put_bignum(&buffer, key->rsa->n);
- buffer_put_bignum(&buffer, challenge);
- buffer_append(&buffer, session_id, 16);
- buffer_put_int(&buffer, response_type);
-
- if (ssh_request_reply(auth, &buffer, &buffer) == 0) {
- buffer_free(&buffer);
- return 0;
- }
- type = buffer_get_char(&buffer);
-
- if (agent_failed(type)) {
- log("Agent admitted failure to authenticate using the key.");
- } else if (type != SSH_AGENT_RSA_RESPONSE) {
- fatal("Bad authentication response: %d", type);
- } else {
- success = 1;
- /*
- * Get the response from the packet. This will abort with a
- * fatal error if the packet is corrupt.
- */
- for (i = 0; i < 16; i++)
- response[i] = buffer_get_char(&buffer);
- }
- buffer_free(&buffer);
- return success;
-}
-
-/* ask agent to sign data, returns -1 on error, 0 on success */
-int
-ssh_agent_sign(AuthenticationConnection *auth,
- Key *key,
- u_char **sigp, u_int *lenp,
- u_char *data, u_int datalen)
-{
- Buffer msg;
- u_char *blob;
- u_int blen;
- int type, flags = 0;
- int ret = -1;
-
- if (key_to_blob(key, &blob, &blen) == 0)
- return -1;
-
- if (datafellows & SSH_BUG_SIGBLOB)
- flags = SSH_AGENT_OLD_SIGNATURE;
-
- buffer_init(&msg);
- buffer_put_char(&msg, SSH2_AGENTC_SIGN_REQUEST);
- buffer_put_string(&msg, blob, blen);
- buffer_put_string(&msg, data, datalen);
- buffer_put_int(&msg, flags);
- xfree(blob);
-
- if (ssh_request_reply(auth, &msg, &msg) == 0) {
- buffer_free(&msg);
- return -1;
- }
- type = buffer_get_char(&msg);
- if (agent_failed(type)) {
- log("Agent admitted failure to sign using the key.");
- } else if (type != SSH2_AGENT_SIGN_RESPONSE) {
- fatal("Bad authentication response: %d", type);
- } else {
- ret = 0;
- *sigp = buffer_get_string(&msg, lenp);
- }
- buffer_free(&msg);
- return ret;
-}
-
-/* Encode key for a message to the agent. */
-
-static void
-ssh_encode_identity_rsa1(Buffer *b, RSA *key, const char *comment)
-{
- buffer_put_int(b, BN_num_bits(key->n));
- buffer_put_bignum(b, key->n);
- buffer_put_bignum(b, key->e);
- buffer_put_bignum(b, key->d);
- /* To keep within the protocol: p < q for ssh. in SSL p > q */
- buffer_put_bignum(b, key->iqmp); /* ssh key->u */
- buffer_put_bignum(b, key->q); /* ssh key->p, SSL key->q */
- buffer_put_bignum(b, key->p); /* ssh key->q, SSL key->p */
- buffer_put_cstring(b, comment);
-}
-
-static void
-ssh_encode_identity_ssh2(Buffer *b, Key *key, const char *comment)
-{
- buffer_put_cstring(b, key_ssh_name(key));
- switch (key->type) {
- case KEY_RSA:
- buffer_put_bignum2(b, key->rsa->n);
- buffer_put_bignum2(b, key->rsa->e);
- buffer_put_bignum2(b, key->rsa->d);
- buffer_put_bignum2(b, key->rsa->iqmp);
- buffer_put_bignum2(b, key->rsa->p);
- buffer_put_bignum2(b, key->rsa->q);
- break;
- case KEY_DSA:
- buffer_put_bignum2(b, key->dsa->p);
- buffer_put_bignum2(b, key->dsa->q);
- buffer_put_bignum2(b, key->dsa->g);
- buffer_put_bignum2(b, key->dsa->pub_key);
- buffer_put_bignum2(b, key->dsa->priv_key);
- break;
- }
- buffer_put_cstring(b, comment);
-}
-
-/*
- * Adds an identity to the authentication server. This call is not meant to
- * be used by normal applications.
- */
-
-int
-ssh_add_identity_constrained(AuthenticationConnection *auth, Key *key,
- const char *comment, u_int life)
-{
- Buffer msg;
- int type, constrained = (life != 0);
-
- buffer_init(&msg);
-
- switch (key->type) {
- case KEY_RSA1:
- type = constrained ?
- SSH_AGENTC_ADD_RSA_ID_CONSTRAINED :
- SSH_AGENTC_ADD_RSA_IDENTITY;
- buffer_put_char(&msg, type);
- ssh_encode_identity_rsa1(&msg, key->rsa, comment);
- break;
- case KEY_RSA:
- case KEY_DSA:
- type = constrained ?
- SSH2_AGENTC_ADD_ID_CONSTRAINED :
- SSH2_AGENTC_ADD_IDENTITY;
- buffer_put_char(&msg, type);
- ssh_encode_identity_ssh2(&msg, key, comment);
- break;
- default:
- buffer_free(&msg);
- return 0;
- break;
- }
- if (constrained) {
- if (life != 0) {
- buffer_put_char(&msg, SSH_AGENT_CONSTRAIN_LIFETIME);
- buffer_put_int(&msg, life);
- }
- }
- if (ssh_request_reply(auth, &msg, &msg) == 0) {
- buffer_free(&msg);
- return 0;
- }
- type = buffer_get_char(&msg);
- buffer_free(&msg);
- return decode_reply(type);
-}
-
-int
-ssh_add_identity(AuthenticationConnection *auth, Key *key, const char *comment)
-{
- return ssh_add_identity_constrained(auth, key, comment, 0);
-}
-
-/*
- * Removes an identity from the authentication server. This call is not
- * meant to be used by normal applications.
- */
-
-int
-ssh_remove_identity(AuthenticationConnection *auth, Key *key)
-{
- Buffer msg;
- int type;
- u_char *blob;
- u_int blen;
-
- buffer_init(&msg);
-
- if (key->type == KEY_RSA1) {
- buffer_put_char(&msg, SSH_AGENTC_REMOVE_RSA_IDENTITY);
- buffer_put_int(&msg, BN_num_bits(key->rsa->n));
- buffer_put_bignum(&msg, key->rsa->e);
- buffer_put_bignum(&msg, key->rsa->n);
- } else if (key->type == KEY_DSA || key->type == KEY_RSA) {
- key_to_blob(key, &blob, &blen);
- buffer_put_char(&msg, SSH2_AGENTC_REMOVE_IDENTITY);
- buffer_put_string(&msg, blob, blen);
- xfree(blob);
- } else {
- buffer_free(&msg);
- return 0;
- }
- if (ssh_request_reply(auth, &msg, &msg) == 0) {
- buffer_free(&msg);
- return 0;
- }
- type = buffer_get_char(&msg);
- buffer_free(&msg);
- return decode_reply(type);
-}
-
-
-/*
- * Removes all identities from the agent. This call is not meant to be used
- * by normal applications.
- */
-
-int
-ssh_remove_all_identities(AuthenticationConnection *auth, int version)
-{
- Buffer msg;
- int type;
- int code = (version==1) ?
- SSH_AGENTC_REMOVE_ALL_RSA_IDENTITIES :
- SSH2_AGENTC_REMOVE_ALL_IDENTITIES;
-
- buffer_init(&msg);
- buffer_put_char(&msg, code);
-
- if (ssh_request_reply(auth, &msg, &msg) == 0) {
- buffer_free(&msg);
- return 0;
- }
- type = buffer_get_char(&msg);
- buffer_free(&msg);
- return decode_reply(type);
-}
-
-int
-decode_reply(int type)
-{
- switch (type) {
- case SSH_AGENT_FAILURE:
- case SSH_COM_AGENT2_FAILURE:
- case SSH2_AGENT_FAILURE:
- log("SSH_AGENT_FAILURE");
- return 0;
- case SSH_AGENT_SUCCESS:
- return 1;
- default:
- fatal("Bad response from authentication agent: %d", type);
- }
- /* NOTREACHED */
- return 0;
-}
diff --git a/usr/src/cmd/ssh/libssh/common/authfile.c b/usr/src/cmd/ssh/libssh/common/authfile.c
deleted file mode 100644
index 29076f390f..0000000000
--- a/usr/src/cmd/ssh/libssh/common/authfile.c
+++ /dev/null
@@ -1,624 +0,0 @@
-/*
- * Author: Tatu Ylonen <ylo@cs.hut.fi>
- * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
- * All rights reserved
- * This file contains functions for reading and writing identity files, and
- * for reading the passphrase from the user.
- *
- * As far as I am concerned, the code I have written for this software
- * can be used freely for any purpose. Any derived versions of this
- * software must be clearly marked as such, and if the derived work is
- * incompatible with the protocol description in the RFC file, it must be
- * called by a name other than "ssh" or "Secure Shell".
- *
- *
- * Copyright (c) 2000 Markus Friedl. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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.
- */
-
-#include "includes.h"
-RCSID("$OpenBSD: authfile.c,v 1.50 2002/06/24 14:55:38 markus Exp $");
-
-#pragma ident "%Z%%M% %I% %E% SMI"
-
-#include <openssl/err.h>
-#include <openssl/evp.h>
-#include <openssl/pem.h>
-
-#include "cipher.h"
-#include "xmalloc.h"
-#include "buffer.h"
-#include "bufaux.h"
-#include "key.h"
-#include "ssh.h"
-#include "log.h"
-#include "authfile.h"
-#include "rsa.h"
-
-/* Version identification string for SSH v1 identity files. */
-static const char authfile_id_string[] =
- "SSH PRIVATE KEY FILE FORMAT 1.1\n";
-
-/*
- * Saves the authentication (private) key in a file, encrypting it with
- * passphrase. The identification of the file (lowest 64 bits of n) will
- * precede the key to provide identification of the key without needing a
- * passphrase.
- */
-
-static int
-key_save_private_rsa1(Key *key, const char *filename, const char *passphrase,
- const char *comment)
-{
- Buffer buffer, encrypted;
- u_char buf[100], *cp;
- int fd, i, cipher_num;
- CipherContext ciphercontext;
- Cipher *cipher;
- u_int32_t rand;
-
- /*
- * If the passphrase is empty, use SSH_CIPHER_NONE to ease converting
- * to another cipher; otherwise use SSH_AUTHFILE_CIPHER.
- */
- cipher_num = (strcmp(passphrase, "") == 0) ?
- SSH_CIPHER_NONE : SSH_AUTHFILE_CIPHER;
- if ((cipher = cipher_by_number(cipher_num)) == NULL)
- fatal("save_private_key_rsa: bad cipher");
-
- /* This buffer is used to built the secret part of the private key. */
- buffer_init(&buffer);
-
- /* Put checkbytes for checking passphrase validity. */
- rand = arc4random();
- buf[0] = rand & 0xff;
- buf[1] = (rand >> 8) & 0xff;
- buf[2] = buf[0];
- buf[3] = buf[1];
- buffer_append(&buffer, buf, 4);
-
- /*
- * Store the private key (n and e will not be stored because they
- * will be stored in plain text, and storing them also in encrypted
- * format would just give known plaintext).
- */
- buffer_put_bignum(&buffer, key->rsa->d);
- buffer_put_bignum(&buffer, key->rsa->iqmp);
- buffer_put_bignum(&buffer, key->rsa->q); /* reverse from SSL p */
- buffer_put_bignum(&buffer, key->rsa->p); /* reverse from SSL q */
-
- /* Pad the part to be encrypted until its size is a multiple of 8. */
- while (buffer_len(&buffer) % 8 != 0)
- buffer_put_char(&buffer, 0);
-
- /* This buffer will be used to contain the data in the file. */
- buffer_init(&encrypted);
-
- /* First store keyfile id string. */
- for (i = 0; authfile_id_string[i]; i++)
- buffer_put_char(&encrypted, authfile_id_string[i]);
- buffer_put_char(&encrypted, 0);
-
- /* Store cipher type. */
- buffer_put_char(&encrypted, cipher_num);
- buffer_put_int(&encrypted, 0); /* For future extension */
-
- /* Store public key. This will be in plain text. */
- buffer_put_int(&encrypted, BN_num_bits(key->rsa->n));
- buffer_put_bignum(&encrypted, key->rsa->n);
- buffer_put_bignum(&encrypted, key->rsa->e);
- buffer_put_cstring(&encrypted, comment);
-
- /* Allocate space for the private part of the key in the buffer. */
- cp = buffer_append_space(&encrypted, buffer_len(&buffer));
-
- cipher_set_key_string(&ciphercontext, cipher, passphrase,
- CIPHER_ENCRYPT);
- cipher_crypt(&ciphercontext, cp,
- buffer_ptr(&buffer), buffer_len(&buffer));
- cipher_cleanup(&ciphercontext);
- memset(&ciphercontext, 0, sizeof(ciphercontext));
-
- /* Destroy temporary data. */
- memset(buf, 0, sizeof(buf));
- buffer_free(&buffer);
-
- fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC, 0600);
- if (fd < 0) {
- error("open %s failed: %s.", filename, strerror(errno));
- return 0;
- }
- if (write(fd, buffer_ptr(&encrypted), buffer_len(&encrypted)) !=
- buffer_len(&encrypted)) {
- error("write to key file %s failed: %s", filename,
- strerror(errno));
- buffer_free(&encrypted);
- close(fd);
- unlink(filename);
- return 0;
- }
- close(fd);
- buffer_free(&encrypted);
- return 1;
-}
-
-/* save SSH v2 key in OpenSSL PEM format */
-static int
-key_save_private_pem(Key *key, const char *filename, const char *_passphrase,
- const char *comment)
-{
- FILE *fp;
- int fd;
- int success = 0;
- int len = strlen(_passphrase);
- u_char *passphrase = (len > 0) ? (u_char *)_passphrase : NULL;
- const EVP_CIPHER *cipher = (len > 0) ? EVP_des_ede3_cbc() : NULL;
-
- if (len > 0 && len <= 4) {
- error("passphrase too short: have %d bytes, need > 4", len);
- return 0;
- }
- fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC, 0600);
- if (fd < 0) {
- error("open %s failed: %s.", filename, strerror(errno));
- return 0;
- }
- fp = fdopen(fd, "w");
- if (fp == NULL ) {
- error("fdopen %s failed: %s.", filename, strerror(errno));
- close(fd);
- return 0;
- }
- switch (key->type) {
- case KEY_DSA:
- success = PEM_write_DSAPrivateKey(fp, key->dsa,
- cipher, passphrase, len, NULL, NULL);
- break;
- case KEY_RSA:
- success = PEM_write_RSAPrivateKey(fp, key->rsa,
- cipher, passphrase, len, NULL, NULL);
- break;
- }
- fclose(fp);
- return success;
-}
-
-int
-key_save_private(Key *key, const char *filename, const char *passphrase,
- const char *comment)
-{
- switch (key->type) {
- case KEY_RSA1:
- return key_save_private_rsa1(key, filename, passphrase,
- comment);
- break;
- case KEY_DSA:
- case KEY_RSA:
- return key_save_private_pem(key, filename, passphrase,
- comment);
- break;
- default:
- break;
- }
- error("key_save_private: cannot save key type %d", key->type);
- return 0;
-}
-
-/*
- * Loads the public part of the ssh v1 key file. Returns NULL if an error was
- * encountered (the file does not exist or is not readable), and the key
- * otherwise.
- */
-
-static Key *
-key_load_public_rsa1(int fd, const char *filename, char **commentp)
-{
- Buffer buffer;
- Key *pub;
- char *cp;
- int i;
- off_t len;
-
- len = lseek(fd, (off_t) 0, SEEK_END);
- lseek(fd, (off_t) 0, SEEK_SET);
-
- buffer_init(&buffer);
- cp = buffer_append_space(&buffer, len);
-
- if (read(fd, cp, (size_t) len) != (size_t) len) {
- debug("Read from key file %.200s failed: %.100s", filename,
- strerror(errno));
- buffer_free(&buffer);
- return NULL;
- }
-
- /* Check that it is at least big enough to contain the ID string. */
- if (len < sizeof(authfile_id_string)) {
- debug3("Not a RSA1 key file %.200s.", filename);
- buffer_free(&buffer);
- return NULL;
- }
- /*
- * Make sure it begins with the id string. Consume the id string
- * from the buffer.
- */
- for (i = 0; i < sizeof(authfile_id_string); i++)
- if (buffer_get_char(&buffer) != authfile_id_string[i]) {
- debug3("Not a RSA1 key file %.200s.", filename);
- buffer_free(&buffer);
- return NULL;
- }
- /* Skip cipher type and reserved data. */
- (void) buffer_get_char(&buffer); /* cipher type */
- (void) buffer_get_int(&buffer); /* reserved */
-
- /* Read the public key from the buffer. */
- (void) buffer_get_int(&buffer);
- pub = key_new(KEY_RSA1);
- buffer_get_bignum(&buffer, pub->rsa->n);
- buffer_get_bignum(&buffer, pub->rsa->e);
- if (commentp)
- *commentp = buffer_get_string(&buffer, NULL);
- /* The encrypted private part is not parsed by this function. */
-
- buffer_free(&buffer);
- return pub;
-}
-
-/* load public key from private-key file, works only for SSH v1 */
-Key *
-key_load_public_type(int type, const char *filename, char **commentp)
-{
- Key *pub;
- int fd;
-
- if (type == KEY_RSA1) {
- fd = open(filename, O_RDONLY);
- if (fd < 0)
- return NULL;
- pub = key_load_public_rsa1(fd, filename, commentp);
- close(fd);
- return pub;
- }
- return NULL;
-}
-
-/*
- * Loads the private key from the file. Returns 0 if an error is encountered
- * (file does not exist or is not readable, or passphrase is bad). This
- * initializes the private key.
- * Assumes we are called under uid of the owner of the file.
- */
-
-static Key *
-key_load_private_rsa1(int fd, const char *filename, const char *passphrase,
- char **commentp)
-{
- int i, check1, check2, cipher_type;
- off_t len;
- Buffer buffer, decrypted;
- u_char *cp;
- CipherContext ciphercontext;
- Cipher *cipher;
- Key *prv = NULL;
-
- len = lseek(fd, (off_t) 0, SEEK_END);
- lseek(fd, (off_t) 0, SEEK_SET);
-
- buffer_init(&buffer);
- cp = buffer_append_space(&buffer, len);
-
- if (read(fd, cp, (size_t) len) != (size_t) len) {
- debug("Read from key file %.200s failed: %.100s", filename,
- strerror(errno));
- buffer_free(&buffer);
- close(fd);
- return NULL;
- }
-
- /* Check that it is at least big enough to contain the ID string. */
- if (len < sizeof(authfile_id_string)) {
- debug3("Not a RSA1 key file %.200s.", filename);
- buffer_free(&buffer);
- close(fd);
- return NULL;
- }
- /*
- * Make sure it begins with the id string. Consume the id string
- * from the buffer.
- */
- for (i = 0; i < sizeof(authfile_id_string); i++)
- if (buffer_get_char(&buffer) != authfile_id_string[i]) {
- debug3("Not a RSA1 key file %.200s.", filename);
- buffer_free(&buffer);
- close(fd);
- return NULL;
- }
-
- /* Read cipher type. */
- cipher_type = buffer_get_char(&buffer);
- (void) buffer_get_int(&buffer); /* Reserved data. */
-
- /* Read the public key from the buffer. */
- (void) buffer_get_int(&buffer);
- prv = key_new_private(KEY_RSA1);
-
- buffer_get_bignum(&buffer, prv->rsa->n);
- buffer_get_bignum(&buffer, prv->rsa->e);
- if (commentp)
- *commentp = buffer_get_string(&buffer, NULL);
- else
- xfree(buffer_get_string(&buffer, NULL));
-
- /* Check that it is a supported cipher. */
- cipher = cipher_by_number(cipher_type);
- if (cipher == NULL) {
- debug("Unsupported cipher %d used in key file %.200s.",
- cipher_type, filename);
- buffer_free(&buffer);
- goto fail;
- }
- /* Initialize space for decrypted data. */
- buffer_init(&decrypted);
- cp = buffer_append_space(&decrypted, buffer_len(&buffer));
-
- /* Rest of the buffer is encrypted. Decrypt it using the passphrase. */
- cipher_set_key_string(&ciphercontext, cipher, passphrase,
- CIPHER_DECRYPT);
- cipher_crypt(&ciphercontext, cp,
- buffer_ptr(&buffer), buffer_len(&buffer));
- cipher_cleanup(&ciphercontext);
- memset(&ciphercontext, 0, sizeof(ciphercontext));
- buffer_free(&buffer);
-
- check1 = buffer_get_char(&decrypted);
- check2 = buffer_get_char(&decrypted);
- if (check1 != buffer_get_char(&decrypted) ||
- check2 != buffer_get_char(&decrypted)) {
- if (strcmp(passphrase, "") != 0)
- debug("Bad passphrase supplied for key file %.200s.",
- filename);
- /* Bad passphrase. */
- buffer_free(&decrypted);
- goto fail;
- }
- /* Read the rest of the private key. */
- buffer_get_bignum(&decrypted, prv->rsa->d);
- buffer_get_bignum(&decrypted, prv->rsa->iqmp); /* u */
- /* in SSL and SSH v1 p and q are exchanged */
- buffer_get_bignum(&decrypted, prv->rsa->q); /* p */
- buffer_get_bignum(&decrypted, prv->rsa->p); /* q */
-
- /* calculate p-1 and q-1 */
- rsa_generate_additional_parameters(prv->rsa);
-
- buffer_free(&decrypted);
- close(fd);
- return prv;
-
-fail:
- if (commentp)
- xfree(*commentp);
- close(fd);
- key_free(prv);
- return NULL;
-}
-
-Key *
-key_load_private_pem(int fd, int type, const char *passphrase,
- char **commentp)
-{
- FILE *fp;
- EVP_PKEY *pk = NULL;
- Key *prv = NULL;
- char *name = "<no key>";
-
- fp = fdopen(fd, "r");
- if (fp == NULL) {
- error("fdopen failed: %s", strerror(errno));
- close(fd);
- return NULL;
- }
- pk = PEM_read_PrivateKey(fp, NULL, NULL, (char *)passphrase);
- if (pk == NULL) {
- debug("PEM_read_PrivateKey failed");
- (void)ERR_get_error();
- } else if (pk->type == EVP_PKEY_RSA &&
- (type == KEY_UNSPEC||type==KEY_RSA)) {
- prv = key_new(KEY_UNSPEC);
- prv->rsa = EVP_PKEY_get1_RSA(pk);
- prv->type = KEY_RSA;
- name = "rsa w/o comment";
-#ifdef DEBUG_PK
- RSA_print_fp(stderr, prv->rsa, 8);
-#endif
- } else if (pk->type == EVP_PKEY_DSA &&
- (type == KEY_UNSPEC||type==KEY_DSA)) {
- prv = key_new(KEY_UNSPEC);
- prv->dsa = EVP_PKEY_get1_DSA(pk);
- prv->type = KEY_DSA;
- name = "dsa w/o comment";
-#ifdef DEBUG_PK
- DSA_print_fp(stderr, prv->dsa, 8);
-#endif
- } else {
- error("PEM_read_PrivateKey: mismatch or "
- "unknown EVP_PKEY save_type %d", pk->save_type);
- }
- fclose(fp);
- if (pk != NULL)
- EVP_PKEY_free(pk);
- if (prv != NULL && commentp)
- *commentp = xstrdup(name);
- debug("read PEM private key done: type %s",
- prv ? key_type(prv) : "<unknown>");
- return prv;
-}
-
-static int
-key_perm_ok(int fd, const char *filename)
-{
- struct stat st;
-
- if (fstat(fd, &st) < 0)
- return 0;
- /*
- * if a key owned by the user is accessed, then we check the
- * permissions of the file. if the key owned by a different user,
- * then we don't care.
- */
-#ifdef HAVE_CYGWIN
- if (check_ntsec(filename))
-#endif
- if ((st.st_uid == getuid()) && (st.st_mode & 077) != 0) {
- error("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@");
- error("@ WARNING: UNPROTECTED PRIVATE KEY FILE! @");
- error("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@");
- error("Permissions 0%3.3o for '%s' are too open.",
- (int)(st.st_mode & 0777), filename);
- error("It is recommended that your private key files are NOT accessible by others.");
- error("This private key will be ignored.");
- return 0;
- }
- return 1;
-}
-
-Key *
-key_load_private_type(int type, const char *filename, const char *passphrase,
- char **commentp)
-{
- int fd;
-
- fd = open(filename, O_RDONLY);
- if (fd < 0)
- return NULL;
- if (!key_perm_ok(fd, filename)) {
- error("bad permissions: ignore key: %s", filename);
- close(fd);
- return NULL;
- }
- switch (type) {
- case KEY_RSA1:
- return key_load_private_rsa1(fd, filename, passphrase,
- commentp);
- /* closes fd */
- break;
- case KEY_DSA:
- case KEY_RSA:
- case KEY_UNSPEC:
- return key_load_private_pem(fd, type, passphrase, commentp);
- /* closes fd */
- break;
- default:
- close(fd);
- break;
- }
- return NULL;
-}
-
-Key *
-key_load_private(const char *filename, const char *passphrase,
- char **commentp)
-{
- Key *pub, *prv;
- int fd;
-
- fd = open(filename, O_RDONLY);
- if (fd < 0)
- return NULL;
- if (!key_perm_ok(fd, filename)) {
- error("bad permissions: ignore key: %s", filename);
- close(fd);
- return NULL;
- }
- pub = key_load_public_rsa1(fd, filename, commentp);
- lseek(fd, (off_t) 0, SEEK_SET); /* rewind */
- if (pub == NULL) {
- /* closes fd */
- prv = key_load_private_pem(fd, KEY_UNSPEC, passphrase, NULL);
- /* use the filename as a comment for PEM */
- if (commentp && prv)
- *commentp = xstrdup(filename);
- } else {
- /* it's a SSH v1 key if the public key part is readable */
- key_free(pub);
- /* closes fd */
- prv = key_load_private_rsa1(fd, filename, passphrase, NULL);
- }
- return prv;
-}
-
-static int
-key_try_load_public(Key *k, const char *filename, char **commentp)
-{
- FILE *f;
- char line[4096];
- char *cp;
-
- f = fopen(filename, "r");
- if (f != NULL) {
- while (fgets(line, sizeof(line), f)) {
- line[sizeof(line)-1] = '\0';
- cp = line;
- switch (*cp) {
- case '#':
- case '\n':
- case '\0':
- continue;
- }
- /* Skip leading whitespace. */
- for (; *cp && (*cp == ' ' || *cp == '\t'); cp++)
- ;
- if (*cp) {
- if (key_read(k, &cp) == 1) {
- if (commentp)
- *commentp=xstrdup(filename);
- fclose(f);
- return 1;
- }
- }
- }
- fclose(f);
- }
- return 0;
-}
-
-/* load public key from ssh v1 private or any pubkey file */
-Key *
-key_load_public(const char *filename, char **commentp)
-{
- Key *pub;
- char file[MAXPATHLEN];
-
- pub = key_load_public_type(KEY_RSA1, filename, commentp);
- if (pub != NULL)
- return pub;
- pub = key_new(KEY_UNSPEC);
- if (key_try_load_public(pub, filename, commentp) == 1)
- return pub;
- if ((strlcpy(file, filename, sizeof file) < sizeof(file)) &&
- (strlcat(file, ".pub", sizeof file) < sizeof(file)) &&
- (key_try_load_public(pub, file, commentp) == 1))
- return pub;
- key_free(pub);
- return NULL;
-}
diff --git a/usr/src/cmd/ssh/libssh/common/bufaux.c b/usr/src/cmd/ssh/libssh/common/bufaux.c
deleted file mode 100644
index 0a94ba9054..0000000000
--- a/usr/src/cmd/ssh/libssh/common/bufaux.c
+++ /dev/null
@@ -1,469 +0,0 @@
-/*
- * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
- */
-/*
- * Author: Tatu Ylonen <ylo@cs.hut.fi>
- * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
- * All rights reserved
- * Auxiliary functions for storing and retrieving various data types to/from
- * Buffers.
- *
- * As far as I am concerned, the code I have written for this software
- * can be used freely for any purpose. Any derived versions of this
- * software must be clearly marked as such, and if the derived work is
- * incompatible with the protocol description in the RFC file, it must be
- * called by a name other than "ssh" or "Secure Shell".
- *
- *
- * SSH2 packet format added by Markus Friedl
- * Copyright (c) 2000 Markus Friedl. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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.
- */
-
-#include "includes.h"
-RCSID("$OpenBSD: bufaux.c,v 1.27 2002/06/26 08:53:12 markus Exp $");
-
-#include <langinfo.h>
-#include <openssl/bn.h>
-#include "bufaux.h"
-#include "xmalloc.h"
-#include "getput.h"
-#include "log.h"
-#include "g11n.h"
-
-/*
- * Stores an BIGNUM in the buffer with a 2-byte msb first bit count, followed
- * by (bits+7)/8 bytes of binary data, msb first.
- */
-int
-buffer_put_bignum_ret(Buffer *buffer, const BIGNUM *value)
-{
- int bits = BN_num_bits(value);
- int bin_size = (bits + 7) / 8;
- u_char *buf = xmalloc(bin_size);
- int oi;
- char msg[2];
-
- /* Get the value of in binary */
- oi = BN_bn2bin(value, buf);
- if (oi != bin_size) {
- error("buffer_put_bignum_ret: BN_bn2bin() failed: oi %d != bin_size %d",
- oi, bin_size);
- xfree(buf);
- return (-1);
- }
-
- /* Store the number of bits in the buffer in two bytes, msb first. */
- PUT_16BIT(msg, bits);
- buffer_append(buffer, msg, 2);
- /* Store the binary data. */
- buffer_append(buffer, (char *)buf, oi);
-
- memset(buf, 0, bin_size);
- xfree(buf);
-
- return (0);
-}
-
-void
-buffer_put_bignum(Buffer *buffer, const BIGNUM *value)
-{
- if (buffer_put_bignum_ret(buffer, value) == -1)
- fatal("buffer_put_bignum: buffer error");
-}
-
-/*
- * Retrieves an BIGNUM from the buffer.
- */
-int
-buffer_get_bignum_ret(Buffer *buffer, BIGNUM *value)
-{
- u_int bits, bytes;
- u_char buf[2], *bin;
-
- /* Get the number for bits. */
- if (buffer_get_ret(buffer, (char *) buf, 2) == -1) {
- error("buffer_get_bignum_ret: invalid length");
- return (-1);
- }
- bits = GET_16BIT(buf);
- /* Compute the number of binary bytes that follow. */
- bytes = (bits + 7) / 8;
- if (bytes > 8 * 1024) {
- error("buffer_get_bignum_ret: cannot handle BN of size %d", bytes);
- return (-1);
- }
- if (buffer_len(buffer) < bytes) {
- error("buffer_get_bignum_ret: input buffer too small");
- return (-1);
- }
- bin = buffer_ptr(buffer);
- BN_bin2bn(bin, bytes, value);
- if (buffer_consume_ret(buffer, bytes) == -1) {
- error("buffer_get_bignum_ret: buffer_consume failed");
- return (-1);
- }
- return (0);
-}
-
-void
-buffer_get_bignum(Buffer *buffer, BIGNUM *value)
-{
- if (buffer_get_bignum_ret(buffer, value) == -1)
- fatal("buffer_get_bignum: buffer error");
-}
-
-/*
- * Stores an BIGNUM in the buffer in SSH2 format.
- */
-int
-buffer_put_bignum2_ret(Buffer *buffer, const BIGNUM *value)
-{
- u_int bytes;
- u_char *buf;
- int oi;
- u_int hasnohigh = 0;
-
- if (BN_is_zero(value)) {
- buffer_put_int(buffer, 0);
- return 0;
- }
- if (value->neg) {
- error("buffer_put_bignum2_ret: negative numbers not supported");
- return (-1);
- }
- bytes = BN_num_bytes(value) + 1; /* extra padding byte */
- if (bytes < 2) {
- error("buffer_put_bignum2_ret: BN too small");
- return (-1);
- }
- buf = xmalloc(bytes);
- buf[0] = 0x00;
- /* Get the value of in binary */
- oi = BN_bn2bin(value, buf+1);
- if (oi < 0 || (u_int)oi != bytes - 1) {
- error("buffer_put_bignum2_ret: BN_bn2bin() failed: "
- "oi %d != bin_size %d", oi, bytes);
- xfree(buf);
- return (-1);
- }
- hasnohigh = (buf[1] & 0x80) ? 0 : 1;
- buffer_put_string(buffer, buf+hasnohigh, bytes-hasnohigh);
- memset(buf, 0, bytes);
- xfree(buf);
- return (0);
-}
-
-void
-buffer_put_bignum2(Buffer *buffer, const BIGNUM *value)
-{
- if (buffer_put_bignum2_ret(buffer, value) == -1)
- fatal("buffer_put_bignum2: buffer error");
-}
-
-/* XXX does not handle negative BNs */
-int
-buffer_get_bignum2_ret(Buffer *buffer, BIGNUM *value)
-{
- u_int len;
- u_char *bin;
-
- if ((bin = buffer_get_string_ret(buffer, &len)) == NULL) {
- error("buffer_get_bignum2_ret: invalid bignum");
- return (-1);
- }
-
- if (len > 0 && (bin[0] & 0x80)) {
- error("buffer_get_bignum2_ret: negative numbers not supported");
- xfree(bin);
- return (-1);
- }
- if (len > 8 * 1024) {
- error("buffer_get_bignum2_ret: cannot handle BN of size %d", len);
- xfree(bin);
- return (-1);
- }
- BN_bin2bn(bin, len, value);
- xfree(bin);
- return (0);
-}
-
-void
-buffer_get_bignum2(Buffer *buffer, BIGNUM *value)
-{
- if (buffer_get_bignum2_ret(buffer, value) == -1)
- fatal("buffer_get_bignum2: buffer error");
-}
-
-/*
- * Returns integers from the buffer (msb first).
- */
-
-int
-buffer_get_short_ret(u_short *ret, Buffer *buffer)
-{
- u_char buf[2];
-
- if (buffer_get_ret(buffer, (char *) buf, 2) == -1)
- return (-1);
- *ret = GET_16BIT(buf);
- return (0);
-}
-
-u_short
-buffer_get_short(Buffer *buffer)
-{
- u_short ret;
-
- if (buffer_get_short_ret(&ret, buffer) == -1)
- fatal("buffer_get_short: buffer error");
-
- return (ret);
-}
-
-int
-buffer_get_int_ret(u_int *ret, Buffer *buffer)
-{
- u_char buf[4];
-
- if (buffer_get_ret(buffer, (char *) buf, 4) == -1)
- return (-1);
- *ret = GET_32BIT(buf);
- return (0);
-}
-
-u_int
-buffer_get_int(Buffer *buffer)
-{
- u_int ret;
-
- if (buffer_get_int_ret(&ret, buffer) == -1)
- fatal("buffer_get_int: buffer error");
-
- return (ret);
-}
-
-#ifdef HAVE_U_INT64_T
-int
-buffer_get_int64_ret(u_int64_t *ret, Buffer *buffer)
-{
- u_char buf[8];
-
- if (buffer_get_ret(buffer, (char *) buf, 8) == -1)
- return (-1);
- *ret = GET_64BIT(buf);
- return (0);
-}
-
-u_int64_t
-buffer_get_int64(Buffer *buffer)
-{
- u_int64_t ret;
-
- if (buffer_get_int64_ret(&ret, buffer) == -1)
- fatal("buffer_get_int: buffer error");
-
- return (ret);
-}
-#endif
-
-/*
- * Stores integers in the buffer, msb first.
- */
-void
-buffer_put_short(Buffer *buffer, u_short value)
-{
- char buf[2];
-
- PUT_16BIT(buf, value);
- buffer_append(buffer, buf, 2);
-}
-
-void
-buffer_put_int(Buffer *buffer, u_int value)
-{
- char buf[4];
-
- PUT_32BIT(buf, value);
- buffer_append(buffer, buf, 4);
-}
-
-#ifdef HAVE_U_INT64_T
-void
-buffer_put_int64(Buffer *buffer, u_int64_t value)
-{
- char buf[8];
-
- PUT_64BIT(buf, value);
- buffer_append(buffer, buf, 8);
-}
-#endif
-
-/*
- * Returns an arbitrary binary string from the buffer. The string cannot
- * be longer than 256k. The returned value points to memory allocated
- * with xmalloc; it is the responsibility of the calling function to free
- * the data. If length_ptr is non-NULL, the length of the returned data
- * will be stored there. A null character will be automatically appended
- * to the returned string, and is not counted in length.
- */
-void *
-buffer_get_string_ret(Buffer *buffer, u_int *length_ptr)
-{
- u_char *value;
- u_int len;
-
- /* Get the length. */
- len = buffer_get_int(buffer);
- if (len > 256 * 1024) {
- error("buffer_get_string_ret: bad string length %u", len);
- return (NULL);
- }
- /* Allocate space for the string. Add one byte for a null character. */
- value = xmalloc(len + 1);
- /* Get the string. */
- if (buffer_get_ret(buffer, value, len) == -1) {
- error("buffer_get_string_ret: buffer_get failed");
- xfree(value);
- return (NULL);
- }
- /* Append a null character to make processing easier. */
- value[len] = 0;
- /* Optionally return the length of the string. */
- if (length_ptr)
- *length_ptr = len;
- return (value);
-}
-
-void *
-buffer_get_string(Buffer *buffer, u_int *length_ptr)
-{
- void *ret;
-
- if ((ret = buffer_get_string_ret(buffer, length_ptr)) == NULL)
- fatal("buffer_get_string: buffer error");
- return (ret);
-}
-
-char *
-buffer_get_utf8_string(Buffer *buffer, uint_t *length_ptr)
-{
- char *value, *converted, *estr;
- uint_t len;
-
- if ((value = buffer_get_string(buffer, &len)) == NULL)
- return (value);
-
- converted = g11n_convert_from_utf8(value, &len, &estr);
- if (converted == NULL) {
- if (estr != NULL)
- error("invalid UTF-8 sequence: %s", estr);
- converted = value;
- } else {
- xfree(value);
- }
-
- if (length_ptr != NULL)
- *length_ptr = len;
-
- return (converted);
-}
-
-/*
- * Stores and arbitrary binary string in the buffer.
- */
-void
-buffer_put_string(Buffer *buffer, const void *buf, u_int len)
-{
- buffer_put_int(buffer, len);
- buffer_append(buffer, buf, len);
-}
-void
-buffer_put_cstring(Buffer *buffer, const char *s)
-{
- if (s == NULL)
- fatal("buffer_put_cstring: s == NULL");
- buffer_put_string(buffer, s, strlen(s));
-}
-
-/*
- * UTF-8 versions of the above.
- */
-void
-buffer_put_utf8_string(Buffer *buffer, const char *s, uint_t len)
-{
- char *converted, *estr;
- uint_t nlen = len;
-
- converted = g11n_convert_to_utf8(s, &nlen, 0, &estr);
- if (converted == NULL) {
- if (estr != NULL)
- error("Can't convert to UTF-8: %s", estr);
- converted = (char *)s;
- }
-
- buffer_put_string(buffer, converted, nlen);
-
- if (converted != s)
- xfree(converted);
-}
-
-void
-buffer_put_utf8_cstring(Buffer *buffer, const char *s)
-{
- buffer_put_utf8_string(buffer, s, strlen(s));
-}
-
-/*
- * Returns a character from the buffer (0 - 255).
- */
-int
-buffer_get_char_ret(char *ret, Buffer *buffer)
-{
- if (buffer_get_ret(buffer, ret, 1) == -1) {
- error("buffer_get_char_ret: buffer_get_ret failed");
- return (-1);
- }
- return (0);
-}
-
-int
-buffer_get_char(Buffer *buffer)
-{
- char ch;
-
- if (buffer_get_char_ret(&ch, buffer) == -1)
- fatal("buffer_get_char: buffer error");
- return (u_char) ch;
-}
-
-/*
- * Stores a character in the buffer.
- */
-void
-buffer_put_char(Buffer *buffer, int value)
-{
- char ch = value;
-
- buffer_append(buffer, &ch, 1);
-}
diff --git a/usr/src/cmd/ssh/libssh/common/buffer.c b/usr/src/cmd/ssh/libssh/common/buffer.c
deleted file mode 100644
index 2ec761b7ad..0000000000
--- a/usr/src/cmd/ssh/libssh/common/buffer.c
+++ /dev/null
@@ -1,263 +0,0 @@
-/*
- * Author: Tatu Ylonen <ylo@cs.hut.fi>
- * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
- * All rights reserved
- * Functions for manipulating fifo buffers (that can grow if needed).
- *
- * As far as I am concerned, the code I have written for this software
- * can be used freely for any purpose. Any derived versions of this
- * software must be clearly marked as such, and if the derived work is
- * incompatible with the protocol description in the RFC file, it must be
- * called by a name other than "ssh" or "Secure Shell".
- */
-/*
- * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
- */
-
-/* $OpenBSD: buffer.c,v 1.31 2006/08/03 03:34:41 deraadt Exp $ */
-
-#include "includes.h"
-
-#include "xmalloc.h"
-#include "buffer.h"
-#include "log.h"
-
-#define BUFFER_MAX_CHUNK 0x100000
-#define BUFFER_MAX_LEN 0xa00000
-#define BUFFER_ALLOCSZ 0x008000
-
-/* Initializes the buffer structure. */
-
-void
-buffer_init(Buffer *buffer)
-{
- const u_int len = 4096;
-
- buffer->alloc = 0;
- buffer->buf = xmalloc(len);
- buffer->alloc = len;
- buffer->offset = 0;
- buffer->end = 0;
-}
-
-/* Frees any memory used for the buffer. */
-
-void
-buffer_free(Buffer *buffer)
-{
- if (buffer->alloc > 0) {
- memset(buffer->buf, 0, buffer->alloc);
- buffer->alloc = 0;
- xfree(buffer->buf);
- }
-}
-
-/*
- * Clears any data from the buffer, making it empty. This does not actually
- * zero the memory.
- */
-
-void
-buffer_clear(Buffer *buffer)
-{
- buffer->offset = 0;
- buffer->end = 0;
-}
-
-/* Appends data to the buffer, expanding it if necessary. */
-
-void
-buffer_append(Buffer *buffer, const void *data, u_int len)
-{
- void *p;
- p = buffer_append_space(buffer, len);
- memcpy(p, data, len);
-}
-
-static int
-buffer_compact(Buffer *buffer)
-{
- /*
- * If the buffer is quite empty, but all data is at the end, move the
- * data to the beginning.
- */
- if (buffer->offset > MIN(buffer->alloc, BUFFER_MAX_CHUNK)) {
- memmove(buffer->buf, buffer->buf + buffer->offset,
- buffer->end - buffer->offset);
- buffer->end -= buffer->offset;
- buffer->offset = 0;
- return (1);
- }
- return (0);
-}
-
-/*
- * Appends space to the buffer, expanding the buffer if necessary. This does
- * not actually copy the data into the buffer, but instead returns a pointer
- * to the allocated region.
- */
-
-void *
-buffer_append_space(Buffer *buffer, u_int len)
-{
- u_int newlen;
- void *p;
-
- if (len > BUFFER_MAX_CHUNK)
- fatal("buffer_append_space: len %u not supported", len);
-
- /* If the buffer is empty, start using it from the beginning. */
- if (buffer->offset == buffer->end) {
- buffer->offset = 0;
- buffer->end = 0;
- }
-restart:
- /* If there is enough space to store all data, store it now. */
- if (buffer->end + len < buffer->alloc) {
- p = buffer->buf + buffer->end;
- buffer->end += len;
- return p;
- }
-
- /* Compact data back to the start of the buffer if necessary */
- if (buffer_compact(buffer))
- goto restart;
-
- /* Increase the size of the buffer and retry. */
- newlen = roundup(buffer->alloc + len, BUFFER_ALLOCSZ);
- if (newlen > BUFFER_MAX_LEN)
- fatal("buffer_append_space: alloc %u not supported",
- newlen);
- buffer->buf = xrealloc(buffer->buf, newlen);
- buffer->alloc = newlen;
- goto restart;
- /* NOTREACHED */
-}
-
-/*
- * Check whether an allocation of 'len' will fit in the buffer
- * This must follow the same math as buffer_append_space
- */
-int
-buffer_check_alloc(Buffer *buffer, u_int len)
-{
- if (buffer->offset == buffer->end) {
- buffer->offset = 0;
- buffer->end = 0;
- }
- restart:
- if (buffer->end + len < buffer->alloc)
- return (1);
- if (buffer_compact(buffer))
- goto restart;
- if (roundup(buffer->alloc + len, BUFFER_ALLOCSZ) <= BUFFER_MAX_LEN)
- return (1);
- return (0);
-}
-
-/* Returns the number of bytes of data in the buffer. */
-
-u_int
-buffer_len(Buffer *buffer)
-{
- return buffer->end - buffer->offset;
-}
-
-/* Gets data from the beginning of the buffer. */
-
-int
-buffer_get_ret(Buffer *buffer, void *buf, u_int len)
-{
- if (len > buffer->end - buffer->offset) {
- error("buffer_get_ret: trying to get more bytes %d than in buffer %d",
- len, buffer->end - buffer->offset);
- return (-1);
- }
- memcpy(buf, buffer->buf + buffer->offset, len);
- buffer->offset += len;
- return (0);
-}
-
-void
-buffer_get(Buffer *buffer, void *buf, u_int len)
-{
- if (buffer_get_ret(buffer, buf, len) == -1)
- fatal("buffer_get: buffer error");
-}
-
-/* Consumes the given number of bytes from the beginning of the buffer. */
-
-int
-buffer_consume_ret(Buffer *buffer, u_int bytes)
-{
- if (bytes > buffer->end - buffer->offset) {
- error("buffer_consume_ret: trying to get more bytes than in buffer");
- return (-1);
- }
- buffer->offset += bytes;
- return (0);
-}
-
-void
-buffer_consume(Buffer *buffer, u_int bytes)
-{
- if (buffer_consume_ret(buffer, bytes) == -1)
- fatal("buffer_consume: buffer error");
-}
-
-/* Consumes the given number of bytes from the end of the buffer. */
-
-int
-buffer_consume_end_ret(Buffer *buffer, u_int bytes)
-{
- if (bytes > buffer->end - buffer->offset)
- return (-1);
- buffer->end -= bytes;
- return (0);
-}
-
-void
-buffer_consume_end(Buffer *buffer, u_int bytes)
-{
- if (buffer_consume_end_ret(buffer, bytes) == -1)
- fatal("buffer_consume_end: trying to get more bytes than in buffer");
-}
-
-/* Returns a pointer to the first used byte in the buffer. */
-
-void *
-buffer_ptr(Buffer *buffer)
-{
- return buffer->buf + buffer->offset;
-}
-
-/* Dumps the contents of the buffer to stderr. */
-void
-buffer_dump(Buffer *buffer)
-{
- u_int i;
- u_char *ucp = buffer->buf;
-
- for (i = buffer->offset; i < buffer->end; i++) {
- fprintf(stderr, "%02x", ucp[i]);
- if ((i-buffer->offset)%16==15)
- fprintf(stderr, "\n");
- else if ((i-buffer->offset)%2==1)
- fprintf(stderr, " ");
- }
-
- if (buffer->offset == buffer->end) {
- /* explicitly state when the buffer is empty */
- fprintf(stderr, "<EMPTY BUFFER>\n");
- } else {
- /* print the terminal '\n' if it wasn't already printed */
- if ((i - buffer->offset) % 16 != 0)
- fprintf(stderr, "\n");
- }
- /*
- * We want an extra empty line after the packet dump for better
- * readability.
- */
- fprintf(stderr, "\n");
-}
diff --git a/usr/src/cmd/ssh/libssh/common/canohost.c b/usr/src/cmd/ssh/libssh/common/canohost.c
deleted file mode 100644
index 2d427b9e8d..0000000000
--- a/usr/src/cmd/ssh/libssh/common/canohost.c
+++ /dev/null
@@ -1,391 +0,0 @@
-/*
- * Author: Tatu Ylonen <ylo@cs.hut.fi>
- * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
- * All rights reserved
- * Functions for returning the canonical host name of the remote site.
- *
- * As far as I am concerned, the code I have written for this software
- * can be used freely for any purpose. Any derived versions of this
- * software must be clearly marked as such, and if the derived work is
- * incompatible with the protocol description in the RFC file, it must be
- * called by a name other than "ssh" or "Secure Shell".
- */
-/*
- * Copyright 2003 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
- *
- * Copyright 2012 Nexenta Systems, Inc. All rights reserved.
- */
-
-#include "includes.h"
-RCSID("$OpenBSD: canohost.c,v 1.34 2002/09/23 20:46:27 stevesk Exp $");
-
-#include "packet.h"
-#include "xmalloc.h"
-#include "log.h"
-#include "canohost.h"
-
-static const char *inet_ntop_native(int af, const void *src,
- char *dst, size_t size);
-
-
-/*
- * Return the canonical name of the host at the other end of the socket. The
- * caller should free the returned string with xfree.
- */
-
-static char *
-get_remote_hostname(int socket, int verify_reverse_mapping)
-{
- struct sockaddr_storage from;
- int i, res;
- socklen_t fromlen;
- struct addrinfo hints, *ai, *aitop;
- char name[NI_MAXHOST], ntop[NI_MAXHOST], ntop2[NI_MAXHOST];
-
- /* Get IP address of client. */
- fromlen = sizeof(from);
- memset(&from, 0, sizeof(from));
- if (getpeername(socket, (struct sockaddr *) &from, &fromlen) < 0) {
- debug("getpeername failed: %.100s", strerror(errno));
- fatal_cleanup();
- }
-
- if ((res = getnameinfo((struct sockaddr *)&from, fromlen, ntop, sizeof(ntop),
- NULL, 0, NI_NUMERICHOST)) != 0)
- fatal("get_remote_hostname: getnameinfo NI_NUMERICHOST failed: %d", res);
-
-#ifdef IPV4_IN_IPV6
- if (from.ss_family == AF_INET6) {
- struct sockaddr_in6 *from6 = (struct sockaddr_in6 *)&from;
-
- (void) inet_ntop_native(from.ss_family,
- from6->sin6_addr.s6_addr,
- ntop, sizeof(ntop));
- }
-#endif /* IPV4_IN_IPV6 */
-
- if (!verify_reverse_mapping)
- return xstrdup(ntop);
-
- debug3("Trying to reverse map address %.100s.", ntop);
- /* Map the IP address to a host name. */
- if (getnameinfo((struct sockaddr *)&from, fromlen, name, sizeof(name),
- NULL, 0, NI_NAMEREQD) != 0) {
- /* Host name not found. Use ip address. */
-#if 0
- log("Could not reverse map address %.100s.", ntop);
-#endif
- return xstrdup(ntop);
- }
-
- /* Got host name. */
- name[sizeof(name) - 1] = '\0';
- /*
- * Convert it to all lowercase (which is expected by the rest
- * of this software).
- */
- for (i = 0; name[i]; i++)
- if (isupper(name[i]))
- name[i] = tolower(name[i]);
-
- /*
- * Map it back to an IP address and check that the given
- * address actually is an address of this host. This is
- * necessary because anyone with access to a name server can
- * define arbitrary names for an IP address. Mapping from
- * name to IP address can be trusted better (but can still be
- * fooled if the intruder has access to the name server of
- * the domain).
- */
- memset(&hints, 0, sizeof(hints));
- hints.ai_family = from.ss_family;
- hints.ai_socktype = SOCK_STREAM;
- if (getaddrinfo(name, NULL, &hints, &aitop) != 0) {
- log("reverse mapping checking getaddrinfo for %.700s "
- "failed - POSSIBLE BREAKIN ATTEMPT!", name);
- return xstrdup(ntop);
- }
- /* Look for the address from the list of addresses. */
- for (ai = aitop; ai; ai = ai->ai_next) {
- if (getnameinfo(ai->ai_addr, ai->ai_addrlen, ntop2,
- sizeof(ntop2), NULL, 0, NI_NUMERICHOST) == 0 &&
- (strcmp(ntop, ntop2) == 0))
- break;
- }
- freeaddrinfo(aitop);
- /* If we reached the end of the list, the address was not there. */
- if (!ai) {
- /* Address not found for the host name. */
- log("Address %.100s maps to %.600s, but this does not "
- "map back to the address - POSSIBLE BREAKIN ATTEMPT!",
- ntop, name);
- return xstrdup(ntop);
- }
- return xstrdup(name);
-}
-
-/*
- * Return the canonical name of the host in the other side of the current
- * connection. The host name is cached, so it is efficient to call this
- * several times.
- */
-
-const char *
-get_canonical_hostname(int verify_reverse_mapping)
-{
- static char *canonical_host_name = NULL;
- static int verify_reverse_mapping_done = 0;
-
- /* Check if we have previously retrieved name with same option. */
- if (canonical_host_name != NULL) {
- if (verify_reverse_mapping_done != verify_reverse_mapping)
- xfree(canonical_host_name);
- else
- return canonical_host_name;
- }
-
- /* Get the real hostname if socket; otherwise return UNKNOWN. */
- if (packet_connection_is_on_socket())
- canonical_host_name = get_remote_hostname(
- packet_get_connection_in(), verify_reverse_mapping);
- else
- canonical_host_name = xstrdup("UNKNOWN");
-
- verify_reverse_mapping_done = verify_reverse_mapping;
- return canonical_host_name;
-}
-
-/*
- * Returns the remote IP-address of socket as a string. The returned
- * string must be freed.
- */
-char *
-get_socket_address(int socket, int remote, int flags)
-{
- struct sockaddr_storage addr;
- struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)&addr;
- socklen_t addrlen;
- char ntop[NI_MAXHOST];
- const char *result;
- char abuf[INET6_ADDRSTRLEN];
-
- /* Get IP address of client. */
- addrlen = sizeof (addr);
- memset(&addr, 0, sizeof (addr));
-
- if (remote) {
- if (getpeername(socket, (struct sockaddr *)&addr, &addrlen)
- < 0) {
- debug("get_socket_ipaddr: getpeername failed: %.100s",
- strerror(errno));
- return (NULL);
- }
- } else {
- if (getsockname(socket, (struct sockaddr *)&addr, &addrlen)
- < 0) {
- debug("get_socket_ipaddr: getsockname failed: %.100s",
- strerror(errno));
- return (NULL);
- }
- }
-
- /* Get the address in ascii. */
- if (getnameinfo((struct sockaddr *)&addr, addrlen, ntop, sizeof (ntop),
- NULL, 0, flags) != 0) {
- error("get_socket_ipaddr: getnameinfo %d failed", flags);
- return (NULL);
- }
-
- if (addr.ss_family == AF_INET) {
- return (xstrdup(ntop));
- }
-
- result = inet_ntop_native(addr.ss_family,
- addr6->sin6_addr.s6_addr, abuf, sizeof (abuf));
-
- return (xstrdup(result));
-}
-#if 0
-static char *
-get_socket_address(int socket, int remote, int flags)
-{
- struct sockaddr_storage addr;
- socklen_t addrlen;
- char ntop[NI_MAXHOST];
-
- /* Get IP address of client. */
- addrlen = sizeof(addr);
- memset(&addr, 0, sizeof(addr));
-
- if (remote) {
- if (getpeername(socket, (struct sockaddr *)&addr, &addrlen)
- < 0)
- return NULL;
- } else {
- if (getsockname(socket, (struct sockaddr *)&addr, &addrlen)
- < 0)
- return NULL;
- }
- /* Get the address in ascii. */
- if (getnameinfo((struct sockaddr *)&addr, addrlen, ntop, sizeof(ntop),
- NULL, 0, flags) != 0) {
- error("get_socket_ipaddr: getnameinfo %d failed", flags);
- return NULL;
- }
- return xstrdup(ntop);
-}
-#endif
-
-char *
-get_peer_ipaddr(int socket)
-{
- char *p;
-
- if ((p = get_socket_address(socket, 1, NI_NUMERICHOST)) != NULL)
- return p;
- return xstrdup("UNKNOWN");
-}
-
-char *
-get_local_ipaddr(int socket)
-{
- char *p;
-
- if ((p = get_socket_address(socket, 0, NI_NUMERICHOST)) != NULL)
- return p;
- return xstrdup("UNKNOWN");
-}
-
-char *
-get_local_name(int socket)
-{
- return get_socket_address(socket, 0, NI_NAMEREQD);
-}
-
-/*
- * Returns the IP-address of the remote host as a string. The returned
- * string must not be freed.
- */
-
-const char *
-get_remote_ipaddr(void)
-{
- static char *canonical_host_ip = NULL;
-
- /* Check whether we have cached the ipaddr. */
- if (canonical_host_ip == NULL) {
- if (packet_connection_is_on_socket()) {
- canonical_host_ip =
- get_peer_ipaddr(packet_get_connection_in());
- if (canonical_host_ip == NULL)
- fatal_cleanup();
- } else {
- /* If not on socket, return UNKNOWN. */
- canonical_host_ip = xstrdup("UNKNOWN");
- }
- }
- return canonical_host_ip;
-}
-
-const char *
-get_remote_name_or_ip(u_int utmp_len, int verify_reverse_mapping)
-{
- static const char *remote = "";
- if (utmp_len > 0)
- remote = get_canonical_hostname(verify_reverse_mapping);
- if (utmp_len == 0 || strlen(remote) > utmp_len)
- remote = get_remote_ipaddr();
- return remote;
-}
-
-/* Returns the local/remote port for the socket. */
-
-static int
-get_sock_port(int sock, int local)
-{
- struct sockaddr_storage from;
- socklen_t fromlen;
- char strport[NI_MAXSERV];
-
- /* Get IP address of client. */
- fromlen = sizeof(from);
- memset(&from, 0, sizeof(from));
- if (local) {
- if (getsockname(sock, (struct sockaddr *)&from, &fromlen) < 0) {
- error("getsockname failed: %.100s", strerror(errno));
- return 0;
- }
- } else {
- if (getpeername(sock, (struct sockaddr *) & from, &fromlen) < 0) {
- debug("getpeername failed: %.100s", strerror(errno));
- fatal_cleanup();
- }
- }
- /* Return port number. */
- if (getnameinfo((struct sockaddr *)&from, fromlen, NULL, 0,
- strport, sizeof(strport), NI_NUMERICSERV) != 0)
- fatal("get_sock_port: getnameinfo NI_NUMERICSERV failed");
- return atoi(strport);
-}
-
-/* Returns remote/local port number for the current connection. */
-
-static int
-get_port(int local)
-{
- /*
- * If the connection is not a socket, return 65535. This is
- * intentionally chosen to be an unprivileged port number.
- */
- if (!packet_connection_is_on_socket())
- return 65535;
-
- /* Get socket and return the port number. */
- return get_sock_port(packet_get_connection_in(), local);
-}
-
-int
-get_peer_port(int sock)
-{
- return get_sock_port(sock, 0);
-}
-
-int
-get_remote_port(void)
-{
- return get_port(0);
-}
-
-int
-get_local_port(void)
-{
- return get_port(1);
-}
-
-/*
- * Taken from inetd.c
- * This is a wrapper function for inet_ntop(). In case the af is AF_INET6
- * and the address pointed by src is a IPv4-mapped IPv6 address, it
- * returns printable IPv4 address, not IPv4-mapped IPv6 address. In other cases
- * it behaves just like inet_ntop().
- */
-static const char *
-inet_ntop_native(int af, const void *src, char *dst, size_t size)
-{
- struct in_addr src4;
- const char *result;
-
- if (af == AF_INET6) {
- if (IN6_IS_ADDR_V4MAPPED((struct in6_addr *)src)) {
- IN6_V4MAPPED_TO_INADDR((struct in6_addr *)src, &src4);
- result = inet_ntop(AF_INET, &src4, dst, size);
- } else {
- result = inet_ntop(AF_INET6, src, dst, size);
- }
- } else {
- result = inet_ntop(af, src, dst, size);
- }
-
- return (result);
-}
diff --git a/usr/src/cmd/ssh/libssh/common/channels.c b/usr/src/cmd/ssh/libssh/common/channels.c
deleted file mode 100644
index 7133758b73..0000000000
--- a/usr/src/cmd/ssh/libssh/common/channels.c
+++ /dev/null
@@ -1,3035 +0,0 @@
-/*
- * Author: Tatu Ylonen <ylo@cs.hut.fi>
- * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
- * All rights reserved
- * This file contains functions for generic socket connection forwarding.
- * There is also code for initiating connection forwarding for X11 connections,
- * arbitrary tcp/ip connections, and the authentication agent connection.
- *
- * As far as I am concerned, the code I have written for this software
- * can be used freely for any purpose. Any derived versions of this
- * software must be clearly marked as such, and if the derived work is
- * incompatible with the protocol description in the RFC file, it must be
- * called by a name other than "ssh" or "Secure Shell".
- *
- * SSH2 support added by Markus Friedl.
- * Copyright (c) 1999, 2000, 2001, 2002 Markus Friedl. All rights reserved.
- * Copyright (c) 1999 Dug Song. All rights reserved.
- * Copyright (c) 1999 Theo de Raadt. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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.
- */
-/*
- * Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved.
- */
-
-#include "includes.h"
-RCSID("$OpenBSD: channels.c,v 1.183 2002/09/17 07:47:02 itojun Exp $");
-
-#include "ssh.h"
-#include "ssh1.h"
-#include "ssh2.h"
-#include "packet.h"
-#include "xmalloc.h"
-#include "log.h"
-#include "misc.h"
-#include "channels.h"
-#include "compat.h"
-#include "canohost.h"
-#include "key.h"
-#include "authfd.h"
-#include "pathnames.h"
-#include "bufaux.h"
-
-
-/* -- channel core */
-
-/*
- * Pointer to an array containing all allocated channels. The array is
- * dynamically extended as needed.
- */
-static Channel **channels = NULL;
-
-/*
- * Size of the channel array. All slots of the array must always be
- * initialized (at least the type field); unused slots set to NULL
- */
-static int channels_alloc = 0;
-
-/*
- * Maximum file descriptor value used in any of the channels. This is
- * updated in channel_new.
- */
-static int channel_max_fd = 0;
-
-
-/* -- tcp forwarding */
-
-/*
- * Data structure for storing which hosts are permitted for forward requests.
- * The local sides of any remote forwards are stored in this array to prevent
- * a corrupt remote server from accessing arbitrary TCP/IP ports on our local
- * network (which might be behind a firewall).
- */
-typedef struct {
- char *host_to_connect; /* Connect to 'host'. */
- u_short port_to_connect; /* Connect to 'port'. */
- u_short listen_port; /* Remote side should listen port number. */
-} ForwardPermission;
-
-/* List of all permitted host/port pairs to connect. */
-static ForwardPermission permitted_opens[SSH_MAX_FORWARDS_PER_DIRECTION];
-
-/* Number of permitted host/port pairs in the array. */
-static int num_permitted_opens = 0;
-/*
- * If this is true, all opens are permitted. This is the case on the server
- * on which we have to trust the client anyway, and the user could do
- * anything after logging in anyway.
- */
-static int all_opens_permitted = 0;
-
-
-/* -- X11 forwarding */
-
-/* Maximum number of fake X11 displays to try. */
-#define MAX_DISPLAYS 1000
-
-/* Saved X11 authentication protocol name. */
-static char *x11_saved_proto = NULL;
-
-/* Saved X11 authentication data. This is the real data. */
-static char *x11_saved_data = NULL;
-static u_int x11_saved_data_len = 0;
-
-/*
- * Fake X11 authentication data. This is what the server will be sending us;
- * we should replace any occurrences of this by the real data.
- */
-static u_char *x11_fake_data = NULL;
-static u_int x11_fake_data_len;
-
-
-/* -- agent forwarding */
-
-#define NUM_SOCKS 10
-
-/* AF_UNSPEC or AF_INET or AF_INET6 */
-static int IPv4or6 = AF_UNSPEC;
-
-/* helper */
-static void port_open_helper(Channel *c, char *rtype);
-
-/* -- channel core */
-
-Channel *
-channel_lookup(int id)
-{
- Channel *c;
-
- if (id < 0 || id >= channels_alloc) {
- log("channel_lookup: %d: bad id", id);
- return NULL;
- }
- c = channels[id];
- if (c == NULL) {
- log("channel_lookup: %d: bad id: channel free", id);
- return NULL;
- }
- return c;
-}
-
-/*
- * Register filedescriptors for a channel, used when allocating a channel or
- * when the channel consumer/producer is ready, e.g. shell exec'd
- */
-
-static void
-channel_register_fds(Channel *c, int rfd, int wfd, int efd,
- int extusage, int nonblock)
-{
- /* Update the maximum file descriptor value. */
- channel_max_fd = MAX(channel_max_fd, rfd);
- channel_max_fd = MAX(channel_max_fd, wfd);
- channel_max_fd = MAX(channel_max_fd, efd);
-
- /* XXX set close-on-exec -markus */
-
- c->rfd = rfd;
- c->wfd = wfd;
- c->sock = (rfd == wfd) ? rfd : -1;
- c->efd = efd;
- c->extended_usage = extusage;
-
- /* XXX ugly hack: nonblock is only set by the server */
- if (nonblock && isatty(c->rfd)) {
- debug("channel %d: rfd %d isatty", c->self, c->rfd);
- c->isatty = 1;
- if (!isatty(c->wfd)) {
- error("channel %d: wfd %d is not a tty?",
- c->self, c->wfd);
- }
- } else {
- c->isatty = 0;
- }
- c->wfd_isatty = isatty(c->wfd);
-
- /* enable nonblocking mode */
- if (nonblock) {
- if (rfd != -1)
- set_nonblock(rfd);
- if (wfd != -1)
- set_nonblock(wfd);
- if (efd != -1)
- set_nonblock(efd);
- }
-}
-
-/*
- * Allocate a new channel object and set its type and socket. This will cause
- * remote_name to be freed.
- */
-
-Channel *
-channel_new(char *ctype, int type, int rfd, int wfd, int efd,
- u_int window, u_int maxpack, int extusage, char *remote_name, int nonblock)
-{
- int i, found;
- Channel *c;
-
- /* Do initial allocation if this is the first call. */
- if (channels_alloc == 0) {
- channels_alloc = 10;
- channels = xmalloc(channels_alloc * sizeof(Channel *));
- for (i = 0; i < channels_alloc; i++)
- channels[i] = NULL;
- fatal_add_cleanup((void (*) (void *)) channel_free_all, NULL);
- }
- /* Try to find a free slot where to put the new channel. */
- for (found = -1, i = 0; i < channels_alloc; i++)
- if (channels[i] == NULL) {
- /* Found a free slot. */
- found = i;
- break;
- }
- if (found == -1) {
- /* There are no free slots. Take last+1 slot and expand the array. */
- found = channels_alloc;
- if (channels_alloc > 10000)
- fatal("channel_new: internal error: channels_alloc %d "
- "too big.", channels_alloc);
- channels = xrealloc(channels,
- (channels_alloc + 10) * sizeof(Channel *));
- channels_alloc += 10;
- debug2("channel: expanding %d", channels_alloc);
- for (i = found; i < channels_alloc; i++)
- channels[i] = NULL;
- }
- /* Initialize and return new channel. */
- c = channels[found] = xmalloc(sizeof(Channel));
- memset(c, 0, sizeof(Channel));
- buffer_init(&c->input);
- buffer_init(&c->output);
- buffer_init(&c->extended);
- c->ostate = CHAN_OUTPUT_OPEN;
- c->istate = CHAN_INPUT_OPEN;
- c->flags = 0;
- channel_register_fds(c, rfd, wfd, efd, extusage, nonblock);
- c->self = found;
- c->type = type;
- c->ctype = ctype;
- c->local_window = window;
- c->local_window_max = window;
- c->local_consumed = 0;
- c->local_maxpacket = maxpack;
- c->remote_id = -1;
- c->remote_name = remote_name;
- c->remote_window = 0;
- c->remote_maxpacket = 0;
- c->force_drain = 0;
- c->single_connection = 0;
- c->detach_user = NULL;
- c->confirm = NULL;
- c->input_filter = NULL;
- c->delayed = 1; /* prevent call to channel_post handler */
- debug("channel %d: new [%s]", found, remote_name);
- return c;
-}
-
-static int
-channel_find_maxfd(void)
-{
- int i, max = 0;
- Channel *c;
-
- for (i = 0; i < channels_alloc; i++) {
- c = channels[i];
- if (c != NULL) {
- max = MAX(max, c->rfd);
- max = MAX(max, c->wfd);
- max = MAX(max, c->efd);
- }
- }
- return max;
-}
-
-int
-channel_close_fd(int *fdp)
-{
- int ret = 0, fd = *fdp;
-
- if (fd != -1) {
- ret = close(fd);
- *fdp = -1;
- if (fd == channel_max_fd)
- channel_max_fd = channel_find_maxfd();
- }
- return ret;
-}
-
-/* Close all channel fd/socket. */
-
-static void
-channel_close_fds(Channel *c)
-{
- debug3("channel_close_fds: channel %d: r %d w %d e %d",
- c->self, c->rfd, c->wfd, c->efd);
-
- channel_close_fd(&c->sock);
- channel_close_fd(&c->rfd);
- channel_close_fd(&c->wfd);
- channel_close_fd(&c->efd);
-}
-
-/* Free the channel and close its fd/socket. */
-
-void
-channel_free(Channel *c)
-{
- char *s;
- int i, n;
-
- for (n = 0, i = 0; i < channels_alloc; i++)
- if (channels[i])
- n++;
- debug("channel_free: channel %d: %s, nchannels %d", c->self,
- c->remote_name ? c->remote_name : "???", n);
-
- s = channel_open_message();
- debug3("channel_free: status: %s", s);
- xfree(s);
-
- if (c->sock != -1)
- shutdown(c->sock, SHUT_RDWR);
- channel_close_fds(c);
- buffer_free(&c->input);
- buffer_free(&c->output);
- buffer_free(&c->extended);
- if (c->remote_name) {
- xfree(c->remote_name);
- c->remote_name = NULL;
- }
- channels[c->self] = NULL;
- xfree(c);
-}
-
-void
-channel_free_all(void)
-{
- int i;
-
- for (i = 0; i < channels_alloc; i++)
- if (channels[i] != NULL)
- channel_free(channels[i]);
-}
-
-/*
- * Closes the sockets/fds of all channels. This is used to close extra file
- * descriptors after a fork.
- */
-
-void
-channel_close_all(void)
-{
- int i;
-
- for (i = 0; i < channels_alloc; i++)
- if (channels[i] != NULL)
- channel_close_fds(channels[i]);
-}
-
-/*
- * Stop listening to channels.
- */
-
-void
-channel_stop_listening(void)
-{
- int i;
- Channel *c;
-
- for (i = 0; i < channels_alloc; i++) {
- c = channels[i];
- if (c != NULL) {
- switch (c->type) {
- case SSH_CHANNEL_AUTH_SOCKET:
- case SSH_CHANNEL_PORT_LISTENER:
- case SSH_CHANNEL_RPORT_LISTENER:
- case SSH_CHANNEL_X11_LISTENER:
- channel_close_fd(&c->sock);
- channel_free(c);
- break;
- }
- }
- }
-}
-
-/*
- * Returns true if no channel has too much buffered data, and false if one or
- * more channel is overfull.
- */
-
-int
-channel_not_very_much_buffered_data(void)
-{
- u_int i;
- Channel *c;
-
- for (i = 0; i < channels_alloc; i++) {
- c = channels[i];
- if (c != NULL && c->type == SSH_CHANNEL_OPEN) {
-#if 0
- if (!compat20 &&
- buffer_len(&c->input) > packet_get_maxsize()) {
- debug("channel %d: big input buffer %d",
- c->self, buffer_len(&c->input));
- return 0;
- }
-#endif
- if (buffer_len(&c->output) > packet_get_maxsize()) {
- debug("channel %d: big output buffer %d > %d",
- c->self, buffer_len(&c->output),
- packet_get_maxsize());
- return 0;
- }
- }
- }
- return 1;
-}
-
-/* Returns true if any channel is still open. */
-
-int
-channel_still_open(void)
-{
- int i;
- Channel *c;
-
- for (i = 0; i < channels_alloc; i++) {
- c = channels[i];
- if (c == NULL)
- continue;
- switch (c->type) {
- case SSH_CHANNEL_X11_LISTENER:
- case SSH_CHANNEL_PORT_LISTENER:
- case SSH_CHANNEL_RPORT_LISTENER:
- case SSH_CHANNEL_CLOSED:
- case SSH_CHANNEL_AUTH_SOCKET:
- case SSH_CHANNEL_DYNAMIC:
- case SSH_CHANNEL_CONNECTING:
- case SSH_CHANNEL_ZOMBIE:
- continue;
- case SSH_CHANNEL_LARVAL:
- if (!compat20)
- fatal("cannot happen: SSH_CHANNEL_LARVAL");
- continue;
- case SSH_CHANNEL_OPENING:
- case SSH_CHANNEL_OPEN:
- case SSH_CHANNEL_X11_OPEN:
- return 1;
- case SSH_CHANNEL_INPUT_DRAINING:
- case SSH_CHANNEL_OUTPUT_DRAINING:
- if (!compat13)
- fatal("cannot happen: OUT_DRAIN");
- return 1;
- default:
- fatal("channel_still_open: bad channel type %d", c->type);
- /* NOTREACHED */
- }
- }
- return 0;
-}
-
-/* Returns the id of an open channel suitable for keepaliving */
-
-int
-channel_find_open(void)
-{
- int i;
- Channel *c;
-
- for (i = 0; i < channels_alloc; i++) {
- c = channels[i];
- if (c == NULL)
- continue;
- switch (c->type) {
- case SSH_CHANNEL_CLOSED:
- case SSH_CHANNEL_DYNAMIC:
- case SSH_CHANNEL_X11_LISTENER:
- case SSH_CHANNEL_PORT_LISTENER:
- case SSH_CHANNEL_RPORT_LISTENER:
- case SSH_CHANNEL_OPENING:
- case SSH_CHANNEL_CONNECTING:
- case SSH_CHANNEL_ZOMBIE:
- continue;
- case SSH_CHANNEL_LARVAL:
- case SSH_CHANNEL_AUTH_SOCKET:
- case SSH_CHANNEL_OPEN:
- case SSH_CHANNEL_X11_OPEN:
- return i;
- case SSH_CHANNEL_INPUT_DRAINING:
- case SSH_CHANNEL_OUTPUT_DRAINING:
- if (!compat13)
- fatal("cannot happen: OUT_DRAIN");
- return i;
- default:
- fatal("channel_find_open: bad channel type %d", c->type);
- /* NOTREACHED */
- }
- }
- return -1;
-}
-
-
-/*
- * Returns a message describing the currently open forwarded connections,
- * suitable for sending to the client. The message contains crlf pairs for
- * newlines.
- */
-
-char *
-channel_open_message(void)
-{
- Buffer buffer;
- Channel *c;
- char buf[1024], *cp;
- int i;
-
- buffer_init(&buffer);
- snprintf(buf, sizeof buf, "The following connections are open:\r\n");
- buffer_append(&buffer, buf, strlen(buf));
- for (i = 0; i < channels_alloc; i++) {
- c = channels[i];
- if (c == NULL)
- continue;
- switch (c->type) {
- case SSH_CHANNEL_X11_LISTENER:
- case SSH_CHANNEL_PORT_LISTENER:
- case SSH_CHANNEL_RPORT_LISTENER:
- case SSH_CHANNEL_CLOSED:
- case SSH_CHANNEL_AUTH_SOCKET:
- case SSH_CHANNEL_ZOMBIE:
- continue;
- case SSH_CHANNEL_LARVAL:
- case SSH_CHANNEL_OPENING:
- case SSH_CHANNEL_CONNECTING:
- case SSH_CHANNEL_DYNAMIC:
- case SSH_CHANNEL_OPEN:
- case SSH_CHANNEL_X11_OPEN:
- case SSH_CHANNEL_INPUT_DRAINING:
- case SSH_CHANNEL_OUTPUT_DRAINING:
- snprintf(buf, sizeof buf, " #%d %.300s (t%d r%d i%d/%d o%d/%d fd %d/%d)\r\n",
- c->self, c->remote_name,
- c->type, c->remote_id,
- c->istate, buffer_len(&c->input),
- c->ostate, buffer_len(&c->output),
- c->rfd, c->wfd);
- buffer_append(&buffer, buf, strlen(buf));
- continue;
- default:
- fatal("channel_open_message: bad channel type %d", c->type);
- /* NOTREACHED */
- }
- }
- buffer_append(&buffer, "\0", 1);
- cp = xstrdup(buffer_ptr(&buffer));
- buffer_free(&buffer);
- return cp;
-}
-
-void
-channel_send_open(int id)
-{
- Channel *c = channel_lookup(id);
-
- if (c == NULL) {
- log("channel_send_open: %d: bad id", id);
- return;
- }
- debug("send channel open %d", id);
- packet_start(SSH2_MSG_CHANNEL_OPEN);
- packet_put_cstring(c->ctype);
- packet_put_int(c->self);
- packet_put_int(c->local_window);
- packet_put_int(c->local_maxpacket);
- packet_send();
-}
-
-void
-channel_request_start(int local_id, char *service, int wantconfirm)
-{
- Channel *c = channel_lookup(local_id);
-
- debug("channel request %d: %s", local_id, service);
- if (c == NULL) {
- log("channel_request_start: %d: unknown channel id", local_id);
- return;
- }
- packet_start(SSH2_MSG_CHANNEL_REQUEST);
- packet_put_int(c->remote_id);
- packet_put_cstring(service);
- packet_put_char(wantconfirm);
-}
-void
-channel_register_confirm(int id, channel_callback_fn *fn)
-{
- Channel *c = channel_lookup(id);
-
- if (c == NULL) {
- log("channel_register_comfirm: %d: bad id", id);
- return;
- }
- c->confirm = fn;
-}
-void
-channel_register_cleanup(int id, channel_callback_fn *fn)
-{
- Channel *c = channel_lookup(id);
-
- if (c == NULL) {
- log("channel_register_cleanup: %d: bad id", id);
- return;
- }
- c->detach_user = fn;
-}
-void
-channel_cancel_cleanup(int id)
-{
- Channel *c = channel_lookup(id);
-
- if (c == NULL) {
- log("channel_cancel_cleanup: %d: bad id", id);
- return;
- }
- c->detach_user = NULL;
-}
-void
-channel_register_filter(int id, channel_filter_fn *fn)
-{
- Channel *c = channel_lookup(id);
-
- if (c == NULL) {
- log("channel_register_filter: %d: bad id", id);
- return;
- }
- c->input_filter = fn;
-}
-
-void
-channel_set_fds(int id, int rfd, int wfd, int efd,
- int extusage, int nonblock, u_int window_max)
-{
- Channel *c = channel_lookup(id);
-
- if (c == NULL || c->type != SSH_CHANNEL_LARVAL)
- fatal("channel_activate for non-larval channel %d.", id);
- channel_register_fds(c, rfd, wfd, efd, extusage, nonblock);
- c->type = SSH_CHANNEL_OPEN;
- c->local_window = c->local_window_max = window_max;
- packet_start(SSH2_MSG_CHANNEL_WINDOW_ADJUST);
- packet_put_int(c->remote_id);
- packet_put_int(c->local_window);
- packet_send();
-}
-
-void
-channel_set_wait_for_exit(int id, int wait_for_exit)
-{
- Channel *c = channel_lookup(id);
-
- if (c == NULL || c->type != SSH_CHANNEL_OPEN)
- fatal("channel_set_wait_for_exit for non-open channel %d.", id);
-
- debug3("channel_set_wait_for_exit %d, %d (type: %d)", id, wait_for_exit, c->type);
- c->wait_for_exit = wait_for_exit;
-}
-
-/*
- * 'channel_pre*' are called just before select() to add any bits relevant to
- * channels in the select bitmasks.
- */
-/*
- * 'channel_post*': perform any appropriate operations for channels which
- * have events pending.
- */
-typedef void chan_fn(Channel *c, fd_set * readset, fd_set * writeset);
-chan_fn *channel_pre[SSH_CHANNEL_MAX_TYPE];
-chan_fn *channel_post[SSH_CHANNEL_MAX_TYPE];
-
-static void
-channel_pre_listener(Channel *c, fd_set * readset, fd_set * writeset)
-{
- FD_SET(c->sock, readset);
-}
-
-static void
-channel_pre_connecting(Channel *c, fd_set * readset, fd_set * writeset)
-{
- debug3("channel %d: waiting for connection", c->self);
- FD_SET(c->sock, writeset);
-}
-
-static void
-channel_pre_open_13(Channel *c, fd_set * readset, fd_set * writeset)
-{
- if (buffer_len(&c->input) < packet_get_maxsize())
- FD_SET(c->sock, readset);
- if (buffer_len(&c->output) > 0)
- FD_SET(c->sock, writeset);
-}
-
-static void
-channel_pre_open(Channel *c, fd_set * readset, fd_set * writeset)
-{
- u_int limit = compat20 ? c->remote_window : packet_get_maxsize();
-
- if (c->istate == CHAN_INPUT_OPEN &&
- limit > 0 &&
- buffer_len(&c->input) < limit &&
- buffer_check_alloc(&c->input, CHAN_RBUF))
- FD_SET(c->rfd, readset);
- if (c->ostate == CHAN_OUTPUT_OPEN ||
- c->ostate == CHAN_OUTPUT_WAIT_DRAIN) {
- if (buffer_len(&c->output) > 0) {
- FD_SET(c->wfd, writeset);
- } else if (c->ostate == CHAN_OUTPUT_WAIT_DRAIN) {
- if (CHANNEL_EFD_OUTPUT_ACTIVE(c))
- debug2("channel %d: obuf_empty delayed efd %d/(%d)",
- c->self, c->efd, buffer_len(&c->extended));
- else
- chan_obuf_empty(c);
- }
- }
- /** XXX check close conditions, too */
- if (compat20 && c->efd != -1) {
- if (c->extended_usage == CHAN_EXTENDED_WRITE &&
- buffer_len(&c->extended) > 0)
- FD_SET(c->efd, writeset);
- else if (!(c->flags & CHAN_EOF_SENT) &&
- c->extended_usage == CHAN_EXTENDED_READ &&
- buffer_len(&c->extended) < c->remote_window)
- FD_SET(c->efd, readset);
- }
-}
-
-static void
-channel_pre_input_draining(Channel *c, fd_set * readset, fd_set * writeset)
-{
- if (buffer_len(&c->input) == 0) {
- packet_start(SSH_MSG_CHANNEL_CLOSE);
- packet_put_int(c->remote_id);
- packet_send();
- c->type = SSH_CHANNEL_CLOSED;
- debug("channel %d: closing after input drain.", c->self);
- }
-}
-
-static void
-channel_pre_output_draining(Channel *c, fd_set * readset, fd_set * writeset)
-{
- if (buffer_len(&c->output) == 0)
- chan_mark_dead(c);
- else
- FD_SET(c->sock, writeset);
-}
-
-/*
- * This is a special state for X11 authentication spoofing. An opened X11
- * connection (when authentication spoofing is being done) remains in this
- * state until the first packet has been completely read. The authentication
- * data in that packet is then substituted by the real data if it matches the
- * fake data, and the channel is put into normal mode.
- * XXX All this happens at the client side.
- * Returns: 0 = need more data, -1 = wrong cookie, 1 = ok
- */
-static int
-x11_open_helper(Buffer *b)
-{
- u_char *ucp;
- u_int proto_len, data_len;
-
- /* Check if the fixed size part of the packet is in buffer. */
- if (buffer_len(b) < 12)
- return 0;
-
- /* Parse the lengths of variable-length fields. */
- ucp = buffer_ptr(b);
- if (ucp[0] == 0x42) { /* Byte order MSB first. */
- proto_len = 256 * ucp[6] + ucp[7];
- data_len = 256 * ucp[8] + ucp[9];
- } else if (ucp[0] == 0x6c) { /* Byte order LSB first. */
- proto_len = ucp[6] + 256 * ucp[7];
- data_len = ucp[8] + 256 * ucp[9];
- } else {
- debug("Initial X11 packet contains bad byte order byte: 0x%x",
- ucp[0]);
- return -1;
- }
-
- /* Check if the whole packet is in buffer. */
- if (buffer_len(b) <
- 12 + ((proto_len + 3) & ~3) + ((data_len + 3) & ~3))
- return 0;
-
- /* Check if authentication protocol matches. */
- if (proto_len != strlen(x11_saved_proto) ||
- memcmp(ucp + 12, x11_saved_proto, proto_len) != 0) {
- debug("X11 connection uses different authentication protocol.");
- return -1;
- }
- /* Check if authentication data matches our fake data. */
- if (data_len != x11_fake_data_len ||
- memcmp(ucp + 12 + ((proto_len + 3) & ~3),
- x11_fake_data, x11_fake_data_len) != 0) {
- debug("X11 auth data does not match fake data.");
- return -1;
- }
- /* Check fake data length */
- if (x11_fake_data_len != x11_saved_data_len) {
- error("X11 fake_data_len %d != saved_data_len %d",
- x11_fake_data_len, x11_saved_data_len);
- return -1;
- }
- /*
- * Received authentication protocol and data match
- * our fake data. Substitute the fake data with real
- * data.
- */
- memcpy(ucp + 12 + ((proto_len + 3) & ~3),
- x11_saved_data, x11_saved_data_len);
- return 1;
-}
-
-static void
-channel_pre_x11_open_13(Channel *c, fd_set * readset, fd_set * writeset)
-{
- int ret = x11_open_helper(&c->output);
-
- if (ret == 1) {
- /* Start normal processing for the channel. */
- c->type = SSH_CHANNEL_OPEN;
- channel_pre_open_13(c, readset, writeset);
- } else if (ret == -1) {
- /*
- * We have received an X11 connection that has bad
- * authentication information.
- */
- log("X11 connection rejected because of wrong authentication.");
- buffer_clear(&c->input);
- buffer_clear(&c->output);
- channel_close_fd(&c->sock);
- c->sock = -1;
- c->type = SSH_CHANNEL_CLOSED;
- packet_start(SSH_MSG_CHANNEL_CLOSE);
- packet_put_int(c->remote_id);
- packet_send();
- }
-}
-
-static void
-channel_pre_x11_open(Channel *c, fd_set * readset, fd_set * writeset)
-{
- int ret = x11_open_helper(&c->output);
-
- /* c->force_drain = 1; */
-
- if (ret == 1) {
- c->type = SSH_CHANNEL_OPEN;
- channel_pre_open(c, readset, writeset);
- } else if (ret == -1) {
- log("X11 connection rejected because of wrong authentication.");
- debug("X11 rejected %d i%d/o%d", c->self, c->istate, c->ostate);
- chan_read_failed(c);
- buffer_clear(&c->input);
- chan_ibuf_empty(c);
- buffer_clear(&c->output);
- /* for proto v1, the peer will send an IEOF */
- if (compat20)
- chan_write_failed(c);
- else
- c->type = SSH_CHANNEL_OPEN;
- debug("X11 closed %d i%d/o%d", c->self, c->istate, c->ostate);
- }
-}
-
-/* try to decode a socks4 header */
-static int
-channel_decode_socks4(Channel *c, fd_set * readset, fd_set * writeset)
-{
- char *p, *host;
- int len, have, i, found;
- char username[256];
- struct {
- u_int8_t version;
- u_int8_t command;
- u_int16_t dest_port;
- struct in_addr dest_addr;
- } s4_req, s4_rsp;
-
- debug2("channel %d: decode socks4", c->self);
-
- have = buffer_len(&c->input);
- len = sizeof(s4_req);
- if (have < len)
- return 0;
- p = buffer_ptr(&c->input);
- for (found = 0, i = len; i < have; i++) {
- if (p[i] == '\0') {
- found = 1;
- break;
- }
- if (i > 1024) {
- /* the peer is probably sending garbage */
- debug("channel %d: decode socks4: too long",
- c->self);
- return -1;
- }
- }
- if (!found)
- return 0;
- buffer_get(&c->input, (char *)&s4_req.version, 1);
- buffer_get(&c->input, (char *)&s4_req.command, 1);
- buffer_get(&c->input, (char *)&s4_req.dest_port, 2);
- buffer_get(&c->input, (char *)&s4_req.dest_addr, 4);
- have = buffer_len(&c->input);
- p = buffer_ptr(&c->input);
- len = strlen(p);
- debug2("channel %d: decode socks4: user %s/%d", c->self, p, len);
- if (len > have)
- fatal("channel %d: decode socks4: len %d > have %d",
- c->self, len, have);
- strlcpy(username, p, sizeof(username));
- buffer_consume(&c->input, len);
- buffer_consume(&c->input, 1); /* trailing '\0' */
-
- host = inet_ntoa(s4_req.dest_addr);
- strlcpy(c->path, host, sizeof(c->path));
- c->host_port = ntohs(s4_req.dest_port);
-
- debug("channel %d: dynamic request: socks4 host %s port %u command %u",
- c->self, host, c->host_port, s4_req.command);
-
- if (s4_req.command != 1) {
- debug("channel %d: cannot handle: socks4 cn %d",
- c->self, s4_req.command);
- return -1;
- }
- s4_rsp.version = 0; /* vn: 0 for reply */
- s4_rsp.command = 90; /* cd: req granted */
- s4_rsp.dest_port = 0; /* ignored */
- s4_rsp.dest_addr.s_addr = INADDR_ANY; /* ignored */
- buffer_append(&c->output, (char *)&s4_rsp, sizeof(s4_rsp));
- return 1;
-}
-
-/* try to decode a socks5 header */
-#define SSH_SOCKS5_AUTHDONE 0x1000
-#define SSH_SOCKS5_NOAUTH 0x00
-#define SSH_SOCKS5_IPV4 0x01
-#define SSH_SOCKS5_DOMAIN 0x03
-#define SSH_SOCKS5_IPV6 0x04
-#define SSH_SOCKS5_CONNECT 0x01
-#define SSH_SOCKS5_SUCCESS 0x00
-
-/* ARGSUSED */
-static int
-channel_decode_socks5(Channel *c, fd_set *readset, fd_set *writeset)
-{
- struct {
- u_int8_t version;
- u_int8_t command;
- u_int8_t reserved;
- u_int8_t atyp;
- } s5_req, s5_rsp;
- u_int16_t dest_port;
- u_char *p, dest_addr[255+1];
- u_int have, need, i, found, nmethods, addrlen;
- struct in_addr bnd_addr;
- int af;
-
- debug2("channel %d: decode socks5", c->self);
- p = buffer_ptr(&c->input);
- if (p[0] != 0x05)
- return -1;
- have = buffer_len(&c->input);
- if (!(c->flags & SSH_SOCKS5_AUTHDONE)) {
- /* format: ver | nmethods | methods */
- if (have < 2)
- return 0;
- nmethods = p[1];
- if (have < nmethods + 2)
- return 0;
- /* look for method: "NO AUTHENTICATION REQUIRED" */
- for (found = 0, i = 2 ; i < nmethods + 2; i++) {
- if (p[i] == SSH_SOCKS5_NOAUTH) {
- found = 1;
- break;
- }
- }
- if (!found) {
- error("channel %d: socks5 authentication methods not implemented",
- c->self);
- error("channel %d: forwarding failed: "
- "SSH_SOCKS5_NOAUTH method not found", c->self);
- return -1;
- }
- buffer_consume(&c->input, nmethods + 2);
- buffer_put_char(&c->output, 0x05); /* version */
- buffer_put_char(&c->output, SSH_SOCKS5_NOAUTH); /* method */
- FD_SET(c->sock, writeset);
- c->flags |= SSH_SOCKS5_AUTHDONE;
- debug2("channel %d: socks5 auth done", c->self);
- return 0; /* need more */
- }
- debug2("channel %d: socks5 post auth", c->self);
- if (have < sizeof(s5_req)+1)
- return 0; /* need more */
- memcpy(&s5_req, p, sizeof(s5_req));
- if (s5_req.version != 0x05 ||
- s5_req.command != SSH_SOCKS5_CONNECT ||
- s5_req.reserved != 0x00) {
- error("channel %d: forwarding failed: "
- "only socks5 connect is supported", c->self);
- return -1;
- }
- switch (s5_req.atyp){
- case SSH_SOCKS5_IPV4:
- addrlen = 4;
- af = AF_INET;
- break;
- case SSH_SOCKS5_DOMAIN:
- addrlen = p[sizeof(s5_req)];
- af = -1;
- break;
- case SSH_SOCKS5_IPV6:
- addrlen = 16;
- af = AF_INET6;
- break;
- default:
- error("channel %d: forwarding failed: "
- "bad socks5 atyp %d", c->self, s5_req.atyp);
- return -1;
- }
- need = sizeof(s5_req) + addrlen + 2;
- if (s5_req.atyp == SSH_SOCKS5_DOMAIN)
- need++;
- if (have < need)
- return 0;
- buffer_consume(&c->input, sizeof(s5_req));
- if (s5_req.atyp == SSH_SOCKS5_DOMAIN)
- buffer_consume(&c->input, 1); /* host string length */
- buffer_get(&c->input, (char *)&dest_addr, addrlen);
- buffer_get(&c->input, (char *)&dest_port, 2);
- dest_addr[addrlen] = '\0';
- if (s5_req.atyp == SSH_SOCKS5_DOMAIN)
- strlcpy(c->path, (char *)dest_addr, sizeof(c->path));
- else if (inet_ntop(af, dest_addr, c->path, sizeof(c->path)) == NULL)
- return -1;
- c->host_port = ntohs(dest_port);
-
- debug2("channel %d: dynamic request: socks5 host %s port %u command %u",
- c->self, c->path, c->host_port, s5_req.command);
-
- s5_rsp.version = 0x05;
- s5_rsp.command = SSH_SOCKS5_SUCCESS;
- s5_rsp.reserved = 0; /* ignored */
- s5_rsp.atyp = SSH_SOCKS5_IPV4;
- bzero(&bnd_addr, sizeof(bnd_addr));
- bnd_addr.s_addr = htonl(INADDR_ANY);
- dest_port = 0; /* ignored */
-
- buffer_append(&c->output, &s5_rsp, sizeof(s5_rsp));
- buffer_append(&c->output, &bnd_addr, sizeof(struct in_addr));
- buffer_append(&c->output, &dest_port, sizeof(dest_port));
- return 1;
-}
-
-/* dynamic port forwarding */
-static void
-channel_pre_dynamic(Channel *c, fd_set * readset, fd_set * writeset)
-{
- u_char *p;
- int have, ret;
-
- have = buffer_len(&c->input);
- debug2("channel %d: pre_dynamic: have %d", c->self, have);
- /* buffer_dump(&c->input); */
- /* check if the fixed size part of the packet is in buffer. */
- if (have < 3) {
- /* need more */
- FD_SET(c->sock, readset);
- return;
- }
- /* try to guess the protocol */
- p = buffer_ptr(&c->input);
- switch (p[0]) {
- case 0x04:
- ret = channel_decode_socks4(c, readset, writeset);
- break;
- case 0x05:
- ret = channel_decode_socks5(c, readset, writeset);
- break;
- default:
- error("channel %d: forwarding failed: unknown socks "
- "version 0x%02X", c->self, p[0]);
- ret = -1;
- break;
- }
- if (ret < 0) {
- chan_mark_dead(c);
- } else if (ret == 0) {
- debug2("channel %d: pre_dynamic: need more", c->self);
- /* need more */
- FD_SET(c->sock, readset);
- } else {
- /* switch to the next state */
- c->type = SSH_CHANNEL_OPENING;
- port_open_helper(c, "direct-tcpip");
- }
-}
-
-/* This is our fake X11 server socket. */
-static void
-channel_post_x11_listener(Channel *c, fd_set * readset, fd_set * writeset)
-{
- Channel *nc;
- struct sockaddr addr;
- int newsock;
- socklen_t addrlen;
- char buf[16384], *remote_ipaddr;
- int remote_port;
-
- if (FD_ISSET(c->sock, readset)) {
- debug("X11 connection requested.");
- addrlen = sizeof(addr);
- newsock = accept(c->sock, &addr, &addrlen);
- if (c->single_connection) {
- debug("single_connection: closing X11 listener.");
- channel_close_fd(&c->sock);
- chan_mark_dead(c);
- }
- if (newsock < 0) {
- error("accept: %.100s", strerror(errno));
- return;
- }
- set_nodelay(newsock);
- remote_ipaddr = get_peer_ipaddr(newsock);
- remote_port = get_peer_port(newsock);
- snprintf(buf, sizeof buf, "X11 connection from %.200s port %d",
- remote_ipaddr, remote_port);
-
- nc = channel_new("accepted x11 socket",
- SSH_CHANNEL_OPENING, newsock, newsock, -1,
- c->local_window_max, c->local_maxpacket,
- 0, xstrdup(buf), 1);
- if (compat20) {
- packet_start(SSH2_MSG_CHANNEL_OPEN);
- packet_put_cstring("x11");
- packet_put_int(nc->self);
- packet_put_int(nc->local_window_max);
- packet_put_int(nc->local_maxpacket);
- /* originator ipaddr and port */
- packet_put_cstring(remote_ipaddr);
- if (datafellows & SSH_BUG_X11FWD) {
- debug("ssh2 x11 bug compat mode");
- } else {
- packet_put_int(remote_port);
- }
- packet_send();
- } else {
- packet_start(SSH_SMSG_X11_OPEN);
- packet_put_int(nc->self);
- if (packet_get_protocol_flags() &
- SSH_PROTOFLAG_HOST_IN_FWD_OPEN)
- packet_put_cstring(buf);
- packet_send();
- }
- xfree(remote_ipaddr);
- }
-}
-
-static void
-port_open_helper(Channel *c, char *rtype)
-{
- int direct;
- char buf[1024];
- char *remote_ipaddr = get_peer_ipaddr(c->sock);
- u_short remote_port = get_peer_port(c->sock);
-
- direct = (strcmp(rtype, "direct-tcpip") == 0);
-
- snprintf(buf, sizeof buf,
- "%s: listening port %d for %.100s port %d, "
- "connect from %.200s port %d",
- rtype, c->listening_port, c->path, c->host_port,
- remote_ipaddr, remote_port);
-
- xfree(c->remote_name);
- c->remote_name = xstrdup(buf);
-
- if (compat20) {
- packet_start(SSH2_MSG_CHANNEL_OPEN);
- packet_put_cstring(rtype);
- packet_put_int(c->self);
- packet_put_int(c->local_window_max);
- packet_put_int(c->local_maxpacket);
- if (direct) {
- /* target host, port */
- packet_put_cstring(c->path);
- packet_put_int(c->host_port);
- } else {
- /* listen address, port */
- packet_put_cstring(c->path);
- packet_put_int(c->listening_port);
- }
- /* originator host and port */
- packet_put_cstring(remote_ipaddr);
- packet_put_int(remote_port);
- packet_send();
- } else {
- packet_start(SSH_MSG_PORT_OPEN);
- packet_put_int(c->self);
- packet_put_cstring(c->path);
- packet_put_int(c->host_port);
- if (packet_get_protocol_flags() &
- SSH_PROTOFLAG_HOST_IN_FWD_OPEN)
- packet_put_cstring(c->remote_name);
- packet_send();
- }
- xfree(remote_ipaddr);
-}
-
-/*
- * This socket is listening for connections to a forwarded TCP/IP port.
- */
-static void
-channel_post_port_listener(Channel *c, fd_set * readset, fd_set * writeset)
-{
- Channel *nc;
- struct sockaddr addr;
- int newsock, nextstate;
- socklen_t addrlen;
- char *rtype;
-
- if (FD_ISSET(c->sock, readset)) {
- debug("Connection to port %d forwarding "
- "to %.100s port %d requested.",
- c->listening_port, c->path, c->host_port);
-
- if (c->type == SSH_CHANNEL_RPORT_LISTENER) {
- nextstate = SSH_CHANNEL_OPENING;
- rtype = "forwarded-tcpip";
- } else {
- if (c->host_port == 0) {
- nextstate = SSH_CHANNEL_DYNAMIC;
- rtype = "dynamic-tcpip";
- } else {
- nextstate = SSH_CHANNEL_OPENING;
- rtype = "direct-tcpip";
- }
- }
-
- addrlen = sizeof(addr);
- newsock = accept(c->sock, &addr, &addrlen);
- if (newsock < 0) {
- error("accept: %.100s", strerror(errno));
- return;
- }
- set_nodelay(newsock);
- nc = channel_new(rtype,
- nextstate, newsock, newsock, -1,
- c->local_window_max, c->local_maxpacket,
- 0, xstrdup(rtype), 1);
- nc->listening_port = c->listening_port;
- nc->host_port = c->host_port;
- strlcpy(nc->path, c->path, sizeof(nc->path));
-
- if (nextstate != SSH_CHANNEL_DYNAMIC)
- port_open_helper(nc, rtype);
- }
-}
-
-/*
- * This is the authentication agent socket listening for connections from
- * clients.
- */
-static void
-channel_post_auth_listener(Channel *c, fd_set * readset, fd_set * writeset)
-{
- Channel *nc;
- char *name;
- int newsock;
- struct sockaddr addr;
- socklen_t addrlen;
-
- if (FD_ISSET(c->sock, readset)) {
- addrlen = sizeof(addr);
- newsock = accept(c->sock, &addr, &addrlen);
- if (newsock < 0) {
- error("accept from auth socket: %.100s", strerror(errno));
- return;
- }
- name = xstrdup("accepted auth socket");
- nc = channel_new("accepted auth socket",
- SSH_CHANNEL_OPENING, newsock, newsock, -1,
- c->local_window_max, c->local_maxpacket,
- 0, name, 1);
- if (compat20) {
- packet_start(SSH2_MSG_CHANNEL_OPEN);
- packet_put_cstring("auth-agent@openssh.com");
- packet_put_int(nc->self);
- packet_put_int(c->local_window_max);
- packet_put_int(c->local_maxpacket);
- } else {
- packet_start(SSH_SMSG_AGENT_OPEN);
- packet_put_int(nc->self);
- }
- packet_send();
- }
-}
-
-static void
-channel_post_connecting(Channel *c, fd_set * readset, fd_set * writeset)
-{
- int err = 0;
- socklen_t sz = sizeof(err);
-
- if (FD_ISSET(c->sock, writeset)) {
- if (getsockopt(c->sock, SOL_SOCKET, SO_ERROR, &err, &sz) < 0) {
- err = errno;
- error("getsockopt SO_ERROR failed");
- }
- if (err == 0) {
- debug("channel %d: connected", c->self);
- c->type = SSH_CHANNEL_OPEN;
- if (compat20) {
- packet_start(SSH2_MSG_CHANNEL_OPEN_CONFIRMATION);
- packet_put_int(c->remote_id);
- packet_put_int(c->self);
- packet_put_int(c->local_window);
- packet_put_int(c->local_maxpacket);
- } else {
- packet_start(SSH_MSG_CHANNEL_OPEN_CONFIRMATION);
- packet_put_int(c->remote_id);
- packet_put_int(c->self);
- }
- } else {
- debug("channel %d: not connected: %s",
- c->self, strerror(err));
- if (compat20) {
- packet_start(SSH2_MSG_CHANNEL_OPEN_FAILURE);
- packet_put_int(c->remote_id);
- packet_put_int(SSH2_OPEN_CONNECT_FAILED);
- if (!(datafellows & SSH_BUG_OPENFAILURE)) {
- packet_put_utf8_cstring(strerror(err));
- packet_put_cstring("");
- }
- } else {
- packet_start(SSH_MSG_CHANNEL_OPEN_FAILURE);
- packet_put_int(c->remote_id);
- }
- chan_mark_dead(c);
- }
- packet_send();
- }
-}
-
-static int
-channel_handle_rfd(Channel *c, fd_set * readset, fd_set * writeset)
-{
- char buf[CHAN_RBUF];
- int len;
-
- if (c->rfd != -1 &&
- FD_ISSET(c->rfd, readset)) {
- len = read(c->rfd, buf, sizeof(buf));
- if (len < 0 && (errno == EINTR || errno == EAGAIN))
- return 1;
- if (len <= 0) {
- debug("channel %d: read<=0 rfd %d len %d",
- c->self, c->rfd, len);
- if (c->type != SSH_CHANNEL_OPEN) {
- debug("channel %d: not open", c->self);
- chan_mark_dead(c);
- return -1;
- } else if (compat13) {
- buffer_clear(&c->output);
- c->type = SSH_CHANNEL_INPUT_DRAINING;
- debug("channel %d: input draining.", c->self);
- } else {
- chan_read_failed(c);
- }
- return -1;
- }
- if (c->input_filter != NULL) {
- if (c->input_filter(c, buf, len) == -1) {
- debug("channel %d: filter stops", c->self);
- chan_read_failed(c);
- }
- } else {
- buffer_append(&c->input, buf, len);
- }
- }
- return 1;
-}
-static int
-channel_handle_wfd(Channel *c, fd_set * readset, fd_set * writeset)
-{
- struct termios tio;
- u_char *data;
- u_int dlen;
- int len;
-
- /* Send buffered output data to the socket. */
- if (c->wfd != -1 &&
- FD_ISSET(c->wfd, writeset) &&
- buffer_len(&c->output) > 0) {
- data = buffer_ptr(&c->output);
- dlen = buffer_len(&c->output);
-#ifdef _AIX
- /* XXX: Later AIX versions can't push as much data to tty */
- if (compat20 && c->wfd_isatty && dlen > 8*1024)
- dlen = 8*1024;
-#endif
- len = write(c->wfd, data, dlen);
- if (len < 0 && (errno == EINTR || errno == EAGAIN))
- return 1;
- if (len <= 0) {
- if (c->type != SSH_CHANNEL_OPEN) {
- debug("channel %d: not open", c->self);
- chan_mark_dead(c);
- return -1;
- } else if (compat13) {
- buffer_clear(&c->output);
- debug("channel %d: input draining.", c->self);
- c->type = SSH_CHANNEL_INPUT_DRAINING;
- } else {
- chan_write_failed(c);
- }
- return -1;
- }
- if (compat20 && c->isatty && dlen >= 1 && data[0] != '\r') {
- if (tcgetattr(c->wfd, &tio) == 0 &&
- !(tio.c_lflag & ECHO) && (tio.c_lflag & ICANON)) {
- /*
- * Simulate echo to reduce the impact of
- * traffic analysis. We need to match the
- * size of a SSH2_MSG_CHANNEL_DATA message
- * (4 byte channel id + data)
- */
- packet_send_ignore(4 + len);
- packet_send();
- }
- }
- buffer_consume(&c->output, len);
- if (compat20 && len > 0) {
- c->local_consumed += len;
- }
- }
- return 1;
-}
-static int
-channel_handle_efd(Channel *c, fd_set * readset, fd_set * writeset)
-{
- char buf[CHAN_RBUF];
- int len;
-
-/** XXX handle drain efd, too */
- if (c->efd != -1) {
- if (c->extended_usage == CHAN_EXTENDED_WRITE &&
- FD_ISSET(c->efd, writeset) &&
- buffer_len(&c->extended) > 0) {
- len = write(c->efd, buffer_ptr(&c->extended),
- buffer_len(&c->extended));
- debug2("channel %d: written %d to efd %d",
- c->self, len, c->efd);
- if (len < 0 && (errno == EINTR || errno == EAGAIN))
- return 1;
- if (len <= 0) {
- debug2("channel %d: closing write-efd %d",
- c->self, c->efd);
- channel_close_fd(&c->efd);
- } else {
- buffer_consume(&c->extended, len);
- c->local_consumed += len;
- }
- } else if (c->extended_usage == CHAN_EXTENDED_READ &&
- FD_ISSET(c->efd, readset)) {
- len = read(c->efd, buf, sizeof(buf));
- debug2("channel %d: read %d from efd %d",
- c->self, len, c->efd);
- if (len < 0 && (errno == EINTR || errno == EAGAIN))
- return 1;
- if (len <= 0) {
- debug2("channel %d: closing read-efd %d",
- c->self, c->efd);
- channel_close_fd(&c->efd);
- } else {
- buffer_append(&c->extended, buf, len);
- }
- }
- }
- return 1;
-}
-static int
-channel_check_window(Channel *c)
-{
- if (c->type == SSH_CHANNEL_OPEN &&
- !(c->flags & (CHAN_CLOSE_SENT|CHAN_CLOSE_RCVD)) &&
- c->local_window < c->local_window_max/2 &&
- c->local_consumed > 0) {
- packet_start(SSH2_MSG_CHANNEL_WINDOW_ADJUST);
- packet_put_int(c->remote_id);
- packet_put_int(c->local_consumed);
- packet_send();
- debug2("channel %d: window %d sent adjust %d",
- c->self, c->local_window,
- c->local_consumed);
- c->local_window += c->local_consumed;
- c->local_consumed = 0;
- }
- return 1;
-}
-
-static void
-channel_post_open(Channel *c, fd_set * readset, fd_set * writeset)
-{
- channel_handle_rfd(c, readset, writeset);
- channel_handle_wfd(c, readset, writeset);
- if (!compat20)
- return;
- channel_handle_efd(c, readset, writeset);
- channel_check_window(c);
-}
-
-static void
-channel_post_output_drain_13(Channel *c, fd_set * readset, fd_set * writeset)
-{
- int len;
-
- /* Send buffered output data to the socket. */
- if (FD_ISSET(c->sock, writeset) && buffer_len(&c->output) > 0) {
- len = write(c->sock, buffer_ptr(&c->output),
- buffer_len(&c->output));
- if (len <= 0)
- buffer_clear(&c->output);
- else
- buffer_consume(&c->output, len);
- }
-}
-
-static void
-channel_handler_init_20(void)
-{
- channel_pre[SSH_CHANNEL_OPEN] = &channel_pre_open;
- channel_pre[SSH_CHANNEL_X11_OPEN] = &channel_pre_x11_open;
- channel_pre[SSH_CHANNEL_PORT_LISTENER] = &channel_pre_listener;
- channel_pre[SSH_CHANNEL_RPORT_LISTENER] = &channel_pre_listener;
- channel_pre[SSH_CHANNEL_X11_LISTENER] = &channel_pre_listener;
- channel_pre[SSH_CHANNEL_AUTH_SOCKET] = &channel_pre_listener;
- channel_pre[SSH_CHANNEL_CONNECTING] = &channel_pre_connecting;
- channel_pre[SSH_CHANNEL_DYNAMIC] = &channel_pre_dynamic;
-
- channel_post[SSH_CHANNEL_OPEN] = &channel_post_open;
- channel_post[SSH_CHANNEL_PORT_LISTENER] = &channel_post_port_listener;
- channel_post[SSH_CHANNEL_RPORT_LISTENER] = &channel_post_port_listener;
- channel_post[SSH_CHANNEL_X11_LISTENER] = &channel_post_x11_listener;
- channel_post[SSH_CHANNEL_AUTH_SOCKET] = &channel_post_auth_listener;
- channel_post[SSH_CHANNEL_CONNECTING] = &channel_post_connecting;
- channel_post[SSH_CHANNEL_DYNAMIC] = &channel_post_open;
-}
-
-static void
-channel_handler_init_13(void)
-{
- channel_pre[SSH_CHANNEL_OPEN] = &channel_pre_open_13;
- channel_pre[SSH_CHANNEL_X11_OPEN] = &channel_pre_x11_open_13;
- channel_pre[SSH_CHANNEL_X11_LISTENER] = &channel_pre_listener;
- channel_pre[SSH_CHANNEL_PORT_LISTENER] = &channel_pre_listener;
- channel_pre[SSH_CHANNEL_AUTH_SOCKET] = &channel_pre_listener;
- channel_pre[SSH_CHANNEL_INPUT_DRAINING] = &channel_pre_input_draining;
- channel_pre[SSH_CHANNEL_OUTPUT_DRAINING] = &channel_pre_output_draining;
- channel_pre[SSH_CHANNEL_CONNECTING] = &channel_pre_connecting;
- channel_pre[SSH_CHANNEL_DYNAMIC] = &channel_pre_dynamic;
-
- channel_post[SSH_CHANNEL_OPEN] = &channel_post_open;
- channel_post[SSH_CHANNEL_X11_LISTENER] = &channel_post_x11_listener;
- channel_post[SSH_CHANNEL_PORT_LISTENER] = &channel_post_port_listener;
- channel_post[SSH_CHANNEL_AUTH_SOCKET] = &channel_post_auth_listener;
- channel_post[SSH_CHANNEL_OUTPUT_DRAINING] = &channel_post_output_drain_13;
- channel_post[SSH_CHANNEL_CONNECTING] = &channel_post_connecting;
- channel_post[SSH_CHANNEL_DYNAMIC] = &channel_post_open;
-}
-
-static void
-channel_handler_init_15(void)
-{
- channel_pre[SSH_CHANNEL_OPEN] = &channel_pre_open;
- channel_pre[SSH_CHANNEL_X11_OPEN] = &channel_pre_x11_open;
- channel_pre[SSH_CHANNEL_X11_LISTENER] = &channel_pre_listener;
- channel_pre[SSH_CHANNEL_PORT_LISTENER] = &channel_pre_listener;
- channel_pre[SSH_CHANNEL_AUTH_SOCKET] = &channel_pre_listener;
- channel_pre[SSH_CHANNEL_CONNECTING] = &channel_pre_connecting;
- channel_pre[SSH_CHANNEL_DYNAMIC] = &channel_pre_dynamic;
-
- channel_post[SSH_CHANNEL_X11_LISTENER] = &channel_post_x11_listener;
- channel_post[SSH_CHANNEL_PORT_LISTENER] = &channel_post_port_listener;
- channel_post[SSH_CHANNEL_AUTH_SOCKET] = &channel_post_auth_listener;
- channel_post[SSH_CHANNEL_OPEN] = &channel_post_open;
- channel_post[SSH_CHANNEL_CONNECTING] = &channel_post_connecting;
- channel_post[SSH_CHANNEL_DYNAMIC] = &channel_post_open;
-}
-
-static void
-channel_handler_init(void)
-{
- int i;
-
- for (i = 0; i < SSH_CHANNEL_MAX_TYPE; i++) {
- channel_pre[i] = NULL;
- channel_post[i] = NULL;
- }
- if (compat20)
- channel_handler_init_20();
- else if (compat13)
- channel_handler_init_13();
- else
- channel_handler_init_15();
-}
-
-/* gc dead channels */
-static void
-channel_garbage_collect(Channel *c)
-{
- if (c == NULL)
- return;
- if (c->detach_user != NULL) {
- if (!chan_is_dead(c, 0))
- return;
- debug("channel %d: gc: notify user", c->self);
- c->detach_user(c->self, NULL);
- /* if we still have a callback */
- if (c->detach_user != NULL)
- return;
- debug("channel %d: gc: user detached", c->self);
- }
- if (!c->wait_for_exit && !chan_is_dead(c, 1))
- return;
- debug("channel %d: garbage collecting", c->self);
- channel_free(c);
-}
-
-static void
-channel_handler(chan_fn *ftab[], fd_set * readset, fd_set * writeset)
-{
- static int did_init = 0;
- int i, oalloc;
- Channel *c;
-
- if (!did_init) {
- channel_handler_init();
- did_init = 1;
- }
- for (i = 0, oalloc = channels_alloc; i < oalloc; i++) {
- c = channels[i];
- if (c == NULL)
- continue;
- if (c->delayed) {
- if (ftab == channel_pre)
- c->delayed = 0;
- else
- continue;
- }
- if (ftab[c->type] != NULL)
- (*ftab[c->type])(c, readset, writeset);
- channel_garbage_collect(c);
- }
-}
-
-/*
- * Allocate/update select bitmasks and add any bits relevant to channels in
- * select bitmasks.
- */
-void
-channel_prepare_select(fd_set **readsetp, fd_set **writesetp, int *maxfdp,
- int *nallocp, int rekeying)
-{
- int n;
- u_int sz;
-
- n = MAX(*maxfdp, channel_max_fd);
-
- sz = howmany(n+1, NFDBITS) * sizeof(fd_mask);
- /* perhaps check sz < nalloc/2 and shrink? */
- if (*readsetp == NULL || sz > *nallocp) {
- *readsetp = xrealloc(*readsetp, sz);
- *writesetp = xrealloc(*writesetp, sz);
- *nallocp = sz;
- }
- *maxfdp = n;
- memset(*readsetp, 0, sz);
- memset(*writesetp, 0, sz);
-
- if (!rekeying)
- channel_handler(channel_pre, *readsetp, *writesetp);
-}
-
-/*
- * After select, perform any appropriate operations for channels which have
- * events pending.
- */
-void
-channel_after_select(fd_set * readset, fd_set * writeset)
-{
- channel_handler(channel_post, readset, writeset);
-}
-
-
-/* If there is data to send to the connection, enqueue some of it now. */
-
-void
-channel_output_poll(void)
-{
- Channel *c;
- int i;
- u_int len;
-
- for (i = 0; i < channels_alloc; i++) {
- c = channels[i];
- if (c == NULL)
- continue;
-
- /*
- * We are only interested in channels that can have buffered
- * incoming data.
- */
- if (compat13) {
- if (c->type != SSH_CHANNEL_OPEN &&
- c->type != SSH_CHANNEL_INPUT_DRAINING)
- continue;
- } else {
- if (c->type != SSH_CHANNEL_OPEN)
- continue;
- }
- if (compat20 &&
- (c->flags & (CHAN_CLOSE_SENT|CHAN_CLOSE_RCVD))) {
- /* XXX is this true? */
- debug3("channel %d: will not send data after close", c->self);
- continue;
- }
-
- /* Get the amount of buffered data for this channel. */
- if ((c->istate == CHAN_INPUT_OPEN ||
- c->istate == CHAN_INPUT_WAIT_DRAIN) &&
- (len = buffer_len(&c->input)) > 0) {
- /*
- * Send some data for the other side over the secure
- * connection.
- */
- if (compat20) {
- if (len > c->remote_window)
- len = c->remote_window;
- if (len > c->remote_maxpacket)
- len = c->remote_maxpacket;
- } else {
- if (packet_is_interactive()) {
- if (len > 1024)
- len = 512;
- } else {
- /* Keep the packets at reasonable size. */
- if (len > packet_get_maxsize()/2)
- len = packet_get_maxsize()/2;
- }
- }
- if (len > 0) {
- packet_start(compat20 ?
- SSH2_MSG_CHANNEL_DATA : SSH_MSG_CHANNEL_DATA);
- packet_put_int(c->remote_id);
- packet_put_string(buffer_ptr(&c->input), len);
- packet_send();
- buffer_consume(&c->input, len);
- c->remote_window -= len;
- }
- } else if (c->istate == CHAN_INPUT_WAIT_DRAIN) {
- if (compat13)
- fatal("cannot happen: istate == INPUT_WAIT_DRAIN for proto 1.3");
- /*
- * input-buffer is empty and read-socket shutdown:
- * tell peer, that we will not send more data: send IEOF.
- * hack for extended data: delay EOF if EFD still in use.
- */
- if (CHANNEL_EFD_INPUT_ACTIVE(c))
- debug2("channel %d: ibuf_empty delayed efd %d/(%d)",
- c->self, c->efd, buffer_len(&c->extended));
- else
- chan_ibuf_empty(c);
- }
- /* Send extended data, i.e. stderr */
- if (compat20 &&
- !(c->flags & CHAN_EOF_SENT) &&
- c->remote_window > 0 &&
- (len = buffer_len(&c->extended)) > 0 &&
- c->extended_usage == CHAN_EXTENDED_READ) {
- debug2("channel %d: rwin %u elen %u euse %d",
- c->self, c->remote_window, buffer_len(&c->extended),
- c->extended_usage);
- if (len > c->remote_window)
- len = c->remote_window;
- if (len > c->remote_maxpacket)
- len = c->remote_maxpacket;
- packet_start(SSH2_MSG_CHANNEL_EXTENDED_DATA);
- packet_put_int(c->remote_id);
- packet_put_int(SSH2_EXTENDED_DATA_STDERR);
- packet_put_string(buffer_ptr(&c->extended), len);
- packet_send();
- buffer_consume(&c->extended, len);
- c->remote_window -= len;
- debug2("channel %d: sent ext data %d", c->self, len);
- }
- }
-}
-
-
-/* -- protocol input */
-
-void
-channel_input_data(int type, u_int32_t seq, void *ctxt)
-{
- int id;
- char *data;
- u_int data_len;
- Channel *c;
-
- /* Get the channel number and verify it. */
- id = packet_get_int();
- c = channel_lookup(id);
- if (c == NULL)
- packet_disconnect("Received data for nonexistent channel %d.", id);
-
- /* Ignore any data for non-open channels (might happen on close) */
- if (c->type != SSH_CHANNEL_OPEN &&
- c->type != SSH_CHANNEL_X11_OPEN)
- return;
-
- /* same for protocol 1.5 if output end is no longer open */
- if (!compat13 && c->ostate != CHAN_OUTPUT_OPEN)
- return;
-
- /* Get the data. */
- data = packet_get_string(&data_len);
-
- if (compat20) {
- if (data_len > c->local_maxpacket) {
- log("channel %d: rcvd big packet %d, maxpack %d",
- c->self, data_len, c->local_maxpacket);
- }
- if (data_len > c->local_window) {
- log("channel %d: rcvd too much data %d, win %d",
- c->self, data_len, c->local_window);
- xfree(data);
- return;
- }
- c->local_window -= data_len;
- }
- packet_check_eom();
- buffer_append(&c->output, data, data_len);
- xfree(data);
-}
-
-void
-channel_input_extended_data(int type, u_int32_t seq, void *ctxt)
-{
- int id;
- char *data;
- u_int data_len, tcode;
- Channel *c;
-
- /* Get the channel number and verify it. */
- id = packet_get_int();
- c = channel_lookup(id);
-
- if (c == NULL)
- packet_disconnect("Received extended_data for bad channel %d.", id);
- if (c->type != SSH_CHANNEL_OPEN) {
- log("channel %d: ext data for non open", id);
- return;
- }
- if (c->flags & CHAN_EOF_RCVD) {
- if (datafellows & SSH_BUG_EXTEOF)
- debug("channel %d: accepting ext data after eof", id);
- else
- packet_disconnect("Received extended_data after EOF "
- "on channel %d.", id);
- }
- tcode = packet_get_int();
- if (c->efd == -1 ||
- c->extended_usage != CHAN_EXTENDED_WRITE ||
- tcode != SSH2_EXTENDED_DATA_STDERR) {
- log("channel %d: bad ext data", c->self);
- return;
- }
- data = packet_get_string(&data_len);
- packet_check_eom();
- if (data_len > c->local_window) {
- log("channel %d: rcvd too much extended_data %d, win %d",
- c->self, data_len, c->local_window);
- xfree(data);
- return;
- }
- debug2("channel %d: rcvd ext data %d", c->self, data_len);
- c->local_window -= data_len;
- buffer_append(&c->extended, data, data_len);
- xfree(data);
-}
-
-void
-channel_input_ieof(int type, u_int32_t seq, void *ctxt)
-{
- int id;
- Channel *c;
-
- id = packet_get_int();
- packet_check_eom();
- c = channel_lookup(id);
- if (c == NULL)
- packet_disconnect("Received ieof for nonexistent channel %d.", id);
- chan_rcvd_ieof(c);
-
- /* XXX force input close */
- if (c->force_drain && c->istate == CHAN_INPUT_OPEN) {
- debug("channel %d: FORCE input drain", c->self);
- c->istate = CHAN_INPUT_WAIT_DRAIN;
- if (buffer_len(&c->input) == 0)
- chan_ibuf_empty(c);
- }
-
-}
-
-void
-channel_input_close(int type, u_int32_t seq, void *ctxt)
-{
- int id;
- Channel *c;
-
- id = packet_get_int();
- packet_check_eom();
- c = channel_lookup(id);
- if (c == NULL)
- packet_disconnect("Received close for nonexistent channel %d.", id);
-
- /*
- * Send a confirmation that we have closed the channel and no more
- * data is coming for it.
- */
- packet_start(SSH_MSG_CHANNEL_CLOSE_CONFIRMATION);
- packet_put_int(c->remote_id);
- packet_send();
-
- /*
- * If the channel is in closed state, we have sent a close request,
- * and the other side will eventually respond with a confirmation.
- * Thus, we cannot free the channel here, because then there would be
- * no-one to receive the confirmation. The channel gets freed when
- * the confirmation arrives.
- */
- if (c->type != SSH_CHANNEL_CLOSED) {
- /*
- * Not a closed channel - mark it as draining, which will
- * cause it to be freed later.
- */
- buffer_clear(&c->input);
- c->type = SSH_CHANNEL_OUTPUT_DRAINING;
- }
-}
-
-/* proto version 1.5 overloads CLOSE_CONFIRMATION with OCLOSE */
-void
-channel_input_oclose(int type, u_int32_t seq, void *ctxt)
-{
- int id = packet_get_int();
- Channel *c = channel_lookup(id);
-
- packet_check_eom();
- if (c == NULL)
- packet_disconnect("Received oclose for nonexistent channel %d.", id);
- chan_rcvd_oclose(c);
-}
-
-void
-channel_input_close_confirmation(int type, u_int32_t seq, void *ctxt)
-{
- int id = packet_get_int();
- Channel *c = channel_lookup(id);
-
- packet_check_eom();
- if (c == NULL)
- packet_disconnect("Received close confirmation for "
- "out-of-range channel %d.", id);
- if (c->type != SSH_CHANNEL_CLOSED)
- packet_disconnect("Received close confirmation for "
- "non-closed channel %d (type %d).", id, c->type);
- channel_free(c);
-}
-
-void
-channel_input_open_confirmation(int type, u_int32_t seq, void *ctxt)
-{
- int id, remote_id;
- Channel *c;
-
- id = packet_get_int();
- c = channel_lookup(id);
-
- if (c==NULL || c->type != SSH_CHANNEL_OPENING)
- packet_disconnect("Received open confirmation for "
- "non-opening channel %d.", id);
- remote_id = packet_get_int();
- /* Record the remote channel number and mark that the channel is now open. */
- c->remote_id = remote_id;
- c->type = SSH_CHANNEL_OPEN;
-
- if (compat20) {
- c->remote_window = packet_get_int();
- c->remote_maxpacket = packet_get_int();
- if (c->confirm) {
- debug2("callback start");
- c->confirm(c->self, NULL);
- debug2("callback done");
- }
- debug("channel %d: open confirm rwindow %u rmax %u", c->self,
- c->remote_window, c->remote_maxpacket);
- }
- packet_check_eom();
-}
-
-static char *
-reason2txt(int reason)
-{
- switch (reason) {
- case SSH2_OPEN_ADMINISTRATIVELY_PROHIBITED:
- return "administratively prohibited";
- case SSH2_OPEN_CONNECT_FAILED:
- return "connect failed";
- case SSH2_OPEN_UNKNOWN_CHANNEL_TYPE:
- return "unknown channel type";
- case SSH2_OPEN_RESOURCE_SHORTAGE:
- return "resource shortage";
- }
- return "unknown reason";
-}
-
-void
-channel_input_open_failure(int type, u_int32_t seq, void *ctxt)
-{
- int id, reason;
- char *msg = NULL, *lang = NULL;
- Channel *c;
-
- id = packet_get_int();
- c = channel_lookup(id);
-
- if (c==NULL || c->type != SSH_CHANNEL_OPENING)
- packet_disconnect("Received open failure for "
- "non-opening channel %d.", id);
- if (compat20) {
- reason = packet_get_int();
- if (!(datafellows & SSH_BUG_OPENFAILURE)) {
- msg = packet_get_string(NULL);
- lang = packet_get_string(NULL);
- }
- log("channel %d: open failed: %s%s%s", id,
- reason2txt(reason), msg ? ": ": "", msg ? msg : "");
- if (msg != NULL)
- xfree(msg);
- if (lang != NULL)
- xfree(lang);
- }
- packet_check_eom();
- /* Free the channel. This will also close the socket. */
- channel_free(c);
-}
-
-void
-channel_input_window_adjust(int type, u_int32_t seq, void *ctxt)
-{
- Channel *c;
- int id;
- u_int adjust;
-
- if (!compat20)
- return;
-
- /* Get the channel number and verify it. */
- id = packet_get_int();
- c = channel_lookup(id);
-
- if (c == NULL || c->type != SSH_CHANNEL_OPEN) {
- log("Received window adjust for "
- "non-open channel %d.", id);
- return;
- }
- adjust = packet_get_int();
- packet_check_eom();
- debug2("channel %d: rcvd adjust %u", id, adjust);
- c->remote_window += adjust;
-}
-
-void
-channel_input_port_open(int type, u_int32_t seq, void *ctxt)
-{
- Channel *c = NULL;
- u_short host_port;
- char *host, *originator_string;
- int remote_id, sock = -1;
-
- remote_id = packet_get_int();
- host = packet_get_string(NULL);
- host_port = packet_get_int();
-
- if (packet_get_protocol_flags() & SSH_PROTOFLAG_HOST_IN_FWD_OPEN) {
- originator_string = packet_get_string(NULL);
- } else {
- originator_string = xstrdup("unknown (remote did not supply name)");
- }
- packet_check_eom();
- sock = channel_connect_to(host, host_port);
- if (sock != -1) {
- c = channel_new("connected socket",
- SSH_CHANNEL_CONNECTING, sock, sock, -1, 0, 0, 0,
- originator_string, 1);
- c->remote_id = remote_id;
- }
- if (c == NULL) {
- packet_start(SSH_MSG_CHANNEL_OPEN_FAILURE);
- packet_put_int(remote_id);
- packet_send();
- }
- xfree(host);
-}
-
-
-/* -- tcp forwarding */
-
-void
-channel_set_af(int af)
-{
- IPv4or6 = af;
-}
-
-static int
-channel_setup_fwd_listener(int type, const char *listen_addr, u_short listen_port,
- const char *host_to_connect, u_short port_to_connect, int gateway_ports)
-{
- Channel *c;
- int sock, r, is_client, on = 1, wildcard = 0, success = 0;
- struct addrinfo hints, *ai, *aitop;
- const char *host, *addr;
- char ntop[NI_MAXHOST], strport[NI_MAXSERV];
-
- host = (type == SSH_CHANNEL_RPORT_LISTENER) ?
- listen_addr : host_to_connect;
- is_client = (type == SSH_CHANNEL_PORT_LISTENER);
-
- if (host == NULL) {
- error("No forward host name.");
- return 0;
- }
- if (strlen(host) > SSH_CHANNEL_PATH_LEN - 1) {
- error("Forward host name too long.");
- return 0;
- }
-
- /*
- * Determine whether or not a port forward listens to loopback,
- * specified address or wildcard. On the client, a specified bind
- * address will always override gateway_ports. On the server, a
- * gateway_ports of 1 (``yes'') will override the client's
- * specification and force a wildcard bind, whereas a value of 2
- * (``clientspecified'') will bind to whatever address the client
- * asked for.
- *
- * Special-case listen_addrs are:
- *
- * "0.0.0.0" -> wildcard v4/v6 if SSH_OLD_FORWARD_ADDR
- * "" (empty string), "*" -> wildcard v4/v6
- * "localhost" -> loopback v4/v6
- */
- addr = NULL;
- if (listen_addr == NULL) {
- /* No address specified: default to gateway_ports setting */
- if (gateway_ports)
- wildcard = 1;
- } else if (gateway_ports || is_client) {
- if (((datafellows & SSH_OLD_FORWARD_ADDR) &&
- strcmp(listen_addr, "0.0.0.0") == 0 && is_client == 0) ||
- *listen_addr == '\0' || strcmp(listen_addr, "*") == 0 ||
- (!is_client && gateway_ports == 1))
- wildcard = 1;
- else if (strcmp(listen_addr, "localhost") != 0)
- addr = listen_addr;
- }
-
- debug3("channel_setup_fwd_listener: type %d wildcard %d addr %s",
- type, wildcard, (addr == NULL) ? "NULL" : addr);
-
- /*
- * getaddrinfo returns a loopback address if the hostname is
- * set to NULL and hints.ai_flags is not AI_PASSIVE
- */
- memset(&hints, 0, sizeof(hints));
- hints.ai_family = IPv4or6;
- hints.ai_flags = wildcard ? AI_PASSIVE : 0;
- hints.ai_socktype = SOCK_STREAM;
- snprintf(strport, sizeof strport, "%d", listen_port);
- if ((r = getaddrinfo(addr, strport, &hints, &aitop)) != 0) {
- if (addr == NULL) {
- /* This really shouldn't happen */
- packet_disconnect("getaddrinfo: fatal error: %s",
- gai_strerror(r));
- } else {
- error("channel_setup_fwd_listener: "
- "getaddrinfo(%.64s): %s", addr, gai_strerror(r));
- }
- return 0;
- }
-
- for (ai = aitop; ai; ai = ai->ai_next) {
- if (ai->ai_family != AF_INET && ai->ai_family != AF_INET6)
- continue;
- if (getnameinfo(ai->ai_addr, ai->ai_addrlen, ntop, sizeof(ntop),
- strport, sizeof(strport), NI_NUMERICHOST|NI_NUMERICSERV) != 0) {
- error("channel_setup_fwd_listener: getnameinfo failed");
- continue;
- }
- /* Create a port to listen for the host. */
- sock = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol);
- if (sock < 0) {
- /* this is no error since kernel may not support ipv6 */
- verbose("socket: %.100s", strerror(errno));
- continue;
- }
- /*
- * Set socket options.
- * Allow local port reuse in TIME_WAIT.
- */
- if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &on,
- sizeof(on)) == -1)
- error("setsockopt SO_REUSEADDR: %s", strerror(errno));
-
- debug("Local forwarding listening on %s port %s.", ntop, strport);
-
- /* Bind the socket to the address. */
- if (bind(sock, ai->ai_addr, ai->ai_addrlen) < 0) {
- /* address can be in use ipv6 address is already bound */
- if (!ai->ai_next)
- error("bind: %.100s", strerror(errno));
- else
- verbose("bind: %.100s", strerror(errno));
-
- close(sock);
- continue;
- }
- /* Start listening for connections on the socket. */
- if (listen(sock, 5) < 0) {
- error("listen: %.100s", strerror(errno));
- close(sock);
- continue;
- }
- /* Allocate a channel number for the socket. */
- c = channel_new("port listener", type, sock, sock, -1,
- CHAN_TCP_WINDOW_DEFAULT, CHAN_TCP_PACKET_DEFAULT,
- 0, xstrdup("port listener"), 1);
- strlcpy(c->path, host, sizeof(c->path));
- c->host_port = port_to_connect;
- c->listening_port = listen_port;
- success = 1;
- }
- if (success == 0)
- error("channel_setup_fwd_listener: cannot listen to port: %d",
- listen_port);
- freeaddrinfo(aitop);
- return success;
-}
-
-int
-channel_cancel_rport_listener(const char *host, u_short port)
-{
- u_int i;
- int found = 0;
-
- for (i = 0; i < channels_alloc; i++) {
- Channel *c = channels[i];
-
- if (c != NULL && c->type == SSH_CHANNEL_RPORT_LISTENER &&
- strncmp(c->path, host, sizeof(c->path)) == 0 &&
- c->listening_port == port) {
- debug2("%s: close channel %d", __func__, i);
- channel_free(c);
- found = 1;
- }
- }
-
- return (found);
-}
-
-/* protocol local port fwd, used by ssh (and sshd in v1) */
-int
-channel_setup_local_fwd_listener(const char *listen_host, u_short listen_port,
- const char *host_to_connect, u_short port_to_connect, int gateway_ports)
-{
- return channel_setup_fwd_listener(SSH_CHANNEL_PORT_LISTENER,
- listen_host, listen_port, host_to_connect, port_to_connect,
- gateway_ports);
-}
-
-/* protocol v2 remote port fwd, used by sshd */
-int
-channel_setup_remote_fwd_listener(const char *listen_address,
- u_short listen_port, int gateway_ports)
-{
- return channel_setup_fwd_listener(SSH_CHANNEL_RPORT_LISTENER,
- listen_address, listen_port, NULL, 0, gateway_ports);
-}
-
-/*
- * Initiate forwarding of connections to port "port" on remote host through
- * the secure channel to host:port from local side.
- */
-
-int
-channel_request_remote_forwarding(const char *listen_host, u_short listen_port,
- const char *host_to_connect, u_short port_to_connect)
-{
- int type, success = 0;
-
- /* Record locally that connection to this host/port is permitted. */
- if (num_permitted_opens >= SSH_MAX_FORWARDS_PER_DIRECTION)
- fatal("channel_request_remote_forwarding: too many forwards");
-
- if (listen_host != NULL &&
- strlen(listen_host) > SSH_CHANNEL_PATH_LEN - 1) {
- error("Binding address too long.");
- return -1;
- }
-
- /* Send the forward request to the remote side. */
- if (compat20) {
- const char *address_to_bind;
- if (listen_host == NULL) {
- if (datafellows & SSH_BUG_RFWD_ADDR)
- address_to_bind = "127.0.0.1";
- else
- address_to_bind = "localhost";
- } else if (*listen_host == '\0' ||
- strcmp(listen_host, "*") == 0) {
- if (datafellows & SSH_BUG_RFWD_ADDR)
- address_to_bind = "0.0.0.0";
- else
- address_to_bind = "";
- } else
- address_to_bind = listen_host;
-
- packet_start(SSH2_MSG_GLOBAL_REQUEST);
- packet_put_cstring("tcpip-forward");
- packet_put_char(1); /* boolean: want reply */
- packet_put_cstring(address_to_bind);
- packet_put_int(listen_port);
- packet_send();
- packet_write_wait();
- /* Assume that server accepts the request */
- success = 1;
- } else {
- packet_start(SSH_CMSG_PORT_FORWARD_REQUEST);
- packet_put_int(listen_port);
- packet_put_cstring(host_to_connect);
- packet_put_int(port_to_connect);
- packet_send();
- packet_write_wait();
-
- /* Wait for response from the remote side. */
- type = packet_read();
- switch (type) {
- case SSH_SMSG_SUCCESS:
- success = 1;
- break;
- case SSH_SMSG_FAILURE:
- log("Warning: Server denied remote port forwarding.");
- break;
- default:
- /* Unknown packet */
- packet_disconnect("Protocol error for port forward request:"
- "received packet type %d.", type);
- }
- }
- if (success) {
- permitted_opens[num_permitted_opens].host_to_connect = xstrdup(host_to_connect);
- permitted_opens[num_permitted_opens].port_to_connect = port_to_connect;
- permitted_opens[num_permitted_opens].listen_port = listen_port;
- num_permitted_opens++;
- }
- return (success ? 0 : -1);
-}
-
-/*
- * Request cancellation of remote forwarding of connection host:port from
- * local side.
- */
-void
-channel_request_rforward_cancel(const char *host, u_short port)
-{
- int i;
-
- if (!compat20)
- return;
-
- for (i = 0; i < num_permitted_opens; i++) {
- if (permitted_opens[i].host_to_connect != NULL &&
- permitted_opens[i].listen_port == port)
- break;
- }
- if (i >= num_permitted_opens) {
- debug("%s: requested forward not found", __func__);
- return;
- }
- packet_start(SSH2_MSG_GLOBAL_REQUEST);
- packet_put_cstring("cancel-tcpip-forward");
- packet_put_char(0);
- packet_put_cstring(host == NULL ? "" : host);
- packet_put_int(port);
- packet_send();
-
- permitted_opens[i].listen_port = 0;
- permitted_opens[i].port_to_connect = 0;
- xfree(permitted_opens[i].host_to_connect);
- permitted_opens[i].host_to_connect = NULL;
-}
-
-/*
- * This is called after receiving CHANNEL_FORWARDING_REQUEST. This initates
- * listening for the port, and sends back a success reply (or disconnect
- * message if there was an error). This never returns if there was an error.
- */
-
-void
-channel_input_port_forward_request(int is_root, int gateway_ports)
-{
- u_short port, host_port;
- char *hostname;
-
- /* Get arguments from the packet. */
- port = packet_get_int();
- hostname = packet_get_string(NULL);
- host_port = packet_get_int();
-
-#ifndef HAVE_CYGWIN
- /*
- * Check that an unprivileged user is not trying to forward a
- * privileged port.
- */
- if (port < IPPORT_RESERVED && !is_root)
- packet_disconnect("Requested forwarding of port %d but user is not root.",
- port);
-#endif
- /* Initiate forwarding */
- channel_setup_local_fwd_listener(NULL, port, hostname,
- host_port, gateway_ports);
-
- /* Free the argument string. */
- xfree(hostname);
-}
-
-/*
- * Permits opening to any host/port if permitted_opens[] is empty. This is
- * usually called by the server, because the user could connect to any port
- * anyway, and the server has no way to know but to trust the client anyway.
- */
-void
-channel_permit_all_opens(void)
-{
- if (num_permitted_opens == 0)
- all_opens_permitted = 1;
-}
-
-void
-channel_add_permitted_opens(char *host, int port)
-{
- if (num_permitted_opens >= SSH_MAX_FORWARDS_PER_DIRECTION)
- fatal("channel_add_permitted_opens: too many forwards");
- debug("allow port forwarding to host %s port %d", host, port);
-
- permitted_opens[num_permitted_opens].host_to_connect = xstrdup(host);
- permitted_opens[num_permitted_opens].port_to_connect = port;
- num_permitted_opens++;
-
- all_opens_permitted = 0;
-}
-
-void
-channel_clear_permitted_opens(void)
-{
- int i;
-
- for (i = 0; i < num_permitted_opens; i++)
- xfree(permitted_opens[i].host_to_connect);
- num_permitted_opens = 0;
-}
-
-
-/* return socket to remote host, port */
-static int
-connect_to(const char *host, u_short port)
-{
- struct addrinfo hints, *ai, *aitop;
- char ntop[NI_MAXHOST], strport[NI_MAXSERV];
- int gaierr;
- int sock = -1;
-
- memset(&hints, 0, sizeof(hints));
- hints.ai_family = IPv4or6;
- hints.ai_socktype = SOCK_STREAM;
- snprintf(strport, sizeof strport, "%d", port);
- if ((gaierr = getaddrinfo(host, strport, &hints, &aitop)) != 0) {
- error("connect_to %.100s: unknown host (%s)", host,
- gai_strerror(gaierr));
- return -1;
- }
- for (ai = aitop; ai; ai = ai->ai_next) {
- if (ai->ai_family != AF_INET && ai->ai_family != AF_INET6)
- continue;
- if (getnameinfo(ai->ai_addr, ai->ai_addrlen, ntop, sizeof(ntop),
- strport, sizeof(strport), NI_NUMERICHOST|NI_NUMERICSERV) != 0) {
- error("connect_to: getnameinfo failed");
- continue;
- }
- sock = socket(ai->ai_family, SOCK_STREAM, 0);
- if (sock < 0) {
- error("socket: %.100s", strerror(errno));
- continue;
- }
- if (fcntl(sock, F_SETFL, O_NONBLOCK) < 0)
- fatal("connect_to: F_SETFL: %s", strerror(errno));
- if (connect(sock, ai->ai_addr, ai->ai_addrlen) < 0 &&
- errno != EINPROGRESS) {
- error("connect_to %.100s port %s: %.100s", ntop, strport,
- strerror(errno));
- close(sock);
- continue; /* fail -- try next */
- }
- break; /* success */
-
- }
- freeaddrinfo(aitop);
- if (!ai) {
- error("connect_to %.100s port %d: failed.", host, port);
- return -1;
- }
- /* success */
- set_nodelay(sock);
- return sock;
-}
-
-int
-channel_connect_by_listen_address(u_short listen_port)
-{
- int i;
-
- for (i = 0; i < num_permitted_opens; i++)
- if (permitted_opens[i].listen_port == listen_port)
- return connect_to(
- permitted_opens[i].host_to_connect,
- permitted_opens[i].port_to_connect);
- error("WARNING: Server requests forwarding for unknown listen_port %d",
- listen_port);
- return -1;
-}
-
-/* Check if connecting to that port is permitted and connect. */
-int
-channel_connect_to(const char *host, u_short port)
-{
- int i, permit;
-
- permit = all_opens_permitted;
- if (!permit) {
- for (i = 0; i < num_permitted_opens; i++)
- if (permitted_opens[i].port_to_connect == port &&
- strcmp(permitted_opens[i].host_to_connect, host) == 0)
- permit = 1;
-
- }
- if (!permit) {
- log("Received request to connect to host %.100s port %d, "
- "but the request was denied.", host, port);
- return -1;
- }
- return connect_to(host, port);
-}
-
-/* -- X11 forwarding */
-
-/*
- * Creates an internet domain socket for listening for X11 connections.
- * Returns 0 and a suitable display number for the DISPLAY variable
- * stored in display_numberp , or -1 if an error occurs.
- */
-int
-x11_create_display_inet(int x11_display_offset, int x11_use_localhost,
- int single_connection, u_int *display_numberp)
-{
- Channel *nc = NULL;
- int display_number, sock;
- u_short port;
- struct addrinfo hints, *ai, *aitop;
- char strport[NI_MAXSERV];
- int gaierr, n, num_socks = 0, socks[NUM_SOCKS];
-
- for (display_number = x11_display_offset;
- display_number < MAX_DISPLAYS;
- display_number++) {
- port = 6000 + display_number;
- memset(&hints, 0, sizeof(hints));
- hints.ai_family = IPv4or6;
- hints.ai_flags = x11_use_localhost ? 0: AI_PASSIVE;
- hints.ai_socktype = SOCK_STREAM;
- snprintf(strport, sizeof strport, "%d", port);
- if ((gaierr = getaddrinfo(NULL, strport, &hints, &aitop)) != 0) {
- error("getaddrinfo: %.100s", gai_strerror(gaierr));
- return -1;
- }
- for (ai = aitop; ai; ai = ai->ai_next) {
- if (ai->ai_family != AF_INET && ai->ai_family != AF_INET6)
- continue;
- sock = socket(ai->ai_family, SOCK_STREAM, 0);
- if (sock < 0) {
- if ((errno != EINVAL) && (errno != EAFNOSUPPORT)) {
- error("socket: %.100s", strerror(errno));
- freeaddrinfo(aitop);
- for (n = 0; n < num_socks; n++)
- close(socks[n]);
- return -1;
- } else {
- debug("x11_create_display_inet: Socket family %d not supported",
- ai->ai_family);
- continue;
- }
- }
-#ifdef IPV6_V6ONLY
- if (ai->ai_family == AF_INET6) {
- int on = 1;
- if (setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY, &on, sizeof(on)) < 0)
- error("setsockopt IPV6_V6ONLY: %.100s", strerror(errno));
- }
-#endif
- if (bind(sock, ai->ai_addr, ai->ai_addrlen) < 0) {
- /*
- * If bind() fails with EADDRNOTAVAIL, we
- * should not break immediately but rather
- * try the next address available.
- */
- if (errno == EADDRNOTAVAIL) {
- close(sock);
- continue;
- }
-
- debug("bind port %d: %.100s; skipping this port", port,
- strerror(errno));
- close(sock);
-
- for (n = 0; n < num_socks; n++) {
- close(socks[n]);
- }
- num_socks = 0;
- break;
- }
- socks[num_socks++] = sock;
-#ifndef DONT_TRY_OTHER_AF
- if (num_socks == NUM_SOCKS)
- break;
-#else
- if (x11_use_localhost) {
- if (num_socks == NUM_SOCKS)
- break;
- } else {
- break;
- }
-#endif
- }
- freeaddrinfo(aitop);
- if (num_socks > 0)
- break;
- }
- if (display_number >= MAX_DISPLAYS) {
- error("Failed to allocate internet-domain X11 display socket.");
- return -1;
- }
- /* Start listening for connections on the socket. */
- for (n = 0; n < num_socks; n++) {
- sock = socks[n];
- if (listen(sock, 5) < 0) {
- int i;
- error("listen: %.100s", strerror(errno));
- for (i = 0; i < num_socks; i++)
- close(socks[i]);
- return -1;
- }
- }
-
- /* Allocate a channel for each socket. */
- for (n = 0; n < num_socks; n++) {
- sock = socks[n];
- nc = channel_new("x11 listener",
- SSH_CHANNEL_X11_LISTENER, sock, sock, -1,
- CHAN_X11_WINDOW_DEFAULT, CHAN_X11_PACKET_DEFAULT,
- 0, xstrdup("X11 inet listener"), 1);
- nc->single_connection = single_connection;
- }
-
- /* Return the display number for the DISPLAY environment variable. */
- *display_numberp = display_number;
- return (0);
-}
-
-static int
-connect_local_xsocket(u_int dnr)
-{
- int sock;
- struct sockaddr_un addr;
-
- sock = socket(AF_UNIX, SOCK_STREAM, 0);
- if (sock < 0)
- error("socket: %.100s", strerror(errno));
- memset(&addr, 0, sizeof(addr));
- addr.sun_family = AF_UNIX;
- snprintf(addr.sun_path, sizeof addr.sun_path, _PATH_UNIX_X, dnr);
- if (connect(sock, (struct sockaddr *) & addr, sizeof(addr)) == 0)
- return sock;
- close(sock);
- error("connect %.100s: %.100s", addr.sun_path, strerror(errno));
- return -1;
-}
-
-int
-x11_connect_display(void)
-{
- int display_number, sock = 0;
- const char *display;
- char buf[1024], *cp;
- struct addrinfo hints, *ai, *aitop;
- char strport[NI_MAXSERV];
- int gaierr;
-
- /* Try to open a socket for the local X server. */
- display = getenv("DISPLAY");
- if (!display) {
- error("DISPLAY not set.");
- return -1;
- }
- /*
- * Now we decode the value of the DISPLAY variable and make a
- * connection to the real X server.
- */
-
- /*
- * Check if it is a unix domain socket. Unix domain displays are in
- * one of the following formats: unix:d[.s], :d[.s], ::d[.s]
- */
- if (strncmp(display, "unix:", 5) == 0 ||
- display[0] == ':') {
- /* Connect to the unix domain socket. */
- if (sscanf(strrchr(display, ':') + 1, "%d", &display_number) != 1) {
- error("Could not parse display number from DISPLAY: %.100s",
- display);
- return -1;
- }
- /* Create a socket. */
- sock = connect_local_xsocket(display_number);
- if (sock < 0)
- return -1;
-
- /* OK, we now have a connection to the display. */
- return sock;
- }
- /*
- * Connect to an inet socket. The DISPLAY value is supposedly
- * hostname:d[.s], where hostname may also be numeric IP address.
- */
- strlcpy(buf, display, sizeof(buf));
- cp = strchr(buf, ':');
- if (!cp) {
- error("Could not find ':' in DISPLAY: %.100s", display);
- return -1;
- }
- *cp = 0;
- /* buf now contains the host name. But first we parse the display number. */
- if (sscanf(cp + 1, "%d", &display_number) != 1) {
- error("Could not parse display number from DISPLAY: %.100s",
- display);
- return -1;
- }
-
- /* Look up the host address */
- memset(&hints, 0, sizeof(hints));
- hints.ai_family = IPv4or6;
- hints.ai_socktype = SOCK_STREAM;
- snprintf(strport, sizeof strport, "%d", 6000 + display_number);
- if ((gaierr = getaddrinfo(buf, strport, &hints, &aitop)) != 0) {
- error("%.100s: unknown host. (%s)", buf, gai_strerror(gaierr));
- return -1;
- }
- for (ai = aitop; ai; ai = ai->ai_next) {
- /* Create a socket. */
- sock = socket(ai->ai_family, SOCK_STREAM, 0);
- if (sock < 0) {
- debug("socket: %.100s", strerror(errno));
- continue;
- }
- /* Connect it to the display. */
- if (connect(sock, ai->ai_addr, ai->ai_addrlen) < 0) {
- debug("connect %.100s port %d: %.100s", buf,
- 6000 + display_number, strerror(errno));
- close(sock);
- continue;
- }
- /* Success */
- break;
- }
- freeaddrinfo(aitop);
- if (!ai) {
- error("connect %.100s port %d: %.100s", buf, 6000 + display_number,
- strerror(errno));
- return -1;
- }
- set_nodelay(sock);
- return sock;
-}
-
-/*
- * This is called when SSH_SMSG_X11_OPEN is received. The packet contains
- * the remote channel number. We should do whatever we want, and respond
- * with either SSH_MSG_OPEN_CONFIRMATION or SSH_MSG_OPEN_FAILURE.
- */
-
-void
-x11_input_open(int type, u_int32_t seq, void *ctxt)
-{
- Channel *c = NULL;
- int remote_id, sock = 0;
- char *remote_host;
-
- debug("Received X11 open request.");
-
- remote_id = packet_get_int();
-
- if (packet_get_protocol_flags() & SSH_PROTOFLAG_HOST_IN_FWD_OPEN) {
- remote_host = packet_get_string(NULL);
- } else {
- remote_host = xstrdup("unknown (remote did not supply name)");
- }
- packet_check_eom();
-
- /* Obtain a connection to the real X display. */
- sock = x11_connect_display();
- if (sock != -1) {
- /* Allocate a channel for this connection. */
- c = channel_new("connected x11 socket",
- SSH_CHANNEL_X11_OPEN, sock, sock, -1, 0, 0, 0,
- remote_host, 1);
- c->remote_id = remote_id;
- c->force_drain = 1;
- }
- if (c == NULL) {
- /* Send refusal to the remote host. */
- packet_start(SSH_MSG_CHANNEL_OPEN_FAILURE);
- packet_put_int(remote_id);
- } else {
- /* Send a confirmation to the remote host. */
- packet_start(SSH_MSG_CHANNEL_OPEN_CONFIRMATION);
- packet_put_int(remote_id);
- packet_put_int(c->self);
- }
- packet_send();
-}
-
-/* dummy protocol handler that denies SSH-1 requests (agent/x11) */
-void
-deny_input_open(int type, u_int32_t seq, void *ctxt)
-{
- int rchan = packet_get_int();
-
- switch (type) {
- case SSH_SMSG_AGENT_OPEN:
- error("Warning: ssh server tried agent forwarding.");
- break;
- case SSH_SMSG_X11_OPEN:
- error("Warning: ssh server tried X11 forwarding.");
- break;
- default:
- error("deny_input_open: type %d", type);
- break;
- }
- error("Warning: this is probably a break in attempt by a malicious server.");
- packet_start(SSH_MSG_CHANNEL_OPEN_FAILURE);
- packet_put_int(rchan);
- packet_send();
-}
-
-/*
- * Requests forwarding of X11 connections, generates fake authentication
- * data, and enables authentication spoofing.
- * This should be called in the client only.
- */
-void
-x11_request_forwarding_with_spoofing(int client_session_id, const char *disp,
- const char *proto, const char *data)
-{
- u_int data_len = (u_int) strlen(data) / 2;
- u_int i, value;
- char *new_data;
- int screen_number;
- const char *cp;
- u_int32_t rand = 0;
-
- cp = disp;
- if (disp)
- cp = strchr(disp, ':');
- if (cp)
- cp = strchr(cp, '.');
- if (cp)
- screen_number = atoi(cp + 1);
- else
- screen_number = 0;
-
- /* Save protocol name. */
- x11_saved_proto = xstrdup(proto);
-
- /*
- * Extract real authentication data and generate fake data of the
- * same length.
- */
- x11_saved_data = xmalloc(data_len);
- x11_fake_data = xmalloc(data_len);
- for (i = 0; i < data_len; i++) {
- if (sscanf(data + 2 * i, "%2x", &value) != 1)
- fatal("x11_request_forwarding: bad authentication data: %.100s", data);
- if (i % 4 == 0)
- rand = arc4random();
- x11_saved_data[i] = value;
- x11_fake_data[i] = rand & 0xff;
- rand >>= 8;
- }
- x11_saved_data_len = data_len;
- x11_fake_data_len = data_len;
-
- /* Convert the fake data into hex. */
- new_data = tohex(x11_fake_data, data_len);
-
- /* Send the request packet. */
- if (compat20) {
- channel_request_start(client_session_id, "x11-req", 0);
- packet_put_char(0); /* XXX bool single connection */
- } else {
- packet_start(SSH_CMSG_X11_REQUEST_FORWARDING);
- }
- packet_put_cstring(proto);
- packet_put_cstring(new_data);
- packet_put_int(screen_number);
- packet_send();
- packet_write_wait();
- xfree(new_data);
-}
-
-
-/* -- agent forwarding */
-
-/* Sends a message to the server to request authentication fd forwarding. */
-
-void
-auth_request_forwarding(void)
-{
- packet_start(SSH_CMSG_AGENT_REQUEST_FORWARDING);
- packet_send();
- packet_write_wait();
-}
-
-/* This is called to process an SSH_SMSG_AGENT_OPEN message. */
-
-void
-auth_input_open_request(int type, u_int32_t seq, void *ctxt)
-{
- Channel *c = NULL;
- int remote_id, sock;
- char *name;
-
- /* Read the remote channel number from the message. */
- remote_id = packet_get_int();
- packet_check_eom();
-
- /*
- * Get a connection to the local authentication agent (this may again
- * get forwarded).
- */
- sock = ssh_get_authentication_socket();
-
- /*
- * If we could not connect the agent, send an error message back to
- * the server. This should never happen unless the agent dies,
- * because authentication forwarding is only enabled if we have an
- * agent.
- */
- if (sock >= 0) {
- name = xstrdup("authentication agent connection");
- c = channel_new("", SSH_CHANNEL_OPEN, sock, sock,
- -1, 0, 0, 0, name, 1);
- c->remote_id = remote_id;
- c->force_drain = 1;
- }
- if (c == NULL) {
- packet_start(SSH_MSG_CHANNEL_OPEN_FAILURE);
- packet_put_int(remote_id);
- } else {
- /* Send a confirmation to the remote host. */
- debug("Forwarding authentication connection.");
- packet_start(SSH_MSG_CHANNEL_OPEN_CONFIRMATION);
- packet_put_int(remote_id);
- packet_put_int(c->self);
- }
- packet_send();
-}
diff --git a/usr/src/cmd/ssh/libssh/common/cipher-ctr.c b/usr/src/cmd/ssh/libssh/common/cipher-ctr.c
deleted file mode 100644
index d728064b53..0000000000
--- a/usr/src/cmd/ssh/libssh/common/cipher-ctr.c
+++ /dev/null
@@ -1,172 +0,0 @@
-/*
- * Copyright (c) 2003 Markus Friedl <markus@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.
- */
-/*
- * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
- */
-
-#include "includes.h"
-RCSID("$OpenBSD: cipher-ctr.c,v 1.4 2004/02/06 23:41:13 dtucker Exp $");
-
-#include <openssl/evp.h>
-
-#include "log.h"
-#include "xmalloc.h"
-#include <openssl/aes.h>
-
-const EVP_CIPHER *evp_aes_128_ctr(void);
-void ssh_aes_ctr_iv(EVP_CIPHER_CTX *, int, u_char *, u_int);
-
-struct ssh_aes_ctr_ctx
-{
- AES_KEY aes_ctx;
- u_char aes_counter[AES_BLOCK_SIZE];
-};
-
-/*
- * increment counter 'ctr',
- * the counter is of size 'len' bytes and stored in network-byte-order.
- * (LSB at ctr[len-1], MSB at ctr[0])
- */
-static void
-ssh_ctr_inc(u_char *ctr, u_int len)
-{
- int i;
-
- for (i = len - 1; i >= 0; i--)
- if (++ctr[i]) /* continue on overflow */
- return;
-}
-
-static int
-ssh_aes_ctr(EVP_CIPHER_CTX *ctx, u_char *dest, const u_char *src,
- u_int len)
-{
- struct ssh_aes_ctr_ctx *c;
- u_int n = 0;
- u_char buf[AES_BLOCK_SIZE];
-
- if (len == 0)
- return (1);
- if ((c = EVP_CIPHER_CTX_get_app_data(ctx)) == NULL)
- return (0);
-
- while ((len--) > 0) {
- if (n == 0) {
- AES_encrypt(c->aes_counter, buf, &c->aes_ctx);
- ssh_ctr_inc(c->aes_counter, AES_BLOCK_SIZE);
- }
- *(dest++) = *(src++) ^ buf[n];
- n = (n + 1) % AES_BLOCK_SIZE;
- }
- return (1);
-}
-
-static int
-ssh_aes_ctr_init(EVP_CIPHER_CTX *ctx, const u_char *key, const u_char *iv,
- int enc)
-{
- struct ssh_aes_ctr_ctx *c;
-
- if ((c = EVP_CIPHER_CTX_get_app_data(ctx)) == NULL) {
- c = xmalloc(sizeof(*c));
- EVP_CIPHER_CTX_set_app_data(ctx, c);
- }
- if (key != NULL)
- AES_set_encrypt_key(key, EVP_CIPHER_CTX_key_length(ctx) * 8,
- &c->aes_ctx);
- if (iv != NULL)
- memcpy(c->aes_counter, iv, AES_BLOCK_SIZE);
- return (1);
-}
-
-static int
-ssh_aes_ctr_cleanup(EVP_CIPHER_CTX *ctx)
-{
- struct ssh_aes_ctr_ctx *c;
-
- if ((c = EVP_CIPHER_CTX_get_app_data(ctx)) != NULL) {
- memset(c, 0, sizeof(*c));
- xfree(c);
- EVP_CIPHER_CTX_set_app_data(ctx, NULL);
- }
- return (1);
-}
-
-void
-ssh_aes_ctr_iv(EVP_CIPHER_CTX *evp, int doset, u_char * iv, u_int len)
-{
- struct ssh_aes_ctr_ctx *c;
-
- if ((c = EVP_CIPHER_CTX_get_app_data(evp)) == NULL)
- fatal("ssh_aes_ctr_iv: no context");
- if (doset)
- memcpy(c->aes_counter, iv, len);
- else
- memcpy(iv, c->aes_counter, len);
-}
-
-/*
- * Function fills an EVP_CIPHER structure for AES CTR functions based on the NID
- * and the key length.
- */
-static const EVP_CIPHER *
-evp_aes_ctr(const char *nid, int key_len, EVP_CIPHER *aes_ctr)
-{
- memset(aes_ctr, 0, sizeof(EVP_CIPHER));
- /*
- * If the PKCS#11 engine is used the AES CTR NIDs were dynamically
- * created during the engine initialization. If the engine is not used
- * we work with NID_undef's which is OK since in that case OpenSSL
- * doesn't use NIDs at all.
- */
- if ((aes_ctr->nid = OBJ_ln2nid(nid)) != NID_undef)
- debug3("%s NID found", nid);
-
- aes_ctr->block_size = AES_BLOCK_SIZE;
- aes_ctr->iv_len = AES_BLOCK_SIZE;
- aes_ctr->key_len = key_len;
- aes_ctr->init = ssh_aes_ctr_init;
- aes_ctr->cleanup = ssh_aes_ctr_cleanup;
- aes_ctr->do_cipher = ssh_aes_ctr;
- aes_ctr->flags = EVP_CIPH_CBC_MODE | EVP_CIPH_VARIABLE_LENGTH |
- EVP_CIPH_ALWAYS_CALL_INIT | EVP_CIPH_CUSTOM_IV;
- return (aes_ctr);
-}
-
-const EVP_CIPHER *
-evp_aes_128_ctr(void)
-{
- static EVP_CIPHER aes_ctr;
-
- return (evp_aes_ctr("aes-128-ctr", 16, &aes_ctr));
-}
-
-const EVP_CIPHER *
-evp_aes_192_ctr(void)
-{
- static EVP_CIPHER aes_ctr;
-
- return (evp_aes_ctr("aes-192-ctr", 24, &aes_ctr));
-}
-
-const EVP_CIPHER *
-evp_aes_256_ctr(void)
-{
- static EVP_CIPHER aes_ctr;
-
- return (evp_aes_ctr("aes-256-ctr", 32, &aes_ctr));
-}
diff --git a/usr/src/cmd/ssh/libssh/common/cipher.c b/usr/src/cmd/ssh/libssh/common/cipher.c
deleted file mode 100644
index 3cb001a150..0000000000
--- a/usr/src/cmd/ssh/libssh/common/cipher.c
+++ /dev/null
@@ -1,585 +0,0 @@
-/*
- * Author: Tatu Ylonen <ylo@cs.hut.fi>
- * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
- * All rights reserved
- *
- * As far as I am concerned, the code I have written for this software
- * can be used freely for any purpose. Any derived versions of this
- * software must be clearly marked as such, and if the derived work is
- * incompatible with the protocol description in the RFC file, it must be
- * called by a name other than "ssh" or "Secure Shell".
- *
- *
- * Copyright (c) 1999 Niels Provos. All rights reserved.
- * Copyright (c) 1999, 2000 Markus Friedl. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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.
- */
-
-/*
- * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
- */
-
-#include "includes.h"
-RCSID("$OpenBSD: cipher.c,v 1.61 2002/07/12 15:50:17 markus Exp $");
-
-#include "xmalloc.h"
-#include "log.h"
-#include "cipher.h"
-
-#include <openssl/md5.h>
-
-/*
- * Symmetric ciphers can be offloaded to any engine through the EVP API only.
- * However, OpenSSL doesn't offer AES in counter mode through EVP. So, we must
- * define our own EVP functions.
- */
-extern const EVP_CIPHER *evp_aes_128_ctr(void);
-extern const EVP_CIPHER *evp_aes_192_ctr(void);
-extern const EVP_CIPHER *evp_aes_256_ctr(void);
-extern void ssh_aes_ctr_iv(EVP_CIPHER_CTX *, int, u_char *, u_int);
-
-static const EVP_CIPHER *evp_ssh1_3des(void);
-static const EVP_CIPHER *evp_ssh1_bf(void);
-
-struct Cipher {
- char *name;
- int number; /* for ssh1 only */
- u_int block_size;
- u_int key_len;
- u_int discard_len;
- const EVP_CIPHER *(*evptype)(void);
-} ciphers[] = {
- { "none", SSH_CIPHER_NONE, 8, 0, 0, EVP_enc_null },
- { "des", SSH_CIPHER_DES, 8, 8, 0, EVP_des_cbc },
- { "3des", SSH_CIPHER_3DES, 8, 16, 0, evp_ssh1_3des },
- { "blowfish", SSH_CIPHER_BLOWFISH, 8, 32, 0, evp_ssh1_bf },
- { "3des-cbc", SSH_CIPHER_SSH2, 8, 24, 0, EVP_des_ede3_cbc },
- { "blowfish-cbc", SSH_CIPHER_SSH2, 8, 16, 0, EVP_bf_cbc },
-#ifdef SOLARIS_SSH_ENABLE_CAST5_128
- { "cast128-cbc", SSH_CIPHER_SSH2, 8, 16, 0, EVP_cast5_cbc },
-#endif /* SOLARIS_SSH_ENABLE_CAST5_128 */
- { "arcfour", SSH_CIPHER_SSH2, 8, 16, 0, EVP_rc4 },
- { "arcfour128", SSH_CIPHER_SSH2, 8, 16, 1536, EVP_rc4 },
- { "arcfour256", SSH_CIPHER_SSH2, 8, 32, 1536, EVP_rc4 },
- { "aes128-cbc", SSH_CIPHER_SSH2, 16, 16, 0, EVP_aes_128_cbc },
- { "aes192-cbc", SSH_CIPHER_SSH2, 16, 24, 0, EVP_aes_192_cbc },
- { "aes256-cbc", SSH_CIPHER_SSH2, 16, 32, 0, EVP_aes_256_cbc },
- { "aes128-ctr", SSH_CIPHER_SSH2, 16, 16, 0, evp_aes_128_ctr },
- { "aes192-ctr", SSH_CIPHER_SSH2, 16, 24, 0, evp_aes_192_ctr },
- { "aes256-ctr", SSH_CIPHER_SSH2, 16, 32, 0, evp_aes_256_ctr },
- { NULL, SSH_CIPHER_ILLEGAL, 0, 0, 0, NULL }
-};
-
-/*--*/
-
-u_int
-cipher_blocksize(Cipher *c)
-{
- return (c->block_size);
-}
-
-u_int
-cipher_keylen(Cipher *c)
-{
- return (c->key_len);
-}
-
-u_int
-cipher_get_number(Cipher *c)
-{
- return (c->number);
-}
-
-u_int
-cipher_mask_ssh1(int client)
-{
- u_int mask = 0;
- mask |= 1 << SSH_CIPHER_3DES; /* Mandatory */
- mask |= 1 << SSH_CIPHER_BLOWFISH;
- if (client) {
- mask |= 1 << SSH_CIPHER_DES;
- }
- return mask;
-}
-
-Cipher *
-cipher_by_name(const char *name)
-{
- Cipher *c;
- for (c = ciphers; c->name != NULL; c++)
- if (strcasecmp(c->name, name) == 0)
- return c;
- return NULL;
-}
-
-Cipher *
-cipher_by_number(int id)
-{
- Cipher *c;
- for (c = ciphers; c->name != NULL; c++)
- if (c->number == id)
- return c;
- return NULL;
-}
-
-#define CIPHER_SEP ","
-int
-ciphers_valid(const char *names)
-{
- Cipher *c;
- char *ciphers, *cp;
- char *p;
-
- if (names == NULL || strcmp(names, "") == 0)
- return 0;
- ciphers = cp = xstrdup(names);
- for ((p = strsep(&cp, CIPHER_SEP)); p && *p != '\0';
- (p = strsep(&cp, CIPHER_SEP))) {
- c = cipher_by_name(p);
- if (c == NULL || c->number != SSH_CIPHER_SSH2) {
- debug("bad cipher %s [%s]", p, names);
- xfree(ciphers);
- return 0;
- } else {
- debug3("cipher ok: %s [%s]", p, names);
- }
- }
- debug3("ciphers ok: [%s]", names);
- xfree(ciphers);
- return 1;
-}
-
-/*
- * Parses the name of the cipher. Returns the number of the corresponding
- * cipher, or -1 on error.
- */
-
-int
-cipher_number(const char *name)
-{
- Cipher *c;
- if (name == NULL)
- return -1;
- c = cipher_by_name(name);
- return (c==NULL) ? -1 : c->number;
-}
-
-char *
-cipher_name(int id)
-{
- Cipher *c = cipher_by_number(id);
- return (c==NULL) ? "<unknown>" : c->name;
-}
-
-void
-cipher_init(CipherContext *cc, Cipher *cipher,
- const u_char *key, u_int keylen, const u_char *iv, u_int ivlen,
- int encrypt)
-{
- static int dowarn = 1;
- const EVP_CIPHER *type;
- int klen;
- u_char *junk, *discard;
-
- if (cipher->number == SSH_CIPHER_DES) {
- if (dowarn) {
- error("Warning: use of DES is strongly discouraged "
- "due to cryptographic weaknesses");
- dowarn = 0;
- }
- if (keylen > 8)
- keylen = 8;
- }
- cc->plaintext = (cipher->number == SSH_CIPHER_NONE);
-
- if (keylen < cipher->key_len)
- fatal("cipher_init: key length %d is insufficient for %s.",
- keylen, cipher->name);
- if (iv != NULL && ivlen < cipher->block_size)
- fatal("cipher_init: iv length %d is insufficient for %s.",
- ivlen, cipher->name);
- cc->cipher = cipher;
-
- type = (*cipher->evptype)();
-
- EVP_CIPHER_CTX_init(&cc->evp);
- /*
- * cc->evp is of type EVP_CIPHER_CTX and its key_len will be set to the
- * default value here for the cipher type. If the requested key length
- * is different from the default value we will call EVP_CipherInit()
- * again, see below.
- */
- if (EVP_CipherInit(&cc->evp, type, NULL, (u_char *)iv,
- (encrypt == CIPHER_ENCRYPT)) == 0)
- fatal("cipher_init: EVP_CipherInit failed for %s",
- cipher->name);
- klen = EVP_CIPHER_CTX_key_length(&cc->evp);
- if (klen > 0 && keylen != klen) {
- debug("cipher_init: set keylen (%d -> %d)", klen, keylen);
- if (EVP_CIPHER_CTX_set_key_length(&cc->evp, keylen) == 0)
- fatal("cipher_init: set keylen failed (%d -> %d)",
- klen, keylen);
- }
- if (EVP_CipherInit(&cc->evp, NULL, (u_char *)key, NULL, -1) == 0)
- fatal("cipher_init: EVP_CipherInit: set key failed for %s",
- cipher->name);
-
- if (cipher->discard_len > 0) {
- junk = xmalloc(cipher->discard_len);
- discard = xmalloc(cipher->discard_len);
- if (EVP_Cipher(&cc->evp, discard, junk,
- cipher->discard_len) == 0)
- fatal("cipher_init: EVP_Cipher failed during discard");
- memset(discard, 0, cipher->discard_len);
- xfree(junk);
- xfree(discard);
- }
-}
-
-void
-cipher_crypt(CipherContext *cc, u_char *dest, const u_char *src, u_int len)
-{
- if (len % cc->cipher->block_size)
- fatal("cipher_encrypt: bad plaintext length %d", len);
- if (EVP_Cipher(&cc->evp, dest, (u_char *)src, len) == 0)
- fatal("evp_crypt: EVP_Cipher failed");
-}
-
-void
-cipher_cleanup(CipherContext *cc)
-{
- if (EVP_CIPHER_CTX_cleanup(&cc->evp) == 0)
- error("cipher_cleanup: EVP_CIPHER_CTX_cleanup failed");
-}
-
-/*
- * Selects the cipher, and keys if by computing the MD5 checksum of the
- * passphrase and using the resulting 16 bytes as the key.
- */
-
-void
-cipher_set_key_string(CipherContext *cc, Cipher *cipher,
- const char *passphrase, int encrypt)
-{
- MD5_CTX md;
- u_char digest[16];
-
- MD5_Init(&md);
- MD5_Update(&md, (const u_char *)passphrase, strlen(passphrase));
- MD5_Final(digest, &md);
-
- cipher_init(cc, cipher, digest, 16, NULL, 0, encrypt);
-
- memset(digest, 0, sizeof(digest));
- memset(&md, 0, sizeof(md));
-}
-
-/* Implementations for other non-EVP ciphers */
-
-/*
- * This is used by SSH1:
- *
- * What kind of triple DES are these 2 routines?
- *
- * Why is there a redundant initialization vector?
- *
- * If only iv3 was used, then, this would till effect have been
- * outer-cbc. However, there is also a private iv1 == iv2 which
- * perhaps makes differential analysis easier. On the other hand, the
- * private iv1 probably makes the CRC-32 attack ineffective. This is a
- * result of that there is no longer any known iv1 to use when
- * choosing the X block.
- */
-struct ssh1_3des_ctx
-{
- EVP_CIPHER_CTX k1, k2, k3;
-};
-
-static int
-ssh1_3des_init(EVP_CIPHER_CTX *ctx, const u_char *key, const u_char *iv,
- int enc)
-{
- struct ssh1_3des_ctx *c;
- u_char *k1, *k2, *k3;
-
- if ((c = EVP_CIPHER_CTX_get_app_data(ctx)) == NULL) {
- c = xmalloc(sizeof(*c));
- EVP_CIPHER_CTX_set_app_data(ctx, c);
- }
- if (key == NULL)
- return (1);
- if (enc == -1)
- enc = ctx->encrypt;
- k1 = k2 = k3 = (u_char *) key;
- k2 += 8;
- if (EVP_CIPHER_CTX_key_length(ctx) >= 16+8) {
- if (enc)
- k3 += 16;
- else
- k1 += 16;
- }
- EVP_CIPHER_CTX_init(&c->k1);
- EVP_CIPHER_CTX_init(&c->k2);
- EVP_CIPHER_CTX_init(&c->k3);
- if (EVP_CipherInit(&c->k1, EVP_des_cbc(), k1, NULL, enc) == 0 ||
- EVP_CipherInit(&c->k2, EVP_des_cbc(), k2, NULL, !enc) == 0 ||
- EVP_CipherInit(&c->k3, EVP_des_cbc(), k3, NULL, enc) == 0) {
- memset(c, 0, sizeof(*c));
- xfree(c);
- EVP_CIPHER_CTX_set_app_data(ctx, NULL);
- return (0);
- }
- return (1);
-}
-
-static int
-ssh1_3des_cbc(EVP_CIPHER_CTX *ctx, u_char *dest, const u_char *src, u_int len)
-{
- struct ssh1_3des_ctx *c;
-
- if ((c = EVP_CIPHER_CTX_get_app_data(ctx)) == NULL) {
- error("ssh1_3des_cbc: no context");
- return (0);
- }
- if (EVP_Cipher(&c->k1, dest, (u_char *)src, len) == 0 ||
- EVP_Cipher(&c->k2, dest, dest, len) == 0 ||
- EVP_Cipher(&c->k3, dest, dest, len) == 0)
- return (0);
- return (1);
-}
-
-static int
-ssh1_3des_cleanup(EVP_CIPHER_CTX *ctx)
-{
- struct ssh1_3des_ctx *c;
-
- if ((c = EVP_CIPHER_CTX_get_app_data(ctx)) != NULL) {
- memset(c, 0, sizeof(*c));
- xfree(c);
- EVP_CIPHER_CTX_set_app_data(ctx, NULL);
- }
- return (1);
-}
-
-static const EVP_CIPHER *
-evp_ssh1_3des(void)
-{
- static EVP_CIPHER ssh1_3des;
-
- memset(&ssh1_3des, 0, sizeof(EVP_CIPHER));
- ssh1_3des.nid = NID_undef;
- ssh1_3des.block_size = 8;
- ssh1_3des.iv_len = 0;
- ssh1_3des.key_len = 16;
- ssh1_3des.init = ssh1_3des_init;
- ssh1_3des.cleanup = ssh1_3des_cleanup;
- ssh1_3des.do_cipher = ssh1_3des_cbc;
- ssh1_3des.flags = EVP_CIPH_CBC_MODE | EVP_CIPH_VARIABLE_LENGTH;
- return (&ssh1_3des);
-}
-
-/*
- * SSH1 uses a variation on Blowfish, all bytes must be swapped before
- * and after encryption/decryption. Thus the swap_bytes stuff (yuk).
- */
-static void
-swap_bytes(const u_char *src, u_char *dst, int n)
-{
- u_char c[4];
-
- /* Process 4 bytes every lap. */
- for (n = n / 4; n > 0; n--) {
- c[3] = *src++;
- c[2] = *src++;
- c[1] = *src++;
- c[0] = *src++;
-
- *dst++ = c[0];
- *dst++ = c[1];
- *dst++ = c[2];
- *dst++ = c[3];
- }
-}
-
-static int (*orig_bf)(EVP_CIPHER_CTX *, u_char *, const u_char *, u_int) = NULL;
-
-static int
-bf_ssh1_cipher(EVP_CIPHER_CTX *ctx, u_char *out, const u_char *in, u_int len)
-{
- int ret;
-
- swap_bytes(in, out, len);
- ret = (*orig_bf)(ctx, out, out, len);
- swap_bytes(out, out, len);
- return (ret);
-}
-
-static const EVP_CIPHER *
-evp_ssh1_bf(void)
-{
- static EVP_CIPHER ssh1_bf;
-
- memcpy(&ssh1_bf, EVP_bf_cbc(), sizeof(EVP_CIPHER));
- orig_bf = ssh1_bf.do_cipher;
- ssh1_bf.nid = NID_undef;
- ssh1_bf.do_cipher = bf_ssh1_cipher;
- ssh1_bf.key_len = 32;
- return (&ssh1_bf);
-}
-
-/*
- * Exports an IV from the CipherContext required to export the key
- * state back from the unprivileged child to the privileged parent
- * process.
- */
-
-int
-cipher_get_keyiv_len(CipherContext *cc)
-{
- Cipher *c = cc->cipher;
- int ivlen;
-
- if (c->number == SSH_CIPHER_3DES)
- ivlen = 24;
- else
- ivlen = EVP_CIPHER_CTX_iv_length(&cc->evp);
- return (ivlen);
-}
-
-void
-cipher_get_keyiv(CipherContext *cc, u_char *iv, u_int len)
-{
- Cipher *c = cc->cipher;
- u_char *civ = NULL;
- int evplen;
-
- switch (c->number) {
- case SSH_CIPHER_SSH2:
- case SSH_CIPHER_DES:
- case SSH_CIPHER_BLOWFISH:
- evplen = EVP_CIPHER_CTX_iv_length(&cc->evp);
- if (evplen == 0)
- return;
- if (evplen != len)
- fatal("%s: wrong iv length %d != %d", __func__,
- evplen, len);
-
- if (c->evptype == evp_aes_128_ctr) {
- ssh_aes_ctr_iv(&cc->evp, 0, iv, len);
- return;
- } else {
- civ = cc->evp.iv;
- }
- break;
- case SSH_CIPHER_3DES: {
- struct ssh1_3des_ctx *desc;
- if (len != 24)
- fatal("%s: bad 3des iv length: %d", __func__, len);
- desc = EVP_CIPHER_CTX_get_app_data(&cc->evp);
- if (desc == NULL)
- fatal("%s: no 3des context", __func__);
- debug3("%s: Copying 3DES IV", __func__);
- memcpy(iv, desc->k1.iv, 8);
- memcpy(iv + 8, desc->k2.iv, 8);
- memcpy(iv + 16, desc->k3.iv, 8);
- return;
- }
- default:
- fatal("%s: bad cipher %d", __func__, c->number);
- }
- memcpy(iv, civ, len);
-}
-
-void
-cipher_set_keyiv(CipherContext *cc, u_char *iv)
-{
- Cipher *c = cc->cipher;
- u_char *div = NULL;
- int evplen = 0;
-
- switch (c->number) {
- case SSH_CIPHER_SSH2:
- case SSH_CIPHER_DES:
- case SSH_CIPHER_BLOWFISH:
- evplen = EVP_CIPHER_CTX_iv_length(&cc->evp);
- if (evplen == 0)
- return;
-
- if (c->evptype == evp_aes_128_ctr) {
- ssh_aes_ctr_iv(&cc->evp, 1, iv, evplen);
- return;
- } else {
- div = cc->evp.iv;
- }
- break;
- case SSH_CIPHER_3DES: {
- struct ssh1_3des_ctx *desc;
- desc = EVP_CIPHER_CTX_get_app_data(&cc->evp);
- if (desc == NULL)
- fatal("%s: no 3des context", __func__);
- debug3("%s: Installed 3DES IV", __func__);
- memcpy(desc->k1.iv, iv, 8);
- memcpy(desc->k2.iv, iv + 8, 8);
- memcpy(desc->k3.iv, iv + 16, 8);
- return;
- }
- default:
- fatal("%s: bad cipher %d", __func__, c->number);
- }
- memcpy(div, iv, evplen);
-}
-
-#if OPENSSL_VERSION_NUMBER < 0x00907000L
-#define EVP_X_STATE(evp) &(evp).c
-#define EVP_X_STATE_LEN(evp) sizeof((evp).c)
-#else
-#define EVP_X_STATE(evp) (evp).cipher_data
-#define EVP_X_STATE_LEN(evp) (evp).cipher->ctx_size
-#endif
-
-int
-cipher_get_keycontext(CipherContext *cc, u_char *dat)
-{
- int plen = 0;
- Cipher *c = cc->cipher;
-
- if (c->evptype == EVP_rc4) {
- plen = EVP_X_STATE_LEN(cc->evp);
- if (dat == NULL)
- return (plen);
- memcpy(dat, EVP_X_STATE(cc->evp), plen);
- }
- return (plen);
-}
-
-void
-cipher_set_keycontext(CipherContext *cc, u_char *dat)
-{
- Cipher *c = cc->cipher;
- int plen;
-
- if (c->evptype == EVP_rc4) {
- plen = EVP_X_STATE_LEN(cc->evp);
- memcpy(EVP_X_STATE(cc->evp), dat, plen);
- }
-}
diff --git a/usr/src/cmd/ssh/libssh/common/compat.c b/usr/src/cmd/ssh/libssh/common/compat.c
deleted file mode 100644
index 6d85d6e511..0000000000
--- a/usr/src/cmd/ssh/libssh/common/compat.c
+++ /dev/null
@@ -1,260 +0,0 @@
-/*
- * Copyright (c) 1999, 2000, 2001, 2002 Markus Friedl. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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.
- */
-/*
- * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
- */
-
-#include "includes.h"
-RCSID("$OpenBSD: compat.c,v 1.65 2002/09/27 10:42:09 mickey Exp $");
-
-#include "buffer.h"
-#include "packet.h"
-#include "xmalloc.h"
-#include "compat.h"
-#include "log.h"
-#include "match.h"
-
-int compat13 = 0;
-int compat20 = 0;
-uint32_t datafellows = 0;
-
-void
-enable_compat20(void)
-{
- debug("Enabling compatibility mode for protocol 2.0");
- compat20 = 1;
-}
-void
-enable_compat13(void)
-{
- debug("Enabling compatibility mode for protocol 1.3");
- compat13 = 1;
-}
-/* datafellows bug compatibility */
-void
-compat_datafellows(const char *version)
-{
- int i;
- static struct {
- char *pat;
- uint32_t bugs;
- } check[] = {
- { "OpenSSH-2.0*,"
- "OpenSSH-2.1*,"
- "OpenSSH_2.1*,"
- "OpenSSH_2.2*", SSH_OLD_SESSIONID|SSH_BUG_BANNER|
- SSH_OLD_DHGEX|SSH_BUG_NOREKEY|
- SSH_BUG_EXTEOF|SSH_OLD_FORWARD_ADDR},
- { "OpenSSH_2.3.0*", SSH_BUG_BANNER|SSH_BUG_BIGENDIANAES|
- SSH_OLD_DHGEX|SSH_BUG_NOREKEY|
- SSH_BUG_EXTEOF|SSH_OLD_FORWARD_ADDR},
- { "OpenSSH_2.3.*", SSH_BUG_BIGENDIANAES|SSH_OLD_DHGEX|
- SSH_BUG_NOREKEY|SSH_BUG_EXTEOF|
- SSH_OLD_FORWARD_ADDR},
- { "OpenSSH_2.5.0p1*,"
- "OpenSSH_2.5.1p1*",
- SSH_BUG_BIGENDIANAES|SSH_OLD_DHGEX|
- SSH_BUG_NOREKEY|SSH_BUG_EXTEOF|
- SSH_OLD_GSSAPI|SSH_OLD_FORWARD_ADDR},
- { "OpenSSH_2.5.0*,"
- "OpenSSH_2.5.1*,"
- "OpenSSH_2.5.2*", SSH_OLD_DHGEX|SSH_BUG_NOREKEY|
- SSH_BUG_EXTEOF|SSH_OLD_FORWARD_ADDR},
- { "OpenSSH_2.5.3*", SSH_BUG_NOREKEY|SSH_BUG_EXTEOF|
- SSH_OLD_FORWARD_ADDR},
- { "OpenSSH_2.9p*", SSH_BUG_EXTEOF|SSH_OLD_GSSAPI|
- SSH_BUG_GSSKEX_HOSTKEY|SSH_OLD_FORWARD_ADDR},
- { "OpenSSH_2.*,"
- "OpenSSH_3.0*,"
- "OpenSSH_3.1*", SSH_BUG_EXTEOF|SSH_OLD_FORWARD_ADDR|
- SSH_OLD_GSSAPI|SSH_BUG_GSSAPI_BER|
- SSH_BUG_GSSKEX_HOSTKEY},
- { "OpenSSH_3.2*,"
- "OpenSSH_3.3*,"
- "OpenSSH_3.4*,"
- "OpenSSH_3.5*", SSH_BUG_GSSAPI_BER|SSH_OLD_GSSAPI|
- SSH_BUG_GSSKEX_HOSTKEY|SSH_OLD_FORWARD_ADDR},
- { "OpenSSH_3.6*,"
- "OpenSSH_3.7*,"
- "OpenSSH_3.8*", SSH_BUG_GSSKEX_HOSTKEY|SSH_OLD_FORWARD_ADDR},
- { "OpenSSH_3.*", SSH_OLD_FORWARD_ADDR},
- { "OpenSSH*", 0 },
- { "Sun_SSH_1.0.*", SSH_BUG_NOREKEY|
- SSH_BUG_LOCALES_NOT_LANGTAGS|SSH_OLD_FORWARD_ADDR},
- { "Sun_SSH_1.0*", SSH_BUG_NOREKEY|SSH_BUG_EXTEOF|
- SSH_BUG_LOCALES_NOT_LANGTAGS|SSH_OLD_FORWARD_ADDR},
- { "Sun_SSH_1.1.1*", SSH_OLD_FORWARD_ADDR|SSH_BUG_STRING_ENCODING},
- { "Sun_SSH_1.1.2*", SSH_OLD_FORWARD_ADDR},
- { "Sun_SSH_1.1*", SSH_OLD_FORWARD_ADDR|SSH_BUG_STRING_ENCODING},
- { "Sun_SSH_1.2*", SSH_BUG_STRING_ENCODING},
- { "Sun_SSH_1.3*", SSH_BUG_STRING_ENCODING},
- { "Sun_SSH_1.4*", 0 },
- { "Sun_SSH_1.5*", 0 },
- { "Sun_SSH_*", 0 },
- { "*MindTerm*", 0 },
- { "2.1.0*", SSH_BUG_SIGBLOB|SSH_BUG_HMAC|
- SSH_OLD_SESSIONID|SSH_BUG_DEBUG|
- SSH_BUG_RSASIGMD5|SSH_BUG_HBSERVICE|
- SSH_BUG_FIRSTKEX },
- { "2.1 *", SSH_BUG_SIGBLOB|SSH_BUG_HMAC|
- SSH_OLD_SESSIONID|SSH_BUG_DEBUG|
- SSH_BUG_RSASIGMD5|SSH_BUG_HBSERVICE|
- SSH_BUG_FIRSTKEX },
- { "2.0.13*,"
- "2.0.14*,"
- "2.0.15*,"
- "2.0.16*,"
- "2.0.17*,"
- "2.0.18*,"
- "2.0.19*", SSH_BUG_SIGBLOB|SSH_BUG_HMAC|
- SSH_OLD_SESSIONID|SSH_BUG_DEBUG|
- SSH_BUG_PKSERVICE|SSH_BUG_X11FWD|
- SSH_BUG_PKOK|SSH_BUG_RSASIGMD5|
- SSH_BUG_HBSERVICE|SSH_BUG_OPENFAILURE|
- SSH_BUG_DUMMYCHAN|SSH_BUG_FIRSTKEX },
- { "2.0.11*,"
- "2.0.12*", SSH_BUG_SIGBLOB|SSH_BUG_HMAC|
- SSH_OLD_SESSIONID|SSH_BUG_DEBUG|
- SSH_BUG_PKSERVICE|SSH_BUG_X11FWD|
- SSH_BUG_PKAUTH|SSH_BUG_PKOK|
- SSH_BUG_RSASIGMD5|SSH_BUG_OPENFAILURE|
- SSH_BUG_DUMMYCHAN|SSH_BUG_FIRSTKEX },
- { "2.0.*", SSH_BUG_SIGBLOB|SSH_BUG_HMAC|
- SSH_OLD_SESSIONID|SSH_BUG_DEBUG|
- SSH_BUG_PKSERVICE|SSH_BUG_X11FWD|
- SSH_BUG_PKAUTH|SSH_BUG_PKOK|
- SSH_BUG_RSASIGMD5|SSH_BUG_OPENFAILURE|
- SSH_BUG_DERIVEKEY|SSH_BUG_DUMMYCHAN|
- SSH_BUG_FIRSTKEX },
- { "2.2.0*,"
- "2.3.0*", SSH_BUG_HMAC|SSH_BUG_DEBUG|
- SSH_BUG_RSASIGMD5|SSH_BUG_FIRSTKEX },
- { "2.3.*", SSH_BUG_DEBUG|SSH_BUG_RSASIGMD5|
- SSH_BUG_FIRSTKEX },
- { "2.4", SSH_OLD_SESSIONID }, /* Van Dyke */
- { "2.*", SSH_BUG_DEBUG|SSH_BUG_FIRSTKEX|
- SSH_BUG_RFWD_ADDR},
- { "3.0.*", SSH_BUG_DEBUG },
- { "3.0 SecureCRT*", SSH_OLD_SESSIONID },
- { "1.7 SecureFX*", SSH_OLD_SESSIONID },
- { "1.2.18*,"
- "1.2.19*,"
- "1.2.20*,"
- "1.2.21*,"
- "1.2.22*", SSH_BUG_IGNOREMSG|SSH_BUG_K5USER },
- { "1.3.2*", /* F-Secure */
- SSH_BUG_IGNOREMSG|SSH_BUG_K5USER },
- { "1.2.1*,"
- "1.2.2*,"
- "1.2.3*", SSH_BUG_K5USER },
- { "*SSH Compatible Server*", /* Netscreen */
- SSH_BUG_PASSWORDPAD },
- { "*OSU_0*,"
- "OSU_1.0*,"
- "OSU_1.1*,"
- "OSU_1.2*,"
- "OSU_1.3*,"
- "OSU_1.4*,"
- "OSU_1.5alpha1*,"
- "OSU_1.5alpha2*,"
- "OSU_1.5alpha3*", SSH_BUG_PASSWORDPAD },
- { "*SSH_Version_Mapper*",
- SSH_BUG_SCANNER },
- { "Probe-*",
- SSH_BUG_PROBE },
- { NULL, 0 }
- };
-
- /* process table, return first match */
- for (i = 0; check[i].pat; i++) {
- if (match_pattern_list(version, check[i].pat,
- strlen(check[i].pat), 0) == 1) {
- debug("match: %s pat %s", version, check[i].pat);
- datafellows = check[i].bugs;
- return;
- }
- }
- debug("no match: %s", version);
-}
-
-#define SEP ","
-int
-proto_spec(const char *spec)
-{
- char *s, *p, *q;
- int ret = SSH_PROTO_UNKNOWN;
-
- if (spec == NULL)
- return ret;
- q = s = xstrdup(spec);
- for ((p = strsep(&q, SEP)); p && *p != '\0'; (p = strsep(&q, SEP))) {
- switch (atoi(p)) {
- case 1:
- if (ret == SSH_PROTO_UNKNOWN)
- ret |= SSH_PROTO_1_PREFERRED;
- ret |= SSH_PROTO_1;
- break;
- case 2:
- ret |= SSH_PROTO_2;
- break;
- default:
- log("ignoring bad proto spec: '%s'.", p);
- break;
- }
- }
- xfree(s);
- return ret;
-}
-
-char *
-compat_cipher_proposal(char *cipher_prop)
-{
- Buffer b;
- char *orig_prop, *fix_ciphers;
- char *cp, *tmp;
-
- if (!(datafellows & SSH_BUG_BIGENDIANAES))
- return(cipher_prop);
-
- buffer_init(&b);
- tmp = orig_prop = xstrdup(cipher_prop);
- while ((cp = strsep(&tmp, ",")) != NULL) {
- if (strncmp(cp, "aes", 3) != 0) {
- if (buffer_len(&b) > 0)
- buffer_append(&b, ",", 1);
- buffer_append(&b, cp, strlen(cp));
- }
- }
- buffer_append(&b, "\0", 1);
- fix_ciphers = xstrdup(buffer_ptr(&b));
- buffer_free(&b);
- xfree(orig_prop);
- debug2("Original cipher proposal: %s", cipher_prop);
- debug2("Compat cipher proposal: %s", fix_ciphers);
- if (!*fix_ciphers)
- fatal("No available ciphers found.");
-
- return(fix_ciphers);
-}
diff --git a/usr/src/cmd/ssh/libssh/common/compress.c b/usr/src/cmd/ssh/libssh/common/compress.c
deleted file mode 100644
index 6a4965c461..0000000000
--- a/usr/src/cmd/ssh/libssh/common/compress.c
+++ /dev/null
@@ -1,162 +0,0 @@
-/*
- * Author: Tatu Ylonen <ylo@cs.hut.fi>
- * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
- * All rights reserved
- * Interface to packet compression for ssh.
- *
- * As far as I am concerned, the code I have written for this software
- * can be used freely for any purpose. Any derived versions of this
- * software must be clearly marked as such, and if the derived work is
- * incompatible with the protocol description in the RFC file, it must be
- * called by a name other than "ssh" or "Secure Shell".
- */
-
-#include "includes.h"
-RCSID("$OpenBSD: compress.c,v 1.19 2002/03/18 17:31:54 provos Exp $");
-
-#pragma ident "%Z%%M% %I% %E% SMI"
-
-#include "log.h"
-#include "buffer.h"
-#include "zlib.h"
-#include "compress.h"
-
-z_stream incoming_stream;
-z_stream outgoing_stream;
-static int compress_init_send_called = 0;
-static int compress_init_recv_called = 0;
-static int inflate_failed = 0;
-static int deflate_failed = 0;
-
-/*
- * Initializes compression; level is compression level from 1 to 9
- * (as in gzip).
- */
-
-void
-buffer_compress_init_send(int level)
-{
- if (compress_init_send_called == 1)
- deflateEnd(&outgoing_stream);
- compress_init_send_called = 1;
- debug("Enabling compression at level %d.", level);
- if (level < 1 || level > 9)
- fatal("Bad compression level %d.", level);
- deflateInit(&outgoing_stream, level);
-}
-void
-buffer_compress_init_recv(void)
-{
- if (compress_init_recv_called == 1)
- inflateEnd(&incoming_stream);
- compress_init_recv_called = 1;
- inflateInit(&incoming_stream);
-}
-
-/* Frees any data structures allocated for compression. */
-
-void
-buffer_compress_uninit(void)
-{
- debug("compress outgoing: raw data %lu, compressed %lu, factor %.2f",
- outgoing_stream.total_in, outgoing_stream.total_out,
- outgoing_stream.total_in == 0 ? 0.0 :
- (double) outgoing_stream.total_out / outgoing_stream.total_in);
- debug("compress incoming: raw data %lu, compressed %lu, factor %.2f",
- incoming_stream.total_out, incoming_stream.total_in,
- incoming_stream.total_out == 0 ? 0.0 :
- (double) incoming_stream.total_in / incoming_stream.total_out);
- if (compress_init_recv_called == 1 && inflate_failed == 0)
- inflateEnd(&incoming_stream);
- if (compress_init_send_called == 1 && deflate_failed == 0)
- deflateEnd(&outgoing_stream);
-}
-
-/*
- * Compresses the contents of input_buffer into output_buffer. All packets
- * compressed using this function will form a single compressed data stream;
- * however, data will be flushed at the end of every call so that each
- * output_buffer can be decompressed independently (but in the appropriate
- * order since they together form a single compression stream) by the
- * receiver. This appends the compressed data to the output buffer.
- */
-
-void
-buffer_compress(Buffer * input_buffer, Buffer * output_buffer)
-{
- u_char buf[4096];
- int status;
-
- /* This case is not handled below. */
- if (buffer_len(input_buffer) == 0)
- return;
-
- /* Input is the contents of the input buffer. */
- outgoing_stream.next_in = buffer_ptr(input_buffer);
- outgoing_stream.avail_in = buffer_len(input_buffer);
-
- /* Loop compressing until deflate() returns with avail_out != 0. */
- do {
- /* Set up fixed-size output buffer. */
- outgoing_stream.next_out = buf;
- outgoing_stream.avail_out = sizeof(buf);
-
- /* Compress as much data into the buffer as possible. */
- status = deflate(&outgoing_stream, Z_PARTIAL_FLUSH);
- switch (status) {
- case Z_OK:
- /* Append compressed data to output_buffer. */
- buffer_append(output_buffer, buf,
- sizeof(buf) - outgoing_stream.avail_out);
- break;
- default:
- deflate_failed = 1;
- fatal("buffer_compress: deflate returned %d", status);
- /* NOTREACHED */
- }
- } while (outgoing_stream.avail_out == 0);
-}
-
-/*
- * Uncompresses the contents of input_buffer into output_buffer. All packets
- * uncompressed using this function will form a single compressed data
- * stream; however, data will be flushed at the end of every call so that
- * each output_buffer. This must be called for the same size units that the
- * buffer_compress was called, and in the same order that buffers compressed
- * with that. This appends the uncompressed data to the output buffer.
- */
-
-void
-buffer_uncompress(Buffer * input_buffer, Buffer * output_buffer)
-{
- u_char buf[4096];
- int status;
-
- incoming_stream.next_in = buffer_ptr(input_buffer);
- incoming_stream.avail_in = buffer_len(input_buffer);
-
- for (;;) {
- /* Set up fixed-size output buffer. */
- incoming_stream.next_out = buf;
- incoming_stream.avail_out = sizeof(buf);
-
- status = inflate(&incoming_stream, Z_PARTIAL_FLUSH);
- switch (status) {
- case Z_OK:
- buffer_append(output_buffer, buf,
- sizeof(buf) - incoming_stream.avail_out);
- break;
- case Z_BUF_ERROR:
- /*
- * Comments in zlib.h say that we should keep calling
- * inflate() until we get an error. This appears to
- * be the error that we get.
- */
- return;
- default:
- inflate_failed = 1;
- fatal("buffer_uncompress: inflate returned %d", status);
- /* NOTREACHED */
- }
- }
-}
diff --git a/usr/src/cmd/ssh/libssh/common/crc32.c b/usr/src/cmd/ssh/libssh/common/crc32.c
deleted file mode 100644
index 213b7b8aa8..0000000000
--- a/usr/src/cmd/ssh/libssh/common/crc32.c
+++ /dev/null
@@ -1,116 +0,0 @@
-/*
- * COPYRIGHT (C) 1986 Gary S. Brown. You may use this program, or
- * code or tables extracted from it, as desired without restriction.
- *
- * First, the polynomial itself and its table of feedback terms. The
- * polynomial is
- * X^32+X^26+X^23+X^22+X^16+X^12+X^11+X^10+X^8+X^7+X^5+X^4+X^2+X^1+X^0
- *
- * Note that we take it "backwards" and put the highest-order term in
- * the lowest-order bit. The X^32 term is "implied"; the LSB is the
- * X^31 term, etc. The X^0 term (usually shown as "+1") results in
- * the MSB being 1
- *
- * Note that the usual hardware shift register implementation, which
- * is what we're using (we're merely optimizing it by doing eight-bit
- * chunks at a time) shifts bits into the lowest-order term. In our
- * implementation, that means shifting towards the right. Why do we
- * do it this way? Because the calculated CRC must be transmitted in
- * order from highest-order term to lowest-order term. UARTs transmit
- * characters in order from LSB to MSB. By storing the CRC this way
- * we hand it to the UART in the order low-byte to high-byte; the UART
- * sends each low-bit to hight-bit; and the result is transmission bit
- * by bit from highest- to lowest-order term without requiring any bit
- * shuffling on our part. Reception works similarly
- *
- * The feedback terms table consists of 256, 32-bit entries. Notes
- *
- * The table can be generated at runtime if desired; code to do so
- * is shown later. It might not be obvious, but the feedback
- * terms simply represent the results of eight shift/xor opera
- * tions for all combinations of data and CRC register values
- *
- * The values must be right-shifted by eight bits by the "updcrc
- * logic; the shift must be u_(bring in zeroes). On some
- * hardware you could probably optimize the shift in assembler by
- * using byte-swap instructions
- * polynomial $edb88320
- */
-
-
-#include "includes.h"
-RCSID("$OpenBSD: crc32.c,v 1.8 2000/12/19 23:17:56 markus Exp $");
-
-#pragma ident "%Z%%M% %I% %E% SMI"
-
-#include "crc32.h"
-
-static u_int crc32_tab[] = {
- 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419,
- 0x706af48f, 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4,
- 0xe0d5e91e, 0x97d2d988, 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07,
- 0x90bf1d91, 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de,
- 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, 0x136c9856,
- 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9,
- 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4,
- 0xa2677172, 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b,
- 0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3,
- 0x45df5c75, 0xdcd60dcf, 0xabd13d59, 0x26d930ac, 0x51de003a,
- 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, 0xcfba9599,
- 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
- 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190,
- 0x01db7106, 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f,
- 0x9fbfe4a5, 0xe8b8d433, 0x7807c9a2, 0x0f00f934, 0x9609a88e,
- 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01,
- 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, 0x6c0695ed,
- 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950,
- 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3,
- 0xfbd44c65, 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2,
- 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a,
- 0x346ed9fc, 0xad678846, 0xda60b8d0, 0x44042d73, 0x33031de5,
- 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa, 0xbe0b1010,
- 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
- 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17,
- 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6,
- 0x03b6e20c, 0x74b1d29a, 0xead54739, 0x9dd277af, 0x04db2615,
- 0x73dc1683, 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8,
- 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, 0xf00f9344,
- 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb,
- 0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a,
- 0x67dd4acc, 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5,
- 0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1,
- 0xa6bc5767, 0x3fb506dd, 0x48b2364b, 0xd80d2bda, 0xaf0a1b4c,
- 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, 0x316e8eef,
- 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
- 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe,
- 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31,
- 0x2cd99e8b, 0x5bdeae1d, 0x9b64c2b0, 0xec63f226, 0x756aa39c,
- 0x026d930a, 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713,
- 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, 0x92d28e9b,
- 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242,
- 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1,
- 0x18b74777, 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c,
- 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45, 0xa00ae278,
- 0xd70dd2ee, 0x4e048354, 0x3903b3c2, 0xa7672661, 0xd06016f7,
- 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc, 0x40df0b66,
- 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
- 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605,
- 0xcdd70693, 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8,
- 0x5d681b02, 0x2a6f2b94, 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b,
- 0x2d02ef8d
-};
-
-/* Return a 32-bit CRC of the contents of the buffer. */
-
-u_int
-ssh_crc32(const u_char *s, u_int len)
-{
- u_int i;
- u_int crc32val;
-
- crc32val = 0;
- for (i = 0; i < len; i ++) {
- crc32val = crc32_tab[(crc32val ^ s[i]) & 0xff] ^ (crc32val >> 8);
- }
- return crc32val;
-}
diff --git a/usr/src/cmd/ssh/libssh/common/deattack.c b/usr/src/cmd/ssh/libssh/common/deattack.c
deleted file mode 100644
index 82afd4f16b..0000000000
--- a/usr/src/cmd/ssh/libssh/common/deattack.c
+++ /dev/null
@@ -1,178 +0,0 @@
-/*
- * Cryptographic attack detector for ssh - source code
- *
- * Copyright (c) 1998 CORE SDI S.A., Buenos Aires, Argentina.
- *
- * All rights reserved. Redistribution and use in source and binary
- * forms, with or without modification, are permitted provided that
- * this copyright notice is retained.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES ARE DISCLAIMED. IN NO EVENT SHALL CORE SDI S.A. BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY OR
- * CONSEQUENTIAL DAMAGES RESULTING FROM THE USE OR MISUSE OF THIS
- * SOFTWARE.
- *
- * Ariel Futoransky <futo@core-sdi.com>
- * <http://www.core-sdi.com>
- */
-
-#include "includes.h"
-RCSID("$OpenBSD: deattack.c,v 1.18 2002/03/04 17:27:39 stevesk Exp $");
-
-#pragma ident "%Z%%M% %I% %E% SMI"
-
-#include "deattack.h"
-#include "log.h"
-#include "crc32.h"
-#include "getput.h"
-#include "xmalloc.h"
-#include "deattack.h"
-
-/*
- * CRC attack detection has a worst-case behaviour that is O(N^2) over
- * the number of identical blocks in a packet. This behaviour can be
- * exploited to create a limited denial of service attack.
- *
- * However, because we are dealing with encrypted data, identical
- * blocks should only occur every 2^35 maximally-sized packets or so.
- * Consequently, we can detect this DoS by looking for identical blocks
- * in a packet.
- *
- * The parameter below determines how many identical blocks we will
- * accept in a single packet, trading off between attack detection and
- * likelihood of terminating a legitimate connection. A value of 32
- * corresponds to an average of 2^40 messages before an attack is
- * misdetected
- */
-#define MAX_IDENTICAL 32
-
-/* SSH Constants */
-#define SSH_MAXBLOCKS (32 * 1024)
-#define SSH_BLOCKSIZE (8)
-
-/* Hashing constants */
-#define HASH_MINSIZE (8 * 1024)
-#define HASH_ENTRYSIZE (2)
-#define HASH_FACTOR(x) ((x)*3/2)
-#define HASH_UNUSEDCHAR (0xff)
-#define HASH_UNUSED (0xffff)
-#define HASH_IV (0xfffe)
-
-#define HASH_MINBLOCKS (7*SSH_BLOCKSIZE)
-
-
-/* Hash function (Input keys are cipher results) */
-#define HASH(x) GET_32BIT(x)
-
-#define CMP(a, b) (memcmp(a, b, SSH_BLOCKSIZE))
-
-static void
-crc_update(u_int32_t *a, u_int32_t b)
-{
- b ^= *a;
- *a = ssh_crc32((u_char *) &b, sizeof(b));
-}
-
-/* detect if a block is used in a particular pattern */
-static int
-check_crc(u_char *S, u_char *buf, u_int32_t len,
- u_char *IV)
-{
- u_int32_t crc;
- u_char *c;
-
- crc = 0;
- if (IV && !CMP(S, IV)) {
- crc_update(&crc, 1);
- crc_update(&crc, 0);
- }
- for (c = buf; c < buf + len; c += SSH_BLOCKSIZE) {
- if (!CMP(S, c)) {
- crc_update(&crc, 1);
- crc_update(&crc, 0);
- } else {
- crc_update(&crc, 0);
- crc_update(&crc, 0);
- }
- }
- return (crc == 0);
-}
-
-
-/* Detect a crc32 compensation attack on a packet */
-int
-detect_attack(u_char *buf, u_int32_t len, u_char *IV)
-{
- static u_int16_t *h = (u_int16_t *) NULL;
- static u_int32_t n = HASH_MINSIZE / HASH_ENTRYSIZE;
- u_int32_t i, j;
- u_int32_t l, same;
- u_char *c;
- u_char *d;
-
- if (len > (SSH_MAXBLOCKS * SSH_BLOCKSIZE) ||
- len % SSH_BLOCKSIZE != 0) {
- fatal("detect_attack: bad length %d", len);
- }
- for (l = n; l < HASH_FACTOR(len / SSH_BLOCKSIZE); l = l << 2)
- ;
-
- if (h == NULL) {
- debug("Installing crc compensation attack detector.");
- n = l;
- h = (u_int16_t *) xmalloc(n * HASH_ENTRYSIZE);
- } else {
- if (l > n) {
- n = l;
- h = (u_int16_t *) xrealloc(h, n * HASH_ENTRYSIZE);
- }
- }
-
- if (len <= HASH_MINBLOCKS) {
- for (c = buf; c < buf + len; c += SSH_BLOCKSIZE) {
- if (IV && (!CMP(c, IV))) {
- if ((check_crc(c, buf, len, IV)))
- return (DEATTACK_DETECTED);
- else
- break;
- }
- for (d = buf; d < c; d += SSH_BLOCKSIZE) {
- if (!CMP(c, d)) {
- if ((check_crc(c, buf, len, IV)))
- return (DEATTACK_DETECTED);
- else
- break;
- }
- }
- }
- return (DEATTACK_OK);
- }
- memset(h, HASH_UNUSEDCHAR, n * HASH_ENTRYSIZE);
-
- if (IV)
- h[HASH(IV) & (n - 1)] = HASH_IV;
-
- for (c = buf, same = j = 0; c < (buf + len); c += SSH_BLOCKSIZE, j++) {
- for (i = HASH(c) & (n - 1); h[i] != HASH_UNUSED;
- i = (i + 1) & (n - 1)) {
- if (h[i] == HASH_IV) {
- if (!CMP(c, IV)) {
- if (check_crc(c, buf, len, IV))
- return (DEATTACK_DETECTED);
- else
- break;
- }
- } else if (!CMP(c, buf + h[i] * SSH_BLOCKSIZE)) {
- if (++same > MAX_IDENTICAL)
- return (DEATTACK_DOS_DETECTED);
- if (check_crc(c, buf, len, IV))
- return (DEATTACK_DETECTED);
- else
- break;
- }
- }
- h[i] = j;
- }
- return (DEATTACK_OK);
-}
diff --git a/usr/src/cmd/ssh/libssh/common/dh.c b/usr/src/cmd/ssh/libssh/common/dh.c
deleted file mode 100644
index 9293db7bb7..0000000000
--- a/usr/src/cmd/ssh/libssh/common/dh.c
+++ /dev/null
@@ -1,289 +0,0 @@
-/*
- * Copyright (c) 2000 Niels Provos. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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.
- */
-
-#include "includes.h"
-RCSID("$OpenBSD: dh.c,v 1.22 2002/06/27 08:49:44 markus Exp $");
-
-#include "xmalloc.h"
-
-#include <openssl/bn.h>
-#include <openssl/dh.h>
-#include <openssl/evp.h>
-
-#include "buffer.h"
-#include "cipher.h"
-#include "kex.h"
-#include "dh.h"
-#include "pathnames.h"
-#include "log.h"
-#include "misc.h"
-
-static int
-parse_prime(int linenum, char *line, struct dhgroup *dhg)
-{
- char *cp, *arg;
- char *strsize, *gen, *prime;
-
- cp = line;
- arg = strdelim(&cp);
- /* Ignore leading whitespace */
- if (*arg == '\0')
- arg = strdelim(&cp);
- if (!arg || !*arg || *arg == '#')
- return 0;
-
- /* time */
- if (cp == NULL || *arg == '\0')
- goto fail;
- arg = strsep(&cp, " "); /* type */
- if (cp == NULL || *arg == '\0')
- goto fail;
- arg = strsep(&cp, " "); /* tests */
- if (cp == NULL || *arg == '\0')
- goto fail;
- arg = strsep(&cp, " "); /* tries */
- if (cp == NULL || *arg == '\0')
- goto fail;
- strsize = strsep(&cp, " "); /* size */
- if (cp == NULL || *strsize == '\0' ||
- (dhg->size = atoi(strsize)) == 0)
- goto fail;
- /* The whole group is one bit larger */
- dhg->size++;
- gen = strsep(&cp, " "); /* gen */
- if (cp == NULL || *gen == '\0')
- goto fail;
- prime = strsep(&cp, " "); /* prime */
- if (cp != NULL || *prime == '\0')
- goto fail;
-
- if ((dhg->g = BN_new()) == NULL)
- fatal("parse_prime: BN_new failed");
- if ((dhg->p = BN_new()) == NULL)
- fatal("parse_prime: BN_new failed");
- if (BN_hex2bn(&dhg->g, gen) == 0)
- goto failclean;
-
- if (BN_hex2bn(&dhg->p, prime) == 0)
- goto failclean;
-
- if (BN_num_bits(dhg->p) != dhg->size)
- goto failclean;
-
- return (1);
-
- failclean:
- BN_clear_free(dhg->g);
- BN_clear_free(dhg->p);
- fail:
- error("Bad prime description in line %d", linenum);
- return (0);
-}
-
-DH *
-choose_dh(int min, int wantbits, int max)
-{
- FILE *f;
- char line[2048];
- int best, bestcount, which;
- int linenum;
- struct dhgroup dhg;
-
- if ((f = fopen(_PATH_DH_MODULI, "r")) == NULL &&
- (f = fopen(_PATH_DH_PRIMES, "r")) == NULL) {
- log("WARNING: %s does not exist, using old modulus", _PATH_DH_MODULI);
- return (dh_new_group1());
- }
-
- linenum = 0;
- best = bestcount = 0;
- while (fgets(line, sizeof(line), f)) {
- linenum++;
- if (!parse_prime(linenum, line, &dhg))
- continue;
- BN_clear_free(dhg.g);
- BN_clear_free(dhg.p);
-
- if (dhg.size > max || dhg.size < min)
- continue;
-
- if ((dhg.size > wantbits && dhg.size < best) ||
- (dhg.size > best && best < wantbits)) {
- best = dhg.size;
- bestcount = 0;
- }
- if (dhg.size == best)
- bestcount++;
- }
- rewind(f);
-
- if (bestcount == 0) {
- fclose(f);
- log("WARNING: no suitable primes in %s", _PATH_DH_PRIMES);
- return (NULL);
- }
-
- linenum = 0;
- which = arc4random() % bestcount;
- while (fgets(line, sizeof(line), f)) {
- if (!parse_prime(linenum, line, &dhg))
- continue;
- if ((dhg.size > max || dhg.size < min) ||
- dhg.size != best ||
- linenum++ != which) {
- BN_clear_free(dhg.g);
- BN_clear_free(dhg.p);
- continue;
- }
- break;
- }
- fclose(f);
- if (linenum != which+1)
- fatal("WARNING: line %d disappeared in %s, giving up",
- which, _PATH_DH_PRIMES);
-
- return (dh_new_group(dhg.g, dhg.p));
-}
-
-/* diffie-hellman-group1-sha1 */
-
-int
-dh_pub_is_valid(DH *dh, BIGNUM *dh_pub)
-{
- int i;
- int n = BN_num_bits(dh_pub);
- int bits_set = 0;
-
- if (dh_pub->neg) {
- log("invalid public DH value: negativ");
- return 0;
- }
- for (i = 0; i <= n; i++)
- if (BN_is_bit_set(dh_pub, i))
- bits_set++;
- debug("bits set: %d/%d", bits_set, BN_num_bits(dh->p));
-
- /* if g==2 and bits_set==1 then computing log_g(dh_pub) is trivial */
- if (bits_set > 1 && (BN_cmp(dh_pub, dh->p) == -1))
- return 1;
- log("invalid public DH value (%d/%d)", bits_set, BN_num_bits(dh->p));
- return 0;
-}
-
-void
-dh_gen_key(DH *dh, int need)
-{
- int i, bits_set = 0, tries = 0;
-
- if (dh->p == NULL)
- fatal("dh_gen_key: dh->p == NULL");
- if (2*need >= BN_num_bits(dh->p))
- fatal("dh_gen_key: group too small: %d (2*need %d)",
- BN_num_bits(dh->p), 2*need);
- do {
- if (dh->priv_key != NULL)
- BN_clear_free(dh->priv_key);
- if ((dh->priv_key = BN_new()) == NULL)
- fatal("dh_gen_key: BN_new failed");
- /* generate a 2*need bits random private exponent */
- if (!BN_rand(dh->priv_key, 2*need, 0, 0))
- fatal("dh_gen_key: BN_rand failed");
- if (DH_generate_key(dh) == 0)
- fatal("dh_gen_key: DH_generate_key() failed");
- for (i = 0; i <= BN_num_bits(dh->priv_key); i++)
- if (BN_is_bit_set(dh->priv_key, i))
- bits_set++;
- debug("dh_gen_key: priv key bits set: %d/%d",
- bits_set, BN_num_bits(dh->priv_key));
- if (tries++ > 10)
- fatal("dh_gen_key: too many bad keys: giving up");
- } while (!dh_pub_is_valid(dh, dh->pub_key));
-}
-
-DH *
-dh_new_group_asc(const char *gen, const char *modulus)
-{
- DH *dh;
-
- if ((dh = DH_new()) == NULL)
- fatal("dh_new_group_asc: DH_new");
-
- if (BN_hex2bn(&dh->p, modulus) == 0)
- fatal("BN_hex2bn p");
- if (BN_hex2bn(&dh->g, gen) == 0)
- fatal("BN_hex2bn g");
-
- return (dh);
-}
-
-/*
- * This just returns the group, we still need to generate the exchange
- * value.
- */
-
-DH *
-dh_new_group(BIGNUM *gen, BIGNUM *modulus)
-{
- DH *dh;
-
- if ((dh = DH_new()) == NULL)
- fatal("dh_new_group: DH_new");
- dh->p = modulus;
- dh->g = gen;
-
- return (dh);
-}
-
-DH *
-dh_new_group1(void)
-{
- static char *gen = "2", *group1 =
- "FFFFFFFF" "FFFFFFFF" "C90FDAA2" "2168C234" "C4C6628B" "80DC1CD1"
- "29024E08" "8A67CC74" "020BBEA6" "3B139B22" "514A0879" "8E3404DD"
- "EF9519B3" "CD3A431B" "302B0A6D" "F25F1437" "4FE1356D" "6D51C245"
- "E485B576" "625E7EC6" "F44C42E9" "A637ED6B" "0BFF5CB6" "F406B7ED"
- "EE386BFB" "5A899FA5" "AE9F2411" "7C4B1FE6" "49286651" "ECE65381"
- "FFFFFFFF" "FFFFFFFF";
-
- return (dh_new_group_asc(gen, group1));
-}
-
-/*
- * Estimates the group order for a Diffie-Hellman group that has an
- * attack complexity approximately the same as O(2**bits). Estimate
- * with: O(exp(1.9223 * (ln q)^(1/3) (ln ln q)^(2/3)))
- */
-
-int
-dh_estimate(int bits)
-{
-
- if (bits < 64)
- return (512); /* O(2**63) */
- if (bits < 128)
- return (1024); /* O(2**86) */
- if (bits < 192)
- return (2048); /* O(2**116) */
- return (4096); /* O(2**156) */
-}
diff --git a/usr/src/cmd/ssh/libssh/common/dispatch.c b/usr/src/cmd/ssh/libssh/common/dispatch.c
deleted file mode 100644
index f2bf9b6847..0000000000
--- a/usr/src/cmd/ssh/libssh/common/dispatch.c
+++ /dev/null
@@ -1,101 +0,0 @@
-/*
- * Copyright (c) 2000 Markus Friedl. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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.
- */
-#include "includes.h"
-RCSID("$OpenBSD: dispatch.c,v 1.15 2002/01/11 13:39:36 markus Exp $");
-
-#pragma ident "%Z%%M% %I% %E% SMI"
-
-#include "ssh1.h"
-#include "ssh2.h"
-#include "log.h"
-#include "dispatch.h"
-#include "packet.h"
-#include "compat.h"
-
-#define DISPATCH_MIN 0
-#define DISPATCH_MAX 255
-
-dispatch_fn *dispatch[DISPATCH_MAX];
-
-void
-dispatch_protocol_error(int type, u_int32_t seq, void *ctxt)
-{
- log("dispatch_protocol_error: type %d seq %u", type, seq);
- if (!compat20)
- fatal("protocol error");
- packet_start(SSH2_MSG_UNIMPLEMENTED);
- packet_put_int(seq);
- packet_send();
- packet_write_wait();
-}
-void
-dispatch_protocol_ignore(int type, u_int32_t seq, void *ctxt)
-{
- log("dispatch_protocol_ignore: type %d seq %u", type, seq);
-}
-void
-dispatch_init(dispatch_fn *dflt)
-{
- u_int i;
- for (i = 0; i < DISPATCH_MAX; i++)
- dispatch[i] = dflt;
-}
-void
-dispatch_range(u_int from, u_int to, dispatch_fn *fn)
-{
- u_int i;
-
- for (i = from; i <= to; i++) {
- if (i >= DISPATCH_MAX)
- break;
- dispatch[i] = fn;
- }
-}
-void
-dispatch_set(int type, dispatch_fn *fn)
-{
- dispatch[type] = fn;
-}
-void
-dispatch_run(int mode, int *done, void *ctxt)
-{
- for (;;) {
- int type;
- u_int32_t seqnr;
-
- if (mode == DISPATCH_BLOCK) {
- type = packet_read_seqnr(&seqnr);
- } else {
- type = packet_read_poll_seqnr(&seqnr);
- if (type == SSH_MSG_NONE)
- return;
- }
- if (type > 0 && type < DISPATCH_MAX && dispatch[type] != NULL)
- (*dispatch[type])(type, seqnr, ctxt);
- else
- packet_disconnect("protocol error: rcvd type %d", type);
- if (done != NULL && *done)
- return;
- }
-}
diff --git a/usr/src/cmd/ssh/libssh/common/engine.c b/usr/src/cmd/ssh/libssh/common/engine.c
deleted file mode 100644
index 0541c658df..0000000000
--- a/usr/src/cmd/ssh/libssh/common/engine.c
+++ /dev/null
@@ -1,118 +0,0 @@
-/*
- * CDDL HEADER START
- *
- * The contents of this file are subject to the terms of the
- * Common Development and Distribution License (the "License").
- * You may not use this file except in compliance with the License.
- *
- * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
- * See the License for the specific language governing permissions
- * and limitations under the License.
- *
- * When distributing Covered Code, include this CDDL HEADER in each
- * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
- * If applicable, add the following below this CDDL HEADER, with the
- * fields enclosed by brackets "[]" replaced with your own identifying
- * information: Portions Copyright [yyyy] [name of copyright owner]
- *
- * CDDL HEADER END
- */
-/*
- * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
- */
-
-#include "includes.h"
-#include "log.h"
-#include "engine.h"
-
-#define PKCS11_ENGINE "pkcs11"
-
-/*
- * Loads the PKCS#11 engine if the UseOpenSSLEngine is set to yes which is the
- * default value.
- */
-ENGINE *
-pkcs11_engine_load(int use_engine)
-{
- ENGINE *e = NULL;
-
- debug("use_engine is '%s'", use_engine == 1 ? "yes" : "no");
- if (use_engine == 0)
- return (NULL);
-
- ENGINE_load_pk11();
- /* get structural reference */
- if ((e = ENGINE_by_id(PKCS11_ENGINE)) == NULL) {
- error("%s engine does not exist", PKCS11_ENGINE);
- return (NULL);
- }
-
- /* get functional reference */
- if (ENGINE_init(e) == 0) {
- error("can't initialize %s engine", PKCS11_ENGINE);
- return (NULL);
- }
-
- debug("%s engine initialized, now setting it as default for "
- "RSA, DSA, and symmetric ciphers", PKCS11_ENGINE);
-
- /*
- * Offloading RSA, DSA and symmetric ciphers to the engine is all we
- * want. We don't offload Diffie-Helmann since we use longer DH keys
- * than supported in ncp/n2cp (2048 bits). And, we don't offload digest
- * operations since that would be beneficial if only big packets were
- * processed (~8K). However, that's not the case. For example,
- * SSH_MSG_CHANNEL_WINDOW_ADJUST messages are always small. Given the
- * fact that digest operations are fast in software and the inherent
- * overhead of offloading anything to HW is quite big, not offloading
- * digests to HW actually makes SSH data transfer faster.
- */
- if (!ENGINE_set_default_RSA(e)) {
- error("can't use %s engine for RSA", PKCS11_ENGINE);
- return (NULL);
- }
- if (!ENGINE_set_default_DSA(e)) {
- error("can't use %s engine for DSA", PKCS11_ENGINE);
- return (NULL);
- }
- if (!ENGINE_set_default_ciphers(e)) {
- error("can't use %s engine for symmetric ciphers",
- PKCS11_ENGINE);
- return (NULL);
- }
-
- debug("%s engine initialization complete", PKCS11_ENGINE);
- return (e);
-}
-
-/*
- * Finishes the PKCS#11 engine after all remaining structural and functional
- * references to the ENGINE structure are freed.
- */
-void
-pkcs11_engine_finish(void *engine)
-{
- ENGINE *e = (ENGINE *)engine;
-
- debug("in pkcs11_engine_finish(), engine pointer is %p", e);
- /* UseOpenSSLEngine was 'no' */
- if (engine == NULL)
- return;
-
- debug("unregistering RSA");
- ENGINE_unregister_RSA(e);
- debug("unregistering DSA");
- ENGINE_unregister_DSA(e);
- debug("unregistering ciphers");
- ENGINE_unregister_ciphers(e);
-
- debug("calling ENGINE_finish()");
- ENGINE_finish(engine);
- debug("calling ENGINE_remove()");
- ENGINE_remove(engine);
- debug("calling ENGINE_free()");
- ENGINE_free(engine);
- debug("%s engine finished", PKCS11_ENGINE);
-}
diff --git a/usr/src/cmd/ssh/libssh/common/entropy.c b/usr/src/cmd/ssh/libssh/common/entropy.c
deleted file mode 100644
index c661b74496..0000000000
--- a/usr/src/cmd/ssh/libssh/common/entropy.c
+++ /dev/null
@@ -1,156 +0,0 @@
-/*
- * Copyright (c) 2001 Damien Miller. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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.
- */
-
-#include "includes.h"
-
-#include <openssl/rand.h>
-#include <openssl/crypto.h>
-
-#include "ssh.h"
-#include "misc.h"
-#include "xmalloc.h"
-#include "atomicio.h"
-#include "pathnames.h"
-#include "log.h"
-
-/*
- * Portable OpenSSH PRNG seeding:
- * If OpenSSL has not "internally seeded" itself (e.g. pulled data from
- * /dev/random), then we execute a "ssh-rand-helper" program which
- * collects entropy and writes it to stdout. The child program must
- * write at least RANDOM_SEED_SIZE bytes. The child is run with stderr
- * attached, so error/debugging output should be visible.
- *
- * XXX: we should tell the child how many bytes we need.
- */
-
-RCSID("$Id: entropy.c,v 1.44 2002/06/09 19:41:48 mouring Exp $");
-
-#pragma ident "%Z%%M% %I% %E% SMI"
-
-#ifndef OPENSSL_PRNG_ONLY
-#define RANDOM_SEED_SIZE 48
-static uid_t original_uid, original_euid;
-#endif
-
-void
-seed_rng(void)
-{
-#ifndef OPENSSL_PRNG_ONLY
- int devnull;
- int p[2];
- pid_t pid;
- int ret;
- unsigned char buf[RANDOM_SEED_SIZE];
- mysig_t old_sigchld;
-
- if (RAND_status() == 1) {
- debug3("RNG is ready, skipping seeding");
- return;
- }
-
- debug3("Seeding PRNG from %s", SSH_RAND_HELPER);
-
- if ((devnull = open("/dev/null", O_RDWR)) == -1)
- fatal("Couldn't open /dev/null: %s", strerror(errno));
- if (pipe(p) == -1)
- fatal("pipe: %s", strerror(errno));
-
- old_sigchld = mysignal(SIGCHLD, SIG_DFL);
- if ((pid = fork()) == -1)
- fatal("Couldn't fork: %s", strerror(errno));
- if (pid == 0) {
- dup2(devnull, STDIN_FILENO);
- dup2(p[1], STDOUT_FILENO);
- /* Keep stderr open for errors */
- close(p[0]);
- close(p[1]);
- close(devnull);
-
- if (original_uid != original_euid &&
- ( seteuid(getuid()) == -1 ||
- setuid(original_uid) == -1) ) {
- fprintf(stderr, "(rand child) setuid(%d): %s\n",
- original_uid, strerror(errno));
- _exit(1);
- }
-
- execl(SSH_RAND_HELPER, "ssh-rand-helper", NULL);
- fprintf(stderr, "(rand child) Couldn't exec '%s': %s\n",
- SSH_RAND_HELPER, strerror(errno));
- _exit(1);
- }
-
- close(devnull);
- close(p[1]);
-
- memset(buf, '\0', sizeof(buf));
- ret = atomicio(read, p[0], buf, sizeof(buf));
- if (ret == -1)
- fatal("Couldn't read from ssh-rand-helper: %s",
- strerror(errno));
- if (ret != sizeof(buf))
- fatal("ssh-rand-helper child produced insufficient data");
-
- close(p[0]);
-
- if (waitpid(pid, &ret, 0) == -1)
- fatal("Couldn't wait for ssh-rand-helper completion: %s",
- strerror(errno));
- mysignal(SIGCHLD, old_sigchld);
-
- /* We don't mind if the child exits upon a SIGPIPE */
- if (!WIFEXITED(ret) &&
- (!WIFSIGNALED(ret) || WTERMSIG(ret) != SIGPIPE))
- fatal("ssh-rand-helper terminated abnormally");
- if (WEXITSTATUS(ret) != 0)
- fatal("ssh-rand-helper exit with exit status %d", ret);
-
- RAND_add(buf, sizeof(buf), sizeof(buf));
- memset(buf, '\0', sizeof(buf));
-
-#endif /* OPENSSL_PRNG_ONLY */
- if (RAND_status() != 1)
- fatal("PRNG is not seeded");
-}
-
-void
-init_rng(void)
-{
- /*
- * OpenSSL version numbers: MNNFFPPS: major minor fix patch status
- * We match major, minor, fix and status (not patch)
- */
- if ((SSLeay() ^ OPENSSL_VERSION_NUMBER) & ~0xff0L)
- fatal("OpenSSL version mismatch. Built against %lx, you "
- "have %lx", OPENSSL_VERSION_NUMBER, SSLeay());
-
-#ifndef OPENSSL_PRNG_ONLY
- if ((original_uid = getuid()) == -1)
- fatal("getuid: %s", strerror(errno));
- if ((original_euid = geteuid()) == -1)
- fatal("geteuid: %s", strerror(errno));
-#endif
-}
-
diff --git a/usr/src/cmd/ssh/libssh/common/fatal.c b/usr/src/cmd/ssh/libssh/common/fatal.c
deleted file mode 100644
index 0b5038f365..0000000000
--- a/usr/src/cmd/ssh/libssh/common/fatal.c
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * Copyright (c) 2002 Markus Friedl. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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.
- */
-
-#include "includes.h"
-RCSID("$OpenBSD: fatal.c,v 1.1 2002/02/22 12:20:34 markus Exp $");
-
-#pragma ident "%Z%%M% %I% %E% SMI"
-
-#include "log.h"
-
-/* Fatal messages. This function never returns. */
-
-void
-fatal(const char *fmt,...)
-{
- va_list args;
- va_start(args, fmt);
- do_log(SYSLOG_LEVEL_FATAL, fmt, args);
- va_end(args);
- fatal_cleanup();
-}
diff --git a/usr/src/cmd/ssh/libssh/common/g11n.c b/usr/src/cmd/ssh/libssh/common/g11n.c
deleted file mode 100644
index 558b410c96..0000000000
--- a/usr/src/cmd/ssh/libssh/common/g11n.c
+++ /dev/null
@@ -1,964 +0,0 @@
-/*
- * CDDL HEADER START
- *
- * The contents of this file are subject to the terms of the
- * Common Development and Distribution License (the "License").
- * You may not use this file except in compliance with the License.
- *
- * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
- * See the License for the specific language governing permissions
- * and limitations under the License.
- *
- * When distributing Covered Code, include this CDDL HEADER in each
- * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
- * If applicable, add the following below this CDDL HEADER, with the
- * fields enclosed by brackets "[]" replaced with your own identifying
- * information: Portions Copyright [yyyy] [name of copyright owner]
- *
- * CDDL HEADER END
- *
- * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
- */
-
-#include <errno.h>
-#include <locale.h>
-#include <langinfo.h>
-#include <iconv.h>
-#include <ctype.h>
-#include <wctype.h>
-#include <strings.h>
-#include <string.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include "includes.h"
-#include "xmalloc.h"
-#include "xlist.h"
-#include "compat.h"
-#include "log.h"
-
-#ifdef MIN
-#undef MIN
-#endif /* MIN */
-
-#define MIN(x, y) ((x) < (y) ? (x) : (y))
-
-#define LOCALE_PATH "/usr/bin/locale"
-
-/* two-char country code, '-' and two-char region code */
-#define LANGTAG_MAX 5
-
-static int locale_cmp(const void *d1, const void *d2);
-static char *g11n_locale2langtag(char *locale);
-
-static char *do_iconv(iconv_t cd, const char *s, uint_t *lenp, char **err_str);
-
-/*
- * native_codeset records the codeset of the default system locale.
- * It is used to convert the contents of file (eg /etc/issue) which is
- * supposed to be in the codeset of default system locale.
- */
-static char *native_codeset;
-
-/*
- * Convert locale string name into a language tag. The caller is responsible for
- * freeing the memory allocated for the result.
- */
-static char *
-g11n_locale2langtag(char *locale)
-{
- char *langtag;
-
- /* base cases */
- if (!locale || !*locale)
- return (NULL);
-
- if (strcmp(locale, "POSIX") == 0 || strcmp(locale, "C") == 0)
- return (xstrdup("i-default"));
-
- /* punt for language codes which are not exactly 2 letters */
- if (strlen(locale) < 2 ||
- !isalpha(locale[0]) ||
- !isalpha(locale[1]) ||
- (locale[2] != '\0' &&
- locale[2] != '_' &&
- locale[2] != '.' &&
- locale[2] != '@'))
- return (NULL);
-
-
- /* we have a primary language sub-tag */
- langtag = (char *)xmalloc(LANGTAG_MAX + 1);
-
- strncpy(langtag, locale, 2);
- langtag[2] = '\0';
-
- /* do we have country sub-tag? For example: cs_CZ */
- if (locale[2] == '_') {
- if (strlen(locale) < 5 ||
- !isalpha(locale[3]) ||
- !isalpha(locale[4]) ||
- (locale[5] != '\0' && (locale[5] != '.' &&
- locale[5] != '@'))) {
- return (langtag);
- }
-
- /* example: create cs-CZ from cs_CZ */
- if (snprintf(langtag, 6, "%.*s-%.*s", 2, locale, 2,
- locale + 3) == 5)
- return (langtag);
- }
-
- /* in all other cases we just use the primary language sub-tag */
- return (langtag);
-}
-
-uint_t
-g11n_langtag_is_default(char *langtag)
-{
- return (strcmp(langtag, "i-default") == 0);
-}
-
-/*
- * This lang tag / locale matching function works only for two-character
- * language primary sub-tags and two-character country sub-tags.
- */
-uint_t
-g11n_langtag_matches_locale(char *langtag, char *locale)
-{
- /* match "i-default" to the process' current locale if possible */
- if (g11n_langtag_is_default(langtag)) {
- if (strcasecmp(locale, "POSIX") == 0 ||
- strcasecmp(locale, "C") == 0)
- return (1);
- else
- return (0);
- }
-
- /*
- * locale must be at least 2 chars long and the lang part must be
- * exactly two characters
- */
- if (strlen(locale) < 2 ||
- (!isalpha(locale[0]) || !isalpha(locale[1]) ||
- (locale[2] != '\0' && locale[2] != '_' &&
- locale[2] != '.' && locale[2] != '@')))
- return (0);
-
- /* same thing with the langtag */
- if (strlen(langtag) < 2 ||
- (!isalpha(langtag[0]) || !isalpha(langtag[1]) ||
- (langtag[2] != '\0' && langtag[2] != '-')))
- return (0);
-
- /* primary language sub-tag and the locale's language part must match */
- if (strncasecmp(langtag, locale, 2) != 0)
- return (0);
-
- /*
- * primary language sub-tag and the locale's language match, now
- * fuzzy check country part
- */
-
- /* neither langtag nor locale have more than one component */
- if (langtag[2] == '\0' &&
- (locale[2] == '\0' || locale[2] == '.' || locale[2] == '@'))
- return (2);
-
- /* langtag has only one sub-tag... */
- if (langtag[2] == '\0')
- return (1);
-
- /* locale has no country code... */
- if (locale[2] == '\0' || locale[2] == '.' || locale[2] == '@')
- return (1);
-
- /* langtag has more than one subtag and the locale has a country code */
-
- /* ignore second subtag if not two chars */
- if (strlen(langtag) < 5)
- return (1);
-
- if (!isalpha(langtag[3]) || !isalpha(langtag[4]) ||
- (langtag[5] != '\0' && langtag[5] != '-'))
- return (1);
-
- /* ignore rest of locale if there is no two-character country part */
- if (strlen(locale) < 5)
- return (1);
-
- if (locale[2] != '_' || !isalpha(locale[3]) || !isalpha(locale[4]) ||
- (locale[5] != '\0' && locale[5] != '.' && locale[5] != '@'))
- return (1);
-
- /* if the country part matches, return 2 */
- if (strncasecmp(&langtag[3], &locale[3], 2) == 0)
- return (2);
-
- return (1);
-}
-
-char *
-g11n_getlocale()
-{
- /* we have one text domain - always set it */
- (void) textdomain(TEXT_DOMAIN);
-
- /* if the locale is not set, set it from the env vars */
- if (!setlocale(LC_MESSAGES, NULL))
- (void) setlocale(LC_MESSAGES, "");
-
- return (setlocale(LC_MESSAGES, NULL));
-}
-
-void
-g11n_setlocale(int category, const char *locale)
-{
- char *curr;
-
- if (native_codeset == NULL) {
- /* set default locale, and record current codeset */
- (void) setlocale(LC_ALL, "");
- curr = nl_langinfo(CODESET);
- native_codeset = xstrdup(curr);
- }
-
- /* we have one text domain - always set it */
- (void) textdomain(TEXT_DOMAIN);
-
- if (!locale)
- return;
-
- if (*locale && ((curr = setlocale(category, NULL))) &&
- strcmp(curr, locale) == 0)
- return;
-
- /* if <category> is bogus, setlocale() will do nothing */
- (void) setlocale(category, locale);
-}
-
-char **
-g11n_getlocales()
-{
- FILE *locale_out;
- uint_t n_elems, list_size, long_line = 0;
- char **list;
- char locale[64]; /* 64 bytes is plenty for locale names */
-
- if ((locale_out = popen(LOCALE_PATH " -a", "r")) == NULL)
- return (NULL);
-
- /*
- * start with enough room for 65 locales - that's a lot fewer than
- * all the locales available for installation, but a lot more than
- * what most users will need and install
- */
- n_elems = 0;
- list_size = 192;
- list = (char **) xmalloc(sizeof (char *) * (list_size + 1));
- memset(list, 0, sizeof (char *) * (list_size + 1));
-
- while (fgets(locale, sizeof (locale), locale_out)) {
- /* skip long locale names (if any) */
- if (!strchr(locale, '\n')) {
- long_line = 1;
- continue;
- } else if (long_line) {
- long_line = 0;
- continue;
- }
-
- if (strncmp(locale, "iso_8859", 8) == 0)
- /* ignore locale names like "iso_8859-1" */
- continue;
-
- if (n_elems == list_size) {
- list_size *= 2;
- list = (char **)xrealloc((void *) list,
- (list_size + 1) * sizeof (char *));
- memset(&list[n_elems + 1], 0,
- sizeof (char *) * (list_size - n_elems + 1));
- }
-
- *(strchr(locale, '\n')) = '\0'; /* remove the trailing \n */
- list[n_elems++] = xstrdup(locale);
- }
-
- (void) pclose(locale_out);
-
- if (n_elems == 0) {
- xfree(list);
- return (NULL);
- }
-
- list[n_elems] = NULL;
-
- qsort(list, n_elems - 1, sizeof (char *), locale_cmp);
- return (list);
-}
-
-char *
-g11n_getlangs()
-{
- char *locale;
-
- if (getenv("SSH_LANGS"))
- return (xstrdup(getenv("SSH_LANGS")));
-
- locale = g11n_getlocale();
-
- if (!locale || !*locale)
- return (xstrdup("i-default"));
-
- return (g11n_locale2langtag(locale));
-}
-
-char *
-g11n_locales2langs(char **locale_set)
-{
- char **p, **r, **q;
- char *langtag, *langs;
- int locales, skip;
-
- for (locales = 0, p = locale_set; p && *p; p++)
- locales++;
-
- r = (char **)xmalloc((locales + 1) * sizeof (char *));
- memset(r, 0, (locales + 1) * sizeof (char *));
-
- for (p = locale_set; p && *p && ((p - locale_set) <= locales); p++) {
- skip = 0;
- if ((langtag = g11n_locale2langtag(*p)) == NULL)
- continue;
- for (q = r; (q - r) < locales; q++) {
- if (!*q)
- break;
- if (*q && strcmp(*q, langtag) == 0)
- skip = 1;
- }
- if (!skip)
- *(q++) = langtag;
- else
- xfree(langtag);
- *q = NULL;
- }
-
- langs = xjoin(r, ',');
- g11n_freelist(r);
-
- return (langs);
-}
-
-static int
-sortcmp(const void *d1, const void *d2)
-{
- char *s1 = *(char **)d1;
- char *s2 = *(char **)d2;
-
- return (strcmp(s1, s2));
-}
-
-int
-g11n_langtag_match(char *langtag1, char *langtag2)
-{
- int len1, len2;
- char c1, c2;
-
- len1 = (strchr(langtag1, '-')) ?
- (strchr(langtag1, '-') - langtag1)
- : strlen(langtag1);
-
- len2 = (strchr(langtag2, '-')) ?
- (strchr(langtag2, '-') - langtag2)
- : strlen(langtag2);
-
- /* no match */
- if (len1 != len2 || strncmp(langtag1, langtag2, len1) != 0)
- return (0);
-
- c1 = *(langtag1 + len1);
- c2 = *(langtag2 + len2);
-
- /* no country sub-tags - exact match */
- if (c1 == '\0' && c2 == '\0')
- return (2);
-
- /* one langtag has a country sub-tag, the other doesn't */
- if (c1 == '\0' || c2 == '\0')
- return (1);
-
- /* can't happen - both langtags have a country sub-tag */
- if (c1 != '-' || c2 != '-')
- return (1);
-
- /* compare country subtags */
- langtag1 = langtag1 + len1 + 1;
- langtag2 = langtag2 + len2 + 1;
-
- len1 = (strchr(langtag1, '-')) ?
- (strchr(langtag1, '-') - langtag1) : strlen(langtag1);
-
- len2 = (strchr(langtag2, '-')) ?
- (strchr(langtag2, '-') - langtag2) : strlen(langtag2);
-
- if (len1 != len2 || strncmp(langtag1, langtag2, len1) != 0)
- return (1);
-
- /* country tags matched - exact match */
- return (2);
-}
-
-char *
-g11n_langtag_set_intersect(char *set1, char *set2)
-{
- char **list1, **list2, **list3, **p, **q, **r;
- char *set3, *lang_subtag;
- uint_t n1, n2, n3;
- uint_t do_append;
-
- list1 = xsplit(set1, ',');
- list2 = xsplit(set2, ',');
-
- for (n1 = 0, p = list1; p && *p; p++, n1++)
- ;
- for (n2 = 0, p = list2; p && *p; p++, n2++)
- ;
-
- list3 = (char **) xmalloc(sizeof (char *) * (n1 + n2 + 1));
- *list3 = NULL;
-
- /*
- * we must not sort the user langtags - sorting or not the server's
- * should not affect the outcome
- */
- qsort(list2, n2, sizeof (char *), sortcmp);
-
- for (n3 = 0, p = list1; p && *p; p++) {
- do_append = 0;
- for (q = list2; q && *q; q++) {
- if (g11n_langtag_match(*p, *q) != 2) continue;
- /* append element */
- for (r = list3; (r - list3) <= (n1 + n2); r++) {
- do_append = 1;
- if (!*r)
- break;
- if (strcmp(*p, *r) == 0) {
- do_append = 0;
- break;
- }
- }
- if (do_append && n3 <= (n1 + n2)) {
- list3[n3++] = xstrdup(*p);
- list3[n3] = NULL;
- }
- }
- }
-
- for (p = list1; p && *p; p++) {
- do_append = 0;
- for (q = list2; q && *q; q++) {
- if (g11n_langtag_match(*p, *q) != 1)
- continue;
-
- /* append element */
- lang_subtag = xstrdup(*p);
- if (strchr(lang_subtag, '-'))
- *(strchr(lang_subtag, '-')) = '\0';
- for (r = list3; (r - list3) <= (n1 + n2); r++) {
- do_append = 1;
- if (!*r)
- break;
- if (strcmp(lang_subtag, *r) == 0) {
- do_append = 0;
- break;
- }
- }
- if (do_append && n3 <= (n1 + n2)) {
- list3[n3++] = lang_subtag;
- list3[n3] = NULL;
- } else
- xfree(lang_subtag);
- }
- }
-
- set3 = xjoin(list3, ',');
- xfree_split_list(list1);
- xfree_split_list(list2);
- xfree_split_list(list3);
-
- return (set3);
-}
-
-char *
-g11n_clnt_langtag_negotiate(char *clnt_langtags, char *srvr_langtags)
-{
- char *list, *result;
- char **xlist;
-
- /* g11n_langtag_set_intersect uses xmalloc - should not return NULL */
- list = g11n_langtag_set_intersect(clnt_langtags, srvr_langtags);
-
- if (!list)
- return (NULL);
-
- xlist = xsplit(list, ',');
-
- xfree(list);
-
- if (!xlist || !*xlist)
- return (NULL);
-
- result = xstrdup(*xlist);
- xfree_split_list(xlist);
-
- return (result);
-}
-
-/*
- * Compare locales, preferring UTF-8 codesets to others, otherwise doing
- * a stright strcmp()
- */
-static int
-locale_cmp(const void *d1, const void *d2)
-{
- char *dot_ptr;
- char *s1 = *(char **)d1;
- char *s2 = *(char **)d2;
- int s1_is_utf8 = 0;
- int s2_is_utf8 = 0;
-
- /* check if s1 is a UTF-8 locale */
- if (((dot_ptr = strchr((char *)s1, '.')) != NULL) &&
- (*dot_ptr != '\0') && (strncmp(dot_ptr + 1, "UTF-8", 5) == 0) &&
- (*(dot_ptr + 6) == '\0' || *(dot_ptr + 6) == '@')) {
- s1_is_utf8++;
- }
-
- /* check if s2 is a UTF-8 locale */
- if (((dot_ptr = strchr((char *)s2, '.')) != NULL) &&
- (*dot_ptr != '\0') && (strncmp(dot_ptr + 1, "UTF-8", 5) == 0) &&
- (*(dot_ptr + 6) == '\0' || *(dot_ptr + 6) == '@')) {
- s2_is_utf8++;
- }
-
- /* prefer UTF-8 locales */
- if (s1_is_utf8 && !s2_is_utf8)
- return (-1);
-
- if (s2_is_utf8 && !s1_is_utf8)
- return (1);
-
- /* prefer any locale over the default locales */
- if (strcmp(s1, "C") == 0 || strcmp(s1, "POSIX") == 0 ||
- strcmp(s1, "common") == 0) {
- if (strcmp(s2, "C") != 0 && strcmp(s2, "POSIX") != 0 &&
- strcmp(s2, "common") != 0)
- return (1);
- }
-
- if (strcmp(s2, "C") == 0 || strcmp(s2, "POSIX") == 0 ||
- strcmp(s2, "common") == 0) {
- if (strcmp(s1, "C") != 0 &&
- strcmp(s1, "POSIX") != 0 &&
- strcmp(s1, "common") != 0)
- return (-1);
- }
-
- return (strcmp(s1, s2));
-}
-
-
-char **
-g11n_langtag_set_locale_set_intersect(char *langtag_set, char **locale_set)
-{
- char **langtag_list, **result, **p, **q, **r;
- char *s;
- uint_t do_append, n_langtags, n_locales, n_results, max_results;
-
- if (locale_set == NULL)
- return (NULL);
-
- /* count lang tags and locales */
- for (n_locales = 0, p = locale_set; p && *p; p++)
- n_locales++;
-
- n_langtags = ((s = langtag_set) != NULL && *s && *s != ',') ? 1 : 0;
- /* count the number of langtags */
- for (; s = strchr(s, ','); s++, n_langtags++)
- ;
-
- qsort(locale_set, n_locales, sizeof (char *), locale_cmp);
-
- langtag_list = xsplit(langtag_set, ',');
- for (n_langtags = 0, p = langtag_list; p && *p; p++, n_langtags++)
- ;
-
- max_results = MIN(n_locales, n_langtags) * 2;
- result = (char **) xmalloc(sizeof (char *) * (max_results + 1));
- *result = NULL;
- n_results = 0;
-
- /* more specific matches first */
- for (p = langtag_list; p && *p; p++) {
- do_append = 0;
- for (q = locale_set; q && *q; q++) {
- if (g11n_langtag_matches_locale(*p, *q) == 2) {
- do_append = 1;
- for (r = result; (r - result) <=
- MIN(n_locales, n_langtags); r++) {
- if (!*r)
- break;
- if (strcmp(*q, *r) == 0) {
- do_append = 0;
- break;
- }
- }
- if (do_append && n_results < max_results) {
- result[n_results++] = xstrdup(*q);
- result[n_results] = NULL;
- }
- break;
- }
- }
- }
-
- for (p = langtag_list; p && *p; p++) {
- do_append = 0;
- for (q = locale_set; q && *q; q++) {
- if (g11n_langtag_matches_locale(*p, *q) == 1) {
- do_append = 1;
- for (r = result; (r - result) <=
- MIN(n_locales, n_langtags); r++) {
- if (!*r)
- break;
- if (strcmp(*q, *r) == 0) {
- do_append = 0;
- break;
- }
- }
- if (do_append && n_results < max_results) {
- result[n_results++] = xstrdup(*q);
- result[n_results] = NULL;
- }
- break;
- }
- }
- }
-
- xfree_split_list(langtag_list);
-
- return (result);
-}
-
-char *
-g11n_srvr_locale_negotiate(char *clnt_langtags, char **srvr_locales)
-{
- char **results, **locales, *result = NULL;
-
- if (srvr_locales == NULL)
- locales = g11n_getlocales();
- else
- locales = srvr_locales;
-
- if ((results = g11n_langtag_set_locale_set_intersect(clnt_langtags,
- locales)) == NULL)
- goto err;
-
- if (*results != NULL)
- result = xstrdup(*results);
-
- xfree_split_list(results);
-
-err:
- if (locales != NULL && locales != srvr_locales)
- g11n_freelist(locales);
- return (result);
-}
-
-/*
- * Functions for converting to UTF-8 from the local codeset and
- * converting from UTF-8 to the local codeset.
- *
- * The error_str parameter is an pointer to a char variable where to
- * store a string suitable for use with error() or fatal() or friends.
- * It is also used for an error indicator when NULL is returned.
- *
- * If conversion isn't necessary, *error_str is set to NULL, and
- * NULL is returned.
- * If conversion error occured, *error_str points to an error message,
- * and NULL is returned.
- */
-char *
-g11n_convert_from_utf8(const char *str, uint_t *lenp, char **error_str)
-{
- static char *last_codeset;
- static iconv_t cd = (iconv_t)-1;
- char *codeset;
-
- *error_str = NULL;
-
- codeset = nl_langinfo(CODESET);
-
- if (strcmp(codeset, "UTF-8") == 0)
- return (NULL);
-
- if (last_codeset == NULL || strcmp(codeset, last_codeset) != 0) {
- if (last_codeset != NULL) {
- xfree(last_codeset);
- last_codeset = NULL;
- }
- if (cd != (iconv_t)-1)
- (void) iconv_close(cd);
-
- if ((cd = iconv_open(codeset, "UTF-8")) == (iconv_t)-1) {
- *error_str = gettext("Cannot convert UTF-8 "
- "strings to the local codeset");
- return (NULL);
- }
- last_codeset = xstrdup(codeset);
- }
- return (do_iconv(cd, str, lenp, error_str));
-}
-
-char *
-g11n_convert_to_utf8(const char *str, uint_t *lenp,
- int native, char **error_str)
-{
- static char *last_codeset;
- static iconv_t cd = (iconv_t)-1;
- char *codeset;
-
- *error_str = NULL;
-
- if (native)
- codeset = native_codeset;
- else
- codeset = nl_langinfo(CODESET);
-
- if (strcmp(codeset, "UTF-8") == 0)
- return (NULL);
-
- if (last_codeset == NULL || strcmp(codeset, last_codeset) != 0) {
- if (last_codeset != NULL) {
- xfree(last_codeset);
- last_codeset = NULL;
- }
- if (cd != (iconv_t)-1)
- (void) iconv_close(cd);
-
- if ((cd = iconv_open("UTF-8", codeset)) == (iconv_t)-1) {
- *error_str = gettext("Cannot convert the "
- "local codeset strings to UTF-8");
- return (NULL);
- }
- last_codeset = xstrdup(codeset);
- }
- return (do_iconv(cd, str, lenp, error_str));
-}
-
-/*
- * Wrapper around iconv()
- *
- * The caller is responsible for freeing the result. NULL is returned when
- * (errno && errno != E2BIG) (i.e., EILSEQ, EINVAL, EBADF).
- * The caller must ensure that the input string isn't NULL pointer.
- */
-static char *
-do_iconv(iconv_t cd, const char *str, uint_t *lenp, char **err_str)
-{
- int ilen, olen;
- size_t ileft, oleft;
- char *ostr, *optr;
- const char *istr;
-
- ilen = *lenp;
- olen = ilen + 1;
-
- ostr = NULL;
- for (;;) {
- olen *= 2;
- oleft = olen;
- ostr = optr = xrealloc(ostr, olen);
- istr = (const char *)str;
- if ((ileft = ilen) == 0)
- break;
-
- if (iconv(cd, &istr, &ileft, &optr, &oleft) != (size_t)-1) {
- /* success: generate reset sequence */
- if (iconv(cd, NULL, NULL,
- &optr, &oleft) == (size_t)-1 && errno == E2BIG) {
- continue;
- }
- break;
- }
- /* failed */
- if (errno != E2BIG) {
- oleft = olen;
- (void) iconv(cd, NULL, NULL, &ostr, &oleft);
- xfree(ostr);
- *err_str = gettext("Codeset conversion failed");
- return (NULL);
- }
- }
- olen = optr - ostr;
- optr = xmalloc(olen + 1);
- (void) memcpy(optr, ostr, olen);
- xfree(ostr);
-
- optr[olen] = '\0';
- *lenp = olen;
-
- return (optr);
-}
-
-/*
- * A filter for output string. Control and unprintable characters
- * are converted into visible form (eg "\ooo").
- */
-char *
-g11n_filter_string(char *s)
-{
- int mb_cur_max = MB_CUR_MAX;
- int mblen, len;
- char *os = s;
- wchar_t wc;
- char *obuf, *op;
-
- /* all character may be converted into the form of \ooo */
- obuf = op = xmalloc(strlen(s) * 4 + 1);
-
- while (*s != '\0') {
- mblen = mbtowc(&wc, s, mb_cur_max);
- if (mblen <= 0) {
- mblen = 1;
- wc = (unsigned char)*s;
- }
- if (!iswprint(wc) &&
- wc != L'\n' && wc != L'\r' && wc != L'\t') {
- /*
- * control chars which need to be replaced
- * with safe character sequence.
- */
- while (mblen != 0) {
- op += sprintf(op, "\\%03o",
- (unsigned char)*s++);
- mblen--;
- }
- } else {
- while (mblen != 0) {
- *op++ = *s++;
- mblen--;
- }
- }
- }
- *op = '\0';
- len = op - obuf + 1;
- op = xrealloc(os, len);
- (void) memcpy(op, obuf, len);
- xfree(obuf);
- return (op);
-}
-
-/*
- * Once we negotiated with a langtag, server need to map it to a system
- * locale. That is done based on the locale supported on the server side.
- * We know (with the locale supported on Solaris) how the langtag is
- * mapped to. However, from the client point of view, there is no way to
- * know exactly what locale(encoding) will be used.
- *
- * With the bug fix of SSH_BUG_STRING_ENCODING, it is guaranteed that the
- * UTF-8 characters always come over the wire, so it is no longer the problem
- * as long as both side has the bug fix. However if the server side doesn't
- * have the fix, client can't safely perform the code conversion since the
- * incoming character encoding is unknown.
- *
- * To alleviate this situation, we take an empirical approach to find
- * encoding from langtag.
- *
- * If langtag has a subtag, we can directly map the langtag to UTF-8 locale
- * (eg en-US can be mapped to en_US.UTF-8) with a few exceptions.
- * Certain xx_YY locales don't support UTF-8 encoding (probably due to lack
- * of L10N support ..). Those are:
- *
- * no_NO, no_NY, sr_SP, sr_YU
- *
- * They all use ISO8859-X encoding.
- *
- * For those "xx" langtags, some of them can be mapped to "xx.UTF-8",
- * but others cannot. So we need to use the "xx" as the locale name.
- * Those locales are:
- *
- * ar, ca, cs, da, et, fi, he, hu, ja, lt, lv, nl, no, pt, sh, th, tr
- *
- * Their encoding vary. They could be ISO8859-X or EUC or something else.
- * So we don't perform code conversion for these langtags.
- */
-static const char *non_utf8_langtag[] = {
- "no-NO", "no-NY", "sr-SP", "sr-YU",
- "ar", "ca", "cs", "da", "et", "fi", "he", "hu", "ja",
- "lt", "lv", "nl", "no", "pt", "sh", "th", "tr", NULL};
-
-void
-g11n_test_langtag(const char *lang, int server)
-{
- const char **lp;
-
- if (datafellows & SSH_BUG_LOCALES_NOT_LANGTAGS) {
- /*
- * We negotiated with real locale name (not lang tag).
- * We shouldn't expect UTF-8, thus shouldn't do code
- * conversion.
- */
- datafellows |= SSH_BUG_STRING_ENCODING;
- return;
- }
-
- if (datafellows & SSH_BUG_STRING_ENCODING) {
- if (server) {
- /*
- * Whatever bug exists in the client side, server
- * side has nothing to do, since server has no way
- * to know what actual encoding is used on the client
- * side. For example, even if we negotiated with
- * en_US, client locale could be en_US.ISO8859-X or
- * en_US.UTF-8.
- */
- return;
- }
- /*
- * We are on the client side. We'll check with known
- * locales to see if non-UTF8 characters could come in.
- */
- for (lp = non_utf8_langtag; *lp != NULL; lp++) {
- if (strcmp(lang, *lp) == 0)
- break;
- }
- if (*lp == NULL) {
- debug2("Server is expected to use UTF-8 locale");
- datafellows &= ~SSH_BUG_STRING_ENCODING;
- } else {
- /*
- * Server is expected to use non-UTF8 encoding.
- */
- debug2("Enforcing no code conversion: %s", lang);
- }
- }
-}
-
-/*
- * Free all strings in the list and then free the list itself. We know that the
- * list ends with a NULL pointer.
- */
-void
-g11n_freelist(char **list)
-{
- int i = 0;
-
- while (list[i] != NULL) {
- xfree(list[i]);
- i++;
- }
-
- xfree(list);
-}
diff --git a/usr/src/cmd/ssh/libssh/common/hostfile.c b/usr/src/cmd/ssh/libssh/common/hostfile.c
deleted file mode 100644
index f71463a973..0000000000
--- a/usr/src/cmd/ssh/libssh/common/hostfile.c
+++ /dev/null
@@ -1,357 +0,0 @@
-/*
- * Author: Tatu Ylonen <ylo@cs.hut.fi>
- * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
- * All rights reserved
- * Functions for manipulating the known hosts files.
- *
- * As far as I am concerned, the code I have written for this software
- * can be used freely for any purpose. Any derived versions of this
- * software must be clearly marked as such, and if the derived work is
- * incompatible with the protocol description in the RFC file, it must be
- * called by a name other than "ssh" or "Secure Shell".
- *
- *
- * Copyright (c) 1999, 2000 Markus Friedl. All rights reserved.
- * Copyright (c) 1999 Niels Provos. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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.
- */
-
-/* $OpenBSD: hostfile.c,v 1.45 2006/08/03 03:34:42 deraadt Exp $ */
-
-#pragma ident "%Z%%M% %I% %E% SMI"
-
-#include "includes.h"
-
-#include <openssl/hmac.h>
-#include <openssl/sha.h>
-
-#include "packet.h"
-#include "xmalloc.h"
-#include "match.h"
-#include "key.h"
-#include "hostfile.h"
-#include "log.h"
-
-/*
- * Format of a hashed hostname is <MAGIC><SALT>|<HASHED_HOSTNAME>. <MAGIC> is
- * "|1|". As in non-hashed hostnames this whole string is then followed by a
- * space, a key type and the key (which is out of scope of this function).
- *
- * Example what can be in 's':
- *
- * |1|t17NtsuXSLwP0H0eYdd8vJeNakM=|9XFVPh3jZUrfY6YCWn8Ua5eGZtA=
- */
-static int
-extract_salt(const char *s, u_int l, char *salt, size_t salt_len)
-{
- char *p;
- u_char *b64salt;
- u_int b64len;
- int ret;
-
- if (l < sizeof(HASH_MAGIC) - 1) {
- debug2("extract_salt: string too short");
- return (-1);
- }
- if (strncmp(s, HASH_MAGIC, sizeof(HASH_MAGIC) - 1) != 0) {
- debug2("extract_salt: invalid magic identifier");
- return (-1);
- }
- s += sizeof(HASH_MAGIC) - 1;
- l -= sizeof(HASH_MAGIC) - 1;
- if ((p = memchr(s, HASH_DELIM, l)) == NULL) {
- debug2("extract_salt: missing salt termination character");
- return (-1);
- }
-
- b64len = p - s;
- /* Sanity check */
- if (b64len == 0 || b64len > 1024) {
- debug2("extract_salt: bad encoded salt length %u", b64len);
- return (-1);
- }
- b64salt = xmalloc(1 + b64len);
- memcpy(b64salt, s, b64len);
- b64salt[b64len] = '\0';
-
- ret = __b64_pton(b64salt, (u_char *) salt, salt_len);
- xfree(b64salt);
- if (ret == -1) {
- debug2("extract_salt: salt decode error");
- return (-1);
- }
- if (ret != SHA_DIGEST_LENGTH) {
- debug2("extract_salt: expected salt len %d, got %d",
- SHA_DIGEST_LENGTH, ret);
- return (-1);
- }
-
- return (0);
-}
-
-char *
-host_hash(const char *host, const char *name_from_hostfile, u_int src_len)
-{
- const EVP_MD *md = EVP_sha1();
- HMAC_CTX mac_ctx;
- char salt[256], result[256], uu_salt[512], uu_result[512];
- static char encoded[1024];
- u_int i, len;
-
- len = EVP_MD_size(md);
-
- if (name_from_hostfile == NULL) {
- /* Create new salt */
- for (i = 0; i < len; i++)
- salt[i] = arc4random();
- } else {
- /* Extract salt from known host entry */
- if (extract_salt(name_from_hostfile, src_len, salt,
- sizeof(salt)) == -1)
- return (NULL);
- }
-
- HMAC_Init(&mac_ctx, salt, len, md);
- HMAC_Update(&mac_ctx, (u_char *) host, strlen(host));
- HMAC_Final(&mac_ctx, (u_char *) result, NULL);
- HMAC_cleanup(&mac_ctx);
-
- if (__b64_ntop((u_char *) salt, len, uu_salt, sizeof(uu_salt)) == -1 ||
- __b64_ntop((u_char *) result, len, uu_result, sizeof(uu_result)) == -1)
- fatal("host_hash: __b64_ntop failed");
-
- snprintf(encoded, sizeof(encoded), "%s%s%c%s", HASH_MAGIC, uu_salt,
- HASH_DELIM, uu_result);
-
- return (encoded);
-}
-
-/*
- * Parses an RSA (number of bits, e, n) or DSA key from a string. Moves the
- * pointer over the key. Skips any whitespace at the beginning and at end.
- */
-
-int
-hostfile_read_key(char **cpp, u_int *bitsp, Key *ret)
-{
- char *cp;
-
- /* Skip leading whitespace. */
- for (cp = *cpp; *cp == ' ' || *cp == '\t'; cp++)
- ;
-
- if (key_read(ret, &cp) != 1)
- return 0;
-
- /* Skip trailing whitespace. */
- for (; *cp == ' ' || *cp == '\t'; cp++)
- ;
-
- /* Return results. */
- *cpp = cp;
- *bitsp = key_size(ret);
- return 1;
-}
-
-static int
-hostfile_check_key(int bits, const Key *key, const char *host, const char *filename, int linenum)
-{
- if (key == NULL || key->type != KEY_RSA1 || key->rsa == NULL)
- return 1;
- if (bits != BN_num_bits(key->rsa->n)) {
- log("Warning: %s, line %d: keysize mismatch for host %s: "
- "actual %d vs. announced %d.",
- filename, linenum, host, BN_num_bits(key->rsa->n), bits);
- log("Warning: replace %d with %d in %s, line %d.",
- bits, BN_num_bits(key->rsa->n), filename, linenum);
- }
- return 1;
-}
-
-/*
- * Checks whether the given host (which must be in all lowercase) is already
- * in the list of our known hosts. Returns HOST_OK if the host is known and
- * has the specified key, HOST_NEW if the host is not known, and HOST_CHANGED
- * if the host is known but used to have a different host key.
- *
- * If no 'key' has been specified and a key of type 'keytype' is known
- * for the specified host, then HOST_FOUND is returned.
- */
-
-static HostStatus
-check_host_in_hostfile_by_key_or_type(const char *filename,
- const char *host, const Key *key, int keytype, Key *found, int *numret)
-{
- FILE *f;
- char line[8192];
- int linenum = 0;
- u_int kbits;
- char *cp, *cp2, *hashed_host;
- HostStatus end_return;
-
- debug3("check_host_in_hostfile: filename %s", filename);
-
- /* Open the file containing the list of known hosts. */
- f = fopen(filename, "r");
- if (!f)
- return HOST_NEW;
-
- /*
- * Return value when the loop terminates. This is set to
- * HOST_CHANGED if we have seen a different key for the host and have
- * not found the proper one.
- */
- end_return = HOST_NEW;
-
- /* Go through the file. */
- while (fgets(line, sizeof(line), f)) {
- cp = line;
- linenum++;
-
- /* Skip any leading whitespace, comments and empty lines. */
- for (; *cp == ' ' || *cp == '\t'; cp++)
- ;
- if (!*cp || *cp == '#' || *cp == '\n')
- continue;
-
- /* Find the end of the host name portion. */
- for (cp2 = cp; *cp2 && *cp2 != ' ' && *cp2 != '\t'; cp2++)
- ;
-
- /* Check if the host name matches. */
- if (match_hostname(host, cp, (u_int) (cp2 - cp)) != 1) {
- if (*cp != HASH_DELIM)
- continue;
- hashed_host = host_hash(host, cp, (u_int) (cp2 - cp));
- if (hashed_host == NULL) {
- debug("Invalid hashed host line %d of %s",
- linenum, filename);
- continue;
- }
- if (strncmp(hashed_host, cp, (u_int) (cp2 - cp)) != 0)
- continue;
- }
-
- /* Got a match. Skip host name. */
- cp = cp2;
-
- /*
- * Extract the key from the line. This will skip any leading
- * whitespace. Ignore badly formatted lines.
- */
- if (!hostfile_read_key(&cp, &kbits, found))
- continue;
-
- if (numret != NULL)
- *numret = linenum;
-
- if (key == NULL) {
- /* we found a key of the requested type */
- if (found->type == keytype) {
- fclose(f);
- return HOST_FOUND;
- }
- continue;
- }
-
- if (!hostfile_check_key(kbits, found, host, filename, linenum))
- continue;
-
- /* Check if the current key is the same as the given key. */
- if (key_equal(key, found)) {
- /* Ok, they match. */
- debug3("check_host_in_hostfile: match line %d", linenum);
- fclose(f);
- return HOST_OK;
- }
- /*
- * They do not match. We will continue to go through the
- * file; however, we note that we will not return that it is
- * new.
- */
- end_return = HOST_CHANGED;
- }
- /* Clear variables and close the file. */
- fclose(f);
-
- /*
- * Return either HOST_NEW or HOST_CHANGED, depending on whether we
- * saw a different key for the host.
- */
- return end_return;
-}
-
-HostStatus
-check_host_in_hostfile(const char *filename, const char *host, const Key *key,
- Key *found, int *numret)
-{
- if (key == NULL)
- fatal("no key to look up");
- return (check_host_in_hostfile_by_key_or_type(filename, host, key, 0,
- found, numret));
-}
-
-int
-lookup_key_in_hostfile_by_type(const char *filename, const char *host,
- int keytype, Key *found, int *numret)
-{
- return (check_host_in_hostfile_by_key_or_type(filename, host, NULL,
- keytype, found, numret) == HOST_FOUND);
-}
-
-/*
- * Appends an entry to the host file. Returns false if the entry could not
- * be appended.
- */
-
-int
-add_host_to_hostfile(const char *filename, const char *host, const Key *key,
- int store_hash)
-{
- FILE *f;
- int success = 0;
- char *hashed_host = NULL;
-
- if (key == NULL)
- return 1; /* XXX ? */
- f = fopen(filename, "a");
- if (!f)
- return 0;
-
- if (store_hash) {
- if ((hashed_host = host_hash(host, NULL, 0)) == NULL) {
- error("add_host_to_hostfile: host_hash failed");
- fclose(f);
- return 0;
- }
- }
- fprintf(f, "%s ", store_hash ? hashed_host : host);
-
- if (key_write(key, f)) {
- success = 1;
- } else {
- error("add_host_to_hostfile: saving key in %s failed", filename);
- }
- fprintf(f, "\n");
- fclose(f);
- return success;
-}
diff --git a/usr/src/cmd/ssh/libssh/common/kex.c b/usr/src/cmd/ssh/libssh/common/kex.c
deleted file mode 100644
index 0eb9e780fa..0000000000
--- a/usr/src/cmd/ssh/libssh/common/kex.c
+++ /dev/null
@@ -1,711 +0,0 @@
-/*
- * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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.
- *
- * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
- */
-
-#include "includes.h"
-RCSID("$OpenBSD: kex.c,v 1.51 2002/06/24 14:55:38 markus Exp $");
-
-#include <locale.h>
-
-#include <openssl/crypto.h>
-
-#include "ssh2.h"
-#include "xmalloc.h"
-#include "buffer.h"
-#include "bufaux.h"
-#include "packet.h"
-#include "compat.h"
-#include "cipher.h"
-#include "kex.h"
-#include "key.h"
-#include "log.h"
-#include "mac.h"
-#include "match.h"
-#include "dispatch.h"
-#include "g11n.h"
-
-#ifdef GSSAPI
-#include "ssh-gss.h"
-#endif
-
-#define KEX_COOKIE_LEN 16
-
-char *session_lang = NULL;
-
-
-/* prototype */
-static void kex_do_hook(Kex *kex);
-static void kex_kexinit_finish(Kex *);
-static void kex_choose_conf(Kex *);
-
-/* put algorithm proposal into buffer */
-static
-void
-kex_prop2buf(Buffer *b, char *proposal[PROPOSAL_MAX])
-{
- int i;
-
- buffer_clear(b);
- /*
- * add a dummy cookie, the cookie will be overwritten by
- * kex_send_kexinit(), each time a kexinit is set
- */
- for (i = 0; i < KEX_COOKIE_LEN; i++)
- buffer_put_char(b, 0);
- for (i = 0; i < PROPOSAL_MAX; i++)
- buffer_put_cstring(b, proposal[i]);
- buffer_put_char(b, 0); /* first_kex_packet_follows */
- buffer_put_int(b, 0); /* uint32 reserved */
-}
-
-/* parse buffer and return algorithm proposal */
-static
-char **
-kex_buf2prop(Buffer *raw, int *first_kex_follows)
-{
- Buffer b;
- int i;
- char **proposal;
-
- proposal = xmalloc(PROPOSAL_MAX * sizeof(char *));
-
- buffer_init(&b);
- buffer_append(&b, buffer_ptr(raw), buffer_len(raw));
- /* skip cookie */
- for (i = 0; i < KEX_COOKIE_LEN; i++)
- buffer_get_char(&b);
- /* extract kex init proposal strings */
- for (i = 0; i < PROPOSAL_MAX; i++) {
- proposal[i] = buffer_get_string(&b,NULL);
- debug2("kex_parse_kexinit: %s", proposal[i]);
- }
- /* first kex follows / reserved */
- i = buffer_get_char(&b);
- if (first_kex_follows != NULL)
- *first_kex_follows = i;
- debug2("kex_parse_kexinit: first_kex_follows %d ", i);
- i = buffer_get_int(&b);
- debug2("kex_parse_kexinit: reserved %d ", i);
- buffer_free(&b);
- return proposal;
-}
-
-static
-void
-kex_prop_free(char **proposal)
-{
- int i;
-
- for (i = 0; i < PROPOSAL_MAX; i++)
- xfree(proposal[i]);
- xfree(proposal);
-}
-
-static void
-kex_protocol_error(int type, u_int32_t seq, void *ctxt)
-{
- error("Hm, kex protocol error: type %d seq %u", type, seq);
-}
-
-static void
-kex_reset_dispatch(void)
-{
-#ifdef ALTPRIVSEP
- /* unprivileged sshd has a kex packet handler that must not be reset */
- debug3("kex_reset_dispatch -- should we dispatch_set(KEXINIT) here? %d && !%d",
- packet_is_server(), packet_is_monitor());
- if (packet_is_server() && !packet_is_monitor()) {
- debug3("kex_reset_dispatch -- skipping dispatch_set(KEXINIT) in unpriv proc");
- return;
- }
-#endif /* ALTPRIVSEP */
-
- dispatch_range(SSH2_MSG_TRANSPORT_MIN,
- SSH2_MSG_TRANSPORT_MAX, &kex_protocol_error);
- dispatch_set(SSH2_MSG_KEXINIT, &kex_input_kexinit);
-}
-
-void
-kex_finish(Kex *kex)
-{
- kex_reset_dispatch();
-
- packet_start(SSH2_MSG_NEWKEYS);
- packet_send();
- /* packet_write_wait(); */
- debug("SSH2_MSG_NEWKEYS sent");
-
-#ifdef ALTPRIVSEP
- if (packet_is_monitor())
- goto skip_newkeys;
-#endif /* ALTPRIVSEP */
- debug("expecting SSH2_MSG_NEWKEYS");
- packet_read_expect(SSH2_MSG_NEWKEYS);
- packet_check_eom();
- debug("SSH2_MSG_NEWKEYS received");
-#ifdef ALTPRIVSEP
-skip_newkeys:
-#endif /* ALTPRIVSEP */
-
- kex->done = 1;
- kex->initial_kex_done = 1; /* never to be cleared once set */
- buffer_clear(&kex->peer);
- /* buffer_clear(&kex->my); */
- kex->flags &= ~KEX_INIT_SENT;
- xfree(kex->name);
- kex->name = NULL;
-}
-
-void
-kex_send_kexinit(Kex *kex)
-{
- u_int32_t rand = 0;
- u_char *cookie;
- int i;
-
- if (kex == NULL) {
- error("kex_send_kexinit: no kex, cannot rekey");
- return;
- }
- if (kex->flags & KEX_INIT_SENT) {
- debug("KEX_INIT_SENT");
- return;
- }
- kex->done = 0;
-
- /* update my proposal -- e.g., add/remove GSS kexalgs */
- kex_do_hook(kex);
-
- /* generate a random cookie */
- if (buffer_len(&kex->my) < KEX_COOKIE_LEN)
- fatal("kex_send_kexinit: kex proposal too short");
- cookie = buffer_ptr(&kex->my);
- for (i = 0; i < KEX_COOKIE_LEN; i++) {
- if (i % 4 == 0)
- rand = arc4random();
- cookie[i] = rand;
- rand >>= 8;
- }
- packet_start(SSH2_MSG_KEXINIT);
- packet_put_raw(buffer_ptr(&kex->my), buffer_len(&kex->my));
- packet_send();
- debug("SSH2_MSG_KEXINIT sent");
- kex->flags |= KEX_INIT_SENT;
-}
-
-void
-kex_input_kexinit(int type, u_int32_t seq, void *ctxt)
-{
- char *ptr;
- u_int dlen;
- int i;
- Kex *kex = (Kex *)ctxt;
-
- debug("SSH2_MSG_KEXINIT received");
- if (kex == NULL)
- fatal("kex_input_kexinit: no kex, cannot rekey");
-
- ptr = packet_get_raw(&dlen);
- buffer_append(&kex->peer, ptr, dlen);
-
- /* discard packet */
- for (i = 0; i < KEX_COOKIE_LEN; i++)
- packet_get_char();
- for (i = 0; i < PROPOSAL_MAX; i++)
- xfree(packet_get_string(NULL));
- (void) packet_get_char();
- (void) packet_get_int();
- packet_check_eom();
-
- kex_kexinit_finish(kex);
-}
-
-/*
- * This is for GSS keyex, where actual KEX offer can change at rekey
- * time due to credential expiration/renewal...
- */
-static
-void
-kex_do_hook(Kex *kex)
-{
- char **prop;
-
- if (kex->kex_hook == NULL)
- return;
-
- /* Unmarshall my proposal, let the hook modify it, remarshall it */
- prop = kex_buf2prop(&kex->my, NULL);
- buffer_clear(&kex->my);
- (kex->kex_hook)(kex, prop);
- kex_prop2buf(&kex->my, prop);
- kex_prop_free(prop);
-}
-
-/* Initiate the key exchange by sending the SSH2_MSG_KEXINIT message. */
-void
-kex_start(Kex *kex)
-{
- kex_send_kexinit(kex);
- kex_reset_dispatch();
-}
-
-/*
- * Allocate a key exchange structure and populate it with a proposal we are
- * going to use. This function does not start the actual key exchange.
- */
-Kex *
-kex_setup(const char *host, char *proposal[PROPOSAL_MAX], Kex_hook_func hook)
-{
- Kex *kex;
-
- kex = xmalloc(sizeof(*kex));
- memset(kex, 0, sizeof(*kex));
- buffer_init(&kex->peer);
- buffer_init(&kex->my);
-
- kex->kex_hook = hook; /* called by kex_send_kexinit() */
-
- if (host != NULL && *host != '\0')
- kex->serverhost = xstrdup(host);
- else
- kex->server = 1;
-
- kex_prop2buf(&kex->my, proposal);
-
- return kex;
-}
-
-static void
-kex_kexinit_finish(Kex *kex)
-{
- if (!(kex->flags & KEX_INIT_SENT))
- kex_send_kexinit(kex);
-
- kex_choose_conf(kex);
-
- if (kex->kex_type >= 0 && kex->kex_type < KEX_MAX &&
- kex->kex[kex->kex_type] != NULL)
- (kex->kex[kex->kex_type])(kex);
- else
- fatal("Unsupported key exchange %d", kex->kex_type);
-}
-
-static void
-choose_lang(char **lang, char *client, char *server)
-{
- if (datafellows & SSH_BUG_LOCALES_NOT_LANGTAGS)
- *lang = match_list(client, server, NULL);
- else
- *lang = g11n_srvr_locale_negotiate(client, NULL);
-}
-
-/*
- * Make the message clear enough so that if this happens the user can figure out
- * the workaround of changing the Ciphers option.
- */
-#define CLIENT_ERR_MSG \
- "Client and server could not agree on a common cipher:\n" \
- " client: %s\n" \
- " server: %s\n" \
- "\n" \
- "The client cipher list can be controlled using the \"Ciphers\" option, \n" \
- "see ssh_config(4) for more information. The \"-o Ciphers=<cipher-list>\"\n" \
- "option may be used to temporarily override the ciphers the client\n" \
- "offers."
-
-/*
- * The server side message goes to syslogd and we do not want to send multiline
- * messages there. What's more, the server side notification may be shorter
- * since we expect that an administrator will deal with that, not the user.
- */
-#define SERVER_ERR_MSG \
- "Client and server could not agree on a common cipher: client \"%s\", " \
- "server \"%s\". The server cipher list can be controlled using the " \
- "\"Ciphers\" option, see sshd_config(4) for more information."
-
-static void
-choose_enc(int is_server, Enc *enc, char *client, char *server)
-{
- char *name = match_list(client, server, NULL);
-
- if (name == NULL) {
- if (is_server == 1)
- fatal(SERVER_ERR_MSG, client, server);
- else
- fatal(CLIENT_ERR_MSG, client, server);
- }
-
- if ((enc->cipher = cipher_by_name(name)) == NULL)
- fatal("matching cipher is not supported: %s", name);
-
- enc->name = name;
- enc->enabled = 0;
- enc->iv = NULL;
- enc->key = NULL;
- enc->key_len = cipher_keylen(enc->cipher);
- enc->block_size = cipher_blocksize(enc->cipher);
-}
-
-static void
-choose_mac(Mac *mac, char *client, char *server)
-{
- char *name = match_list(client, server, NULL);
- if (name == NULL)
- fatal("no matching mac found: client %s server %s",
- client, server);
- if (mac_setup(mac, name) < 0)
- fatal("unsupported mac %s", name);
- /* truncate the key */
- if (datafellows & SSH_BUG_HMAC)
- mac->key_len = 16;
- mac->name = name;
- mac->key = NULL;
- mac->enabled = 0;
-}
-
-static void
-choose_comp(Comp *comp, char *client, char *server)
-{
- char *name = match_list(client, server, NULL);
- if (name == NULL)
- fatal("no matching comp found: client %s server %s", client, server);
- if (strcmp(name, "zlib") == 0) {
- comp->type = 1;
- } else if (strcmp(name, "none") == 0) {
- comp->type = 0;
- } else {
- fatal("unsupported comp %s", name);
- }
- comp->name = name;
-}
-
-static void
-choose_kex(Kex *k, char *client, char *server)
-{
- k->name = match_list(client, server, NULL);
- if (k->name == NULL)
- fatal("no common kex alg: client '%s', server '%s'", client,
- server);
- /* XXX Finish 3.6/7 merge of kex stuff -- choose_kex() done */
- if (strcmp(k->name, KEX_DH1) == 0) {
- k->kex_type = KEX_DH_GRP1_SHA1;
- } else if (strcmp(k->name, KEX_DHGEX) == 0) {
- k->kex_type = KEX_DH_GEX_SHA1;
-#ifdef GSSAPI
- } else if (strncmp(k->name, KEX_GSS_SHA1, sizeof(KEX_GSS_SHA1)-1) == 0) {
- k->kex_type = KEX_GSS_GRP1_SHA1;
-#endif
- } else
- fatal("bad kex alg %s", k->name);
-}
-
-static void
-choose_hostkeyalg(Kex *k, char *client, char *server)
-{
- char *hostkeyalg = match_list(client, server, NULL);
- if (hostkeyalg == NULL)
- fatal("no hostkey alg");
- k->hostkey_type = key_type_from_name(hostkeyalg);
- if (k->hostkey_type == KEY_UNSPEC)
- fatal("bad hostkey alg '%s'", hostkeyalg);
- xfree(hostkeyalg);
-}
-
-static int
-proposals_match(char *my[PROPOSAL_MAX], char *peer[PROPOSAL_MAX])
-{
- static int check[] = {
- PROPOSAL_KEX_ALGS, PROPOSAL_SERVER_HOST_KEY_ALGS, -1
- };
- int *idx;
- char *p;
-
- for (idx = &check[0]; *idx != -1; idx++) {
- if ((p = strchr(my[*idx], ',')) != NULL)
- *p = '\0';
- if ((p = strchr(peer[*idx], ',')) != NULL)
- *p = '\0';
- if (strcmp(my[*idx], peer[*idx]) != 0) {
- debug2("proposal mismatch: my %s peer %s",
- my[*idx], peer[*idx]);
- return (0);
- }
- }
- debug2("proposals match");
- return (1);
-}
-
-static void
-kex_choose_conf(Kex *kex)
-{
- Newkeys *newkeys;
- char **my, **peer;
- char **cprop, **sprop;
- char *p_langs_c2s, *p_langs_s2c; /* peer's langs */
- char *plangs = NULL; /* peer's langs*/
- char *mlangs = NULL; /* my langs */
- int nenc, nmac, ncomp;
- int mode;
- int ctos; /* direction: if true client-to-server */
- int need;
- int first_kex_follows, type;
-
- my = kex_buf2prop(&kex->my, NULL);
- peer = kex_buf2prop(&kex->peer, &first_kex_follows);
-
- if (kex->server) {
- cprop=peer;
- sprop=my;
- } else {
- cprop=my;
- sprop=peer;
- }
-
- /* Algorithm Negotiation */
- for (mode = 0; mode < MODE_MAX; mode++) {
- newkeys = xmalloc(sizeof(*newkeys));
- memset(newkeys, 0, sizeof(*newkeys));
- kex->newkeys[mode] = newkeys;
- ctos = (!kex->server && mode == MODE_OUT) || (kex->server && mode == MODE_IN);
- nenc = ctos ? PROPOSAL_ENC_ALGS_CTOS : PROPOSAL_ENC_ALGS_STOC;
- nmac = ctos ? PROPOSAL_MAC_ALGS_CTOS : PROPOSAL_MAC_ALGS_STOC;
- ncomp = ctos ? PROPOSAL_COMP_ALGS_CTOS : PROPOSAL_COMP_ALGS_STOC;
- choose_enc(kex->server, &newkeys->enc, cprop[nenc], sprop[nenc]);
- choose_mac(&newkeys->mac, cprop[nmac], sprop[nmac]);
- choose_comp(&newkeys->comp, cprop[ncomp], sprop[ncomp]);
- debug("kex: %s %s %s %s",
- ctos ? "client->server" : "server->client",
- newkeys->enc.name,
- newkeys->mac.name,
- newkeys->comp.name);
- }
- choose_kex(kex, cprop[PROPOSAL_KEX_ALGS], sprop[PROPOSAL_KEX_ALGS]);
- choose_hostkeyalg(kex, cprop[PROPOSAL_SERVER_HOST_KEY_ALGS],
- sprop[PROPOSAL_SERVER_HOST_KEY_ALGS]);
- need = 0;
- for (mode = 0; mode < MODE_MAX; mode++) {
- newkeys = kex->newkeys[mode];
- if (need < newkeys->enc.key_len)
- need = newkeys->enc.key_len;
- if (need < newkeys->enc.block_size)
- need = newkeys->enc.block_size;
- if (need < newkeys->mac.key_len)
- need = newkeys->mac.key_len;
- }
- /* XXX need runden? */
- kex->we_need = need;
-
- /* ignore the next message if the proposals do not match */
- if (first_kex_follows && !proposals_match(my, peer) &&
- !(datafellows & SSH_BUG_FIRSTKEX)) {
- type = packet_read();
- debug2("skipping next packet (type %u)", type);
- }
-
- /* Language/locale negotiation -- not worth doing on re-key */
-
- if (!kex->initial_kex_done) {
- p_langs_c2s = peer[PROPOSAL_LANG_CTOS];
- p_langs_s2c = peer[PROPOSAL_LANG_STOC];
- debug("Peer sent proposed langtags, ctos: %s", p_langs_c2s);
- debug("Peer sent proposed langtags, stoc: %s", p_langs_s2c);
- plangs = NULL;
-
- /* We propose the same langs for each protocol direction */
- mlangs = my[PROPOSAL_LANG_STOC];
- debug("We proposed langtags, ctos: %s", my[PROPOSAL_LANG_CTOS]);
- debug("We proposed langtags, stoc: %s", mlangs);
-
- /*
- * Why oh why did they bother with negotiating langs for
- * each protocol direction?!
- *
- * The semantics of this are vaguely specified, but one can
- * imagine using one language (locale) for the whole session and
- * a different one for message localization (e.g., 'en_US.UTF-8'
- * overall and 'fr' for messages). Weird? Maybe. But lang
- * tags don't include codeset info, like locales do...
- *
- * So, server-side we want:
- * - setlocale(LC_ALL, c2s_locale);
- * and
- * - setlocale(LC_MESSAGES, s2c_locale);
- *
- * Client-side we don't really care. But we could do:
- *
- * - when very verbose, tell the use what lang the server's
- * messages are in, if left out in the protocol
- * - when sending messages to the server, and if applicable, we
- * can localize them according to the language negotiated for
- * that direction.
- *
- * But for now we do nothing on the client side.
- */
- if ((p_langs_c2s && *p_langs_c2s) && !(p_langs_s2c && *p_langs_s2c))
- plangs = p_langs_c2s;
- else if ((p_langs_s2c && *p_langs_s2c) && !(p_langs_c2s && *p_langs_c2s))
- plangs = p_langs_s2c;
- else
- plangs = p_langs_c2s;
-
- if (kex->server) {
- if (plangs && mlangs && *plangs && *mlangs) {
- char *locale;
-
- g11n_test_langtag(plangs, 1);
-
- choose_lang(&locale, plangs, mlangs);
- if (locale) {
- g11n_setlocale(LC_ALL, locale);
- debug("Negotiated main locale: %s", locale);
- packet_send_debug("Negotiated main locale: %s", locale);
- xfree(locale);
- }
- if (plangs != p_langs_s2c &&
- p_langs_s2c && *p_langs_s2c) {
- choose_lang(&locale, p_langs_s2c, mlangs);
- if (locale) {
- g11n_setlocale(LC_MESSAGES, locale);
- debug("Negotiated messages locale: %s", locale);
- packet_send_debug("Negotiated "
- "messages locale: %s", locale);
- xfree(locale);
- }
- }
- }
- }
- else {
- if (plangs && mlangs && *plangs && *mlangs &&
- !(datafellows & SSH_BUG_LOCALES_NOT_LANGTAGS)) {
- char *lang;
- lang = g11n_clnt_langtag_negotiate(mlangs, plangs);
- if (lang) {
- session_lang = lang;
- debug("Negotiated lang: %s", lang);
- g11n_test_langtag(lang, 0);
- }
- }
- }
- }
-
- kex_prop_free(my);
- kex_prop_free(peer);
-}
-
-static u_char *
-derive_key(Kex *kex, int id, int need, u_char *hash, BIGNUM *shared_secret)
-{
- Buffer b;
- const EVP_MD *evp_md = EVP_sha1();
- EVP_MD_CTX md;
- char c = id;
- int have;
- int mdsz = EVP_MD_size(evp_md);
- u_char *digest = xmalloc(roundup(need, mdsz));
-
- buffer_init(&b);
- buffer_put_bignum2(&b, shared_secret);
-
- /* K1 = HASH(K || H || "A" || session_id) */
- EVP_DigestInit(&md, evp_md);
- if (!(datafellows & SSH_BUG_DERIVEKEY))
- EVP_DigestUpdate(&md, buffer_ptr(&b), buffer_len(&b));
- EVP_DigestUpdate(&md, hash, mdsz);
- EVP_DigestUpdate(&md, &c, 1);
- EVP_DigestUpdate(&md, kex->session_id, kex->session_id_len);
- EVP_DigestFinal(&md, digest, NULL);
-
- /*
- * expand key:
- * Kn = HASH(K || H || K1 || K2 || ... || Kn-1)
- * Key = K1 || K2 || ... || Kn
- */
- for (have = mdsz; need > have; have += mdsz) {
- EVP_DigestInit(&md, evp_md);
- if (!(datafellows & SSH_BUG_DERIVEKEY))
- EVP_DigestUpdate(&md, buffer_ptr(&b), buffer_len(&b));
- EVP_DigestUpdate(&md, hash, mdsz);
- EVP_DigestUpdate(&md, digest, have);
- EVP_DigestFinal(&md, digest + have, NULL);
- }
- buffer_free(&b);
-#ifdef DEBUG_KEX
- fprintf(stderr, "key '%c'== ", c);
- dump_digest("key", digest, need);
-#endif
- return digest;
-}
-
-Newkeys *current_keys[MODE_MAX];
-
-#define NKEYS 6
-void
-kex_derive_keys(Kex *kex, u_char *hash, BIGNUM *shared_secret)
-{
- u_char *keys[NKEYS];
- int i, mode, ctos;
-
- for (i = 0; i < NKEYS; i++)
- keys[i] = derive_key(kex, 'A'+i, kex->we_need, hash, shared_secret);
-
- debug2("kex_derive_keys");
- for (mode = 0; mode < MODE_MAX; mode++) {
- current_keys[mode] = kex->newkeys[mode];
- kex->newkeys[mode] = NULL;
- ctos = (!kex->server && mode == MODE_OUT) || (kex->server && mode == MODE_IN);
- current_keys[mode]->enc.iv = keys[ctos ? 0 : 1];
- current_keys[mode]->enc.key = keys[ctos ? 2 : 3];
- current_keys[mode]->mac.key = keys[ctos ? 4 : 5];
- }
-}
-
-Newkeys *
-kex_get_newkeys(int mode)
-{
- Newkeys *ret;
-
- ret = current_keys[mode];
- current_keys[mode] = NULL;
- return ret;
-}
-
-#if defined(DEBUG_KEX) || defined(DEBUG_KEXDH)
-void
-dump_digest(char *msg, u_char *digest, int len)
-{
- int i;
-
- fprintf(stderr, "%s\n", msg);
- for (i = 0; i< len; i++) {
- fprintf(stderr, "%02x", digest[i]);
- if (i%32 == 31)
- fprintf(stderr, "\n");
- else if (i%8 == 7)
- fprintf(stderr, " ");
- }
- fprintf(stderr, "\n");
-}
-#endif
diff --git a/usr/src/cmd/ssh/libssh/common/kexdh.c b/usr/src/cmd/ssh/libssh/common/kexdh.c
deleted file mode 100644
index b15ecd2c5b..0000000000
--- a/usr/src/cmd/ssh/libssh/common/kexdh.c
+++ /dev/null
@@ -1,89 +0,0 @@
-/*
- * Copyright (c) 2001 Markus Friedl. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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.
- */
-
-#include "includes.h"
-RCSID("$OpenBSD: kexdh.c,v 1.18 2002/03/18 17:50:31 provos Exp $");
-
-#pragma ident "%Z%%M% %I% %E% SMI"
-
-#include <openssl/crypto.h>
-#include <openssl/bn.h>
-
-#include "xmalloc.h"
-#include "buffer.h"
-#include "bufaux.h"
-#include "key.h"
-#include "kex.h"
-#include "log.h"
-#include "packet.h"
-#include "dh.h"
-#include "ssh2.h"
-
-u_char *
-kex_dh_hash(
- char *client_version_string,
- char *server_version_string,
- char *ckexinit, int ckexinitlen,
- char *skexinit, int skexinitlen,
- u_char *serverhostkeyblob, int sbloblen,
- BIGNUM *client_dh_pub,
- BIGNUM *server_dh_pub,
- BIGNUM *shared_secret)
-{
- Buffer b;
- static u_char digest[EVP_MAX_MD_SIZE];
- const EVP_MD *evp_md = EVP_sha1();
- EVP_MD_CTX md;
-
- buffer_init(&b);
- buffer_put_cstring(&b, client_version_string);
- buffer_put_cstring(&b, server_version_string);
-
- /* kexinit messages: fake header: len+SSH2_MSG_KEXINIT */
- buffer_put_int(&b, ckexinitlen+1);
- buffer_put_char(&b, SSH2_MSG_KEXINIT);
- buffer_append(&b, ckexinit, ckexinitlen);
- buffer_put_int(&b, skexinitlen+1);
- buffer_put_char(&b, SSH2_MSG_KEXINIT);
- buffer_append(&b, skexinit, skexinitlen);
-
- buffer_put_string(&b, serverhostkeyblob, sbloblen);
- buffer_put_bignum2(&b, client_dh_pub);
- buffer_put_bignum2(&b, server_dh_pub);
- buffer_put_bignum2(&b, shared_secret);
-
-#ifdef DEBUG_KEX
- buffer_dump(&b);
-#endif
- EVP_DigestInit(&md, evp_md);
- EVP_DigestUpdate(&md, buffer_ptr(&b), buffer_len(&b));
- EVP_DigestFinal(&md, digest, NULL);
-
- buffer_free(&b);
-
-#ifdef DEBUG_KEX
- dump_digest("hash", digest, EVP_MD_size(evp_md));
-#endif
- return digest;
-}
diff --git a/usr/src/cmd/ssh/libssh/common/kexdhc.c b/usr/src/cmd/ssh/libssh/common/kexdhc.c
deleted file mode 100644
index 1c75f8449f..0000000000
--- a/usr/src/cmd/ssh/libssh/common/kexdhc.c
+++ /dev/null
@@ -1,144 +0,0 @@
-/*
- * Copyright (c) 2001 Markus Friedl. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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.
- */
-
-#include "includes.h"
-RCSID("$OpenBSD: kexdh.c,v 1.18 2002/03/18 17:50:31 provos Exp $");
-
-#pragma ident "%Z%%M% %I% %E% SMI"
-
-#include <openssl/crypto.h>
-#include <openssl/bn.h>
-
-#include "xmalloc.h"
-#include "buffer.h"
-#include "bufaux.h"
-#include "key.h"
-#include "kex.h"
-#include "log.h"
-#include "packet.h"
-#include "dh.h"
-#include "ssh2.h"
-
-void
-kexdh_client(Kex *kex)
-{
- BIGNUM *dh_server_pub = NULL, *shared_secret = NULL;
- DH *dh;
- Key *server_host_key;
- u_char *server_host_key_blob = NULL, *signature = NULL;
- u_char *kbuf, *hash;
- u_int klen, kout, slen, sbloblen;
-
- /* generate and send 'e', client DH public key */
- dh = dh_new_group1();
- dh_gen_key(dh, kex->we_need * 8);
- packet_start(SSH2_MSG_KEXDH_INIT);
- packet_put_bignum2(dh->pub_key);
- packet_send();
-
- debug("sending SSH2_MSG_KEXDH_INIT");
-#ifdef DEBUG_KEXDH
- DHparams_print_fp(stderr, dh);
- fprintf(stderr, "pub= ");
- BN_print_fp(stderr, dh->pub_key);
- fprintf(stderr, "\n");
-#endif
-
- debug("expecting SSH2_MSG_KEXDH_REPLY");
- packet_read_expect(SSH2_MSG_KEXDH_REPLY);
-
- /* key, cert */
- server_host_key_blob = packet_get_string(&sbloblen);
- server_host_key = key_from_blob(server_host_key_blob, sbloblen);
- if (server_host_key == NULL)
- fatal("cannot decode server_host_key_blob");
- if (server_host_key->type != kex->hostkey_type)
- fatal("type mismatch for decoded server_host_key_blob");
- if (kex->verify_host_key == NULL)
- fatal("cannot verify server_host_key");
- if (kex->verify_host_key(server_host_key) == -1)
- fatal("server_host_key verification failed");
-
- /* DH paramter f, server public DH key */
- if ((dh_server_pub = BN_new()) == NULL)
- fatal("dh_server_pub == NULL");
- packet_get_bignum2(dh_server_pub);
-
-#ifdef DEBUG_KEXDH
- fprintf(stderr, "dh_server_pub= ");
- BN_print_fp(stderr, dh_server_pub);
- fprintf(stderr, "\n");
- debug("bits %d", BN_num_bits(dh_server_pub));
-#endif
-
- /* signed H */
- signature = packet_get_string(&slen);
- packet_check_eom();
-
- if (!dh_pub_is_valid(dh, dh_server_pub))
- packet_disconnect("bad server public DH value");
-
- klen = DH_size(dh);
- kbuf = xmalloc(klen);
- kout = DH_compute_key(kbuf, dh_server_pub, dh);
-#ifdef DEBUG_KEXDH
- dump_digest("shared secret", kbuf, kout);
-#endif
- if ((shared_secret = BN_new()) == NULL)
- fatal("kexdh_client: BN_new failed");
- BN_bin2bn(kbuf, kout, shared_secret);
- memset(kbuf, 0, klen);
- xfree(kbuf);
-
- /* calc and verify H */
- hash = kex_dh_hash(
- kex->client_version_string,
- kex->server_version_string,
- buffer_ptr(&kex->my), buffer_len(&kex->my),
- buffer_ptr(&kex->peer), buffer_len(&kex->peer),
- server_host_key_blob, sbloblen,
- dh->pub_key,
- dh_server_pub,
- shared_secret
- );
- xfree(server_host_key_blob);
- BN_clear_free(dh_server_pub);
- DH_free(dh);
-
- if (key_verify(server_host_key, signature, slen, hash, 20) != 1)
- fatal("key_verify failed for server_host_key");
- key_free(server_host_key);
- xfree(signature);
-
- /* save session id */
- if (kex->session_id == NULL) {
- kex->session_id_len = 20;
- kex->session_id = xmalloc(kex->session_id_len);
- memcpy(kex->session_id, hash, kex->session_id_len);
- }
-
- kex_derive_keys(kex, hash, shared_secret);
- BN_clear_free(shared_secret);
- kex_finish(kex);
-}
diff --git a/usr/src/cmd/ssh/libssh/common/kexdhs.c b/usr/src/cmd/ssh/libssh/common/kexdhs.c
deleted file mode 100644
index 5e14b1333f..0000000000
--- a/usr/src/cmd/ssh/libssh/common/kexdhs.c
+++ /dev/null
@@ -1,144 +0,0 @@
-/*
- * Copyright (c) 2001 Markus Friedl. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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.
- */
-
-#include "includes.h"
-RCSID("$OpenBSD: kexdh.c,v 1.18 2002/03/18 17:50:31 provos Exp $");
-
-#pragma ident "%Z%%M% %I% %E% SMI"
-
-#include <openssl/crypto.h>
-#include <openssl/bn.h>
-
-#include "xmalloc.h"
-#include "buffer.h"
-#include "bufaux.h"
-#include "key.h"
-#include "kex.h"
-#include "log.h"
-#include "packet.h"
-#include "dh.h"
-#include "ssh2.h"
-
-void
-kexdh_server(Kex *kex)
-{
- BIGNUM *shared_secret = NULL, *dh_client_pub = NULL;
- DH *dh;
- Key *server_host_key;
- u_char *kbuf, *hash, *signature = NULL, *server_host_key_blob = NULL;
- u_int sbloblen, klen, kout;
- u_int slen;
-
- /* generate server DH public key */
- dh = dh_new_group1();
- dh_gen_key(dh, kex->we_need * 8);
-
- debug("expecting SSH2_MSG_KEXDH_INIT");
- packet_read_expect(SSH2_MSG_KEXDH_INIT);
-
- if (kex->load_host_key == NULL)
- fatal("Cannot load hostkey");
- server_host_key = kex->load_host_key(kex->hostkey_type);
- if (server_host_key == NULL)
- fatal("Unsupported hostkey type %d", kex->hostkey_type);
-
- /* key, cert */
- if ((dh_client_pub = BN_new()) == NULL)
- fatal("dh_client_pub == NULL");
- packet_get_bignum2(dh_client_pub);
- packet_check_eom();
-
-#ifdef DEBUG_KEXDH
- fprintf(stderr, "dh_client_pub= ");
- BN_print_fp(stderr, dh_client_pub);
- fprintf(stderr, "\n");
- debug("bits %d", BN_num_bits(dh_client_pub));
-#endif
-
-#ifdef DEBUG_KEXDH
- DHparams_print_fp(stderr, dh);
- fprintf(stderr, "pub= ");
- BN_print_fp(stderr, dh->pub_key);
- fprintf(stderr, "\n");
-#endif
- if (!dh_pub_is_valid(dh, dh_client_pub))
- packet_disconnect("bad client public DH value");
-
- klen = DH_size(dh);
- kbuf = xmalloc(klen);
- kout = DH_compute_key(kbuf, dh_client_pub, dh);
-#ifdef DEBUG_KEXDH
- dump_digest("shared secret", kbuf, kout);
-#endif
- if ((shared_secret = BN_new()) == NULL)
- fatal("kexdh_server: BN_new failed");
- BN_bin2bn(kbuf, kout, shared_secret);
- memset(kbuf, 0, klen);
- xfree(kbuf);
-
- key_to_blob(server_host_key, &server_host_key_blob, &sbloblen);
-
- /* calc H */
- hash = kex_dh_hash(
- kex->client_version_string,
- kex->server_version_string,
- buffer_ptr(&kex->peer), buffer_len(&kex->peer),
- buffer_ptr(&kex->my), buffer_len(&kex->my),
- server_host_key_blob, sbloblen,
- dh_client_pub,
- dh->pub_key,
- shared_secret
- );
- BN_clear_free(dh_client_pub);
-
- /* save session id := H */
- /* XXX hashlen depends on KEX */
- if (kex->session_id == NULL) {
- kex->session_id_len = 20;
- kex->session_id = xmalloc(kex->session_id_len);
- memcpy(kex->session_id, hash, kex->session_id_len);
- }
-
- /* sign H */
- /* XXX hashlen depends on KEX */
- key_sign(server_host_key, &signature, &slen, hash, 20);
-
- /* destroy_sensitive_data(); */
-
- /* send server hostkey, DH pubkey 'f' and singed H */
- packet_start(SSH2_MSG_KEXDH_REPLY);
- packet_put_string(server_host_key_blob, sbloblen);
- packet_put_bignum2(dh->pub_key); /* f */
- packet_put_string(signature, slen);
- packet_send();
-
- xfree(signature);
- xfree(server_host_key_blob);
- /* have keys, free DH */
- DH_free(dh);
-
- kex_derive_keys(kex, hash, shared_secret);
- BN_clear_free(shared_secret);
- kex_finish(kex);
-}
diff --git a/usr/src/cmd/ssh/libssh/common/kexgex.c b/usr/src/cmd/ssh/libssh/common/kexgex.c
deleted file mode 100644
index 3652e1c020..0000000000
--- a/usr/src/cmd/ssh/libssh/common/kexgex.c
+++ /dev/null
@@ -1,100 +0,0 @@
-/*
- * Copyright (c) 2000 Niels Provos. All rights reserved.
- * Copyright (c) 2001 Markus Friedl. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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.
- */
-
-#include "includes.h"
-RCSID("$OpenBSD: kexgex.c,v 1.22 2002/03/24 17:27:03 stevesk Exp $");
-
-#pragma ident "%Z%%M% %I% %E% SMI"
-
-#include <openssl/bn.h>
-
-#include "xmalloc.h"
-#include "buffer.h"
-#include "bufaux.h"
-#include "key.h"
-#include "kex.h"
-#include "log.h"
-#include "packet.h"
-#include "dh.h"
-#include "ssh2.h"
-#include "compat.h"
-
-u_char *
-kexgex_hash(
- char *client_version_string,
- char *server_version_string,
- char *ckexinit, int ckexinitlen,
- char *skexinit, int skexinitlen,
- u_char *serverhostkeyblob, int sbloblen,
- int min, int wantbits, int max, BIGNUM *prime, BIGNUM *gen,
- BIGNUM *client_dh_pub,
- BIGNUM *server_dh_pub,
- BIGNUM *shared_secret)
-{
- Buffer b;
- static u_char digest[EVP_MAX_MD_SIZE];
- const EVP_MD *evp_md = EVP_sha1();
- EVP_MD_CTX md;
-
- buffer_init(&b);
- buffer_put_cstring(&b, client_version_string);
- buffer_put_cstring(&b, server_version_string);
-
- /* kexinit messages: fake header: len+SSH2_MSG_KEXINIT */
- buffer_put_int(&b, ckexinitlen+1);
- buffer_put_char(&b, SSH2_MSG_KEXINIT);
- buffer_append(&b, ckexinit, ckexinitlen);
- buffer_put_int(&b, skexinitlen+1);
- buffer_put_char(&b, SSH2_MSG_KEXINIT);
- buffer_append(&b, skexinit, skexinitlen);
-
- buffer_put_string(&b, serverhostkeyblob, sbloblen);
- if (min == -1 || max == -1)
- buffer_put_int(&b, wantbits);
- else {
- buffer_put_int(&b, min);
- buffer_put_int(&b, wantbits);
- buffer_put_int(&b, max);
- }
- buffer_put_bignum2(&b, prime);
- buffer_put_bignum2(&b, gen);
- buffer_put_bignum2(&b, client_dh_pub);
- buffer_put_bignum2(&b, server_dh_pub);
- buffer_put_bignum2(&b, shared_secret);
-
-#ifdef DEBUG_KEXDH
- buffer_dump(&b);
-#endif
- EVP_DigestInit(&md, evp_md);
- EVP_DigestUpdate(&md, buffer_ptr(&b), buffer_len(&b));
- EVP_DigestFinal(&md, digest, NULL);
-
- buffer_free(&b);
-
-#ifdef DEBUG_KEXDH
- dump_digest("hash", digest, EVP_MD_size(evp_md));
-#endif
- return digest;
-}
diff --git a/usr/src/cmd/ssh/libssh/common/kexgexc.c b/usr/src/cmd/ssh/libssh/common/kexgexc.c
deleted file mode 100644
index 5fddebaed9..0000000000
--- a/usr/src/cmd/ssh/libssh/common/kexgexc.c
+++ /dev/null
@@ -1,195 +0,0 @@
-/*
- * Copyright (c) 2000 Niels Provos. All rights reserved.
- * Copyright (c) 2001 Markus Friedl. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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.
- */
-
-#include "includes.h"
-RCSID("$OpenBSD: kexgex.c,v 1.22 2002/03/24 17:27:03 stevesk Exp $");
-
-#pragma ident "%Z%%M% %I% %E% SMI"
-
-#include <openssl/bn.h>
-
-#include "xmalloc.h"
-#include "buffer.h"
-#include "bufaux.h"
-#include "key.h"
-#include "kex.h"
-#include "log.h"
-#include "packet.h"
-#include "dh.h"
-#include "ssh2.h"
-#include "compat.h"
-
-void
-kexgex_client(Kex *kex)
-{
- BIGNUM *dh_server_pub = NULL, *shared_secret = NULL;
- BIGNUM *p = NULL, *g = NULL;
- Key *server_host_key;
- u_char *kbuf, *hash, *signature = NULL, *server_host_key_blob = NULL;
- u_int klen, kout, slen, sbloblen;
- int min, max, nbits;
- DH *dh;
-
- nbits = dh_estimate(kex->we_need * 8);
-
- if (datafellows & SSH_OLD_DHGEX) {
- debug("SSH2_MSG_KEX_DH_GEX_REQUEST_OLD sent");
-
- /* Old GEX request */
- packet_start(SSH2_MSG_KEX_DH_GEX_REQUEST_OLD);
- packet_put_int(nbits);
- min = DH_GRP_MIN;
- max = DH_GRP_MAX;
- } else {
- debug("SSH2_MSG_KEX_DH_GEX_REQUEST sent");
-
- /* New GEX request */
- min = DH_GRP_MIN;
- max = DH_GRP_MAX;
- packet_start(SSH2_MSG_KEX_DH_GEX_REQUEST);
- packet_put_int(min);
- packet_put_int(nbits);
- packet_put_int(max);
- }
-#ifdef DEBUG_KEXDH
- fprintf(stderr, "\nmin = %d, nbits = %d, max = %d\n",
- min, nbits, max);
-#endif
- packet_send();
-
- debug("expecting SSH2_MSG_KEX_DH_GEX_GROUP");
- packet_read_expect(SSH2_MSG_KEX_DH_GEX_GROUP);
-
- if ((p = BN_new()) == NULL)
- fatal("BN_new");
- packet_get_bignum2(p);
- if ((g = BN_new()) == NULL)
- fatal("BN_new");
- packet_get_bignum2(g);
- packet_check_eom();
-
- if (BN_num_bits(p) < min || BN_num_bits(p) > max)
- fatal("DH_GEX group out of range: %d !< %d !< %d",
- min, BN_num_bits(p), max);
-
- dh = dh_new_group(g, p);
- dh_gen_key(dh, kex->we_need * 8);
-
-#ifdef DEBUG_KEXDH
- DHparams_print_fp(stderr, dh);
- fprintf(stderr, "pub= ");
- BN_print_fp(stderr, dh->pub_key);
- fprintf(stderr, "\n");
-#endif
-
- debug("SSH2_MSG_KEX_DH_GEX_INIT sent");
- /* generate and send 'e', client DH public key */
- packet_start(SSH2_MSG_KEX_DH_GEX_INIT);
- packet_put_bignum2(dh->pub_key);
- packet_send();
-
- debug("expecting SSH2_MSG_KEX_DH_GEX_REPLY");
- packet_read_expect(SSH2_MSG_KEX_DH_GEX_REPLY);
-
- /* key, cert */
- server_host_key_blob = packet_get_string(&sbloblen);
- server_host_key = key_from_blob(server_host_key_blob, sbloblen);
- if (server_host_key == NULL)
- fatal("cannot decode server_host_key_blob");
- if (server_host_key->type != kex->hostkey_type)
- fatal("type mismatch for decoded server_host_key_blob");
- if (kex->verify_host_key == NULL)
- fatal("cannot verify server_host_key");
- if (kex->verify_host_key(server_host_key) == -1)
- fatal("server_host_key verification failed");
-
- /* DH paramter f, server public DH key */
- if ((dh_server_pub = BN_new()) == NULL)
- fatal("dh_server_pub == NULL");
- packet_get_bignum2(dh_server_pub);
-
-#ifdef DEBUG_KEXDH
- fprintf(stderr, "dh_server_pub= ");
- BN_print_fp(stderr, dh_server_pub);
- fprintf(stderr, "\n");
- debug("bits %d", BN_num_bits(dh_server_pub));
-#endif
-
- /* signed H */
- signature = packet_get_string(&slen);
- packet_check_eom();
-
- if (!dh_pub_is_valid(dh, dh_server_pub))
- packet_disconnect("bad server public DH value");
-
- klen = DH_size(dh);
- kbuf = xmalloc(klen);
- kout = DH_compute_key(kbuf, dh_server_pub, dh);
-#ifdef DEBUG_KEXDH
- dump_digest("shared secret", kbuf, kout);
-#endif
- if ((shared_secret = BN_new()) == NULL)
- fatal("kexgex_client: BN_new failed");
- BN_bin2bn(kbuf, kout, shared_secret);
- memset(kbuf, 0, klen);
- xfree(kbuf);
-
- if (datafellows & SSH_OLD_DHGEX)
- min = max = -1;
-
- /* calc and verify H */
- hash = kexgex_hash(
- kex->client_version_string,
- kex->server_version_string,
- buffer_ptr(&kex->my), buffer_len(&kex->my),
- buffer_ptr(&kex->peer), buffer_len(&kex->peer),
- server_host_key_blob, sbloblen,
- min, nbits, max,
- dh->p, dh->g,
- dh->pub_key,
- dh_server_pub,
- shared_secret
- );
- /* have keys, free DH */
- DH_free(dh);
- xfree(server_host_key_blob);
- BN_clear_free(dh_server_pub);
-
- if (key_verify(server_host_key, signature, slen, hash, 20) != 1)
- fatal("key_verify failed for server_host_key");
- key_free(server_host_key);
- xfree(signature);
-
- /* save session id */
- if (kex->session_id == NULL) {
- kex->session_id_len = 20;
- kex->session_id = xmalloc(kex->session_id_len);
- memcpy(kex->session_id, hash, kex->session_id_len);
- }
- kex_derive_keys(kex, hash, shared_secret);
- BN_clear_free(shared_secret);
-
- kex_finish(kex);
-}
diff --git a/usr/src/cmd/ssh/libssh/common/kexgexs.c b/usr/src/cmd/ssh/libssh/common/kexgexs.c
deleted file mode 100644
index b0bd4e3272..0000000000
--- a/usr/src/cmd/ssh/libssh/common/kexgexs.c
+++ /dev/null
@@ -1,191 +0,0 @@
-/*
- * Copyright (c) 2000 Niels Provos. All rights reserved.
- * Copyright (c) 2001 Markus Friedl. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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.
- */
-
-#include "includes.h"
-RCSID("$OpenBSD: kexgex.c,v 1.22 2002/03/24 17:27:03 stevesk Exp $");
-
-#pragma ident "%Z%%M% %I% %E% SMI"
-
-#include <openssl/bn.h>
-
-#include "xmalloc.h"
-#include "buffer.h"
-#include "bufaux.h"
-#include "key.h"
-#include "kex.h"
-#include "log.h"
-#include "packet.h"
-#include "dh.h"
-#include "ssh2.h"
-#include "compat.h"
-
-void
-kexgex_server(Kex *kex)
-{
- BIGNUM *shared_secret = NULL, *dh_client_pub = NULL;
- Key *server_host_key;
- DH *dh;
- u_char *kbuf, *hash, *signature = NULL, *server_host_key_blob = NULL;
- u_int sbloblen, klen, kout, slen;
- int min = -1, max = -1, nbits = -1, type;
-
- if (kex->load_host_key == NULL)
- fatal("Cannot load hostkey");
- server_host_key = kex->load_host_key(kex->hostkey_type);
- if (server_host_key == NULL)
- fatal("Unsupported hostkey type %d", kex->hostkey_type);
-
- type = packet_read();
- switch (type) {
- case SSH2_MSG_KEX_DH_GEX_REQUEST:
- debug("SSH2_MSG_KEX_DH_GEX_REQUEST received");
- min = packet_get_int();
- nbits = packet_get_int();
- max = packet_get_int();
- min = MAX(DH_GRP_MIN, min);
- max = MIN(DH_GRP_MAX, max);
- break;
- case SSH2_MSG_KEX_DH_GEX_REQUEST_OLD:
- debug("SSH2_MSG_KEX_DH_GEX_REQUEST_OLD received");
- nbits = packet_get_int();
- min = DH_GRP_MIN;
- max = DH_GRP_MAX;
- /* unused for old GEX */
- break;
- default:
- fatal("protocol error during kex, no DH_GEX_REQUEST: %d", type);
- }
- packet_check_eom();
-
- if (max < min || nbits < min || max < nbits)
- fatal("DH_GEX_REQUEST, bad parameters: %d !< %d !< %d",
- min, nbits, max);
-
- /* Contact privileged parent */
- dh = choose_dh(min, nbits, max);
- if (dh == NULL)
- packet_disconnect("Protocol error: no matching DH grp found");
-
- debug("SSH2_MSG_KEX_DH_GEX_GROUP sent");
- packet_start(SSH2_MSG_KEX_DH_GEX_GROUP);
- packet_put_bignum2(dh->p);
- packet_put_bignum2(dh->g);
- packet_send();
-
- /* flush */
- packet_write_wait();
-
- /* Compute our exchange value in parallel with the client */
- dh_gen_key(dh, kex->we_need * 8);
-
- debug("expecting SSH2_MSG_KEX_DH_GEX_INIT");
- packet_read_expect(SSH2_MSG_KEX_DH_GEX_INIT);
-
- /* key, cert */
- if ((dh_client_pub = BN_new()) == NULL)
- fatal("dh_client_pub == NULL");
- packet_get_bignum2(dh_client_pub);
- packet_check_eom();
-
-#ifdef DEBUG_KEXDH
- fprintf(stderr, "dh_client_pub= ");
- BN_print_fp(stderr, dh_client_pub);
- fprintf(stderr, "\n");
- debug("bits %d", BN_num_bits(dh_client_pub));
-#endif
-
-#ifdef DEBUG_KEXDH
- DHparams_print_fp(stderr, dh);
- fprintf(stderr, "pub= ");
- BN_print_fp(stderr, dh->pub_key);
- fprintf(stderr, "\n");
-#endif
- if (!dh_pub_is_valid(dh, dh_client_pub))
- packet_disconnect("bad client public DH value");
-
- klen = DH_size(dh);
- kbuf = xmalloc(klen);
- kout = DH_compute_key(kbuf, dh_client_pub, dh);
-#ifdef DEBUG_KEXDH
- dump_digest("shared secret", kbuf, kout);
-#endif
- if ((shared_secret = BN_new()) == NULL)
- fatal("kexgex_server: BN_new failed");
- BN_bin2bn(kbuf, kout, shared_secret);
- memset(kbuf, 0, klen);
- xfree(kbuf);
-
- key_to_blob(server_host_key, &server_host_key_blob, &sbloblen);
-
- if (type == SSH2_MSG_KEX_DH_GEX_REQUEST_OLD)
- min = max = -1;
-
- /* calc H */ /* XXX depends on 'kex' */
- hash = kexgex_hash(
- kex->client_version_string,
- kex->server_version_string,
- buffer_ptr(&kex->peer), buffer_len(&kex->peer),
- buffer_ptr(&kex->my), buffer_len(&kex->my),
- server_host_key_blob, sbloblen,
- min, nbits, max,
- dh->p, dh->g,
- dh_client_pub,
- dh->pub_key,
- shared_secret
- );
- BN_clear_free(dh_client_pub);
-
- /* save session id := H */
- /* XXX hashlen depends on KEX */
- if (kex->session_id == NULL) {
- kex->session_id_len = 20;
- kex->session_id = xmalloc(kex->session_id_len);
- memcpy(kex->session_id, hash, kex->session_id_len);
- }
-
- /* sign H */
- /* XXX hashlen depends on KEX */
- key_sign(server_host_key, &signature, &slen, hash, 20);
-
- /* destroy_sensitive_data(); */
-
- /* send server hostkey, DH pubkey 'f' and singed H */
- debug("SSH2_MSG_KEX_DH_GEX_REPLY sent");
- packet_start(SSH2_MSG_KEX_DH_GEX_REPLY);
- packet_put_string(server_host_key_blob, sbloblen);
- packet_put_bignum2(dh->pub_key); /* f */
- packet_put_string(signature, slen);
- packet_send();
-
- xfree(signature);
- xfree(server_host_key_blob);
- /* have keys, free DH */
- DH_free(dh);
-
- kex_derive_keys(kex, hash, shared_secret);
- BN_clear_free(shared_secret);
-
- kex_finish(kex);
-}
diff --git a/usr/src/cmd/ssh/libssh/common/kexgssc.c b/usr/src/cmd/ssh/libssh/common/kexgssc.c
deleted file mode 100644
index 60c91ed57b..0000000000
--- a/usr/src/cmd/ssh/libssh/common/kexgssc.c
+++ /dev/null
@@ -1,325 +0,0 @@
-/*
- * Copyright (c) 2001-2003 Simon Wilkinson. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR `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.
- */
-/*
- * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
- */
-
-#pragma ident "%Z%%M% %I% %E% SMI"
-
-
-#include "includes.h"
-
-#ifdef GSSAPI
-
-#include <openssl/crypto.h>
-#include <openssl/bn.h>
-
-#include "xmalloc.h"
-#include "buffer.h"
-#include "bufaux.h"
-#include "kex.h"
-#include "log.h"
-#include "packet.h"
-#include "dh.h"
-#include "canohost.h"
-#include "ssh2.h"
-#include "ssh-gss.h"
-
-extern char *xxx_host;
-
-Gssctxt *xxx_gssctxt;
-
-static void kexgss_verbose_cleanup(void *arg);
-
-void
-kexgss_client(Kex *kex)
-{
- gss_buffer_desc gssbuf, send_tok, recv_tok, msg_tok;
- gss_buffer_t token_ptr;
- gss_OID mech = GSS_C_NULL_OID;
- Gssctxt *ctxt = NULL;
- OM_uint32 maj_status, min_status, smaj_status, smin_status;
- unsigned int klen, kout;
- DH *dh;
- BIGNUM *dh_server_pub = 0;
- BIGNUM *shared_secret = 0;
- Key *server_host_key = NULL;
- unsigned char *kbuf;
- unsigned char *hash;
- unsigned char *server_host_key_blob = NULL;
- char *msg, *lang;
- int type = 0;
- int first = 1;
- uint_t sbloblen = 0;
- uint_t strlen;
-
- /* Map the negotiated kex name to a mech OID */
- ssh_gssapi_oid_of_kexname(kex->name, &mech);
- if (mech == GSS_C_NULL_OID)
- fatal("Couldn't match the negotiated GSS key exchange");
-
- ssh_gssapi_build_ctx(&ctxt, 1, mech);
-
- /* This code should match that in ssh_dh1_client */
-
- /* Step 1 - e is dh->pub_key */
- dh = dh_new_group1();
- dh_gen_key(dh, kex->we_need * 8);
-
- /* This is f, we initialise it now to make life easier */
- dh_server_pub = BN_new();
- if (dh_server_pub == NULL) {
- fatal("dh_server_pub == NULL");
- }
-
- token_ptr = GSS_C_NO_BUFFER;
-
- recv_tok.value = NULL;
- recv_tok.length = 0;
-
- do {
- debug("Calling gss_init_sec_context");
-
- maj_status = ssh_gssapi_init_ctx(ctxt, xxx_host,
- kex->options.gss_deleg_creds, token_ptr, &send_tok);
-
- if (GSS_ERROR(maj_status)) {
- ssh_gssapi_error(ctxt, "performing GSS-API protected "
- "SSHv2 key exchange");
- (void) gss_release_buffer(&min_status, &send_tok);
- packet_disconnect("A GSS-API error occurred during "
- "GSS-API protected SSHv2 key exchange\n");
- }
-
- /* If we've got an old receive buffer get rid of it */
- if (token_ptr != GSS_C_NO_BUFFER) {
- /* We allocated recv_tok */
- xfree(recv_tok.value);
- recv_tok.value = NULL;
- recv_tok.length = 0;
- token_ptr = GSS_C_NO_BUFFER;
- }
-
- if (maj_status == GSS_S_COMPLETE) {
- /* If mutual state flag is not true, kex fails */
- if (!(ctxt->flags & GSS_C_MUTUAL_FLAG)) {
- fatal("Mutual authentication failed");
- }
- /* If integ avail flag is not true kex fails */
- if (!(ctxt->flags & GSS_C_INTEG_FLAG)) {
- fatal("Integrity check failed");
- }
- }
-
- /*
- * If we have data to send, then the last message that we
- * received cannot have been a 'complete'.
- */
- if (send_tok.length != 0) {
- if (first) {
- packet_start(SSH2_MSG_KEXGSS_INIT);
- packet_put_string(send_tok.value,
- send_tok.length);
- packet_put_bignum2(dh->pub_key);
- first = 0;
- } else {
- packet_start(SSH2_MSG_KEXGSS_CONTINUE);
- packet_put_string(send_tok.value,
- send_tok.length);
- }
- (void) gss_release_buffer(&min_status, &send_tok);
- packet_send();
- packet_write_wait();
-
-
- /*
- * If we've sent them data, they'd better be polite and
- * reply.
- */
-
-next_packet:
- /*
- * We need to catch connection closing w/o error
- * tokens or messages so we can tell the user
- * _something_ more useful than "Connection
- * closed by ..."
- *
- * We use a fatal cleanup function as that's
- * all, really, that we can do for now.
- */
- fatal_add_cleanup(kexgss_verbose_cleanup, NULL);
- type = packet_read();
- fatal_remove_cleanup(kexgss_verbose_cleanup, NULL);
- switch (type) {
- case SSH2_MSG_KEXGSS_HOSTKEY:
- debug("Received KEXGSS_HOSTKEY");
- server_host_key_blob =
- packet_get_string(&sbloblen);
- server_host_key =
- key_from_blob(server_host_key_blob,
- sbloblen);
- goto next_packet; /* there MUSt be another */
- break;
- case SSH2_MSG_KEXGSS_CONTINUE:
- debug("Received GSSAPI_CONTINUE");
- if (maj_status == GSS_S_COMPLETE)
- packet_disconnect("Protocol error: "
- "received GSS-API context token "
- "though the context was already "
- "established");
- recv_tok.value = packet_get_string(&strlen);
- recv_tok.length = strlen; /* u_int vs. size_t */
- break;
- case SSH2_MSG_KEXGSS_COMPLETE:
- debug("Received GSSAPI_COMPLETE");
- packet_get_bignum2(dh_server_pub);
- msg_tok.value = packet_get_string(&strlen);
- msg_tok.length = strlen; /* u_int vs. size_t */
-
- /* Is there a token included? */
- if (packet_get_char()) {
- recv_tok.value =
- packet_get_string(&strlen);
- /* u_int/size_t */
- recv_tok.length = strlen;
- }
- if (recv_tok.length > 0 &&
- maj_status == GSS_S_COMPLETE) {
- packet_disconnect("Protocol error: "
- "received GSS-API context token "
- "though the context was already "
- "established");
- } else if (recv_tok.length == 0 &&
- maj_status == GSS_S_CONTINUE_NEEDED) {
- /* No token included */
- packet_disconnect("Protocol error: "
- "did not receive expected "
- "GSS-API context token");
- }
- break;
- case SSH2_MSG_KEXGSS_ERROR:
- smaj_status = packet_get_int();
- smin_status = packet_get_int();
- msg = packet_get_string(NULL);
- lang = packet_get_string(NULL);
- xfree(lang);
- error("Server had a GSS-API error; the "
- "connection will close (%d/%d):\n%s",
- smaj_status, smin_status, msg);
- error("Use the GssKeyEx option to disable "
- "GSS-API key exchange and try again.");
- packet_disconnect("The server had a GSS-API "
- "error during GSS-API protected SSHv2 "
- "key exchange\n");
- break;
- default:
- packet_disconnect("Protocol error: "
- "didn't expect packet type %d", type);
- }
- if (recv_tok.value)
- token_ptr = &recv_tok;
- } else {
- /* No data, and not complete */
- if (maj_status != GSS_S_COMPLETE) {
- fatal("Not complete, and no token output");
- }
- }
- } while (maj_status == GSS_S_CONTINUE_NEEDED);
-
- /*
- * We _must_ have received a COMPLETE message in reply from the
- * server, which will have set dh_server_pub and msg_tok.
- */
- if (type != SSH2_MSG_KEXGSS_COMPLETE)
- fatal("Expected SSH2_MSG_KEXGSS_COMPLETE never arrived");
- if (maj_status != GSS_S_COMPLETE)
- fatal("Internal error in GSS-API protected SSHv2 key exchange");
-
- /* Check f in range [1, p-1] */
- if (!dh_pub_is_valid(dh, dh_server_pub))
- packet_disconnect("bad server public DH value");
-
- /* compute K=f^x mod p */
- klen = DH_size(dh);
- kbuf = xmalloc(klen);
- kout = DH_compute_key(kbuf, dh_server_pub, dh);
-
- shared_secret = BN_new();
- BN_bin2bn(kbuf, kout, shared_secret);
- (void) memset(kbuf, 0, klen);
- xfree(kbuf);
-
- /* The GSS hash is identical to the DH one */
- hash = kex_dh_hash(
- kex->client_version_string,
- kex->server_version_string,
- buffer_ptr(&kex->my), buffer_len(&kex->my),
- buffer_ptr(&kex->peer), buffer_len(&kex->peer),
- server_host_key_blob, sbloblen, /* server host key */
- dh->pub_key, /* e */
- dh_server_pub, /* f */
- shared_secret); /* K */
-
- gssbuf.value = hash;
- gssbuf.length = 20;
-
- /* Verify that H matches the token we just got. */
- if ((maj_status = gss_verify_mic(&min_status, ctxt->context, &gssbuf,
- &msg_tok, NULL))) {
- packet_disconnect("Hash's MIC didn't verify");
- }
-
- if (server_host_key && kex->accept_host_key != NULL)
- (void) kex->accept_host_key(server_host_key);
-
- DH_free(dh);
-
- xxx_gssctxt = ctxt; /* for gss keyex w/ mic userauth */
-
- /* save session id */
- if (kex->session_id == NULL) {
- kex->session_id_len = 20;
- kex->session_id = xmalloc(kex->session_id_len);
- (void) memcpy(kex->session_id, hash, kex->session_id_len);
- }
-
- kex_derive_keys(kex, hash, shared_secret);
- BN_clear_free(shared_secret);
- kex_finish(kex);
-}
-
-/* ARGSUSED */
-static
-void
-kexgss_verbose_cleanup(void *arg)
-{
- error("The GSS-API protected key exchange has failed without "
- "indication\nfrom the server, possibly due to misconfiguration "
- "of the server.");
- error("Use the GssKeyEx option to disable GSS-API key exchange "
- "and try again.");
-}
-
-#endif /* GSSAPI */
diff --git a/usr/src/cmd/ssh/libssh/common/kexgsss.c b/usr/src/cmd/ssh/libssh/common/kexgsss.c
deleted file mode 100644
index 9ee8b630bb..0000000000
--- a/usr/src/cmd/ssh/libssh/common/kexgsss.c
+++ /dev/null
@@ -1,252 +0,0 @@
-/*
- * Copyright (c) 2001-2003 Simon Wilkinson. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR `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.
- */
-/*
- * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
- */
-
-#pragma ident "%Z%%M% %I% %E% SMI"
-
-#include "includes.h"
-
-#ifdef GSSAPI
-
-#include <openssl/crypto.h>
-#include <openssl/bn.h>
-
-#include "xmalloc.h"
-#include "buffer.h"
-#include "bufaux.h"
-#include "compat.h"
-#include "kex.h"
-#include "log.h"
-#include "packet.h"
-#include "dh.h"
-#include "ssh2.h"
-#include "ssh-gss.h"
-#include "auth.h"
-
-Gssctxt *xxx_gssctxt;
-extern Authctxt *x_authctxt;
-
-static void kex_gss_send_error(Gssctxt *ctxt);
-
-void
-kexgss_server(Kex *kex)
-{
- OM_uint32 maj_status, min_status;
- gss_buffer_desc gssbuf, send_tok, recv_tok, msg_tok;
- Gssctxt *ctxt = NULL;
- unsigned int klen, kout;
- unsigned int sbloblen = 0;
- unsigned char *kbuf, *hash;
- unsigned char *server_host_key_blob = NULL;
- DH *dh;
- Key *server_host_key = NULL;
- BIGNUM *shared_secret = NULL;
- BIGNUM *dh_client_pub = NULL;
- int type = 0;
- uint_t slen;
- gss_OID oid;
-
- /*
- * Load host key to advertise in a SSH_MSG_KEXGSS_HOSTKEY packet
- * -- unlike KEX_DH/KEX_GEX no host key, no problem since it's
- * the GSS-API that provides for server host authentication.
- */
- if (kex->load_host_key != NULL &&
- !(datafellows & SSH_BUG_GSSKEX_HOSTKEY))
- server_host_key = kex->load_host_key(kex->hostkey_type);
- if (server_host_key != NULL)
- key_to_blob(server_host_key, &server_host_key_blob, &sbloblen);
-
-
- /* Initialise GSSAPI */
-
- ssh_gssapi_oid_of_kexname(kex->name, &oid);
- if (oid == GSS_C_NULL_OID) {
- fatal("Couldn't match the negotiated GSS key exchange");
- }
-
- ssh_gssapi_build_ctx(&xxx_gssctxt, 0, oid);
-
- ctxt = xxx_gssctxt;
-
- do {
- debug("Wait SSH2_MSG_GSSAPI_INIT");
- type = packet_read();
- switch (type) {
- case SSH2_MSG_KEXGSS_INIT:
- if (dh_client_pub != NULL)
- fatal("Received KEXGSS_INIT after "
- "initialising");
- recv_tok.value = packet_get_string(&slen);
- recv_tok.length = slen; /* int vs. size_t */
-
- dh_client_pub = BN_new();
-
- if (dh_client_pub == NULL)
- fatal("dh_client_pub == NULL");
- packet_get_bignum2(dh_client_pub);
-
- /* Send SSH_MSG_KEXGSS_HOSTKEY here, if we want */
- if (sbloblen) {
- packet_start(SSH2_MSG_KEXGSS_HOSTKEY);
- packet_put_string(server_host_key_blob,
- sbloblen);
- packet_send();
- packet_write_wait();
- }
- break;
- case SSH2_MSG_KEXGSS_CONTINUE:
- recv_tok.value = packet_get_string(&slen);
- recv_tok.length = slen; /* int vs. size_t */
- break;
- default:
- packet_disconnect("Protocol error: didn't expect "
- "packet type %d", type);
- }
-
- maj_status = ssh_gssapi_accept_ctx(ctxt, &recv_tok, &send_tok);
-
- xfree(recv_tok.value); /* We allocated this, not gss */
-
- if (dh_client_pub == NULL)
- fatal("No client public key");
-
- if (maj_status == GSS_S_CONTINUE_NEEDED) {
- debug("Sending GSSAPI_CONTINUE");
- packet_start(SSH2_MSG_KEXGSS_CONTINUE);
- packet_put_string(send_tok.value, send_tok.length);
- packet_send();
- packet_write_wait();
- (void) gss_release_buffer(&min_status, &send_tok);
- }
- } while (maj_status == GSS_S_CONTINUE_NEEDED);
-
- if (GSS_ERROR(maj_status)) {
- kex_gss_send_error(ctxt);
- if (send_tok.length > 0) {
- packet_start(SSH2_MSG_KEXGSS_CONTINUE);
- packet_put_string(send_tok.value, send_tok.length);
- packet_send();
- packet_write_wait();
- (void) gss_release_buffer(&min_status, &send_tok);
- }
- fatal("accept_ctx died");
- }
-
- debug("gss_complete");
- if (!(ctxt->flags & GSS_C_MUTUAL_FLAG))
- fatal("Mutual authentication flag wasn't set");
-
- if (!(ctxt->flags & GSS_C_INTEG_FLAG))
- fatal("Integrity flag wasn't set");
-
- dh = dh_new_group1();
- dh_gen_key(dh, kex->we_need * 8);
-
- if (!dh_pub_is_valid(dh, dh_client_pub))
- packet_disconnect("bad client public DH value");
-
- klen = DH_size(dh);
- kbuf = xmalloc(klen);
- kout = DH_compute_key(kbuf, dh_client_pub, dh);
-
- shared_secret = BN_new();
- BN_bin2bn(kbuf, kout, shared_secret);
- (void) memset(kbuf, 0, klen);
- xfree(kbuf);
-
- /* The GSSAPI hash is identical to the Diffie Helman one */
- hash = kex_dh_hash(
- kex->client_version_string,
- kex->server_version_string,
- buffer_ptr(&kex->peer), buffer_len(&kex->peer),
- buffer_ptr(&kex->my), buffer_len(&kex->my),
- server_host_key_blob, sbloblen,
- dh_client_pub,
- dh->pub_key,
- shared_secret);
-
- BN_free(dh_client_pub);
-
- if (kex->session_id == NULL) {
- kex->session_id_len = 20;
- kex->session_id = xmalloc(kex->session_id_len);
- (void) memcpy(kex->session_id, hash, kex->session_id_len);
- } else if (x_authctxt != NULL && x_authctxt->success) {
- ssh_gssapi_storecreds(ctxt, x_authctxt);
- }
-
- /* Should fix kex_dh_hash to output hash length */
- gssbuf.length = 20; /* yes, it's always 20 (SHA-1) */
- gssbuf.value = hash; /* and it's static constant storage */
-
- if (GSS_ERROR(ssh_gssapi_get_mic(ctxt, &gssbuf, &msg_tok))) {
- kex_gss_send_error(ctxt);
- fatal("Couldn't get MIC");
- }
-
- packet_start(SSH2_MSG_KEXGSS_COMPLETE);
- packet_put_bignum2(dh->pub_key);
- packet_put_string((char *)msg_tok.value, msg_tok.length);
- (void) gss_release_buffer(&min_status, &msg_tok);
-
- if (send_tok.length != 0) {
- packet_put_char(1); /* true */
- packet_put_string((char *)send_tok.value, send_tok.length);
- (void) gss_release_buffer(&min_status, &send_tok);
- } else {
- packet_put_char(0); /* false */
- }
- packet_send();
- packet_write_wait();
-
- DH_free(dh);
-
- kex_derive_keys(kex, hash, shared_secret);
- BN_clear_free(shared_secret);
- kex_finish(kex);
-}
-
-static void
-kex_gss_send_error(Gssctxt *ctxt) {
- char *errstr;
- OM_uint32 maj, min;
-
- errstr = ssh_gssapi_last_error(ctxt, &maj, &min);
- if (errstr) {
- packet_start(SSH2_MSG_KEXGSS_ERROR);
- packet_put_int(maj);
- packet_put_int(min);
- packet_put_cstring(errstr);
- packet_put_cstring("");
- packet_send();
- packet_write_wait();
- /* XXX - We should probably log the error locally here */
- xfree(errstr);
- }
-}
-#endif /* GSSAPI */
diff --git a/usr/src/cmd/ssh/libssh/common/key.c b/usr/src/cmd/ssh/libssh/common/key.c
deleted file mode 100644
index f648d3b640..0000000000
--- a/usr/src/cmd/ssh/libssh/common/key.c
+++ /dev/null
@@ -1,876 +0,0 @@
-/*
- * read_bignum():
- * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
- *
- * As far as I am concerned, the code I have written for this software
- * can be used freely for any purpose. Any derived versions of this
- * software must be clearly marked as such, and if the derived work is
- * incompatible with the protocol description in the RFC file, it must be
- * called by a name other than "ssh" or "Secure Shell".
- *
- *
- * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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.
- */
-#include "includes.h"
-RCSID("$OpenBSD: key.c,v 1.49 2002/09/09 14:54:14 markus Exp $");
-
-#pragma ident "%Z%%M% %I% %E% SMI"
-
-#include <openssl/evp.h>
-
-#include "xmalloc.h"
-#include "key.h"
-#include "rsa.h"
-#include "ssh-dss.h"
-#include "ssh-rsa.h"
-#include "uuencode.h"
-#include "buffer.h"
-#include "bufaux.h"
-#include "log.h"
-
-Key *
-key_new(int type)
-{
- Key *k;
- RSA *rsa;
- DSA *dsa;
- k = xmalloc(sizeof(*k));
- k->type = type;
- k->flags = 0;
- k->dsa = NULL;
- k->rsa = NULL;
- switch (k->type) {
- case KEY_RSA1:
- case KEY_RSA:
- if ((rsa = RSA_new()) == NULL)
- fatal("key_new: RSA_new failed");
- if ((rsa->n = BN_new()) == NULL)
- fatal("key_new: BN_new failed");
- if ((rsa->e = BN_new()) == NULL)
- fatal("key_new: BN_new failed");
- k->rsa = rsa;
- break;
- case KEY_DSA:
- if ((dsa = DSA_new()) == NULL)
- fatal("key_new: DSA_new failed");
- if ((dsa->p = BN_new()) == NULL)
- fatal("key_new: BN_new failed");
- if ((dsa->q = BN_new()) == NULL)
- fatal("key_new: BN_new failed");
- if ((dsa->g = BN_new()) == NULL)
- fatal("key_new: BN_new failed");
- if ((dsa->pub_key = BN_new()) == NULL)
- fatal("key_new: BN_new failed");
- k->dsa = dsa;
- break;
- case KEY_UNSPEC:
- break;
- default:
- fatal("key_new: bad key type %d", k->type);
- break;
- }
- return k;
-}
-
-Key *
-key_new_private(int type)
-{
- Key *k = key_new(type);
- switch (k->type) {
- case KEY_RSA1:
- case KEY_RSA:
- if ((k->rsa->d = BN_new()) == NULL)
- fatal("key_new_private: BN_new failed");
- if ((k->rsa->iqmp = BN_new()) == NULL)
- fatal("key_new_private: BN_new failed");
- if ((k->rsa->q = BN_new()) == NULL)
- fatal("key_new_private: BN_new failed");
- if ((k->rsa->p = BN_new()) == NULL)
- fatal("key_new_private: BN_new failed");
- if ((k->rsa->dmq1 = BN_new()) == NULL)
- fatal("key_new_private: BN_new failed");
- if ((k->rsa->dmp1 = BN_new()) == NULL)
- fatal("key_new_private: BN_new failed");
- break;
- case KEY_DSA:
- if ((k->dsa->priv_key = BN_new()) == NULL)
- fatal("key_new_private: BN_new failed");
- break;
- case KEY_UNSPEC:
- break;
- default:
- break;
- }
- return k;
-}
-
-void
-key_free(Key *k)
-{
- switch (k->type) {
- case KEY_RSA1:
- case KEY_RSA:
- if (k->rsa != NULL)
- RSA_free(k->rsa);
- k->rsa = NULL;
- break;
- case KEY_DSA:
- if (k->dsa != NULL)
- DSA_free(k->dsa);
- k->dsa = NULL;
- break;
- case KEY_UNSPEC:
- break;
- default:
- fatal("key_free: bad key type %d", k->type);
- break;
- }
- xfree(k);
-}
-int
-key_equal(const Key *a, const Key *b)
-{
- if (a == NULL || b == NULL || a->type != b->type)
- return 0;
- switch (a->type) {
- case KEY_RSA1:
- case KEY_RSA:
- return a->rsa != NULL && b->rsa != NULL &&
- BN_cmp(a->rsa->e, b->rsa->e) == 0 &&
- BN_cmp(a->rsa->n, b->rsa->n) == 0;
- break;
- case KEY_DSA:
- return a->dsa != NULL && b->dsa != NULL &&
- BN_cmp(a->dsa->p, b->dsa->p) == 0 &&
- BN_cmp(a->dsa->q, b->dsa->q) == 0 &&
- BN_cmp(a->dsa->g, b->dsa->g) == 0 &&
- BN_cmp(a->dsa->pub_key, b->dsa->pub_key) == 0;
- break;
- default:
- fatal("key_equal: bad key type %d", a->type);
- break;
- }
- return 0;
-}
-
-static u_char *
-key_fingerprint_raw(Key *k, enum fp_type dgst_type, u_int *dgst_raw_length)
-{
- const EVP_MD *md = NULL;
- EVP_MD_CTX ctx;
- u_char *blob = NULL;
- u_char *retval = NULL;
- u_int len = 0;
- int nlen, elen;
-
- *dgst_raw_length = 0;
-
- switch (dgst_type) {
- case SSH_FP_MD5:
- md = EVP_md5();
- break;
- case SSH_FP_SHA1:
- md = EVP_sha1();
- break;
- default:
- fatal("key_fingerprint_raw: bad digest type %d",
- dgst_type);
- }
- switch (k->type) {
- case KEY_RSA1:
- nlen = BN_num_bytes(k->rsa->n);
- elen = BN_num_bytes(k->rsa->e);
- len = nlen + elen;
- blob = xmalloc(len);
- BN_bn2bin(k->rsa->n, blob);
- BN_bn2bin(k->rsa->e, blob + nlen);
- break;
- case KEY_DSA:
- case KEY_RSA:
- key_to_blob(k, &blob, &len);
- break;
- case KEY_UNSPEC:
- return retval;
- break;
- default:
- fatal("key_fingerprint_raw: bad key type %d", k->type);
- break;
- }
- if (blob != NULL) {
- retval = xmalloc(EVP_MAX_MD_SIZE);
- EVP_DigestInit(&ctx, md);
- EVP_DigestUpdate(&ctx, blob, len);
- EVP_DigestFinal(&ctx, retval, dgst_raw_length);
- memset(blob, 0, len);
- xfree(blob);
- } else {
- fatal("key_fingerprint_raw: blob is null");
- }
- return retval;
-}
-
-static char *
-key_fingerprint_hex(u_char *dgst_raw, u_int dgst_raw_len)
-{
- char *retval;
- int i;
-
- retval = xmalloc(dgst_raw_len * 3 + 1);
- retval[0] = '\0';
- for (i = 0; i < dgst_raw_len; i++) {
- char hex[4];
- snprintf(hex, sizeof(hex), "%02x:", dgst_raw[i]);
- strlcat(retval, hex, dgst_raw_len * 3);
- }
- retval[(dgst_raw_len * 3) - 1] = '\0';
- return retval;
-}
-
-static char *
-key_fingerprint_bubblebabble(u_char *dgst_raw, u_int dgst_raw_len)
-{
- char vowels[] = { 'a', 'e', 'i', 'o', 'u', 'y' };
- char consonants[] = { 'b', 'c', 'd', 'f', 'g', 'h', 'k', 'l', 'm',
- 'n', 'p', 'r', 's', 't', 'v', 'z', 'x' };
- u_int i, j = 0, rounds, seed = 1;
- char *retval;
-
- rounds = (dgst_raw_len / 2) + 1;
- retval = xmalloc(sizeof(char) * (rounds*6));
- retval[j++] = 'x';
- for (i = 0; i < rounds; i++) {
- u_int idx0, idx1, idx2, idx3, idx4;
- if ((i + 1 < rounds) || (dgst_raw_len % 2 != 0)) {
- idx0 = (((((u_int)(dgst_raw[2 * i])) >> 6) & 3) +
- seed) % 6;
- idx1 = (((u_int)(dgst_raw[2 * i])) >> 2) & 15;
- idx2 = ((((u_int)(dgst_raw[2 * i])) & 3) +
- (seed / 6)) % 6;
- retval[j++] = vowels[idx0];
- retval[j++] = consonants[idx1];
- retval[j++] = vowels[idx2];
- if ((i + 1) < rounds) {
- idx3 = (((u_int)(dgst_raw[(2 * i) + 1])) >> 4) & 15;
- idx4 = (((u_int)(dgst_raw[(2 * i) + 1]))) & 15;
- retval[j++] = consonants[idx3];
- retval[j++] = '-';
- retval[j++] = consonants[idx4];
- seed = ((seed * 5) +
- ((((u_int)(dgst_raw[2 * i])) * 7) +
- ((u_int)(dgst_raw[(2 * i) + 1])))) % 36;
- }
- } else {
- idx0 = seed % 6;
- idx1 = 16;
- idx2 = seed / 6;
- retval[j++] = vowels[idx0];
- retval[j++] = consonants[idx1];
- retval[j++] = vowels[idx2];
- }
- }
- retval[j++] = 'x';
- retval[j++] = '\0';
- return retval;
-}
-
-char *
-key_fingerprint(Key *k, enum fp_type dgst_type, enum fp_rep dgst_rep)
-{
- char *retval = NULL;
- u_char *dgst_raw;
- u_int dgst_raw_len;
-
- dgst_raw = key_fingerprint_raw(k, dgst_type, &dgst_raw_len);
- if (!dgst_raw)
- fatal("key_fingerprint: null from key_fingerprint_raw()");
- switch (dgst_rep) {
- case SSH_FP_HEX:
- retval = key_fingerprint_hex(dgst_raw, dgst_raw_len);
- break;
- case SSH_FP_BUBBLEBABBLE:
- retval = key_fingerprint_bubblebabble(dgst_raw, dgst_raw_len);
- break;
- default:
- fatal("key_fingerprint_ex: bad digest representation %d",
- dgst_rep);
- break;
- }
- memset(dgst_raw, 0, dgst_raw_len);
- xfree(dgst_raw);
- return retval;
-}
-
-/*
- * Reads a multiple-precision integer in decimal from the buffer, and advances
- * the pointer. The integer must already be initialized. This function is
- * permitted to modify the buffer. This leaves *cpp to point just beyond the
- * last processed (and maybe modified) character. Note that this may modify
- * the buffer containing the number.
- */
-static int
-read_bignum(char **cpp, BIGNUM * value)
-{
- char *cp = *cpp;
- int old;
-
- /* Skip any leading whitespace. */
- for (; *cp == ' ' || *cp == '\t'; cp++)
- ;
-
- /* Check that it begins with a decimal digit. */
- if (*cp < '0' || *cp > '9')
- return 0;
-
- /* Save starting position. */
- *cpp = cp;
-
- /* Move forward until all decimal digits skipped. */
- for (; *cp >= '0' && *cp <= '9'; cp++)
- ;
-
- /* Save the old terminating character, and replace it by \0. */
- old = *cp;
- *cp = 0;
-
- /* Parse the number. */
- if (BN_dec2bn(&value, *cpp) == 0)
- return 0;
-
- /* Restore old terminating character. */
- *cp = old;
-
- /* Move beyond the number and return success. */
- *cpp = cp;
- return 1;
-}
-
-static int
-write_bignum(FILE *f, BIGNUM *num)
-{
- char *buf = BN_bn2dec(num);
- if (buf == NULL) {
- error("write_bignum: BN_bn2dec() failed");
- return 0;
- }
- fprintf(f, " %s", buf);
- OPENSSL_free(buf);
- return 1;
-}
-
-/* returns 1 ok, -1 error */
-int
-key_read(Key *ret, char **cpp)
-{
- Key *k;
- int success = -1;
- char *cp, *space;
- int len, n, type;
- u_int bits;
- u_char *blob;
-
- cp = *cpp;
-
- switch (ret->type) {
- case KEY_RSA1:
- /* Get number of bits. */
- if (*cp < '0' || *cp > '9')
- return -1; /* Bad bit count... */
- for (bits = 0; *cp >= '0' && *cp <= '9'; cp++)
- bits = 10 * bits + *cp - '0';
- if (bits == 0)
- return -1;
- *cpp = cp;
- /* Get public exponent, public modulus. */
- if (!read_bignum(cpp, ret->rsa->e))
- return -1;
- if (!read_bignum(cpp, ret->rsa->n))
- return -1;
- success = 1;
- break;
- case KEY_UNSPEC:
- case KEY_RSA:
- case KEY_DSA:
- space = strchr(cp, ' ');
- if (space == NULL) {
- debug3("key_read: no space");
- return -1;
- }
- *space = '\0';
- type = key_type_from_name(cp);
- *space = ' ';
- if (type == KEY_UNSPEC) {
- debug3("key_read: no key found");
- return -1;
- }
- cp = space+1;
- if (*cp == '\0') {
- debug3("key_read: short string");
- return -1;
- }
- if (ret->type == KEY_UNSPEC) {
- ret->type = type;
- } else if (ret->type != type) {
- /* is a key, but different type */
- debug3("key_read: type mismatch");
- return -1;
- }
- len = 2*strlen(cp);
- blob = xmalloc(len);
- n = uudecode(cp, blob, len);
- if (n < 0) {
- error("key_read: uudecode %s failed", cp);
- xfree(blob);
- return -1;
- }
- k = key_from_blob(blob, n);
- xfree(blob);
- if (k == NULL) {
- error("key_read: key_from_blob %s failed", cp);
- return -1;
- }
- if (k->type != type) {
- error("key_read: type mismatch: encoding error");
- key_free(k);
- return -1;
- }
-/*XXXX*/
- if (ret->type == KEY_RSA) {
- if (ret->rsa != NULL)
- RSA_free(ret->rsa);
- ret->rsa = k->rsa;
- k->rsa = NULL;
- success = 1;
-#ifdef DEBUG_PK
- RSA_print_fp(stderr, ret->rsa, 8);
-#endif
- } else {
- if (ret->dsa != NULL)
- DSA_free(ret->dsa);
- ret->dsa = k->dsa;
- k->dsa = NULL;
- success = 1;
-#ifdef DEBUG_PK
- DSA_print_fp(stderr, ret->dsa, 8);
-#endif
- }
-/*XXXX*/
- key_free(k);
- if (success != 1)
- break;
- /* advance cp: skip whitespace and data */
- while (*cp == ' ' || *cp == '\t')
- cp++;
- while (*cp != '\0' && *cp != ' ' && *cp != '\t')
- cp++;
- *cpp = cp;
- break;
- default:
- fatal("key_read: bad key type: %d", ret->type);
- break;
- }
- return success;
-}
-
-int
-key_write(const Key *key, FILE *f)
-{
- int n, success = 0;
- u_int len, bits = 0;
- u_char *blob;
- char *uu;
-
- if (key->type == KEY_RSA1 && key->rsa != NULL) {
- /* size of modulus 'n' */
- bits = BN_num_bits(key->rsa->n);
- fprintf(f, "%u", bits);
- if (write_bignum(f, key->rsa->e) &&
- write_bignum(f, key->rsa->n)) {
- success = 1;
- } else {
- error("key_write: failed for RSA key");
- }
- } else if ((key->type == KEY_DSA && key->dsa != NULL) ||
- (key->type == KEY_RSA && key->rsa != NULL)) {
- key_to_blob(key, &blob, &len);
- uu = xmalloc(2*len);
- n = uuencode(blob, len, uu, 2*len);
- if (n > 0) {
- fprintf(f, "%s %s", key_ssh_name(key), uu);
- success = 1;
- }
- xfree(blob);
- xfree(uu);
- }
- return success;
-}
-
-char *
-key_type(Key *k)
-{
- switch (k->type) {
- case KEY_RSA1:
- return "RSA1";
- break;
- case KEY_RSA:
- return "RSA";
- break;
- case KEY_DSA:
- return "DSA";
- break;
- }
- return "unknown";
-}
-
-char *
-key_ssh_name(const Key *k)
-{
- switch (k->type) {
- case KEY_RSA:
- return "ssh-rsa";
- break;
- case KEY_DSA:
- return "ssh-dss";
- break;
- }
- return "ssh-unknown";
-}
-
-u_int
-key_size(Key *k)
-{
- switch (k->type) {
- case KEY_RSA1:
- case KEY_RSA:
- return BN_num_bits(k->rsa->n);
- break;
- case KEY_DSA:
- return BN_num_bits(k->dsa->p);
- break;
- }
- return 0;
-}
-
-static RSA *
-rsa_generate_private_key(u_int bits)
-{
- RSA *private;
- private = RSA_generate_key(bits, 35, NULL, NULL);
- if (private == NULL)
- fatal("rsa_generate_private_key: key generation failed.");
- return private;
-}
-
-static DSA*
-dsa_generate_private_key(u_int bits)
-{
- DSA *private = DSA_generate_parameters(bits, NULL, 0, NULL, NULL, NULL, NULL);
- if (private == NULL)
- fatal("dsa_generate_private_key: DSA_generate_parameters failed");
- if (!DSA_generate_key(private))
- fatal("dsa_generate_private_key: DSA_generate_key failed.");
- if (private == NULL)
- fatal("dsa_generate_private_key: NULL.");
- return private;
-}
-
-Key *
-key_generate(int type, u_int bits)
-{
- Key *k = key_new(KEY_UNSPEC);
- switch (type) {
- case KEY_DSA:
- k->dsa = dsa_generate_private_key(bits);
- break;
- case KEY_RSA:
- case KEY_RSA1:
- k->rsa = rsa_generate_private_key(bits);
- break;
- default:
- fatal("key_generate: unknown type %d", type);
- }
- k->type = type;
- return k;
-}
-
-Key *
-key_from_private(Key *k)
-{
- Key *n = NULL;
- switch (k->type) {
- case KEY_DSA:
- n = key_new(k->type);
- BN_copy(n->dsa->p, k->dsa->p);
- BN_copy(n->dsa->q, k->dsa->q);
- BN_copy(n->dsa->g, k->dsa->g);
- BN_copy(n->dsa->pub_key, k->dsa->pub_key);
- break;
- case KEY_RSA:
- case KEY_RSA1:
- n = key_new(k->type);
- BN_copy(n->rsa->n, k->rsa->n);
- BN_copy(n->rsa->e, k->rsa->e);
- break;
- default:
- fatal("key_from_private: unknown type %d", k->type);
- break;
- }
- return n;
-}
-
-int
-key_type_from_name(char *name)
-{
- if (strcmp(name, "rsa1") == 0) {
- return KEY_RSA1;
- } else if (strcmp(name, "rsa") == 0) {
- return KEY_RSA;
- } else if (strcmp(name, "dsa") == 0) {
- return KEY_DSA;
- } else if (strcmp(name, "ssh-rsa") == 0) {
- return KEY_RSA;
- } else if (strcmp(name, "ssh-dss") == 0) {
- return KEY_DSA;
- } else if (strcmp(name, "null") == 0){
- return KEY_NULL;
- }
- debug2("key_type_from_name: unknown key type '%s'", name);
- return KEY_UNSPEC;
-}
-
-int
-key_names_valid2(const char *names)
-{
- char *s, *cp, *p;
-
- if (names == NULL || strcmp(names, "") == 0)
- return 0;
- s = cp = xstrdup(names);
- for ((p = strsep(&cp, ",")); p && *p != '\0';
- (p = strsep(&cp, ","))) {
- switch (key_type_from_name(p)) {
- case KEY_RSA1:
- case KEY_UNSPEC:
- xfree(s);
- return 0;
- }
- }
- debug3("key names ok: [%s]", names);
- xfree(s);
- return 1;
-}
-
-Key *
-key_from_blob(u_char *blob, int blen)
-{
- Buffer b;
- char *ktype;
- int rlen, type;
- Key *key = NULL;
-
-#ifdef DEBUG_PK
- dump_base64(stderr, blob, blen);
-#endif
- buffer_init(&b);
- buffer_append(&b, blob, blen);
- if ((ktype = buffer_get_string_ret(&b, NULL)) == NULL) {
- error("key_from_blob: can't read key type");
- goto out;
- }
-
- type = key_type_from_name(ktype);
-
- switch (type) {
- case KEY_RSA:
- key = key_new(type);
- if (buffer_get_bignum2_ret(&b, key->rsa->e) == -1 ||
- buffer_get_bignum2_ret(&b, key->rsa->n) == -1) {
- error("key_from_blob: can't read rsa key");
- key_free(key);
- key = NULL;
- goto out;
- }
-#ifdef DEBUG_PK
- RSA_print_fp(stderr, key->rsa, 8);
-#endif
- break;
- case KEY_DSA:
- key = key_new(type);
- if (buffer_get_bignum2_ret(&b, key->dsa->p) == -1 ||
- buffer_get_bignum2_ret(&b, key->dsa->q) == -1 ||
- buffer_get_bignum2_ret(&b, key->dsa->g) == -1 ||
- buffer_get_bignum2_ret(&b, key->dsa->pub_key) == -1) {
- error("key_from_blob: can't read dsa key");
- key_free(key);
- key = NULL;
- goto out;
- }
-#ifdef DEBUG_PK
- DSA_print_fp(stderr, key->dsa, 8);
-#endif
- break;
- case KEY_UNSPEC:
- key = key_new(type);
- break;
- default:
- error("key_from_blob: cannot handle type %s", ktype);
- goto out;
- }
- rlen = buffer_len(&b);
- if (key != NULL && rlen != 0)
- error("key_from_blob: remaining bytes in key blob %d", rlen);
- out:
- if (ktype != NULL)
- xfree(ktype);
- buffer_free(&b);
- return key;
-}
-
-int
-key_to_blob(const Key *key, u_char **blobp, u_int *lenp)
-{
- Buffer b;
- int len;
-
- if (key == NULL) {
- error("key_to_blob: key == NULL");
- return 0;
- }
- buffer_init(&b);
- switch (key->type) {
- case KEY_DSA:
- buffer_put_cstring(&b, key_ssh_name(key));
- buffer_put_bignum2(&b, key->dsa->p);
- buffer_put_bignum2(&b, key->dsa->q);
- buffer_put_bignum2(&b, key->dsa->g);
- buffer_put_bignum2(&b, key->dsa->pub_key);
- break;
- case KEY_RSA:
- buffer_put_cstring(&b, key_ssh_name(key));
- buffer_put_bignum2(&b, key->rsa->e);
- buffer_put_bignum2(&b, key->rsa->n);
- break;
- default:
- error("key_to_blob: unsupported key type %d", key->type);
- buffer_free(&b);
- return 0;
- }
- len = buffer_len(&b);
- if (lenp != NULL)
- *lenp = len;
- if (blobp != NULL) {
- *blobp = xmalloc(len);
- memcpy(*blobp, buffer_ptr(&b), len);
- }
- memset(buffer_ptr(&b), 0, len);
- buffer_free(&b);
- return len;
-}
-
-int
-key_sign(
- Key *key,
- u_char **sigp, u_int *lenp,
- u_char *data, u_int datalen)
-{
- switch (key->type) {
- case KEY_DSA:
- return ssh_dss_sign(key, sigp, lenp, data, datalen);
- break;
- case KEY_RSA:
- return ssh_rsa_sign(key, sigp, lenp, data, datalen);
- break;
- default:
- error("key_sign: illegal key type %d", key->type);
- return -1;
- break;
- }
-}
-
-/*
- * key_verify returns 1 for a correct signature, 0 for an incorrect signature
- * and -1 on error.
- */
-int
-key_verify(
- Key *key,
- u_char *signature, u_int signaturelen,
- u_char *data, u_int datalen)
-{
- if (signaturelen == 0)
- return -1;
-
- switch (key->type) {
- case KEY_DSA:
- return ssh_dss_verify(key, signature, signaturelen, data, datalen);
- break;
- case KEY_RSA:
- return ssh_rsa_verify(key, signature, signaturelen, data, datalen);
- break;
- default:
- error("key_verify: illegal key type %d", key->type);
- return -1;
- break;
- }
-}
-
-/* Converts a private to a public key */
-Key *
-key_demote(Key *k)
-{
- Key *pk;
-
- pk = xmalloc(sizeof(*pk));
- pk->type = k->type;
- pk->flags = k->flags;
- pk->dsa = NULL;
- pk->rsa = NULL;
-
- switch (k->type) {
- case KEY_RSA1:
- case KEY_RSA:
- if ((pk->rsa = RSA_new()) == NULL)
- fatal("key_demote: RSA_new failed");
- if ((pk->rsa->e = BN_dup(k->rsa->e)) == NULL)
- fatal("key_demote: BN_dup failed");
- if ((pk->rsa->n = BN_dup(k->rsa->n)) == NULL)
- fatal("key_demote: BN_dup failed");
- break;
- case KEY_DSA:
- if ((pk->dsa = DSA_new()) == NULL)
- fatal("key_demote: DSA_new failed");
- if ((pk->dsa->p = BN_dup(k->dsa->p)) == NULL)
- fatal("key_demote: BN_dup failed");
- if ((pk->dsa->q = BN_dup(k->dsa->q)) == NULL)
- fatal("key_demote: BN_dup failed");
- if ((pk->dsa->g = BN_dup(k->dsa->g)) == NULL)
- fatal("key_demote: BN_dup failed");
- if ((pk->dsa->pub_key = BN_dup(k->dsa->pub_key)) == NULL)
- fatal("key_demote: BN_dup failed");
- break;
- default:
- fatal("key_free: bad key type %d", k->type);
- break;
- }
-
- return (pk);
-}
diff --git a/usr/src/cmd/ssh/libssh/common/llib-lssh b/usr/src/cmd/ssh/libssh/common/llib-lssh
deleted file mode 100644
index c44090abe6..0000000000
--- a/usr/src/cmd/ssh/libssh/common/llib-lssh
+++ /dev/null
@@ -1,130 +0,0 @@
-/* LINTLIBRARY */
-/* PROTOLIB1 */
-
-/*
- * CDDL HEADER START
- *
- * The contents of this file are subject to the terms of the
- * Common Development and Distribution License (the "License").
- * You may not use this file except in compliance with the License.
- *
- * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
- * See the License for the specific language governing permissions
- * and limitations under the License.
- *
- * When distributing Covered Code, include this CDDL HEADER in each
- * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
- * If applicable, add the following below this CDDL HEADER, with the
- * fields enclosed by brackets "[]" replaced with your own identifying
- * information: Portions Copyright [yyyy] [name of copyright owner]
- *
- * CDDL HEADER END
- *
- * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
- */
-
-#include <includes.h>
-#include <ssh.h>
-#include <atomicio.h>
-#include <auth.h>
-#include <auth-pam.h>
-#include <auth2-pam.h>
-#include <authfd.h>
-#include <authfile.h>
-#include <auth-options.h>
-#include <base64.h>
-#include <bindresvport.h>
-#include <bsd-arc4random.h>
-#include <bsd-cray.h>
-#include <bsd-cygwin_util.h>
-#include <bsd-getpeereid.h>
-#include <bsd-misc.h>
-#include <bsd-snprintf.h>
-#include <bsd-waitpid.h>
-#include <bufaux.h>
-#include <buffer.h>
-#include <canohost.h>
-#include <channels.h>
-#include <cipher.h>
-#include <clientloop.h>
-#include <compat.h>
-#include <compress.h>
-#include <config.h>
-#include <crc32.h>
-#include <deattack.h>
-#include <defines.h>
-#include <dh.h>
-#include <dirname.h>
-#include <dispatch.h>
-#include <entropy.h>
-#include <fake-gai-errnos.h>
-#include <fake-getaddrinfo.h>
-#include <fake-getnameinfo.h>
-#include <fake-socket.h>
-#include <g11n.h>
-#include <getcwd.h>
-#include <getgrouplist.h>
-#include <getopt.h>
-#include <getput.h>
-#include <glob.h>
-#include <groupaccess.h>
-#include <hostfile.h>
-#include <inet_ntoa.h>
-#include <inet_ntop.h>
-#include <kex.h>
-#include <key.h>
-#include <log.h>
-#include <loginrec.h>
-#include <mac.h>
-#include <match.h>
-#include <misc.h>
-#include <mktemp.h>
-#include <mpaux.h>
-#include <msg.h>
-#include <myproposal.h>
-#include <openbsd-compat.h>
-#include <packet.h>
-#include <pathnames.h>
-#include <port-aix.h>
-#include <port-irix.h>
-#include <proxy-io.h>
-#include <readconf.h>
-#include <readpass.h>
-#include <readpassphrase.h>
-#include <realpath.h>
-#include <rresvport.h>
-#include <rsa.h>
-#include <servconf.h>
-#include <serverloop.h>
-#include <session.h>
-#include <setproctitle.h>
-#include <sftp-common.h>
-#include <sftp.h>
-#include <sftp-client.h>
-#include <sigact.h>
-#include <ssh1.h>
-#include <ssh2.h>
-#include <sshconnect.h>
-#include <ssh-dss.h>
-#include <sshlogin.h>
-#include <sshpty.h>
-#include <ssh-rsa.h>
-#include <sshtty.h>
-#include <strlcat.h>
-#include <strlcpy.h>
-#include <strmode.h>
-#include <sys-queue.h>
-#include <sys-tree.h>
-#include <tildexpand.h>
-#include <uidswap.h>
-#include <uuencode.h>
-#include <version.h>
-#include <xlist.h>
-#include <xmalloc.h>
-#include <xmmap.h>
-
-extern uid_t original_real_uid;
-extern char *__progname;
-
diff --git a/usr/src/cmd/ssh/libssh/common/log.c b/usr/src/cmd/ssh/libssh/common/log.c
deleted file mode 100644
index 79e4cace6e..0000000000
--- a/usr/src/cmd/ssh/libssh/common/log.c
+++ /dev/null
@@ -1,445 +0,0 @@
-/*
- * Author: Tatu Ylonen <ylo@cs.hut.fi>
- * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
- * All rights reserved
- *
- * As far as I am concerned, the code I have written for this software
- * can be used freely for any purpose. Any derived versions of this
- * software must be clearly marked as such, and if the derived work is
- * incompatible with the protocol description in the RFC file, it must be
- * called by a name other than "ssh" or "Secure Shell".
- */
-/*
- * Copyright (c) 2000 Markus Friedl. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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.
- */
-/*
- * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
- */
-
-#include "includes.h"
-RCSID("$OpenBSD: log.c,v 1.24 2002/07/19 15:43:33 markus Exp $");
-
-#pragma ident "%Z%%M% %I% %E% SMI"
-
-#include "log.h"
-#include "xmalloc.h"
-
-#include <atomic.h>
-#include <syslog.h>
-
-static LogLevel log_level = SYSLOG_LEVEL_INFO;
-static int log_on_stderr = 1;
-static int log_facility = LOG_AUTH;
-static char *argv0;
-
-extern char *__progname;
-
-static const char *log_txt_prefix = "";
-
-/* textual representation of log-facilities/levels */
-
-static struct {
- const char *name;
- SyslogFacility val;
-} log_facilities[] = {
- { "DAEMON", SYSLOG_FACILITY_DAEMON },
- { "USER", SYSLOG_FACILITY_USER },
- { "AUTH", SYSLOG_FACILITY_AUTH },
-#ifdef LOG_AUTHPRIV
- { "AUTHPRIV", SYSLOG_FACILITY_AUTHPRIV },
-#endif
- { "LOCAL0", SYSLOG_FACILITY_LOCAL0 },
- { "LOCAL1", SYSLOG_FACILITY_LOCAL1 },
- { "LOCAL2", SYSLOG_FACILITY_LOCAL2 },
- { "LOCAL3", SYSLOG_FACILITY_LOCAL3 },
- { "LOCAL4", SYSLOG_FACILITY_LOCAL4 },
- { "LOCAL5", SYSLOG_FACILITY_LOCAL5 },
- { "LOCAL6", SYSLOG_FACILITY_LOCAL6 },
- { "LOCAL7", SYSLOG_FACILITY_LOCAL7 },
- { NULL, SYSLOG_FACILITY_NOT_SET }
-};
-
-static struct {
- const char *name;
- LogLevel val;
-} log_levels[] =
-{
- { "QUIET", SYSLOG_LEVEL_QUIET },
- { "FATAL", SYSLOG_LEVEL_FATAL },
- { "ERROR", SYSLOG_LEVEL_ERROR },
- { "NOTICE", SYSLOG_LEVEL_NOTICE },
- { "INFO", SYSLOG_LEVEL_INFO },
- { "VERBOSE", SYSLOG_LEVEL_VERBOSE },
- { "DEBUG", SYSLOG_LEVEL_DEBUG1 },
- { "DEBUG1", SYSLOG_LEVEL_DEBUG1 },
- { "DEBUG2", SYSLOG_LEVEL_DEBUG2 },
- { "DEBUG3", SYSLOG_LEVEL_DEBUG3 },
- { NULL, SYSLOG_LEVEL_NOT_SET }
-};
-
-SyslogFacility
-log_facility_number(char *name)
-{
- int i;
-
- if (name != NULL)
- for (i = 0; log_facilities[i].name; i++)
- if (strcasecmp(log_facilities[i].name, name) == 0)
- return log_facilities[i].val;
- return SYSLOG_FACILITY_NOT_SET;
-}
-
-LogLevel
-log_level_number(char *name)
-{
- int i;
-
- if (name != NULL)
- for (i = 0; log_levels[i].name; i++)
- if (strcasecmp(log_levels[i].name, name) == 0)
- return log_levels[i].val;
- return SYSLOG_LEVEL_NOT_SET;
-}
-
-void
-set_log_txt_prefix(const char *txt)
-{
- log_txt_prefix = txt;
-}
-
-/* Error messages that should be logged. */
-
-void
-error(const char *fmt,...)
-{
- va_list args;
-
- va_start(args, fmt);
- do_log(SYSLOG_LEVEL_ERROR, fmt, args);
- va_end(args);
-}
-
-void
-notice(const char *fmt,...)
-{
- va_list args;
-
- va_start(args, fmt);
- do_log(SYSLOG_LEVEL_NOTICE, fmt, args);
- va_end(args);
-}
-
-/* Log this message (information that usually should go to the log). */
-
-void
-log(const char *fmt,...)
-{
- va_list args;
-
- va_start(args, fmt);
- do_log(SYSLOG_LEVEL_INFO, fmt, args);
- va_end(args);
-}
-
-/* More detailed messages (information that does not need to go to the log). */
-
-void
-verbose(const char *fmt,...)
-{
- va_list args;
-
- va_start(args, fmt);
- do_log(SYSLOG_LEVEL_VERBOSE, fmt, args);
- va_end(args);
-}
-
-/* Debugging messages that should not be logged during normal operation. */
-
-void
-debug(const char *fmt,...)
-{
- va_list args;
-
- va_start(args, fmt);
- do_log(SYSLOG_LEVEL_DEBUG1, fmt, args);
- va_end(args);
-}
-
-void
-debug2(const char *fmt,...)
-{
- va_list args;
-
- va_start(args, fmt);
- do_log(SYSLOG_LEVEL_DEBUG2, fmt, args);
- va_end(args);
-}
-
-void
-debug3(const char *fmt,...)
-{
- va_list args;
-
- va_start(args, fmt);
- do_log(SYSLOG_LEVEL_DEBUG3, fmt, args);
- va_end(args);
-}
-
-/* Fatal cleanup */
-
-struct fatal_cleanup {
- struct fatal_cleanup *next;
- void (*proc) (void *);
- void *context;
-};
-
-static struct fatal_cleanup *fatal_cleanups = NULL;
-
-/* Registers a cleanup function to be called by fatal() before exiting. */
-
-void
-fatal_add_cleanup(void (*proc) (void *), void *context)
-{
- struct fatal_cleanup *cu;
-
- cu = xmalloc(sizeof(*cu));
- cu->proc = proc;
- cu->context = context;
- cu->next = fatal_cleanups;
- fatal_cleanups = cu;
-}
-
-/* Removes a cleanup function to be called at fatal(). */
-
-void
-fatal_remove_cleanup(void (*proc) (void *context), void *context)
-{
- struct fatal_cleanup **cup, *cu;
-
- for (cup = &fatal_cleanups; *cup; cup = &cu->next) {
- cu = *cup;
- if (cu->proc == proc && cu->context == context) {
- *cup = cu->next;
- xfree(cu);
- return;
- }
- }
- debug3("fatal_remove_cleanup: no such cleanup function: 0x%lx 0x%lx",
- (u_long) proc, (u_long) context);
-}
-
-/* Remove all cleanups, to be called after fork() */
-void
-fatal_remove_all_cleanups(void)
-{
- struct fatal_cleanup *cu, *next_cu;
-
- for (cu = fatal_cleanups; cu; cu = next_cu) {
- next_cu = cu->next;
- xfree(cu);
- }
-
- fatal_cleanups = NULL;
-}
-
-/* Cleanup and exit. Make sure each cleanup is called only once. */
-void
-fatal_cleanup(void)
-{
- struct fatal_cleanup *cu, *next_cu;
- static volatile u_int called = 0;
-
- if (atomic_cas_uint(&called, 0, 1) == 1)
- exit(255);
- /* Call cleanup functions. */
- for (cu = fatal_cleanups; cu; cu = next_cu) {
- next_cu = cu->next;
- debug("Calling cleanup 0x%lx(0x%lx)",
- (u_long) cu->proc, (u_long) cu->context);
- (*cu->proc) (cu->context);
- }
- exit(255);
-}
-
-
-/*
- * Initialize the log.
- */
-
-void
-log_init(char *av0, LogLevel level, SyslogFacility facility, int on_stderr)
-{
- argv0 = av0;
-
- switch (level) {
- case SYSLOG_LEVEL_QUIET:
- case SYSLOG_LEVEL_FATAL:
- case SYSLOG_LEVEL_ERROR:
- case SYSLOG_LEVEL_NOTICE:
- case SYSLOG_LEVEL_INFO:
- case SYSLOG_LEVEL_VERBOSE:
- case SYSLOG_LEVEL_DEBUG1:
- case SYSLOG_LEVEL_DEBUG2:
- case SYSLOG_LEVEL_DEBUG3:
- log_level = level;
- break;
- default:
- fprintf(stderr, "Unrecognized internal syslog level code %d\n",
- (int) level);
- exit(1);
- }
-
- log_on_stderr = on_stderr;
- if (on_stderr)
- return;
-
- switch (facility) {
- case SYSLOG_FACILITY_DAEMON:
- log_facility = LOG_DAEMON;
- break;
- case SYSLOG_FACILITY_USER:
- log_facility = LOG_USER;
- break;
- case SYSLOG_FACILITY_AUTH:
- log_facility = LOG_AUTH;
- break;
-#ifdef LOG_AUTHPRIV
- case SYSLOG_FACILITY_AUTHPRIV:
- log_facility = LOG_AUTHPRIV;
- break;
-#endif
- case SYSLOG_FACILITY_LOCAL0:
- log_facility = LOG_LOCAL0;
- break;
- case SYSLOG_FACILITY_LOCAL1:
- log_facility = LOG_LOCAL1;
- break;
- case SYSLOG_FACILITY_LOCAL2:
- log_facility = LOG_LOCAL2;
- break;
- case SYSLOG_FACILITY_LOCAL3:
- log_facility = LOG_LOCAL3;
- break;
- case SYSLOG_FACILITY_LOCAL4:
- log_facility = LOG_LOCAL4;
- break;
- case SYSLOG_FACILITY_LOCAL5:
- log_facility = LOG_LOCAL5;
- break;
- case SYSLOG_FACILITY_LOCAL6:
- log_facility = LOG_LOCAL6;
- break;
- case SYSLOG_FACILITY_LOCAL7:
- log_facility = LOG_LOCAL7;
- break;
- default:
- fprintf(stderr,
- "Unrecognized internal syslog facility code %d\n",
- (int) facility);
- exit(1);
- }
-}
-
-#define MSGBUFSIZ 1024
-
-/* PRINTFLIKE2 */
-void
-do_log(LogLevel level, const char *fmt, va_list args)
-{
- char msgbuf[MSGBUFSIZ];
- char fmtbuf[MSGBUFSIZ];
- char *txt = NULL;
- int pri = LOG_INFO;
- int do_gettext = log_on_stderr; /*
- * Localize user messages - not
- * syslog()ed messages.
- */
-
- if (level > log_level)
- return;
-
- switch (level) {
- case SYSLOG_LEVEL_FATAL:
- if (!log_on_stderr)
- txt = "fatal";
- pri = LOG_CRIT;
- break;
- case SYSLOG_LEVEL_ERROR:
- if (!log_on_stderr)
- txt = "error";
- pri = LOG_ERR;
- break;
- case SYSLOG_LEVEL_NOTICE:
- pri = LOG_NOTICE;
- break;
- case SYSLOG_LEVEL_INFO:
- pri = LOG_INFO;
- break;
- case SYSLOG_LEVEL_VERBOSE:
- pri = LOG_INFO;
- break;
- case SYSLOG_LEVEL_DEBUG1:
- txt = "debug1";
- pri = LOG_DEBUG;
- /*
- * Don't localize debug messages - such are not intended
- * for users but for support staff whose preferred
- * language is unknown, therefore we default to the
- * language used in the source code: English.
- */
- do_gettext = 0;
- break;
- case SYSLOG_LEVEL_DEBUG2:
- txt = "debug2";
- pri = LOG_DEBUG;
- do_gettext = 0; /* Don't localize debug messages. */
- break;
- case SYSLOG_LEVEL_DEBUG3:
- txt = "debug3";
- pri = LOG_DEBUG;
- do_gettext = 0; /* Don't localize debug messages. */
- break;
- default:
- txt = "internal error";
- pri = LOG_ERR;
- break;
- }
- if (txt != NULL) {
- snprintf(fmtbuf, sizeof(fmtbuf), "%s%s: %s", log_txt_prefix,
- do_gettext ? gettext(txt) : txt,
- do_gettext ? gettext(fmt) : fmt);
- vsnprintf(msgbuf, sizeof(msgbuf), fmtbuf, args);
- } else {
- vsnprintf(msgbuf, sizeof(msgbuf),
- do_gettext ? gettext(fmt) : fmt,
- args);
- }
- if (log_on_stderr) {
- fprintf(stderr, "%s\r\n", msgbuf);
- } else {
- openlog(argv0 ? argv0 : __progname, LOG_PID, log_facility);
- syslog(pri, "%.500s", msgbuf);
- closelog();
- }
-}
diff --git a/usr/src/cmd/ssh/libssh/common/mac.c b/usr/src/cmd/ssh/libssh/common/mac.c
deleted file mode 100644
index e25f5eb95d..0000000000
--- a/usr/src/cmd/ssh/libssh/common/mac.c
+++ /dev/null
@@ -1,164 +0,0 @@
-/*
- * Copyright (c) 2001 Markus Friedl. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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.
- */
-
-#include "includes.h"
-RCSID("$OpenBSD: mac.c,v 1.5 2002/05/16 22:02:50 markus Exp $");
-
-#include <openssl/hmac.h>
-
-#include "xmalloc.h"
-#include "getput.h"
-#include "log.h"
-#include "cipher.h"
-#include "kex.h"
-#include "mac.h"
-#include "misc.h"
-
-#define SSH_EVP 1 /* OpenSSL EVP-based MAC */
-
-struct {
- char *name;
- int type;
- const EVP_MD * (*mdfunc)(void);
- int truncatebits; /* truncate digest if != 0 */
- int key_len; /* will be used if we have UMAC */
-} macs[] = {
- { "hmac-sha1", SSH_EVP, EVP_sha1, 0, -1 },
- { "hmac-sha1-96", SSH_EVP, EVP_sha1, 96, -1 },
- { "hmac-md5", SSH_EVP, EVP_md5, 0, -1 },
- { "hmac-md5-96", SSH_EVP, EVP_md5, 96, -1 },
-#ifdef SOLARIS_SSH_ENABLE_RIPEMD160
- { "hmac-ripemd160", SSH_EVP, EVP_ripemd160, 0, -1 },
- { "hmac-ripemd160@openssh.com", SSH_EVP, EVP_ripemd160, 0, -1 },
-#endif /* SOLARIS_SSH_ENABLE_RIPEMD160 */
- { NULL, 0, NULL, 0, -1 }
-};
-
-static void
-mac_setup_by_id(Mac *mac, int which)
-{
- int evp_len;
- mac->type = macs[which].type;
- if (mac->type == SSH_EVP) {
- mac->evp_md = (*macs[which].mdfunc)();
- if ((evp_len = EVP_MD_size(mac->evp_md)) <= 0)
- fatal("mac %s len %d", mac->name, evp_len);
- mac->key_len = mac->mac_len = (u_int)evp_len;
- } else
- fatal("wrong MAC type (%d)", mac->type);
- if (macs[which].truncatebits != 0)
- mac->mac_len = macs[which].truncatebits / 8;
-}
-
-int
-mac_setup(Mac *mac, char *name)
-{
- int i;
-
- for (i = 0; macs[i].name; i++) {
- if (strcmp(name, macs[i].name) == 0) {
- if (mac != NULL)
- mac_setup_by_id(mac, i);
- debug2("mac_setup: found %s", name);
- return (0);
- }
- }
- debug2("mac_setup: unknown %s", name);
- return (-1);
-}
-
-int
-mac_init(Mac *mac)
-{
- if (mac->key == NULL)
- fatal("mac_init: no key");
- switch (mac->type) {
- case SSH_EVP:
- if (mac->evp_md == NULL)
- return -1;
- HMAC_Init(&mac->evp_ctx, mac->key, mac->key_len, mac->evp_md);
- return 0;
- default:
- return -1;
- }
-}
-
-u_char *
-mac_compute(Mac *mac, u_int32_t seqno, u_char *data, int datalen)
-{
- static u_char m[EVP_MAX_MD_SIZE];
- u_char b[4];
-
- if (mac->mac_len > sizeof(m))
- fatal("mac_compute: mac too long %u %lu",
- mac->mac_len, (u_long)sizeof(m));
-
- switch (mac->type) {
- case SSH_EVP:
- put_u32(b, seqno);
- /* reset HMAC context */
- HMAC_Init(&mac->evp_ctx, NULL, 0, NULL);
- HMAC_Update(&mac->evp_ctx, b, sizeof(b));
- HMAC_Update(&mac->evp_ctx, data, datalen);
- HMAC_Final(&mac->evp_ctx, m, NULL);
- break;
- default:
- fatal("mac_compute: unknown MAC type");
- }
-
- return (m);
-}
-
-void
-mac_clear(Mac *mac)
-{
- if (mac->evp_md != NULL)
- HMAC_cleanup(&mac->evp_ctx);
- mac->evp_md = NULL;
-}
-
-/* XXX copied from ciphers_valid */
-#define MAC_SEP ","
-int
-mac_valid(const char *names)
-{
- char *maclist, *cp, *p;
-
- if (names == NULL || strcmp(names, "") == 0)
- return (0);
- maclist = cp = xstrdup(names);
- for ((p = strsep(&cp, MAC_SEP)); p && *p != '\0';
- (p = strsep(&cp, MAC_SEP))) {
- if (mac_setup(NULL, p) < 0) {
- debug("bad mac %s [%s]", p, names);
- xfree(maclist);
- return (0);
- } else {
- debug3("mac ok: %s [%s]", p, names);
- }
- }
- debug3("macs ok: [%s]", names);
- xfree(maclist);
- return (1);
-}
diff --git a/usr/src/cmd/ssh/libssh/common/match.c b/usr/src/cmd/ssh/libssh/common/match.c
deleted file mode 100644
index 4724d435e7..0000000000
--- a/usr/src/cmd/ssh/libssh/common/match.c
+++ /dev/null
@@ -1,271 +0,0 @@
-/*
- * Author: Tatu Ylonen <ylo@cs.hut.fi>
- * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
- * All rights reserved
- * Simple pattern matching, with '*' and '?' as wildcards.
- *
- * As far as I am concerned, the code I have written for this software
- * can be used freely for any purpose. Any derived versions of this
- * software must be clearly marked as such, and if the derived work is
- * incompatible with the protocol description in the RFC file, it must be
- * called by a name other than "ssh" or "Secure Shell".
- */
-/*
- * Copyright (c) 2000 Markus Friedl. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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.
- */
-
-#include "includes.h"
-RCSID("$OpenBSD: match.c,v 1.19 2002/03/01 13:12:10 markus Exp $");
-
-#pragma ident "%Z%%M% %I% %E% SMI"
-
-#include "match.h"
-#include "xmalloc.h"
-
-/*
- * Returns true if the given string matches the pattern (which may contain ?
- * and * as wildcards), and zero if it does not match.
- */
-
-int
-match_pattern(const char *s, const char *pattern)
-{
- for (;;) {
- /* If at end of pattern, accept if also at end of string. */
- if (!*pattern)
- return !*s;
-
- if (*pattern == '*') {
- /* Skip the asterisk. */
- pattern++;
-
- /* If at end of pattern, accept immediately. */
- if (!*pattern)
- return 1;
-
- /* If next character in pattern is known, optimize. */
- if (*pattern != '?' && *pattern != '*') {
- /*
- * Look instances of the next character in
- * pattern, and try to match starting from
- * those.
- */
- for (; *s; s++)
- if (*s == *pattern &&
- match_pattern(s + 1, pattern + 1))
- return 1;
- /* Failed. */
- return 0;
- }
- /*
- * Move ahead one character at a time and try to
- * match at each position.
- */
- for (; *s; s++)
- if (match_pattern(s, pattern))
- return 1;
- /* Failed. */
- return 0;
- }
- /*
- * There must be at least one more character in the string.
- * If we are at the end, fail.
- */
- if (!*s)
- return 0;
-
- /* Check if the next character of the string is acceptable. */
- if (*pattern != '?' && *pattern != *s)
- return 0;
-
- /* Move to the next character, both in string and in pattern. */
- s++;
- pattern++;
- }
- /* NOTREACHED */
-}
-
-/*
- * Tries to match the string against the
- * comma-separated sequence of subpatterns (each possibly preceded by ! to
- * indicate negation). Returns -1 if negation matches, 1 if there is
- * a positive match, 0 if there is no match at all.
- */
-
-int
-match_pattern_list(const char *string, const char *pattern, u_int len,
- int dolower)
-{
- char sub[1024];
- int negated;
- int got_positive;
- u_int i, subi;
-
- got_positive = 0;
- for (i = 0; i < len;) {
- /* Check if the subpattern is negated. */
- if (pattern[i] == '!') {
- negated = 1;
- i++;
- } else
- negated = 0;
-
- /*
- * Extract the subpattern up to a comma or end. Convert the
- * subpattern to lowercase.
- */
- for (subi = 0;
- i < len && subi < sizeof(sub) - 1 && pattern[i] != ',';
- subi++, i++)
- sub[subi] = dolower && isupper(pattern[i]) ?
- tolower(pattern[i]) : pattern[i];
- /* If subpattern too long, return failure (no match). */
- if (subi >= sizeof(sub) - 1)
- return 0;
-
- /* If the subpattern was terminated by a comma, skip the comma. */
- if (i < len && pattern[i] == ',')
- i++;
-
- /* Null-terminate the subpattern. */
- sub[subi] = '\0';
-
- /* Try to match the subpattern against the string. */
- if (match_pattern(string, sub)) {
- if (negated)
- return -1; /* Negative */
- else
- got_positive = 1; /* Positive */
- }
- }
-
- /*
- * Return success if got a positive match. If there was a negative
- * match, we have already returned -1 and never get here.
- */
- return got_positive;
-}
-
-/*
- * Tries to match the host name (which must be in all lowercase) against the
- * comma-separated sequence of subpatterns (each possibly preceded by ! to
- * indicate negation). Returns -1 if negation matches, 1 if there is
- * a positive match, 0 if there is no match at all.
- */
-int
-match_hostname(const char *host, const char *pattern, u_int len)
-{
- return match_pattern_list(host, pattern, len, 1);
-}
-
-/*
- * returns 0 if we get a negative match for the hostname or the ip
- * or if we get no match at all. returns 1 otherwise.
- */
-int
-match_host_and_ip(const char *host, const char *ipaddr,
- const char *patterns)
-{
- int mhost, mip;
-
- /* negative ipaddr match */
- if ((mip = match_hostname(ipaddr, patterns, strlen(patterns))) == -1)
- return 0;
- /* negative hostname match */
- if ((mhost = match_hostname(host, patterns, strlen(patterns))) == -1)
- return 0;
- /* no match at all */
- if (mhost == 0 && mip == 0)
- return 0;
- return 1;
-}
-
-/*
- * match user, user@host_or_ip, user@host_or_ip_list against pattern
- */
-int
-match_user(const char *user, const char *host, const char *ipaddr,
- const char *pattern)
-{
- char *p, *pat;
- int ret;
-
- if ((p = strchr(pattern,'@')) == NULL)
- return match_pattern(user, pattern);
-
- pat = xstrdup(pattern);
- p = strchr(pat, '@');
- *p++ = '\0';
-
- if ((ret = match_pattern(user, pat)) == 1)
- ret = match_host_and_ip(host, ipaddr, p);
- xfree(pat);
-
- return ret;
-}
-
-/*
- * Returns first item from client-list that is also supported by server-list,
- * caller must xfree() returned string.
- */
-#define MAX_PROP 40
-#define SEP ","
-char *
-match_list(const char *client, const char *server, u_int *next)
-{
- char *sproposals[MAX_PROP];
- char *c, *s, *p, *ret, *cp, *sp;
- int i, j, nproposals;
-
- c = cp = xstrdup(client);
- s = sp = xstrdup(server);
-
- for ((p = strsep(&sp, SEP)), i=0; p && *p != '\0';
- (p = strsep(&sp, SEP)), i++) {
- if (i < MAX_PROP)
- sproposals[i] = p;
- else
- break;
- }
- nproposals = i;
-
- for ((p = strsep(&cp, SEP)), i=0; p && *p != '\0';
- (p = strsep(&cp, SEP)), i++) {
- for (j = 0; j < nproposals; j++) {
- if (strcmp(p, sproposals[j]) == 0) {
- ret = xstrdup(p);
- if (next != NULL)
- *next = (cp == NULL) ?
- strlen(c) : cp - c;
- xfree(c);
- xfree(s);
- return ret;
- }
- }
- }
- if (next != NULL)
- *next = strlen(c);
- xfree(c);
- xfree(s);
- return NULL;
-}
diff --git a/usr/src/cmd/ssh/libssh/common/misc.c b/usr/src/cmd/ssh/libssh/common/misc.c
deleted file mode 100644
index e73d3f364b..0000000000
--- a/usr/src/cmd/ssh/libssh/common/misc.c
+++ /dev/null
@@ -1,702 +0,0 @@
-/*
- * Copyright (c) 2000 Markus Friedl. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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.
- */
-/*
- * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
- */
-
-#include "includes.h"
-RCSID("$OpenBSD: misc.c,v 1.19 2002/03/04 17:27:39 stevesk Exp $");
-
-#include "misc.h"
-#include "log.h"
-#include "xmalloc.h"
-
-/* remove newline at end of string */
-char *
-chop(char *s)
-{
- char *t = s;
- while (*t) {
- if (*t == '\n' || *t == '\r') {
- *t = '\0';
- return s;
- }
- t++;
- }
- return s;
-
-}
-
-/* set/unset filedescriptor to non-blocking */
-void
-set_nonblock(int fd)
-{
- int val;
-
- val = fcntl(fd, F_GETFL, 0);
- if (val < 0) {
- error("fcntl(%d, F_GETFL, 0): %s", fd, strerror(errno));
- return;
- }
- if (val & O_NONBLOCK) {
- debug2("fd %d is O_NONBLOCK", fd);
- return;
- }
- debug("fd %d setting O_NONBLOCK", fd);
- val |= O_NONBLOCK;
- if (fcntl(fd, F_SETFL, val) == -1)
- debug("fcntl(%d, F_SETFL, O_NONBLOCK): %s",
- fd, strerror(errno));
-}
-
-void
-unset_nonblock(int fd)
-{
- int val;
-
- val = fcntl(fd, F_GETFL, 0);
- if (val < 0) {
- error("fcntl(%d, F_GETFL, 0): %s", fd, strerror(errno));
- return;
- }
- if (!(val & O_NONBLOCK)) {
- debug2("fd %d is not O_NONBLOCK", fd);
- return;
- }
- debug("fd %d clearing O_NONBLOCK", fd);
- val &= ~O_NONBLOCK;
- if (fcntl(fd, F_SETFL, val) == -1)
- debug("fcntl(%d, F_SETFL, O_NONBLOCK): %s",
- fd, strerror(errno));
-}
-
-/* disable nagle on socket */
-void
-set_nodelay(int fd)
-{
- int opt;
- socklen_t optlen;
-
- optlen = sizeof opt;
- if (getsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &opt, &optlen) == -1) {
- error("getsockopt TCP_NODELAY: %.100s", strerror(errno));
- return;
- }
- if (opt == 1) {
- debug2("fd %d is TCP_NODELAY", fd);
- return;
- }
- opt = 1;
- debug("fd %d setting TCP_NODELAY", fd);
- if (setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &opt, sizeof opt) == -1)
- error("setsockopt TCP_NODELAY: %.100s", strerror(errno));
-}
-
-/* Characters considered whitespace in strsep calls. */
-#define WHITESPACE " \t\r\n"
-
-/*
- * Function returns a pointer to the 1st token on the line. Such a token can
- * be an empty string in the case of '*s' equal to " value". It changes the
- * first whitespace token or '=' character after the 1st token to '\0'. Upon
- * return it changes '*s' to point to the first character of the next token.
- * That token may be an empty string if the 1st token was followed only by
- * whitespace or it could be a NULL pointer if the line contained one token
- * only.
- */
-char *
-strdelim(char **s)
-{
- char *old;
- int wspace = 0;
-
- if (*s == NULL)
- return NULL;
-
- old = *s;
-
- *s = strpbrk(*s, WHITESPACE "=");
- if (*s == NULL)
- return (old);
-
- /* Allow only one '=' to be skipped */
- if (*s[0] == '=')
- wspace = 1;
- *s[0] = '\0';
-
- *s += strspn(*s + 1, WHITESPACE) + 1;
- if (*s[0] == '=' && !wspace)
- *s += strspn(*s + 1, WHITESPACE) + 1;
-
- return (old);
-}
-
-struct passwd *
-pwcopy(struct passwd *pw)
-{
- struct passwd *copy = xmalloc(sizeof(*copy));
-
- memset(copy, 0, sizeof(*copy));
- copy->pw_name = xstrdup(pw->pw_name);
- copy->pw_passwd = xstrdup(pw->pw_passwd);
- copy->pw_gecos = xstrdup(pw->pw_gecos);
- copy->pw_uid = pw->pw_uid;
- copy->pw_gid = pw->pw_gid;
-#ifdef HAVE_PW_EXPIRE_IN_PASSWD
- copy->pw_expire = pw->pw_expire;
-#endif
-#ifdef HAVE_PW_CHANGE_IN_PASSWD
- copy->pw_change = pw->pw_change;
-#endif
-#ifdef HAVE_PW_CLASS_IN_PASSWD
- copy->pw_class = xstrdup(pw->pw_class);
-#endif
- copy->pw_dir = xstrdup(pw->pw_dir);
- copy->pw_shell = xstrdup(pw->pw_shell);
- return copy;
-}
-
-void
-pwfree(struct passwd **pw)
-{
- struct passwd *p;
-
- if (pw == NULL || *pw == NULL)
- return;
-
- p = *pw;
- *pw = NULL;
-
- xfree(p->pw_name);
- xfree(p->pw_passwd);
- xfree(p->pw_gecos);
-#ifdef HAVE_PW_CLASS_IN_PASSWD
- xfree(p->pw_class);
-#endif
- xfree(p->pw_dir);
- xfree(p->pw_shell);
- xfree(p);
-}
-
-/*
- * Convert ASCII string to TCP/IP port number.
- * Port must be >0 and <=65535.
- * Return 0 if invalid.
- */
-int
-a2port(const char *s)
-{
- long port;
- char *endp;
-
- errno = 0;
- port = strtol(s, &endp, 0);
- if (s == endp || *endp != '\0' ||
- (errno == ERANGE && (port == LONG_MIN || port == LONG_MAX)) ||
- port <= 0 || port > 65535)
- return 0;
-
- return port;
-}
-
-#define SECONDS 1
-#define MINUTES (SECONDS * 60)
-#define HOURS (MINUTES * 60)
-#define DAYS (HOURS * 24)
-#define WEEKS (DAYS * 7)
-
-/*
- * Convert a time string into seconds; format is
- * a sequence of:
- * time[qualifier]
- *
- * Valid time qualifiers are:
- * <none> seconds
- * s|S seconds
- * m|M minutes
- * h|H hours
- * d|D days
- * w|W weeks
- *
- * Examples:
- * 90m 90 minutes
- * 1h30m 90 minutes
- * 2d 2 days
- * 1w 1 week
- *
- * Return -1 if time string is invalid.
- */
-long
-convtime(const char *s)
-{
- long total, secs;
- const char *p;
- char *endp;
-
- errno = 0;
- total = 0;
- p = s;
-
- if (p == NULL || *p == '\0')
- return -1;
-
- while (*p) {
- secs = strtol(p, &endp, 10);
- if (p == endp ||
- (errno == ERANGE && (secs == LONG_MIN || secs == LONG_MAX)) ||
- secs < 0)
- return -1;
-
- switch (*endp++) {
- case '\0':
- endp--;
- break;
- case 's':
- case 'S':
- break;
- case 'm':
- case 'M':
- secs *= MINUTES;
- break;
- case 'h':
- case 'H':
- secs *= HOURS;
- break;
- case 'd':
- case 'D':
- secs *= DAYS;
- break;
- case 'w':
- case 'W':
- secs *= WEEKS;
- break;
- default:
- return -1;
- }
- total += secs;
- if (total < 0)
- return -1;
- p = endp;
- }
-
- return total;
-}
-
-/*
- * Search for next delimiter between hostnames/addresses and ports.
- * Argument may be modified (for termination).
- * Returns *cp if parsing succeeds.
- * *cp is set to the start of the next delimiter, if one was found.
- * If this is the last field, *cp is set to NULL.
- */
-char *
-hpdelim(char **cp)
-{
- char *s, *old;
-
- if (cp == NULL || *cp == NULL)
- return NULL;
-
- old = s = *cp;
- if (*s == '[') {
- if ((s = strchr(s, ']')) == NULL)
- return NULL;
- else
- s++;
- } else if ((s = strpbrk(s, ":/")) == NULL)
- s = *cp + strlen(*cp); /* skip to end (see first case below) */
-
- switch (*s) {
- case '\0':
- *cp = NULL; /* no more fields*/
- break;
-
- case ':':
- case '/':
- *s = '\0'; /* terminate */
- *cp = s + 1;
- break;
-
- default:
- return NULL;
- }
-
- return old;
-}
-
-char *
-cleanhostname(char *host)
-{
- if (*host == '[' && host[strlen(host) - 1] == ']') {
- host[strlen(host) - 1] = '\0';
- return (host + 1);
- } else
- return host;
-}
-
-char *
-colon(char *cp)
-{
- int flag = 0;
-
- if (*cp == ':') /* Leading colon is part of file name. */
- return (0);
- if (*cp == '[')
- flag = 1;
-
- for (; *cp; ++cp) {
- if (*cp == '@' && *(cp+1) == '[')
- flag = 1;
- if (*cp == ']' && *(cp+1) == ':' && flag)
- return (cp+1);
- if (*cp == ':' && !flag)
- return (cp);
- if (*cp == '/')
- return (0);
- }
- return (0);
-}
-
-/* function to assist building execv() arguments */
-/* PRINTFLIKE2 */
-void
-addargs(arglist *args, char *fmt, ...)
-{
- va_list ap;
- char buf[1024];
-
- va_start(ap, fmt);
- vsnprintf(buf, sizeof(buf), fmt, ap);
- va_end(ap);
-
- if (args->list == NULL) {
- args->nalloc = 32;
- args->num = 0;
- } else if (args->num+2 >= args->nalloc)
- args->nalloc *= 2;
-
- args->list = xrealloc(args->list, args->nalloc * sizeof(char *));
- args->list[args->num++] = xstrdup(buf);
- args->list[args->num] = NULL;
-}
-
-void
-replacearg(arglist *args, u_int which, char *fmt, ...)
-{
- va_list ap;
- char *cp;
- int r;
-
- va_start(ap, fmt);
- r = vasprintf(&cp, fmt, ap);
- va_end(ap);
- if (r == -1)
- fatal("replacearg: argument too long");
-
- if (which >= args->num)
- fatal("replacearg: tried to replace invalid arg %d >= %d",
- which, args->num);
- xfree(args->list[which]);
- args->list[which] = cp;
-}
-
-void
-freeargs(arglist *args)
-{
- u_int i;
-
- if (args->list != NULL) {
- for (i = 0; i < args->num; i++)
- xfree(args->list[i]);
- xfree(args->list);
- args->nalloc = args->num = 0;
- args->list = NULL;
- }
-}
-
-/*
- * Expand a string with a set of %[char] escapes. A number of escapes may be
- * specified as (char *escape_chars, char *replacement) pairs. The list must
- * be terminated by a NULL escape_char. Returns replaced string in memory
- * allocated by xmalloc.
- */
-char *
-percent_expand(const char *string, ...)
-{
-#define EXPAND_MAX_KEYS 16
- struct {
- const char *key;
- const char *repl;
- } keys[EXPAND_MAX_KEYS];
- u_int num_keys, i, j;
- char buf[4096];
- va_list ap;
-
- /* Gather keys */
- va_start(ap, string);
- for (num_keys = 0; num_keys < EXPAND_MAX_KEYS; num_keys++) {
- keys[num_keys].key = va_arg(ap, char *);
- if (keys[num_keys].key == NULL)
- break;
- keys[num_keys].repl = va_arg(ap, char *);
- if (keys[num_keys].repl == NULL)
- fatal("percent_expand: NULL replacement");
- }
- va_end(ap);
-
- if (num_keys >= EXPAND_MAX_KEYS)
- fatal("percent_expand: too many keys");
-
- /* Expand string */
- *buf = '\0';
- for (i = 0; *string != '\0'; string++) {
- if (*string != '%') {
- append:
- buf[i++] = *string;
- if (i >= sizeof(buf))
- fatal("percent_expand: string too long");
- buf[i] = '\0';
- continue;
- }
- string++;
- if (*string == '%')
- goto append;
- for (j = 0; j < num_keys; j++) {
- if (strchr(keys[j].key, *string) != NULL) {
- i = strlcat(buf, keys[j].repl, sizeof(buf));
- if (i >= sizeof(buf))
- fatal("percent_expand: string too long");
- break;
- }
- }
- if (j >= num_keys)
- fatal("percent_expand: unknown key %%%c", *string);
- }
- return (xstrdup(buf));
-#undef EXPAND_MAX_KEYS
-}
-
-/*
- * Ensure that file descriptors 0, 1 and 2 are open or directed to /dev/null,
- * do not touch those that are already open.
- */
-void
-sanitise_stdfd(void)
-{
- int nullfd, dupfd;
-
- if ((nullfd = dupfd = open(_PATH_DEVNULL, O_RDWR)) == -1) {
- fprintf(stderr, "Couldn't open /dev/null: %s", strerror(errno));
- exit(1);
- }
- while (++dupfd <= 2) {
- /* Only clobber closed fds */
- if (fcntl(dupfd, F_GETFL, 0) >= 0)
- continue;
- if (dup2(nullfd, dupfd) == -1) {
- fprintf(stderr, "dup2: %s", strerror(errno));
- exit(1);
- }
- }
- if (nullfd > 2)
- close(nullfd);
-}
-
-char *
-tohex(const void *vp, size_t l)
-{
- const u_char *p = (const u_char *)vp;
- char b[3], *r;
- size_t i, hl;
-
- if (l > 65536)
- return xstrdup("tohex: length > 65536");
-
- hl = l * 2 + 1;
- r = xcalloc(1, hl);
- for (i = 0; i < l; i++) {
- snprintf(b, sizeof(b), "%02x", p[i]);
- strlcat(r, b, hl);
- }
- return (r);
-}
-
-u_int64_t
-get_u64(const void *vp)
-{
- const u_char *p = (const u_char *)vp;
- u_int64_t v;
-
- v = (u_int64_t)p[0] << 56;
- v |= (u_int64_t)p[1] << 48;
- v |= (u_int64_t)p[2] << 40;
- v |= (u_int64_t)p[3] << 32;
- v |= (u_int64_t)p[4] << 24;
- v |= (u_int64_t)p[5] << 16;
- v |= (u_int64_t)p[6] << 8;
- v |= (u_int64_t)p[7];
-
- return (v);
-}
-
-u_int32_t
-get_u32(const void *vp)
-{
- const u_char *p = (const u_char *)vp;
- u_int32_t v;
-
- v = (u_int32_t)p[0] << 24;
- v |= (u_int32_t)p[1] << 16;
- v |= (u_int32_t)p[2] << 8;
- v |= (u_int32_t)p[3];
-
- return (v);
-}
-
-u_int16_t
-get_u16(const void *vp)
-{
- const u_char *p = (const u_char *)vp;
- u_int16_t v;
-
- v = (u_int16_t)p[0] << 8;
- v |= (u_int16_t)p[1];
-
- return (v);
-}
-
-void
-put_u64(void *vp, u_int64_t v)
-{
- u_char *p = (u_char *)vp;
-
- p[0] = (u_char)(v >> 56) & 0xff;
- p[1] = (u_char)(v >> 48) & 0xff;
- p[2] = (u_char)(v >> 40) & 0xff;
- p[3] = (u_char)(v >> 32) & 0xff;
- p[4] = (u_char)(v >> 24) & 0xff;
- p[5] = (u_char)(v >> 16) & 0xff;
- p[6] = (u_char)(v >> 8) & 0xff;
- p[7] = (u_char)v & 0xff;
-}
-
-void
-put_u32(void *vp, u_int32_t v)
-{
- u_char *p = (u_char *)vp;
-
- p[0] = (u_char)(v >> 24) & 0xff;
- p[1] = (u_char)(v >> 16) & 0xff;
- p[2] = (u_char)(v >> 8) & 0xff;
- p[3] = (u_char)v & 0xff;
-}
-
-
-void
-put_u16(void *vp, u_int16_t v)
-{
- u_char *p = (u_char *)vp;
-
- p[0] = (u_char)(v >> 8) & 0xff;
- p[1] = (u_char)v & 0xff;
-}
-
-mysig_t
-mysignal(int sig, mysig_t act)
-{
-#ifdef HAVE_SIGACTION
- struct sigaction sa, osa;
-
- if (sigaction(sig, NULL, &osa) == -1)
- return (mysig_t) -1;
- if (osa.sa_handler != act) {
- memset(&sa, 0, sizeof(sa));
- sigemptyset(&sa.sa_mask);
- sa.sa_flags = 0;
-#if defined(SA_INTERRUPT)
- if (sig == SIGALRM)
- sa.sa_flags |= SA_INTERRUPT;
-#endif
- sa.sa_handler = act;
- if (sigaction(sig, &sa, NULL) == -1)
- return (mysig_t) -1;
- }
- return (osa.sa_handler);
-#else
- return (signal(sig, act));
-#endif
-}
-
-/*
- * Return true if argument is one of "yes", "true", "no" or "false". If
- * 'active' is 0 than we are in a non-matching Host section of the
- * configuration file so we check the syntax but will not set the value of
- * '*option'. Otherwise we set its value if not already set.
- */
-int
-get_yes_no_flag(int *option, const char *arg, const char *filename, int linenum,
- int active)
-{
- int value = -1;
-
- if (arg == NULL || *arg == '\0')
- fatal("%.200s line %d: Missing argument.", filename, linenum);
- if (strcmp(arg, "yes") == 0 || strcmp(arg, "true") == 0)
- value = 1;
- else if (strcmp(arg, "no") == 0 || strcmp(arg, "false") == 0)
- value = 0;
-
- if (active && *option == -1 && value != -1)
- *option = value;
-
- return (value != -1);
-}
-
-/*
- * Convert a string to lowercase. The string returned is an internally allocated
- * one so the consumer of this function is not expected to change it or free it.
- */
-char *
-tolowercase(const char *s)
-{
- int i, len;
- static int lenret = 0;
- static char *ret = NULL;
-
- /* allocate a new string if the old one it not long enough to store s */
- len = strlen(s) + 1;
- if (len > lenret) {
- if (ret != NULL)
- xfree(ret);
- ret = xmalloc(len);
- lenret = len;
- }
-
- /* process the string including the ending '\0' */
- for (i = 0; i < len; ++i)
- ret[i] = tolower(s[i]);
-
- return (ret);
-}
diff --git a/usr/src/cmd/ssh/libssh/common/mpaux.c b/usr/src/cmd/ssh/libssh/common/mpaux.c
deleted file mode 100644
index 1b77961b62..0000000000
--- a/usr/src/cmd/ssh/libssh/common/mpaux.c
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * Author: Tatu Ylonen <ylo@cs.hut.fi>
- * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
- * All rights reserved
- * This file contains various auxiliary functions related to multiple
- * precision integers.
- *
- * As far as I am concerned, the code I have written for this software
- * can be used freely for any purpose. Any derived versions of this
- * software must be clearly marked as such, and if the derived work is
- * incompatible with the protocol description in the RFC file, it must be
- * called by a name other than "ssh" or "Secure Shell".
- */
-
-#include "includes.h"
-RCSID("$OpenBSD: mpaux.c,v 1.16 2001/02/08 19:30:52 itojun Exp $");
-
-#pragma ident "%Z%%M% %I% %E% SMI"
-
-#include <openssl/bn.h>
-#include "getput.h"
-#include "xmalloc.h"
-
-#include <openssl/md5.h>
-
-#include "mpaux.h"
-
-void
-compute_session_id(u_char session_id[16],
- u_char cookie[8],
- BIGNUM* host_key_n,
- BIGNUM* session_key_n)
-{
- u_int host_key_bytes = BN_num_bytes(host_key_n);
- u_int session_key_bytes = BN_num_bytes(session_key_n);
- u_int bytes = host_key_bytes + session_key_bytes;
- u_char *buf = xmalloc(bytes);
- MD5_CTX md;
-
- BN_bn2bin(host_key_n, buf);
- BN_bn2bin(session_key_n, buf + host_key_bytes);
- MD5_Init(&md);
- MD5_Update(&md, buf, bytes);
- MD5_Update(&md, cookie, 8);
- MD5_Final(session_id, &md);
- memset(buf, 0, bytes);
- xfree(buf);
-}
diff --git a/usr/src/cmd/ssh/libssh/common/msg.c b/usr/src/cmd/ssh/libssh/common/msg.c
deleted file mode 100644
index 26c5eeec61..0000000000
--- a/usr/src/cmd/ssh/libssh/common/msg.c
+++ /dev/null
@@ -1,75 +0,0 @@
-/*
- * Copyright (c) 2002 Markus Friedl. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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.
- */
-#include "includes.h"
-RCSID("$OpenBSD: msg.c,v 1.4 2002/07/01 16:15:25 deraadt Exp $");
-
-#pragma ident "%Z%%M% %I% %E% SMI"
-
-#include "buffer.h"
-#include "getput.h"
-#include "log.h"
-#include "atomicio.h"
-#include "msg.h"
-
-void
-ssh_msg_send(int fd, u_char type, Buffer *m)
-{
- u_char buf[5];
- u_int mlen = buffer_len(m);
-
- debug3("ssh_msg_send: type %u", (unsigned int)type & 0xff);
-
- PUT_32BIT(buf, mlen + 1);
- buf[4] = type; /* 1st byte of payload is mesg-type */
- if (atomicio(write, fd, buf, sizeof(buf)) != sizeof(buf))
- fatal("ssh_msg_send: write");
- if (atomicio(write, fd, buffer_ptr(m), mlen) != mlen)
- fatal("ssh_msg_send: write");
-}
-
-int
-ssh_msg_recv(int fd, Buffer *m)
-{
- u_char buf[4];
- ssize_t res;
- u_int msg_len;
-
- debug3("ssh_msg_recv entering");
-
- res = atomicio(read, fd, buf, sizeof(buf));
- if (res != sizeof(buf)) {
- if (res == 0)
- return -1;
- fatal("ssh_msg_recv: read: header %ld", (long)res);
- }
- msg_len = GET_32BIT(buf);
- if (msg_len > 256 * 1024)
- fatal("ssh_msg_recv: read: bad msg_len %u", msg_len);
- buffer_clear(m);
- buffer_append_space(m, msg_len);
- res = atomicio(read, fd, buffer_ptr(m), msg_len);
- if (res != msg_len)
- fatal("ssh_msg_recv: read: %ld != msg_len", (long)res);
- return 0;
-}
diff --git a/usr/src/cmd/ssh/libssh/common/nchan.c b/usr/src/cmd/ssh/libssh/common/nchan.c
deleted file mode 100644
index 82a371af5b..0000000000
--- a/usr/src/cmd/ssh/libssh/common/nchan.c
+++ /dev/null
@@ -1,512 +0,0 @@
-/*
- * Copyright (c) 1999, 2000, 2001, 2002 Markus Friedl. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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.
- */
-
-#include "includes.h"
-RCSID("$OpenBSD: nchan.c,v 1.47 2002/06/19 00:27:55 deraadt Exp $");
-
-#include "ssh1.h"
-#include "ssh2.h"
-#include "buffer.h"
-#include "packet.h"
-#include "channels.h"
-#include "compat.h"
-#include "log.h"
-
-/*
- * SSH Protocol 1.5 aka New Channel Protocol
- * Thanks to Martina, Axel and everyone who left Erlangen, leaving me bored.
- * Written by Markus Friedl in October 1999
- *
- * Protocol versions 1.3 and 1.5 differ in the handshake protocol used for the
- * tear down of channels:
- *
- * 1.3: strict request-ack-protocol:
- * CLOSE ->
- * <- CLOSE_CONFIRM
- *
- * 1.5: uses variations of:
- * IEOF ->
- * <- OCLOSE
- * <- IEOF
- * OCLOSE ->
- * i.e. both sides have to close the channel
- *
- * 2.0: the EOF messages are optional
- *
- * See the debugging output from 'ssh -v' and 'sshd -d' of
- * ssh-1.2.27 as an example.
- *
- */
-
-/* functions manipulating channel states */
-/*
- * EVENTS update channel input/output states execute ACTIONS
- */
-/*
- * ACTIONS: should never update the channel states
- */
-static void chan_send_ieof1(Channel *);
-static void chan_send_oclose1(Channel *);
-static void chan_send_close2(Channel *);
-static void chan_send_eof2(Channel *);
-static void chan_send_eow2(Channel *);
-
-/* helper */
-static void chan_shutdown_write(Channel *);
-static void chan_shutdown_read(Channel *);
-
-static char *ostates[] = { "open", "drain", "wait_ieof", "closed" };
-static char *istates[] = { "open", "drain", "wait_oclose", "closed" };
-
-static void
-chan_set_istate(Channel *c, u_int next)
-{
- if (c->istate > CHAN_INPUT_CLOSED || next > CHAN_INPUT_CLOSED)
- fatal("chan_set_istate: bad state %d -> %d", c->istate, next);
- debug("channel %d: input %s -> %s", c->self, istates[c->istate],
- istates[next]);
- c->istate = next;
-}
-static void
-chan_set_ostate(Channel *c, u_int next)
-{
- if (c->ostate > CHAN_OUTPUT_CLOSED || next > CHAN_OUTPUT_CLOSED)
- fatal("chan_set_ostate: bad state %d -> %d", c->ostate, next);
- debug("channel %d: output %s -> %s", c->self, ostates[c->ostate],
- ostates[next]);
- c->ostate = next;
-}
-
-/*
- * SSH1 specific implementation of event functions
- */
-
-static void
-chan_rcvd_oclose1(Channel *c)
-{
- debug("channel %d: rcvd oclose", c->self);
- switch (c->istate) {
- case CHAN_INPUT_WAIT_OCLOSE:
- chan_set_istate(c, CHAN_INPUT_CLOSED);
- break;
- case CHAN_INPUT_OPEN:
- chan_shutdown_read(c);
- chan_send_ieof1(c);
- chan_set_istate(c, CHAN_INPUT_CLOSED);
- break;
- case CHAN_INPUT_WAIT_DRAIN:
- /* both local read_failed and remote write_failed */
- chan_send_ieof1(c);
- chan_set_istate(c, CHAN_INPUT_CLOSED);
- break;
- default:
- error("channel %d: protocol error: rcvd_oclose for istate %d",
- c->self, c->istate);
- return;
- }
-}
-void
-chan_read_failed(Channel *c)
-{
- debug("channel %d: read failed", c->self);
- switch (c->istate) {
- case CHAN_INPUT_OPEN:
- chan_shutdown_read(c);
- chan_set_istate(c, CHAN_INPUT_WAIT_DRAIN);
- break;
- default:
- error("channel %d: chan_read_failed for istate %d",
- c->self, c->istate);
- break;
- }
-}
-void
-chan_ibuf_empty(Channel *c)
-{
- debug("channel %d: ibuf empty", c->self);
- if (buffer_len(&c->input)) {
- error("channel %d: chan_ibuf_empty for non empty buffer",
- c->self);
- return;
- }
- switch (c->istate) {
- case CHAN_INPUT_WAIT_DRAIN:
- if (compat20) {
- if (!(c->flags & CHAN_CLOSE_SENT))
- chan_send_eof2(c);
- chan_set_istate(c, CHAN_INPUT_CLOSED);
- } else {
- chan_send_ieof1(c);
- chan_set_istate(c, CHAN_INPUT_WAIT_OCLOSE);
- }
- break;
- default:
- error("channel %d: chan_ibuf_empty for istate %d",
- c->self, c->istate);
- break;
- }
-}
-static void
-chan_rcvd_ieof1(Channel *c)
-{
- debug("channel %d: rcvd ieof", c->self);
- switch (c->ostate) {
- case CHAN_OUTPUT_OPEN:
- chan_set_ostate(c, CHAN_OUTPUT_WAIT_DRAIN);
- break;
- case CHAN_OUTPUT_WAIT_IEOF:
- chan_set_ostate(c, CHAN_OUTPUT_CLOSED);
- break;
- default:
- error("channel %d: protocol error: rcvd_ieof for ostate %d",
- c->self, c->ostate);
- break;
- }
-}
-static void
-chan_write_failed1(Channel *c)
-{
- debug("channel %d: write failed", c->self);
- switch (c->ostate) {
- case CHAN_OUTPUT_OPEN:
- chan_shutdown_write(c);
- chan_send_oclose1(c);
- chan_set_ostate(c, CHAN_OUTPUT_WAIT_IEOF);
- break;
- case CHAN_OUTPUT_WAIT_DRAIN:
- chan_shutdown_write(c);
- chan_send_oclose1(c);
- chan_set_ostate(c, CHAN_OUTPUT_CLOSED);
- break;
- default:
- error("channel %d: chan_write_failed for ostate %d",
- c->self, c->ostate);
- break;
- }
-}
-void
-chan_obuf_empty(Channel *c)
-{
- debug("channel %d: obuf empty", c->self);
- if (buffer_len(&c->output)) {
- error("channel %d: chan_obuf_empty for non empty buffer",
- c->self);
- return;
- }
- switch (c->ostate) {
- case CHAN_OUTPUT_WAIT_DRAIN:
- chan_shutdown_write(c);
- if (!compat20)
- chan_send_oclose1(c);
- chan_set_ostate(c, CHAN_OUTPUT_CLOSED);
- break;
- default:
- error("channel %d: internal error: obuf_empty for ostate %d",
- c->self, c->ostate);
- break;
- }
-}
-static void
-chan_send_ieof1(Channel *c)
-{
- debug("channel %d: send ieof", c->self);
- switch (c->istate) {
- case CHAN_INPUT_OPEN:
- case CHAN_INPUT_WAIT_DRAIN:
- packet_start(SSH_MSG_CHANNEL_INPUT_EOF);
- packet_put_int(c->remote_id);
- packet_send();
- break;
- default:
- error("channel %d: cannot send ieof for istate %d",
- c->self, c->istate);
- break;
- }
-}
-static void
-chan_send_oclose1(Channel *c)
-{
- debug("channel %d: send oclose", c->self);
- switch (c->ostate) {
- case CHAN_OUTPUT_OPEN:
- case CHAN_OUTPUT_WAIT_DRAIN:
- buffer_clear(&c->output);
- packet_start(SSH_MSG_CHANNEL_OUTPUT_CLOSE);
- packet_put_int(c->remote_id);
- packet_send();
- break;
- default:
- error("channel %d: cannot send oclose for ostate %d",
- c->self, c->ostate);
- break;
- }
-}
-
-/*
- * the same for SSH2
- */
-static void
-chan_rcvd_close2(Channel *c)
-{
- debug("channel %d: rcvd close", c->self);
- if (c->flags & CHAN_CLOSE_RCVD)
- error("channel %d: protocol error: close rcvd twice", c->self);
- c->flags |= CHAN_CLOSE_RCVD;
- if (c->type == SSH_CHANNEL_LARVAL) {
- /* tear down larval channels immediately */
- chan_set_ostate(c, CHAN_OUTPUT_CLOSED);
- chan_set_istate(c, CHAN_INPUT_CLOSED);
- return;
- }
- switch (c->ostate) {
- case CHAN_OUTPUT_OPEN:
- /*
- * wait until a data from the channel is consumed if a CLOSE
- * is received
- */
- chan_set_ostate(c, CHAN_OUTPUT_WAIT_DRAIN);
- break;
- }
- switch (c->istate) {
- case CHAN_INPUT_OPEN:
- chan_shutdown_read(c);
- chan_set_istate(c, CHAN_INPUT_CLOSED);
- break;
- case CHAN_INPUT_WAIT_DRAIN:
- chan_send_eof2(c);
- chan_set_istate(c, CHAN_INPUT_CLOSED);
- break;
- }
-}
-void
-chan_rcvd_eow(Channel *c)
-{
- debug2("channel %d: rcvd eow", c->self);
- switch (c->istate) {
- case CHAN_INPUT_OPEN:
- chan_shutdown_read(c);
- chan_set_istate(c, CHAN_INPUT_CLOSED);
- break;
- }
-}
-static void
-chan_rcvd_eof2(Channel *c)
-{
- debug("channel %d: rcvd eof", c->self);
- c->flags |= CHAN_EOF_RCVD;
- if (c->ostate == CHAN_OUTPUT_OPEN)
- chan_set_ostate(c, CHAN_OUTPUT_WAIT_DRAIN);
-}
-static void
-chan_write_failed2(Channel *c)
-{
- debug("channel %d: write failed", c->self);
- switch (c->ostate) {
- case CHAN_OUTPUT_OPEN:
- case CHAN_OUTPUT_WAIT_DRAIN:
- chan_shutdown_write(c);
- if (strcmp(c->ctype, "session") == 0)
- chan_send_eow2(c);
- chan_set_ostate(c, CHAN_OUTPUT_CLOSED);
- break;
- default:
- error("channel %d: chan_write_failed for ostate %d",
- c->self, c->ostate);
- break;
- }
-}
-static void
-chan_send_eof2(Channel *c)
-{
- debug("channel %d: send eof", c->self);
- switch (c->istate) {
- case CHAN_INPUT_WAIT_DRAIN:
- packet_start(SSH2_MSG_CHANNEL_EOF);
- packet_put_int(c->remote_id);
- packet_send();
- c->flags |= CHAN_EOF_SENT;
- break;
- default:
- error("channel %d: cannot send eof for istate %d",
- c->self, c->istate);
- break;
- }
-}
-static void
-chan_send_close2(Channel *c)
-{
- debug("channel %d: send close", c->self);
- if (c->ostate != CHAN_OUTPUT_CLOSED ||
- c->istate != CHAN_INPUT_CLOSED) {
- error("channel %d: cannot send close for istate/ostate %d/%d",
- c->self, c->istate, c->ostate);
- } else if (c->flags & CHAN_CLOSE_SENT) {
- error("channel %d: already sent close", c->self);
- } else {
- packet_start(SSH2_MSG_CHANNEL_CLOSE);
- packet_put_int(c->remote_id);
- packet_send();
- c->flags |= CHAN_CLOSE_SENT;
- }
-}
-static void
-chan_send_eow2(Channel *c)
-{
- debug2("channel %d: send eow", c->self);
- if (c->ostate == CHAN_OUTPUT_CLOSED) {
- error("channel %d: must not sent eow on closed output",
- c->self);
- return;
- }
- packet_start(SSH2_MSG_CHANNEL_REQUEST);
- packet_put_int(c->remote_id);
- packet_put_cstring("eow@openssh.com");
- packet_put_char(0);
- packet_send();
-}
-
-/* shared */
-
-void
-chan_rcvd_ieof(Channel *c)
-{
- if (compat20)
- chan_rcvd_eof2(c);
- else
- chan_rcvd_ieof1(c);
- if (c->ostate == CHAN_OUTPUT_WAIT_DRAIN &&
- buffer_len(&c->output) == 0 &&
- !CHANNEL_EFD_OUTPUT_ACTIVE(c))
- chan_obuf_empty(c);
-}
-void
-chan_rcvd_oclose(Channel *c)
-{
- if (compat20)
- chan_rcvd_close2(c);
- else
- chan_rcvd_oclose1(c);
-}
-void
-chan_write_failed(Channel *c)
-{
- if (compat20)
- chan_write_failed2(c);
- else
- chan_write_failed1(c);
-}
-
-void
-chan_mark_dead(Channel *c)
-{
- c->type = SSH_CHANNEL_ZOMBIE;
-}
-
-int
-chan_is_dead(Channel *c, int send)
-{
- if (c->type == SSH_CHANNEL_ZOMBIE) {
- debug("channel %d: zombie", c->self);
- return 1;
- }
- if (c->istate != CHAN_INPUT_CLOSED || c->ostate != CHAN_OUTPUT_CLOSED)
- return 0;
- if (!compat20) {
- debug("channel %d: is dead", c->self);
- return 1;
- }
- if ((datafellows & SSH_BUG_EXTEOF) &&
- c->extended_usage == CHAN_EXTENDED_WRITE &&
- c->efd != -1 &&
- buffer_len(&c->extended) > 0) {
- debug2("channel %d: active efd: %d len %d",
- c->self, c->efd, buffer_len(&c->extended));
- return 0;
- }
- if (!(c->flags & CHAN_CLOSE_SENT)) {
- if (send) {
- chan_send_close2(c);
- } else {
- /* channel would be dead if we sent a close */
- if (c->flags & CHAN_CLOSE_RCVD) {
- debug("channel %d: almost dead",
- c->self);
- return 1;
- }
- }
- }
- if ((c->flags & CHAN_CLOSE_SENT) &&
- (c->flags & CHAN_CLOSE_RCVD)) {
- debug("channel %d: is dead", c->self);
- return 1;
- }
- return 0;
-}
-
-/* helper */
-static void
-chan_shutdown_write(Channel *c)
-{
- buffer_clear(&c->output);
- if (compat20 && c->type == SSH_CHANNEL_LARVAL)
- return;
- /* shutdown failure is allowed if write failed already */
- debug("channel %d: close_write", c->self);
- if (c->sock != -1) {
- if (shutdown(c->sock, SHUT_WR) < 0)
- debug("channel %d: chan_shutdown_write: "
- "shutdown() failed for fd%d: %.100s",
- c->self, c->sock, strerror(errno));
- } else {
- if (channel_close_fd(&c->wfd) < 0)
- log("channel %d: chan_shutdown_write: "
- "close() failed for fd%d: %.100s",
- c->self, c->wfd, strerror(errno));
- }
-}
-static void
-chan_shutdown_read(Channel *c)
-{
- if (compat20 && c->type == SSH_CHANNEL_LARVAL)
- return;
- debug("channel %d: close_read", c->self);
- if (c->sock != -1) {
- /*
- * shutdown(sock, SHUT_READ) may return ENOTCONN if the
- * write side has been closed already. (bug on Linux)
- * HP-UX may return ENOTCONN also.
- */
- if (shutdown(c->sock, SHUT_RD) < 0
- && errno != ENOTCONN)
- error("channel %d: chan_shutdown_read: "
- "shutdown() failed for fd%d [i%d o%d]: %.100s",
- c->self, c->sock, c->istate, c->ostate,
- strerror(errno));
- } else {
- if (channel_close_fd(&c->rfd) < 0)
- log("channel %d: chan_shutdown_read: "
- "close() failed for fd%d: %.100s",
- c->self, c->rfd, strerror(errno));
- }
-}
diff --git a/usr/src/cmd/ssh/libssh/common/packet.c b/usr/src/cmd/ssh/libssh/common/packet.c
deleted file mode 100644
index 1221db134a..0000000000
--- a/usr/src/cmd/ssh/libssh/common/packet.c
+++ /dev/null
@@ -1,1845 +0,0 @@
-/*
- * Author: Tatu Ylonen <ylo@cs.hut.fi>
- * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
- * All rights reserved
- * This file contains code implementing the packet protocol and communication
- * with the other side. This same code is used both on client and server side.
- *
- * As far as I am concerned, the code I have written for this software
- * can be used freely for any purpose. Any derived versions of this
- * software must be clearly marked as such, and if the derived work is
- * incompatible with the protocol description in the RFC file, it must be
- * called by a name other than "ssh" or "Secure Shell".
- *
- *
- * SSH2 packet format added by Markus Friedl.
- * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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.
- */
-/*
- * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
- */
-
-/* $OpenBSD: packet.c,v 1.148 2007/06/07 19:37:34 pvalchev Exp $ */
-
-#include "includes.h"
-
-#include "sys-queue.h"
-#include "xmalloc.h"
-#include "buffer.h"
-#include "packet.h"
-#include "bufaux.h"
-#include "crc32.h"
-#include "getput.h"
-#include "compress.h"
-#include "deattack.h"
-#include "channels.h"
-#include "compat.h"
-#include "ssh1.h"
-#include "ssh2.h"
-#include "cipher.h"
-#include "kex.h"
-#include "mac.h"
-#include "log.h"
-#include "canohost.h"
-#include "misc.h"
-#include "ssh.h"
-#include "engine.h"
-
-/* PKCS#11 engine */
-ENGINE *e;
-
-#ifdef ALTPRIVSEP
-static int packet_server = 0;
-static int packet_monitor = 0;
-#endif /* ALTPRIVSEP */
-
-#ifdef PACKET_DEBUG
-#define DBG(x) x
-#else
-#define DBG(x)
-#endif
-
-static void packet_send2(void);
-
-/*
- * This variable contains the file descriptors used for communicating with
- * the other side. connection_in is used for reading; connection_out for
- * writing. These can be the same descriptor, in which case it is assumed to
- * be a socket.
- */
-static int connection_in = -1;
-static int connection_out = -1;
-
-/* Protocol flags for the remote side. */
-static u_int remote_protocol_flags = 0;
-
-/* Encryption context for receiving data. This is only used for decryption. */
-static CipherContext receive_context;
-
-/* Encryption context for sending data. This is only used for encryption. */
-static CipherContext send_context;
-
-/* Buffer for raw input data from the socket. */
-Buffer input;
-
-/* Buffer for raw output data going to the socket. */
-Buffer output;
-
-/* Buffer for the partial outgoing packet being constructed. */
-static Buffer outgoing_packet;
-
-/* Buffer for the incoming packet currently being processed. */
-static Buffer incoming_packet;
-
-/* Scratch buffer for packet compression/decompression. */
-static Buffer compression_buffer;
-static int compression_buffer_ready = 0;
-
-/* Flag indicating whether packet compression/decompression is enabled. */
-static int packet_compression = 0;
-
-/* default maximum packet size */
-int max_packet_size = 32768;
-
-/* Flag indicating whether this module has been initialized. */
-static int initialized = 0;
-
-/* Set to true if the connection is interactive. */
-static int interactive_mode = 0;
-
-/* Session key information for Encryption and MAC */
-Newkeys *newkeys[MODE_MAX];
-static struct packet_state {
- u_int32_t seqnr;
- u_int32_t packets;
- u_int64_t blocks;
-} p_read, p_send;
-
-static u_int64_t max_blocks_in, max_blocks_out;
-static u_int32_t rekey_limit;
-
-/* Session key for protocol v1 */
-static u_char ssh1_key[SSH_SESSION_KEY_LENGTH];
-static u_int ssh1_keylen;
-
-/* roundup current message to extra_pad bytes */
-static u_char extra_pad = 0;
-
-struct packet {
- TAILQ_ENTRY(packet) next;
- u_char type;
- Buffer payload;
-};
-TAILQ_HEAD(, packet) outgoing;
-
-/*
- * Part of what -f option and ~& escape sequence do in the client is that they
- * will force it to daemonize itself. Due to the fork safety rules inherent in
- * any PKCS#11 environment, if the engine is used we must do a key re-exchange
- * before forking a child to negotiate the new keys. Those keys will be used to
- * inicialize the new crypto contexts. This involves finishing the engine in the
- * parent and reinitializing it again in both processes after fork() returns.
- * This approach also leaves protocol 1 out since it doesn't support rekeying.
- */
-int will_daemonize;
-
-#ifdef PACKET_DEBUG
-/* This function dumps data onto stderr. This is for debugging only. */
-void
-data_dump(void *data, u_int len)
-{
- Buffer buf;
-
- buffer_init(&buf);
- buffer_append(&buf, data, len);
- buffer_dump(&buf);
- buffer_free(&buf);
-}
-#endif
-
-/*
- * Sets the descriptors used for communication. Disables encryption until
- * packet_set_encryption_key is called.
- */
-void
-packet_set_connection(int fd_in, int fd_out)
-{
- Cipher *none = cipher_by_name("none");
-
- if (none == NULL)
- fatal("packet_set_connection: cannot load cipher 'none'");
- connection_in = fd_in;
- connection_out = fd_out;
- cipher_init(&send_context, none, (unsigned char *) "", 0, NULL, 0, CIPHER_ENCRYPT);
- cipher_init(&receive_context, none, (unsigned char *) "", 0, NULL, 0, CIPHER_DECRYPT);
- newkeys[MODE_IN] = newkeys[MODE_OUT] = NULL;
- if (!initialized) {
- initialized = 1;
- buffer_init(&input);
- buffer_init(&output);
- buffer_init(&outgoing_packet);
- buffer_init(&incoming_packet);
- TAILQ_INIT(&outgoing);
- } else {
- buffer_clear(&input);
- buffer_clear(&output);
- buffer_clear(&outgoing_packet);
- buffer_clear(&incoming_packet);
- }
-
- /*
- * Prime the cache for get_remote_ipaddr() while we have a
- * socket on which to do a getpeername().
- */
- (void) get_remote_ipaddr();
-
- /* Kludge: arrange the close function to be called from fatal(). */
- fatal_add_cleanup((void (*) (void *)) packet_close, NULL);
-}
-
-/* Returns 1 if remote host is connected via socket, 0 if not. */
-
-int
-packet_connection_is_on_socket(void)
-{
- struct sockaddr_storage from, to;
- socklen_t fromlen, tolen;
-
- /* filedescriptors in and out are the same, so it's a socket */
- if (connection_in != -1 && connection_in == connection_out)
- return 1;
- fromlen = sizeof(from);
- memset(&from, 0, sizeof(from));
- if (getpeername(connection_in, (struct sockaddr *)&from, &fromlen) < 0)
- return 0;
- tolen = sizeof(to);
- memset(&to, 0, sizeof(to));
- if (getpeername(connection_out, (struct sockaddr *)&to, &tolen) < 0)
- return 0;
- if (fromlen != tolen || memcmp(&from, &to, fromlen) != 0)
- return 0;
- if (from.ss_family != AF_INET && from.ss_family != AF_INET6)
- return 0;
- return 1;
-}
-
-/* returns 1 if connection is via ipv4 */
-
-int
-packet_connection_is_ipv4(void)
-{
- struct sockaddr_storage to;
- socklen_t tolen = sizeof(to);
-
- memset(&to, 0, sizeof(to));
- if (getsockname(connection_out, (struct sockaddr *)&to, &tolen) < 0)
- return 0;
- if (to.ss_family == AF_INET)
- return 1;
-#ifdef IPV4_IN_IPV6
- if (to.ss_family == AF_INET6 &&
- IN6_IS_ADDR_V4MAPPED(&((struct sockaddr_in6 *)&to)->sin6_addr))
- return 1;
-#endif
- return 0;
-}
-
-/* Sets the connection into non-blocking mode. */
-
-void
-packet_set_nonblocking(void)
-{
- /* Set the socket into non-blocking mode. */
- if (fcntl(connection_in, F_SETFL, O_NONBLOCK) < 0)
- error("fcntl O_NONBLOCK: %.100s", strerror(errno));
-
- if (connection_out != connection_in) {
- if (fcntl(connection_out, F_SETFL, O_NONBLOCK) < 0)
- error("fcntl O_NONBLOCK: %.100s", strerror(errno));
- }
-}
-
-/* Returns the socket used for reading. */
-
-int
-packet_get_connection_in(void)
-{
- return connection_in;
-}
-
-/* Returns the descriptor used for writing. */
-
-int
-packet_get_connection_out(void)
-{
- return connection_out;
-}
-
-/* Closes the connection and clears and frees internal data structures. */
-
-void
-packet_close(void)
-{
- if (!initialized)
- return;
- initialized = 0;
- if (connection_in == connection_out) {
- shutdown(connection_out, SHUT_RDWR);
- close(connection_out);
- } else {
- close(connection_in);
- close(connection_out);
- }
- buffer_free(&input);
- buffer_free(&output);
- buffer_free(&outgoing_packet);
- buffer_free(&incoming_packet);
- if (compression_buffer_ready) {
- buffer_free(&compression_buffer);
- buffer_compress_uninit();
- compression_buffer_ready = 0;
- }
- cipher_cleanup(&send_context);
- cipher_cleanup(&receive_context);
-}
-
-/* Sets remote side protocol flags. */
-
-void
-packet_set_protocol_flags(u_int protocol_flags)
-{
- remote_protocol_flags = protocol_flags;
-}
-
-/* Returns the remote protocol flags set earlier by the above function. */
-
-u_int
-packet_get_protocol_flags(void)
-{
- return remote_protocol_flags;
-}
-
-/*
- * Starts packet compression from the next packet on in both directions.
- * Level is compression level 1 (fastest) - 9 (slow, best) as in gzip.
- */
-
-static void
-packet_init_compression(void)
-{
- if (compression_buffer_ready == 1)
- return;
- compression_buffer_ready = 1;
- buffer_init(&compression_buffer);
-}
-
-void
-packet_start_compression(int level)
-{
-#ifdef ALTPRIVSEP
- /* shouldn't happen! */
- if (packet_monitor)
- fatal("INTERNAL ERROR: The monitor cannot compress.");
-#endif /* ALTPRIVSEP */
-
- if (packet_compression && !compat20)
- fatal("Compression already enabled.");
- packet_compression = 1;
- packet_init_compression();
- buffer_compress_init_send(level);
- buffer_compress_init_recv();
-}
-
-/*
- * Causes any further packets to be encrypted using the given key. The same
- * key is used for both sending and reception. However, both directions are
- * encrypted independently of each other.
- */
-
-void
-packet_set_encryption_key(const u_char *key, u_int keylen,
- int number)
-{
- Cipher *cipher = cipher_by_number(number);
-
- if (cipher == NULL)
- fatal("packet_set_encryption_key: unknown cipher number %d", number);
- if (keylen < 20)
- fatal("packet_set_encryption_key: keylen too small: %d", keylen);
- if (keylen > SSH_SESSION_KEY_LENGTH)
- fatal("packet_set_encryption_key: keylen too big: %d", keylen);
- memcpy(ssh1_key, key, keylen);
- ssh1_keylen = keylen;
- cipher_init(&send_context, cipher, key, keylen, NULL, 0, CIPHER_ENCRYPT);
- cipher_init(&receive_context, cipher, key, keylen, NULL, 0, CIPHER_DECRYPT);
-}
-
-u_int
-packet_get_encryption_key(u_char *key)
-{
- if (key == NULL)
- return (ssh1_keylen);
- memcpy(key, ssh1_key, ssh1_keylen);
- return (ssh1_keylen);
-}
-
-/* Start constructing a packet to send. */
-void
-packet_start(u_char type)
-{
- u_char buf[9];
- int len;
-
- DBG(debug("packet_start[%d]", type));
- len = compat20 ? 6 : 9;
- memset(buf, 0, len - 1);
- buf[len - 1] = type;
- buffer_clear(&outgoing_packet);
- buffer_append(&outgoing_packet, buf, len);
-}
-
-/* Append payload. */
-void
-packet_put_char(int value)
-{
- char ch = value;
-
- buffer_append(&outgoing_packet, &ch, 1);
-}
-
-void
-packet_put_int(u_int value)
-{
- buffer_put_int(&outgoing_packet, value);
-}
-
-void
-packet_put_string(const void *buf, u_int len)
-{
- buffer_put_string(&outgoing_packet, buf, len);
-}
-
-void
-packet_put_cstring(const char *str)
-{
- buffer_put_cstring(&outgoing_packet, str);
-}
-
-void
-packet_put_utf8_cstring(const char *str)
-{
- if (datafellows & SSH_BUG_STRING_ENCODING)
- buffer_put_cstring(&outgoing_packet, str);
- else
- buffer_put_utf8_cstring(&outgoing_packet, str);
-}
-
-void
-packet_put_utf8_string(const char *str, uint_t len)
-{
- if (datafellows & SSH_BUG_STRING_ENCODING)
- buffer_put_string(&outgoing_packet, str, len);
- else
- buffer_put_utf8_string(&outgoing_packet, str, len);
-}
-
-void
-packet_put_raw(const void *buf, u_int len)
-{
- buffer_append(&outgoing_packet, buf, len);
-}
-
-void
-packet_put_bignum(BIGNUM * value)
-{
- buffer_put_bignum(&outgoing_packet, value);
-}
-
-void
-packet_put_bignum2(BIGNUM * value)
-{
- buffer_put_bignum2(&outgoing_packet, value);
-}
-
-/*
- * Finalizes and sends the packet. If the encryption key has been set,
- * encrypts the packet before sending.
- */
-
-static void
-packet_send1(void)
-{
- u_char buf[8], *cp;
- int i, padding, len;
- u_int checksum;
- u_int32_t rnd = 0;
-
- /*
- * If using packet compression, compress the payload of the outgoing
- * packet.
- */
- if (packet_compression) {
- buffer_clear(&compression_buffer);
- /* Skip padding. */
- buffer_consume(&outgoing_packet, 8);
- /* padding */
- buffer_append(&compression_buffer, "\0\0\0\0\0\0\0\0", 8);
- buffer_compress(&outgoing_packet, &compression_buffer);
- buffer_clear(&outgoing_packet);
- buffer_append(&outgoing_packet, buffer_ptr(&compression_buffer),
- buffer_len(&compression_buffer));
- }
- /* Compute packet length without padding (add checksum, remove padding). */
- len = buffer_len(&outgoing_packet) + 4 - 8;
-
- /* Insert padding. Initialized to zero in packet_start1() */
- padding = 8 - len % 8;
- if (!send_context.plaintext) {
- cp = buffer_ptr(&outgoing_packet);
- for (i = 0; i < padding; i++) {
- if (i % 4 == 0)
- rnd = arc4random();
- cp[7 - i] = rnd & 0xff;
- rnd >>= 8;
- }
- }
- buffer_consume(&outgoing_packet, 8 - padding);
-
- /* Add check bytes. */
- checksum = ssh_crc32(buffer_ptr(&outgoing_packet),
- buffer_len(&outgoing_packet));
- PUT_32BIT(buf, checksum);
- buffer_append(&outgoing_packet, buf, 4);
-
-#ifdef PACKET_DEBUG
- fprintf(stderr, "packet_send plain: ");
- buffer_dump(&outgoing_packet);
-#endif
-
- /* Append to output. */
- PUT_32BIT(buf, len);
- buffer_append(&output, buf, 4);
- cp = buffer_append_space(&output, buffer_len(&outgoing_packet));
- cipher_crypt(&send_context, cp, buffer_ptr(&outgoing_packet),
- buffer_len(&outgoing_packet));
-
-#ifdef PACKET_DEBUG
- debug("encrypted output queue now contains (%d bytes):\n",
- buffer_len(&output));
- buffer_dump(&output);
-#endif
-
- buffer_clear(&outgoing_packet);
-
- /*
- * Note that the packet is now only buffered in output. It won\'t be
- * actually sent until packet_write_wait or packet_write_poll is
- * called.
- */
-}
-
-void
-set_newkeys(int mode)
-{
- Enc *enc;
- Mac *mac;
- Comp *comp;
- CipherContext *cc;
- u_int64_t *max_blocks;
- int crypt_type;
-
- debug2("set_newkeys: mode %d", mode);
-
- if (mode == MODE_OUT) {
- cc = &send_context;
- crypt_type = CIPHER_ENCRYPT;
- p_send.packets = p_send.blocks = 0;
- max_blocks = &max_blocks_out;
- } else {
- cc = &receive_context;
- crypt_type = CIPHER_DECRYPT;
- p_read.packets = p_read.blocks = 0;
- max_blocks = &max_blocks_in;
- }
-
- debug("set_newkeys: setting new keys for '%s' mode",
- mode == MODE_IN ? "in" : "out");
-
- if (newkeys[mode] != NULL) {
- cipher_cleanup(cc);
- free_keys(newkeys[mode]);
- }
-
- newkeys[mode] = kex_get_newkeys(mode);
- if (newkeys[mode] == NULL)
- fatal("newkeys: no keys for mode %d", mode);
- enc = &newkeys[mode]->enc;
- mac = &newkeys[mode]->mac;
- comp = &newkeys[mode]->comp;
- if (mac_init(mac) == 0)
- mac->enabled = 1;
-#ifdef PACKET_DEBUG
- debug("new encryption key:\n");
- data_dump(enc->key, enc->key_len);
- debug("new encryption IV:\n");
- data_dump(enc->iv, enc->block_size);
- debug("new MAC key:\n");
- data_dump(mac->key, mac->key_len);
-#endif
- cipher_init(cc, enc->cipher, enc->key, enc->key_len,
- enc->iv, enc->block_size, crypt_type);
- /* Deleting the keys does not gain extra security */
- /* memset(enc->iv, 0, enc->block_size);
- memset(enc->key, 0, enc->key_len); */
- if (comp->type != 0 && comp->enabled == 0) {
- packet_init_compression();
- if (mode == MODE_OUT)
- buffer_compress_init_send(6);
- else
- buffer_compress_init_recv();
- comp->enabled = 1;
- }
-
- /*
- * In accordance to the RFCs listed below we enforce the key
- * re-exchange for:
- *
- * - every 1GB of transmitted data if the selected cipher block size
- * is less than 16 bytes (3DES, Blowfish)
- * - every 2^(2*B) cipher blocks transmitted (B is block size in bytes)
- * if the cipher block size is greater than or equal to 16 bytes (AES)
- * - and we never send more than 2^32 SSH packets using the same keys.
- * The recommendation of 2^31 packets is not enforced here but in
- * packet_need_rekeying(). There is also a hard check in
- * packet_send2_wrapped() that we don't send more than 2^32 packets.
- *
- * Note that if the SSH_BUG_NOREKEY compatibility flag is set then no
- * automatic rekeying is performed nor do we enforce the 3rd rule.
- * This means that we can be always forced by the opposite side to never
- * initiate automatic key re-exchange. This might change in the future.
- *
- * The RekeyLimit option keyword may only enforce more frequent key
- * renegotiation, never less. For more information on key renegotiation,
- * see:
- *
- * - RFC 4253 (SSH Transport Layer Protocol), section "9. Key
- * Re-Exchange"
- * - RFC 4344 (SSH Transport Layer Encryption Modes), sections "3.
- * Rekeying" and "6.1 Rekeying Considerations"
- */
- if (enc->block_size >= 16)
- *max_blocks = (u_int64_t)1 << (enc->block_size * 2);
- else
- *max_blocks = ((u_int64_t)1 << 30) / enc->block_size;
-
- if (rekey_limit)
- *max_blocks = MIN(*max_blocks, rekey_limit / enc->block_size);
-}
-
-void
-free_keys(Newkeys *keys)
-{
- Enc *enc;
- Mac *mac;
- Comp *comp;
-
- enc = &keys->enc;
- mac = &keys->mac;
- comp = &keys->comp;
- xfree(enc->name);
- xfree(enc->iv);
- xfree(enc->key);
-
- memset(mac->key, 0, mac->key_len);
- xfree(mac->key);
- xfree(mac->name);
- mac_clear(mac);
-
- xfree(comp->name);
- xfree(keys);
-}
-
-/*
- * Process SSH2_MSG_NEWKEYS message. If we are using the engine we must have
- * both SSH2_MSG_NEWKEYS processed before we can finish the engine, fork, and
- * reinitialize the crypto contexts. We can't fork before processing the 2nd
- * message otherwise we couldn't encrypt/decrypt that message at all - note that
- * parent's PKCS#11 sessions are useless after the fork and we must process
- * both SSH2_MSG_NEWKEYS messages using the old keys.
- */
-void
-process_newkeys(int mode)
-{
- /* this function is for the client only */
- if (packet_is_server() != 0)
- return;
-
- if (will_daemonize == FIRST_NEWKEYS_PROCESSED) {
- debug3("both SSH2_MSG_NEWKEYS processed, will daemonize now");
- cipher_cleanup(&send_context);
- cipher_cleanup(&receive_context);
- pkcs11_engine_finish(e);
- if (daemon(1, 1) < 0) {
- fatal("daemon() failed: %.200s",
- strerror(errno));
- }
- e = pkcs11_engine_load(e != NULL ? 1 : 0);
-
- set_newkeys(MODE_OUT);
- set_newkeys(MODE_IN);
- will_daemonize = SECOND_NEWKEYS_PROCESSED;
- packet_send2();
- } else {
- if (will_daemonize == DAEMONIZING_REQUESTED)
- will_daemonize = FIRST_NEWKEYS_PROCESSED;
- else
- set_newkeys(mode);
- }
-}
-
-/*
- * Finalize packet in SSH2 format (compress, mac, encrypt, enqueue)
- */
-static void
-packet_send2_wrapped(void)
-{
- u_char type, *cp, *macbuf = NULL;
- u_char padlen, pad;
- u_int packet_length = 0;
- u_int i, len;
- u_int32_t rnd = 0;
- Enc *enc = NULL;
- Mac *mac = NULL;
- Comp *comp = NULL;
- int block_size;
-
- if (newkeys[MODE_OUT] != NULL) {
- enc = &newkeys[MODE_OUT]->enc;
- mac = &newkeys[MODE_OUT]->mac;
- comp = &newkeys[MODE_OUT]->comp;
- }
- block_size = enc ? enc->block_size : 8;
-
- cp = buffer_ptr(&outgoing_packet);
- type = cp[5];
-
-#ifdef PACKET_DEBUG
- debug("plain output packet to be processed (%d bytes):\n",
- buffer_len(&outgoing_packet));
- buffer_dump(&outgoing_packet);
-#endif
-
- if (comp && comp->enabled) {
- len = buffer_len(&outgoing_packet);
- /* skip header, compress only payload */
- buffer_consume(&outgoing_packet, 5);
- buffer_clear(&compression_buffer);
- buffer_compress(&outgoing_packet, &compression_buffer);
- buffer_clear(&outgoing_packet);
- buffer_append(&outgoing_packet, "\0\0\0\0\0", 5);
- buffer_append(&outgoing_packet, buffer_ptr(&compression_buffer),
- buffer_len(&compression_buffer));
- DBG(debug("compression: raw %d compressed %d", len,
- buffer_len(&outgoing_packet)));
- }
-
- /* sizeof (packet_len + pad_len + payload) */
- len = buffer_len(&outgoing_packet);
-
- /*
- * calc size of padding, alloc space, get random data,
- * minimum padding is 4 bytes
- */
- padlen = block_size - (len % block_size);
- if (padlen < 4)
- padlen += block_size;
- if (extra_pad) {
- /* will wrap if extra_pad+padlen > 255 */
- extra_pad = roundup(extra_pad, block_size);
- pad = extra_pad - ((len + padlen) % extra_pad);
- debug3("packet_send2: adding %d (len %d padlen %d extra_pad %d)",
- pad, len, padlen, extra_pad);
- padlen += pad;
- extra_pad = 0;
- }
- cp = buffer_append_space(&outgoing_packet, padlen);
- if (enc && !send_context.plaintext) {
- /* random padding */
- for (i = 0; i < padlen; i++) {
- if (i % 4 == 0)
- rnd = arc4random();
- cp[i] = rnd & 0xff;
- rnd >>= 8;
- }
- } else {
- /* clear padding */
- memset(cp, 0, padlen);
- }
- /* packet_length includes payload, padding and padding length field */
- packet_length = buffer_len(&outgoing_packet) - 4;
- cp = buffer_ptr(&outgoing_packet);
- PUT_32BIT(cp, packet_length);
- cp[4] = padlen;
- DBG(debug("will send %d bytes (includes padlen %d)",
- packet_length + 4, padlen));
-
- /* compute MAC over seqnr and packet(length fields, payload, padding) */
- if (mac && mac->enabled) {
- macbuf = mac_compute(mac, p_send.seqnr,
- buffer_ptr(&outgoing_packet),
- buffer_len(&outgoing_packet));
- DBG(debug("done calc MAC out #%d", p_send.seqnr));
- }
- /* encrypt packet and append to output buffer. */
- cp = buffer_append_space(&output, buffer_len(&outgoing_packet));
- cipher_crypt(&send_context, cp, buffer_ptr(&outgoing_packet),
- buffer_len(&outgoing_packet));
- /* append unencrypted MAC */
- if (mac && mac->enabled)
- buffer_append(&output, (char *)macbuf, mac->mac_len);
-#ifdef PACKET_DEBUG
- debug("encrypted output queue now contains (%d bytes):\n",
- buffer_len(&output));
- buffer_dump(&output);
-#endif
- /* increment sequence number for outgoing packets */
- if (++p_send.seqnr == 0)
- log("outgoing seqnr wraps around");
-
- /*
- * RFC 4344: 3.1. First Rekeying Recommendation
- *
- * "Because of possible information leakage through the MAC tag after a
- * key exchange, .... an SSH implementation SHOULD NOT send more than
- * 2**32 packets before rekeying again."
- *
- * The code below is a hard check so that we are sure we don't go across
- * the suggestion. However, since the largest cipher block size we have
- * (AES) is 16 bytes we can't reach 2^32 SSH packets encrypted with the
- * same key while performing periodic rekeying.
- */
- if (++p_send.packets == 0)
- if (!(datafellows & SSH_BUG_NOREKEY))
- fatal("too many packets encrypted with same key");
- p_send.blocks += (packet_length + 4) / block_size;
- buffer_clear(&outgoing_packet);
-
- if (type == SSH2_MSG_NEWKEYS) {
- /*
- * set_newkeys(MODE_OUT) in the client. Note that in the
- * unprivileged child, set_newkeys() for MODE_OUT are set after
- * SSH2_MSG_NEWKEYS is read from the monitor and forwarded to
- * the client side.
- */
- process_newkeys(MODE_OUT);
- }
-}
-
-/*
- * Packets we deal with here are plain until we encrypt them in
- * packet_send2_wrapped().
- *
- * As already mentioned in a comment at process_newkeys() function we must not
- * fork() until both SSH2_MSG_NEWKEYS packets were processed. Until this is done
- * we must queue all packets so that they can be encrypted with the new keys and
- * then sent to the other side. However, what can happen here is that we get
- * SSH2_MSG_NEWKEYS after we sent it. In that situation we must call
- * packet_send2() anyway to empty the queue, and set the rekey flag to the
- * finished state. If we didn't do that we would just hang and enqueue data.
- */
-static void
-packet_send2(void)
-{
- static int rekeying = 0;
- struct packet *p;
- u_char type, *cp;
-
- if (will_daemonize != SECOND_NEWKEYS_PROCESSED) {
- cp = buffer_ptr(&outgoing_packet);
- type = cp[5];
-
- /* during rekeying we can only send key exchange messages */
- if (rekeying) {
- if (!((type >= SSH2_MSG_TRANSPORT_MIN) &&
- (type <= SSH2_MSG_TRANSPORT_MAX))) {
- debug("enqueue a plain packet because rekex in "
- "progress [type %u]", type);
- p = xmalloc(sizeof(*p));
- p->type = type;
- memcpy(&p->payload, &outgoing_packet, sizeof(Buffer));
- buffer_init(&outgoing_packet);
- TAILQ_INSERT_TAIL(&outgoing, p, next);
- return;
- }
- }
-
- /* rekeying starts with sending KEXINIT */
- if (type == SSH2_MSG_KEXINIT)
- rekeying = 1;
-
- packet_send2_wrapped();
- }
-
- /* after rekex is done we can process the queue of plain packets */
- if (will_daemonize == SECOND_NEWKEYS_PROCESSED ||
- (will_daemonize == NOT_DAEMONIZING && type == SSH2_MSG_NEWKEYS)) {
- rekeying = 0;
- will_daemonize = NOT_DAEMONIZING;
- while ((p = TAILQ_FIRST(&outgoing)) != NULL) {
- type = p->type;
- debug("dequeuing a plain packet since rekex is over "
- "[type %u]", type);
- buffer_free(&outgoing_packet);
- memcpy(&outgoing_packet, &p->payload, sizeof(Buffer));
- TAILQ_REMOVE(&outgoing, p, next);
- xfree(p);
- packet_send2_wrapped();
- }
- }
-}
-
-void
-packet_send(void)
-{
- if (compat20)
- packet_send2();
- else
- packet_send1();
- DBG(debug("packet_send done"));
-}
-
-/*
- * Waits until a packet has been received, and returns its type. Note that
- * no other data is processed until this returns, so this function should not
- * be used during the interactive session.
- *
- * The function is also used in the monitor to read the authentication context
- * in aps_read_auth_context() via packet_read_seqnr(), before the monitor enters
- * aps_monitor_loop() and starts using the process_input() function.
- */
-int
-packet_read_seqnr(u_int32_t *seqnr_p)
-{
- int type, len;
- fd_set *setp;
- char buf[8192];
- DBG(debug("packet_read()"));
-
- setp = (fd_set *)xmalloc(howmany(connection_in+1, NFDBITS) *
- sizeof(fd_mask));
-
- /* Since we are blocking, ensure that all written packets have been sent. */
- packet_write_wait();
-
- /* Stay in the loop until we have received a complete packet. */
- for (;;) {
- /* Try to read a packet from the buffer. */
- type = packet_read_poll_seqnr(seqnr_p);
- if (!compat20 && (
- type == SSH_SMSG_SUCCESS
- || type == SSH_SMSG_FAILURE
- || type == SSH_CMSG_EOF
- || type == SSH_CMSG_EXIT_CONFIRMATION))
- packet_check_eom();
- /* If we got a packet, return it. */
- if (type != SSH_MSG_NONE) {
- xfree(setp);
- return type;
- }
- /*
- * Otherwise, wait for some data to arrive, add it to the
- * buffer, and try again.
- */
- memset(setp, 0, howmany(connection_in + 1, NFDBITS) *
- sizeof(fd_mask));
- FD_SET(connection_in, setp);
-
- /* Wait for some data to arrive. */
- while (select(connection_in + 1, setp, NULL, NULL, NULL) == -1 &&
- (errno == EAGAIN || errno == EINTR))
- ;
-
- /* Read data from the socket. */
- len = read(connection_in, buf, sizeof(buf));
- if (len == 0) {
- if (packet_connection_is_on_socket())
- log("Connection closed by %.200s",
- get_remote_ipaddr());
- else
- debug("child closed the communication pipe "
- "before user auth was finished");
- fatal_cleanup();
- }
- if (len < 0) {
- if (packet_connection_is_on_socket())
- fatal("Read from socket failed: %.100s",
- strerror(errno));
- else
- fatal("Read from communication pipe failed: "
- "%.100s", strerror(errno));
- }
- /* Append it to the buffer. */
- packet_process_incoming(buf, len);
- }
- /* NOTREACHED */
-}
-
-int
-packet_read(void)
-{
- return packet_read_seqnr(NULL);
-}
-
-/*
- * Waits until a packet has been received, verifies that its type matches
- * that given, and gives a fatal error and exits if there is a mismatch.
- */
-
-void
-packet_read_expect(int expected_type)
-{
- int type;
-
- type = packet_read();
- if (type != expected_type)
- packet_disconnect("Protocol error: expected packet type %d, got %d",
- expected_type, type);
-}
-
-/* Checks if a full packet is available in the data received so far via
- * packet_process_incoming. If so, reads the packet; otherwise returns
- * SSH_MSG_NONE. This does not wait for data from the connection.
- *
- * SSH_MSG_DISCONNECT is handled specially here. Also,
- * SSH_MSG_IGNORE messages are skipped by this function and are never returned
- * to higher levels.
- */
-
-static int
-packet_read_poll1(void)
-{
- u_int len, padded_len;
- u_char *cp, type;
- u_int checksum, stored_checksum;
-
- /* Check if input size is less than minimum packet size. */
- if (buffer_len(&input) < 4 + 8)
- return SSH_MSG_NONE;
- /* Get length of incoming packet. */
- cp = buffer_ptr(&input);
- len = GET_32BIT(cp);
- if (len < 1 + 2 + 2 || len > 256 * 1024)
- packet_disconnect("Bad packet length %d.", len);
- padded_len = (len + 8) & ~7;
-
- /* Check if the packet has been entirely received. */
- if (buffer_len(&input) < 4 + padded_len)
- return SSH_MSG_NONE;
-
- /* The entire packet is in buffer. */
-
- /* Consume packet length. */
- buffer_consume(&input, 4);
-
- /*
- * Cryptographic attack detector for ssh
- * (C)1998 CORE-SDI, Buenos Aires Argentina
- * Ariel Futoransky(futo@core-sdi.com)
- */
- if (!receive_context.plaintext) {
- switch (detect_attack(buffer_ptr(&input), padded_len, NULL)) {
- case DEATTACK_DETECTED:
- packet_disconnect("crc32 compensation attack: "
- "network attack detected");
- break;
- case DEATTACK_DOS_DETECTED:
- packet_disconnect("deattack denial of "
- "service detected");
- break;
- }
- }
-
- /* Decrypt data to incoming_packet. */
- buffer_clear(&incoming_packet);
- cp = buffer_append_space(&incoming_packet, padded_len);
- cipher_crypt(&receive_context, cp, buffer_ptr(&input), padded_len);
-
- buffer_consume(&input, padded_len);
-
-#ifdef PACKET_DEBUG
- debug("read_poll plain/full:\n");
- buffer_dump(&incoming_packet);
-#endif
-
- /* Compute packet checksum. */
- checksum = ssh_crc32(buffer_ptr(&incoming_packet),
- buffer_len(&incoming_packet) - 4);
-
- /* Skip padding. */
- buffer_consume(&incoming_packet, 8 - len % 8);
-
- /* Test check bytes. */
- if (len != buffer_len(&incoming_packet))
- packet_disconnect("packet_read_poll1: len %d != buffer_len %d.",
- len, buffer_len(&incoming_packet));
-
- cp = (u_char *)buffer_ptr(&incoming_packet) + len - 4;
- stored_checksum = GET_32BIT(cp);
- if (checksum != stored_checksum)
- packet_disconnect("Corrupted check bytes on input.");
- buffer_consume_end(&incoming_packet, 4);
-
- if (packet_compression) {
- buffer_clear(&compression_buffer);
- buffer_uncompress(&incoming_packet, &compression_buffer);
- buffer_clear(&incoming_packet);
- buffer_append(&incoming_packet, buffer_ptr(&compression_buffer),
- buffer_len(&compression_buffer));
- }
- type = buffer_get_char(&incoming_packet);
- return type;
-}
-
-static int
-packet_read_poll2(u_int32_t *seqnr_p)
-{
- static u_int packet_length = 0;
- u_int padlen, need;
- u_char *macbuf, *cp, type;
- int maclen, block_size;
- Enc *enc = NULL;
- Mac *mac = NULL;
- Comp *comp = NULL;
-
- if (newkeys[MODE_IN] != NULL) {
- enc = &newkeys[MODE_IN]->enc;
- mac = &newkeys[MODE_IN]->mac;
- comp = &newkeys[MODE_IN]->comp;
- }
- maclen = mac && mac->enabled ? mac->mac_len : 0;
- block_size = enc ? enc->block_size : 8;
-
- if (packet_length == 0) {
- /*
- * check if input size is less than the cipher block size,
- * decrypt first block and extract length of incoming packet
- */
- if (buffer_len(&input) < block_size)
- return SSH_MSG_NONE;
-#ifdef PACKET_DEBUG
- debug("encrypted data we have in read queue (%d bytes):\n",
- buffer_len(&input));
- buffer_dump(&input);
-#endif
- buffer_clear(&incoming_packet);
- cp = buffer_append_space(&incoming_packet, block_size);
- cipher_crypt(&receive_context, cp, buffer_ptr(&input),
- block_size);
- cp = buffer_ptr(&incoming_packet);
- packet_length = GET_32BIT(cp);
- if (packet_length < 1 + 4 || packet_length > 256 * 1024) {
- packet_disconnect("Bad packet length.");
- }
- DBG(debug("input: packet len %u", packet_length + 4));
- buffer_consume(&input, block_size);
- }
- /* we have a partial packet of block_size bytes */
- need = 4 + packet_length - block_size;
- DBG(debug("partial packet %d, still need %d, maclen %d", block_size,
- need, maclen));
- if (need % block_size != 0)
- packet_disconnect("Bad packet length.");
- /*
- * check if the entire packet has been received and
- * decrypt into incoming_packet
- */
- if (buffer_len(&input) < need + maclen)
- return SSH_MSG_NONE;
-#ifdef PACKET_DEBUG
- debug("in read_poll, the encrypted input queue now contains "
- "(%d bytes):\n", buffer_len(&input));
- buffer_dump(&input);
-#endif
- cp = buffer_append_space(&incoming_packet, need);
- cipher_crypt(&receive_context, cp, buffer_ptr(&input), need);
- buffer_consume(&input, need);
- /*
- * compute MAC over seqnr and packet,
- * increment sequence number for incoming packet
- */
- if (mac && mac->enabled) {
- macbuf = mac_compute(mac, p_read.seqnr,
- buffer_ptr(&incoming_packet),
- buffer_len(&incoming_packet));
- if (memcmp(macbuf, buffer_ptr(&input), mac->mac_len) != 0)
- packet_disconnect("Corrupted MAC on input.");
- DBG(debug("MAC #%d ok", p_read.seqnr));
- buffer_consume(&input, mac->mac_len);
- }
- if (seqnr_p != NULL)
- *seqnr_p = p_read.seqnr;
- if (++p_read.seqnr == 0)
- log("incoming seqnr wraps around");
-
- /* see above for the comment on "First Rekeying Recommendation" */
- if (++p_read.packets == 0)
- if (!(datafellows & SSH_BUG_NOREKEY))
- fatal("too many packets with same key");
- p_read.blocks += (packet_length + 4) / block_size;
-
- /* get padlen */
- cp = buffer_ptr(&incoming_packet);
- padlen = cp[4];
- DBG(debug("input: padlen %d", padlen));
- if (padlen < 4)
- packet_disconnect("Corrupted padlen %d on input.", padlen);
-
- /* skip packet size + padlen, discard padding */
- buffer_consume(&incoming_packet, 4 + 1);
- buffer_consume_end(&incoming_packet, padlen);
-
- DBG(debug("input: len before de-compress %d", buffer_len(&incoming_packet)));
- if (comp && comp->enabled) {
- buffer_clear(&compression_buffer);
- buffer_uncompress(&incoming_packet, &compression_buffer);
- buffer_clear(&incoming_packet);
- buffer_append(&incoming_packet, buffer_ptr(&compression_buffer),
- buffer_len(&compression_buffer));
- DBG(debug("input: len after de-compress %d",
- buffer_len(&incoming_packet)));
- }
- /*
- * get packet type, implies consume.
- * return length of payload (without type field)
- */
- type = buffer_get_char(&incoming_packet);
- if (type == SSH2_MSG_NEWKEYS) {
- /*
- * set_newkeys(MODE_IN) in the client because it doesn't have a
- * dispatch function for SSH2_MSG_NEWKEYS in contrast to the
- * server processes. Note that in the unprivileged child,
- * set_newkeys() for MODE_IN are set in dispatch function
- * altprivsep_rekey() after SSH2_MSG_NEWKEYS packet is received
- * from the client.
- */
- process_newkeys(MODE_IN);
- }
-
-#ifdef PACKET_DEBUG
- debug("decrypted input packet [type %d]:\n", type);
- buffer_dump(&incoming_packet);
-#endif
- /* reset for next packet */
- packet_length = 0;
- return type;
-}
-
-/*
- * This tries to read a packet from the buffer of received data. Note that it
- * doesn't read() anything from the network socket.
- */
-int
-packet_read_poll_seqnr(u_int32_t *seqnr_p)
-{
- u_int reason, seqnr;
- u_char type;
- char *msg;
-
- for (;;) {
- if (compat20) {
- type = packet_read_poll2(seqnr_p);
- DBG(debug("received packet type %d", type));
- switch (type) {
- case SSH2_MSG_IGNORE:
- break;
- case SSH2_MSG_DEBUG:
- packet_get_char();
- msg = packet_get_utf8_string(NULL);
- msg = g11n_filter_string(msg);
- debug("Remote: %.900s", msg);
- xfree(msg);
- msg = packet_get_string(NULL);
- xfree(msg);
- break;
- case SSH2_MSG_DISCONNECT:
- reason = packet_get_int();
- msg = packet_get_utf8_string(NULL);
- msg = g11n_filter_string(msg);
- log("Received disconnect from %s: %u: %.400s",
- get_remote_ipaddr(), reason, msg);
- xfree(msg);
- fatal_cleanup();
- break;
- case SSH2_MSG_UNIMPLEMENTED:
- seqnr = packet_get_int();
- debug("Received SSH2_MSG_UNIMPLEMENTED for %u",
- seqnr);
- break;
- default:
- return type;
- break;
- }
- } else {
- type = packet_read_poll1();
- DBG(debug("received packet type %d", type));
- switch (type) {
- case SSH_MSG_IGNORE:
- break;
- case SSH_MSG_DEBUG:
- msg = packet_get_string(NULL);
- debug("Remote: %.900s", msg);
- xfree(msg);
- break;
- case SSH_MSG_DISCONNECT:
- msg = packet_get_string(NULL);
- log("Received disconnect from %s: %.400s",
- get_remote_ipaddr(), msg);
- fatal_cleanup();
- xfree(msg);
- break;
- default:
- return type;
- break;
- }
- }
- }
-}
-
-int
-packet_read_poll(void)
-{
- return packet_read_poll_seqnr(NULL);
-}
-
-/*
- * Buffers the given amount of input characters. This is intended to be used
- * together with packet_read_poll.
- */
-
-void
-packet_process_incoming(const char *buf, u_int len)
-{
- buffer_append(&input, buf, len);
-}
-
-/* Returns a character from the packet. */
-
-u_int
-packet_get_char(void)
-{
- char ch;
-
- buffer_get(&incoming_packet, &ch, 1);
- return (u_char) ch;
-}
-
-/* Returns an integer from the packet data. */
-
-u_int
-packet_get_int(void)
-{
- return buffer_get_int(&incoming_packet);
-}
-
-/*
- * Returns an arbitrary precision integer from the packet data. The integer
- * must have been initialized before this call.
- */
-
-void
-packet_get_bignum(BIGNUM * value)
-{
- buffer_get_bignum(&incoming_packet, value);
-}
-
-void
-packet_get_bignum2(BIGNUM * value)
-{
- buffer_get_bignum2(&incoming_packet, value);
-}
-
-void *
-packet_get_raw(u_int *length_ptr)
-{
- u_int bytes = buffer_len(&incoming_packet);
-
- if (length_ptr != NULL)
- *length_ptr = bytes;
- return buffer_ptr(&incoming_packet);
-}
-
-int
-packet_remaining(void)
-{
- return buffer_len(&incoming_packet);
-}
-
-/*
- * Returns a string from the packet data. The string is allocated using
- * xmalloc; it is the responsibility of the calling program to free it when
- * no longer needed. The length_ptr argument may be NULL, or point to an
- * integer into which the length of the string is stored.
- */
-
-void *
-packet_get_string(u_int *length_ptr)
-{
- return buffer_get_string(&incoming_packet, length_ptr);
-}
-
-char *
-packet_get_utf8_string(uint_t *length_ptr)
-{
- if (datafellows & SSH_BUG_STRING_ENCODING)
- return (buffer_get_string(&incoming_packet, length_ptr));
- else
- return (buffer_get_utf8_string(&incoming_packet, length_ptr));
-}
-
-/*
- * Sends a diagnostic message from the server to the client. This message
- * can be sent at any time (but not while constructing another message). The
- * message is printed immediately, but only if the client is being executed
- * in verbose mode. These messages are primarily intended to ease debugging
- * authentication problems. The length of the formatted message must not
- * exceed 1024 bytes. This will automatically call packet_write_wait.
- */
-
-void
-packet_send_debug(const char *fmt,...)
-{
- char buf[1024];
- va_list args;
-
- if (compat20 && (datafellows & SSH_BUG_DEBUG))
- return;
-
- va_start(args, fmt);
- vsnprintf(buf, sizeof(buf), gettext(fmt), args);
- va_end(args);
-
-#ifdef ALTPRIVSEP
- /* shouldn't happen */
- if (packet_monitor) {
- debug("packet_send_debug: %s", buf);
- return;
- }
-#endif /* ALTPRIVSEP */
-
- if (compat20) {
- packet_start(SSH2_MSG_DEBUG);
- packet_put_char(0); /* bool: always display */
- packet_put_utf8_cstring(buf);
- packet_put_cstring("");
- } else {
- packet_start(SSH_MSG_DEBUG);
- packet_put_cstring(buf);
- }
- packet_send();
- packet_write_wait();
-}
-
-/*
- * Logs the error plus constructs and sends a disconnect packet, closes the
- * connection, and exits. This function never returns. The error message
- * should not contain a newline. The length of the formatted message must
- * not exceed 1024 bytes.
- */
-
-void
-packet_disconnect(const char *fmt,...)
-{
- char buf[1024];
- va_list args;
- static int disconnecting = 0;
-
- if (disconnecting) /* Guard against recursive invocations. */
- fatal("packet_disconnect called recursively.");
- disconnecting = 1;
-
- /*
- * Format the message. Note that the caller must make sure the
- * message is of limited size.
- */
- va_start(args, fmt);
- vsnprintf(buf, sizeof(buf), fmt, args);
- va_end(args);
-
-#ifdef ALTPRIVSEP
- /*
- * If we packet_disconnect() in the monitor the fatal cleanups will take
- * care of the child. See main() in sshd.c. We don't send the packet
- * disconnect message here because: a) the child might not be looking
- * for it and b) because we don't really know if the child is compat20
- * or not as we lost that information when packet_set_monitor() was
- * called.
- */
- if (packet_monitor)
- goto close_stuff;
-#endif /* ALTPRIVSEP */
-
- /* Send the disconnect message to the other side, and wait for it to get sent. */
- if (compat20) {
- packet_start(SSH2_MSG_DISCONNECT);
- packet_put_int(SSH2_DISCONNECT_PROTOCOL_ERROR);
- packet_put_utf8_cstring(buf);
- packet_put_cstring("");
- } else {
- packet_start(SSH_MSG_DISCONNECT);
- packet_put_cstring(buf);
- }
- packet_send();
- packet_write_wait();
-
-#ifdef ALTPRIVSEP
-close_stuff:
-#endif /* ALTPRIVSEP */
- /* Stop listening for connections. */
- channel_close_all();
-
- /* Close the connection. */
- packet_close();
-
- /* Display the error locally and exit. */
- log("Disconnecting: %.100s", buf);
- fatal_cleanup();
-}
-
-/* Checks if there is any buffered output, and tries to write some of the output. */
-
-void
-packet_write_poll(void)
-{
- int len = buffer_len(&output);
-
- if (len > 0) {
- len = write(connection_out, buffer_ptr(&output), len);
- if (len <= 0) {
- if (errno == EAGAIN)
- return;
- else
- fatal("Write failed: %.100s", strerror(errno));
- }
-#ifdef PACKET_DEBUG
- debug("in packet_write_poll, %d bytes just sent to the "
- "remote side", len);
-#endif
- buffer_consume(&output, len);
- }
-}
-
-/*
- * Calls packet_write_poll repeatedly until all pending output data has been
- * written.
- */
-
-void
-packet_write_wait(void)
-{
- fd_set *setp;
-
- setp = (fd_set *)xmalloc(howmany(connection_out + 1, NFDBITS) *
- sizeof(fd_mask));
- packet_write_poll();
- while (packet_have_data_to_write()) {
- memset(setp, 0, howmany(connection_out + 1, NFDBITS) *
- sizeof(fd_mask));
- FD_SET(connection_out, setp);
- while (select(connection_out + 1, NULL, setp, NULL, NULL) == -1 &&
- (errno == EAGAIN || errno == EINTR))
- ;
- packet_write_poll();
- }
- xfree(setp);
-}
-
-/* Returns true if there is buffered data to write to the connection. */
-
-int
-packet_have_data_to_write(void)
-{
- return buffer_len(&output) != 0;
-}
-
-/* Returns true if there is not too much data to write to the connection. */
-
-int
-packet_not_very_much_data_to_write(void)
-{
- if (interactive_mode)
- return buffer_len(&output) < 16384;
- else
- return buffer_len(&output) < 128 * 1024;
-}
-
-/* Informs that the current session is interactive. Sets IP flags for that. */
-
-void
-packet_set_interactive(int interactive)
-{
- static int called = 0;
-#if defined(IP_TOS) && !defined(IP_TOS_IS_BROKEN)
- int lowdelay = IPTOS_LOWDELAY;
- int throughput = IPTOS_THROUGHPUT;
-#endif
-
- if (called)
- return;
- called = 1;
-
- /* Record that we are in interactive mode. */
- interactive_mode = interactive;
-
- /* Only set socket options if using a socket. */
- if (!packet_connection_is_on_socket())
- return;
- /*
- * IPTOS_LOWDELAY and IPTOS_THROUGHPUT are IPv4 only
- */
- if (interactive) {
- /*
- * Set IP options for an interactive connection. Use
- * IPTOS_LOWDELAY and TCP_NODELAY.
- */
-#if defined(IP_TOS) && !defined(IP_TOS_IS_BROKEN)
- if (packet_connection_is_ipv4()) {
- if (setsockopt(connection_in, IPPROTO_IP, IP_TOS,
- &lowdelay, sizeof(lowdelay)) < 0)
- error("setsockopt IPTOS_LOWDELAY: %.100s",
- strerror(errno));
- }
-#endif
- set_nodelay(connection_in);
- }
-#if defined(IP_TOS) && !defined(IP_TOS_IS_BROKEN)
- else if (packet_connection_is_ipv4()) {
- /*
- * Set IP options for a non-interactive connection. Use
- * IPTOS_THROUGHPUT.
- */
- if (setsockopt(connection_in, IPPROTO_IP, IP_TOS, &throughput,
- sizeof(throughput)) < 0)
- error("setsockopt IPTOS_THROUGHPUT: %.100s", strerror(errno));
- }
-#endif
-}
-
-/* Returns true if the current connection is interactive. */
-
-int
-packet_is_interactive(void)
-{
- return interactive_mode;
-}
-
-int
-packet_set_maxsize(int s)
-{
- static int called = 0;
-
- if (called) {
- log("packet_set_maxsize: called twice: old %d new %d",
- max_packet_size, s);
- return -1;
- }
- if (s < 4 * 1024 || s > 1024 * 1024) {
- log("packet_set_maxsize: bad size %d", s);
- return -1;
- }
- called = 1;
- debug("packet_set_maxsize: setting to %d", s);
- max_packet_size = s;
- return s;
-}
-
-/* roundup current message to pad bytes */
-void
-packet_add_padding(u_char pad)
-{
- extra_pad = pad;
-}
-
-/*
- * 9.2. Ignored Data Message
- *
- * byte SSH_MSG_IGNORE
- * string data
- *
- * All implementations MUST understand (and ignore) this message at any
- * time (after receiving the protocol version). No implementation is
- * required to send them. This message can be used as an additional
- * protection measure against advanced traffic analysis techniques.
- */
-void
-packet_send_ignore(int nbytes)
-{
- u_int32_t rnd = 0;
- int i;
-
-#ifdef ALTPRIVSEP
- /* shouldn't happen -- see packet_set_monitor() */
- if (packet_monitor)
- return;
-#endif /* ALTPRIVSEP */
-
- packet_start(compat20 ? SSH2_MSG_IGNORE : SSH_MSG_IGNORE);
- packet_put_int(nbytes);
- for (i = 0; i < nbytes; i++) {
- if (i % 4 == 0)
- rnd = arc4random();
- packet_put_char((u_char)rnd & 0xff);
- rnd >>= 8;
- }
-}
-
-#define MAX_PACKETS (1U<<31)
-int
-packet_need_rekeying(void)
-{
- if (datafellows & SSH_BUG_NOREKEY)
- return 0;
- return
- (p_send.packets > MAX_PACKETS) ||
- (p_read.packets > MAX_PACKETS) ||
- (max_blocks_out && (p_send.blocks > max_blocks_out)) ||
- (max_blocks_in && (p_read.blocks > max_blocks_in));
-}
-
-void
-packet_set_rekey_limit(u_int32_t bytes)
-{
- rekey_limit = bytes;
-}
-
-#ifdef ALTPRIVSEP
-void
-packet_set_server(void)
-{
- packet_server = 1;
-}
-
-int
-packet_is_server(void)
-{
- return (packet_server);
-}
-
-void
-packet_set_monitor(int pipe)
-{
- int dup_fd;
-
- packet_server = 1;
- packet_monitor = 1;
-
- /*
- * Awful hack follows.
- *
- * For SSHv1 the monitor does not process any SSHv1 packets, only
- * ALTPRIVSEP packets. We take advantage of that here to keep changes
- * to packet.c to a minimum by using the SSHv2 binary packet protocol,
- * with cipher "none," mac "none" and compression alg "none," as the
- * basis for the monitor protocol. And so to force packet.c to treat
- * packets as SSHv2 we force compat20 == 1 here.
- *
- * For completeness and to help future developers catch this we also
- * force compat20 == 1 in the monitor loop, in serverloop.c.
- */
- compat20 = 1;
-
- /*
- * NOTE: Assumptions below!
- *
- * - lots of packet.c code assumes that (connection_in ==
- * connection_out) -> connection is socket
- *
- * - packet_close() does not shutdown() the connection fildes
- * if connection_in != connection_out
- *
- * - other code assumes the connection is a socket if
- * connection_in == connection_out
- */
-
- if ((dup_fd = dup(pipe)) < 0)
- fatal("Monitor failed to start: %s", strerror(errno));
-
- /*
- * make sure that the monitor's child's socket is not shutdown(3SOCKET)
- * when we packet_close(). Setting connection_out to -1 will take care
- * of that.
- */
- if (packet_connection_is_on_socket())
- connection_out = -1;
-
- /*
- * Now clean up the state related to the server socket. As a side
- * effect, we also clean up existing cipher contexts that were
- * initialized with 'none' cipher in packet_set_connection(). That
- * function was called in the child server process shortly after the
- * master SSH process forked. However, all of that is reinialized again
- * by another packet_set_connection() call right below.
- */
- packet_close();
-
- /*
- * Now make the monitor pipe look like the ssh connection which means
- * that connection_in and connection_out will be set to the
- * communication pipe descriptors.
- */
- packet_set_connection(pipe, dup_fd);
-}
-
-/*
- * We temporarily need to set connection_in and connection_out descriptors so
- * that we can make use of existing code that gets the IP address and hostname
- * of the peer to write a login/logout record. It's not nice but we would have
- * to change more code when implementing the PKCS#11 engine support.
- */
-void
-packet_set_fds(int fd, int restore)
-{
- static int stored_fd;
-
- if (stored_fd == 0 && restore == 0) {
- debug3("packet_set_fds: saving %d, installing %d",
- connection_in, fd);
- stored_fd = connection_in;
- /* we don't have a socket in inetd mode */
- if (fd != -1)
- connection_in = connection_out = fd;
- return;
- }
-
- if (restore == 1) {
- debug3("restoring %d to connection_in/out", stored_fd);
- connection_in = connection_out = stored_fd;
- }
-}
-
-int
-packet_is_monitor(void)
-{
- return (packet_monitor);
-}
-#endif /* ALTPRIVSEP */
diff --git a/usr/src/cmd/ssh/libssh/common/progressmeter.c b/usr/src/cmd/ssh/libssh/common/progressmeter.c
deleted file mode 100644
index 65d28fb596..0000000000
--- a/usr/src/cmd/ssh/libssh/common/progressmeter.c
+++ /dev/null
@@ -1,308 +0,0 @@
-/*
- * Copyright (c) 2003 Nils Nordman. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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.
- */
-
-/* $OpenBSD: progressmeter.c,v 1.37 2006/08/03 03:34:42 deraadt Exp $ */
-
-#pragma ident "%Z%%M% %I% %E% SMI"
-
-#include "includes.h"
-
-#include <sys/types.h>
-#include <sys/ioctl.h>
-#include <sys/uio.h>
-
-#include <errno.h>
-#include <signal.h>
-#include <stdio.h>
-#include <string.h>
-#include <time.h>
-#include <unistd.h>
-
-#include "progressmeter.h"
-#include "atomicio.h"
-#include "misc.h"
-
-#define DEFAULT_WINSIZE 80
-#define MAX_WINSIZE 512
-#define PADDING 1 /* padding between the progress indicators */
-#define UPDATE_INTERVAL 1 /* update the progress meter every second */
-#define STALL_TIME 5 /* we're stalled after this many seconds */
-
-/* determines whether we can output to the terminal */
-static int can_output(void);
-
-/* formats and inserts the specified size into the given buffer */
-static void format_size(char *, int, off_t);
-static void format_rate(char *, int, off_t);
-
-/* window resizing */
-static void sig_winch(int);
-static void setscreensize(void);
-
-/* updates the progressmeter to reflect the current state of the transfer */
-void refresh_progress_meter(void);
-
-/* signal handler for updating the progress meter */
-static void update_progress_meter(int);
-
-static time_t start; /* start progress */
-static time_t last_update; /* last progress update */
-static char *file; /* name of the file being transferred */
-static off_t end_pos; /* ending position of transfer */
-static off_t cur_pos; /* transfer position as of last refresh */
-static volatile off_t *counter; /* progress counter */
-static long stalled; /* how long we have been stalled */
-static int bytes_per_second; /* current speed in bytes per second */
-static int win_size; /* terminal window size */
-static volatile sig_atomic_t win_resized; /* for window resizing */
-
-/* units for format_size */
-static const char unit[] = " KMGT";
-
-static int
-can_output(void)
-{
- return (getpgrp() == tcgetpgrp(STDOUT_FILENO));
-}
-
-static void
-format_rate(char *buf, int size, off_t bytes)
-{
- int i;
-
- bytes *= 100;
- for (i = 0; bytes >= 100*1000 && unit[i] != 'T'; i++)
- bytes = (bytes + 512) / 1024;
- if (i == 0) {
- i++;
- bytes = (bytes + 512) / 1024;
- }
- snprintf(buf, size, "%3lld.%1lld%c%s",
- (long long) (bytes + 5) / 100,
- (long long) (bytes + 5) / 10 % 10,
- unit[i],
- i ? "B" : " ");
-}
-
-static void
-format_size(char *buf, int size, off_t bytes)
-{
- int i;
-
- for (i = 0; bytes >= 10000 && unit[i] != 'T'; i++)
- bytes = (bytes + 512) / 1024;
- snprintf(buf, size, "%4lld%c%s",
- (long long) bytes,
- unit[i],
- i ? "B" : " ");
-}
-
-void
-refresh_progress_meter(void)
-{
- char buf[MAX_WINSIZE + 1];
- time_t now;
- off_t transferred;
- double elapsed;
- int percent;
- off_t bytes_left;
- int cur_speed;
- int hours, minutes, seconds;
- int i, len;
- int file_len;
-
- transferred = *counter - cur_pos;
- cur_pos = *counter;
- now = time(NULL);
- bytes_left = end_pos - cur_pos;
-
- if (bytes_left > 0)
- elapsed = now - last_update;
- else {
- elapsed = now - start;
- /* Calculate true total speed when done */
- transferred = end_pos;
- bytes_per_second = 0;
- }
-
- /* calculate speed */
- if (elapsed != 0)
- cur_speed = (int)(transferred / elapsed);
- else
- cur_speed = transferred;
-
-#define AGE_FACTOR 0.9
- if (bytes_per_second != 0) {
- bytes_per_second = (int)((bytes_per_second * AGE_FACTOR) +
- (cur_speed * (1.0 - AGE_FACTOR)));
- } else
- bytes_per_second = cur_speed;
-
- /* filename */
- buf[0] = '\0';
- file_len = win_size - 35;
- if (file_len > 0) {
- len = snprintf(buf, file_len + 1, "\r%s", file);
- if (len < 0)
- len = 0;
- if (len >= file_len + 1)
- len = file_len;
- for (i = len; i < file_len; i++)
- buf[i] = ' ';
- buf[file_len] = '\0';
- }
-
- /* percent of transfer done */
- if (end_pos != 0)
- percent = (int)(((float)cur_pos / end_pos) * 100);
- else
- percent = 100;
- snprintf(buf + strlen(buf), win_size - strlen(buf),
- " %3d%% ", percent);
-
- /* amount transferred */
- format_size(buf + strlen(buf), win_size - strlen(buf),
- cur_pos);
- strlcat(buf, " ", win_size);
-
- /* bandwidth usage */
- format_rate(buf + strlen(buf), win_size - strlen(buf),
- (off_t)bytes_per_second);
- strlcat(buf, "/s ", win_size);
-
- /* ETA */
- if (!transferred)
- stalled += elapsed;
- else
- stalled = 0;
-
- if (stalled >= STALL_TIME)
- strlcat(buf, "- stalled -", win_size);
- else if (bytes_per_second == 0 && bytes_left)
- strlcat(buf, " --:-- ETA", win_size);
- else {
- if (bytes_left > 0)
- seconds = bytes_left / bytes_per_second;
- else
- seconds = (int)elapsed;
-
- hours = seconds / 3600;
- seconds -= hours * 3600;
- minutes = seconds / 60;
- seconds -= minutes * 60;
-
- if (hours != 0)
- snprintf(buf + strlen(buf), win_size - strlen(buf),
- "%d:%02d:%02d", hours, minutes, seconds);
- else
- snprintf(buf + strlen(buf), win_size - strlen(buf),
- " %02d:%02d", minutes, seconds);
-
- if (bytes_left > 0)
- strlcat(buf, " ETA", win_size);
- else
- strlcat(buf, " ", win_size);
- }
-
- atomicio(vwrite, STDOUT_FILENO, buf, win_size - 1);
- last_update = now;
-}
-
-/*ARGSUSED*/
-static void
-update_progress_meter(int ignore)
-{
- int save_errno;
-
- save_errno = errno;
-
- if (win_resized) {
- setscreensize();
- win_resized = 0;
- }
- if (can_output())
- refresh_progress_meter();
-
- signal(SIGALRM, update_progress_meter);
- alarm(UPDATE_INTERVAL);
- errno = save_errno;
-}
-
-void
-start_progress_meter(char *f, off_t filesize, off_t *ctr)
-{
- start = last_update = time(NULL);
- file = f;
- end_pos = filesize;
- cur_pos = 0;
- counter = ctr;
- stalled = 0;
- bytes_per_second = 0;
-
- setscreensize();
- if (can_output())
- refresh_progress_meter();
-
- signal(SIGALRM, update_progress_meter);
- signal(SIGWINCH, sig_winch);
- alarm(UPDATE_INTERVAL);
-}
-
-void
-stop_progress_meter(void)
-{
- alarm(0);
-
- if (!can_output())
- return;
-
- /* Ensure we complete the progress */
- if (cur_pos != end_pos)
- refresh_progress_meter();
-
- atomicio(vwrite, STDOUT_FILENO, "\n", 1);
-}
-
-/*ARGSUSED*/
-static void
-sig_winch(int sig)
-{
- win_resized = 1;
-}
-
-static void
-setscreensize(void)
-{
- struct winsize winsize;
-
- if (ioctl(STDOUT_FILENO, TIOCGWINSZ, &winsize) != -1 &&
- winsize.ws_col != 0) {
- if (winsize.ws_col > MAX_WINSIZE)
- win_size = MAX_WINSIZE;
- else
- win_size = winsize.ws_col;
- } else
- win_size = DEFAULT_WINSIZE;
- win_size += 1; /* trailing \0 */
-}
diff --git a/usr/src/cmd/ssh/libssh/common/proxy-io.c b/usr/src/cmd/ssh/libssh/common/proxy-io.c
deleted file mode 100644
index c025f28f0a..0000000000
--- a/usr/src/cmd/ssh/libssh/common/proxy-io.c
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * Copyright 2003 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
- */
-
-#pragma ident "%Z%%M% %I% %E% SMI"
-
-#include <stdio.h>
-#include <unistd.h>
-#include "proxy-io.h"
-
-int
-proxy_read_write_loop(int readfd, int writefd)
-{
- int rbytes, bytes_to_write, bytes_written;
- char readbuf[BUFFER_SIZ];
- char *ptr;
-
- rbytes = read(readfd, readbuf, sizeof (readbuf));
-
- if (rbytes > 0) {
- bytes_to_write = rbytes;
- ptr = readbuf;
- while (bytes_to_write > 0) {
- if ((bytes_written =
- write(writefd, ptr, bytes_to_write)) < 0) {
- perror("write");
- return (0);
- }
- bytes_to_write -= bytes_written;
- ptr += bytes_written;
- }
- } else if (rbytes <= 0) {
- return (0);
- }
- /* Read and write successful */
- return (1);
-}
diff --git a/usr/src/cmd/ssh/libssh/common/radix.c b/usr/src/cmd/ssh/libssh/common/radix.c
deleted file mode 100644
index 4200f71b3b..0000000000
--- a/usr/src/cmd/ssh/libssh/common/radix.c
+++ /dev/null
@@ -1,160 +0,0 @@
-/*
- * Copyright (c) 1999 Dug Song. All rights reserved.
- * Copyright (c) 2002 Markus Friedl. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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.
- */
-
-#include "includes.h"
-#include "uuencode.h"
-
-RCSID("$OpenBSD: radix.c,v 1.22 2002/09/09 14:54:15 markus Exp $");
-
-#pragma ident "%Z%%M% %I% %E% SMI"
-
-#ifdef AFS
-#include <krb.h>
-
-#include <radix.h>
-#include "bufaux.h"
-
-int
-creds_to_radix(CREDENTIALS *creds, u_char *buf, size_t buflen)
-{
- Buffer b;
- int ret;
-
- buffer_init(&b);
-
- buffer_put_char(&b, 1); /* version */
-
- buffer_append(&b, creds->service, strlen(creds->service));
- buffer_put_char(&b, '\0');
- buffer_append(&b, creds->instance, strlen(creds->instance));
- buffer_put_char(&b, '\0');
- buffer_append(&b, creds->realm, strlen(creds->realm));
- buffer_put_char(&b, '\0');
- buffer_append(&b, creds->pname, strlen(creds->pname));
- buffer_put_char(&b, '\0');
- buffer_append(&b, creds->pinst, strlen(creds->pinst));
- buffer_put_char(&b, '\0');
-
- /* Null string to repeat the realm. */
- buffer_put_char(&b, '\0');
-
- buffer_put_int(&b, creds->issue_date);
- buffer_put_int(&b, krb_life_to_time(creds->issue_date,
- creds->lifetime));
- buffer_append(&b, creds->session, sizeof(creds->session));
- buffer_put_short(&b, creds->kvno);
-
- /* 32 bit size + data */
- buffer_put_string(&b, creds->ticket_st.dat, creds->ticket_st.length);
-
- ret = uuencode(buffer_ptr(&b), buffer_len(&b), (char *)buf, buflen);
-
- buffer_free(&b);
- return ret;
-}
-
-#define GETSTRING(b, t, tlen) \
- do { \
- int i, found = 0; \
- for (i = 0; i < tlen; i++) { \
- if (buffer_len(b) == 0) \
- goto done; \
- t[i] = buffer_get_char(b); \
- if (t[i] == '\0') { \
- found = 1; \
- break; \
- } \
- } \
- if (!found) \
- goto done; \
- } while(0)
-
-int
-radix_to_creds(const char *buf, CREDENTIALS *creds)
-{
- Buffer b;
- u_char *space;
- char c, version, *p;
- u_int endTime, len;
- int blen, ret;
-
- ret = 0;
- blen = strlen(buf);
-
- /* sanity check for size */
- if (blen > 8192)
- return 0;
-
- buffer_init(&b);
- space = buffer_append_space(&b, blen);
-
- /* check version and length! */
- len = uudecode(buf, space, blen);
- if (len < 1)
- goto done;
-
- version = buffer_get_char(&b);
-
- GETSTRING(&b, creds->service, sizeof creds->service);
- GETSTRING(&b, creds->instance, sizeof creds->instance);
- GETSTRING(&b, creds->realm, sizeof creds->realm);
- GETSTRING(&b, creds->pname, sizeof creds->pname);
- GETSTRING(&b, creds->pinst, sizeof creds->pinst);
-
- if (buffer_len(&b) == 0)
- goto done;
-
- /* Ignore possibly different realm. */
- while (buffer_len(&b) > 0 && (c = buffer_get_char(&b)) != '\0')
- ;
-
- if (buffer_len(&b) == 0)
- goto done;
-
- creds->issue_date = buffer_get_int(&b);
-
- endTime = buffer_get_int(&b);
- creds->lifetime = krb_time_to_life(creds->issue_date, endTime);
-
- len = buffer_len(&b);
- if (len < sizeof(creds->session))
- goto done;
- memcpy(&creds->session, buffer_ptr(&b), sizeof(creds->session));
- buffer_consume(&b, sizeof(creds->session));
-
- creds->kvno = buffer_get_short(&b);
-
- p = buffer_get_string(&b, &len);
- if (len < 0 || len > sizeof(creds->ticket_st.dat))
- goto done;
- memcpy(&creds->ticket_st.dat, p, len);
- creds->ticket_st.length = len;
-
- ret = 1;
-done:
- buffer_free(&b);
- return ret;
-}
-#endif /* AFS */
diff --git a/usr/src/cmd/ssh/libssh/common/readconf.c b/usr/src/cmd/ssh/libssh/common/readconf.c
deleted file mode 100644
index b1e7f89c7a..0000000000
--- a/usr/src/cmd/ssh/libssh/common/readconf.c
+++ /dev/null
@@ -1,1276 +0,0 @@
-/*
- * Author: Tatu Ylonen <ylo@cs.hut.fi>
- * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
- * All rights reserved
- * Functions for reading the configuration files.
- *
- * As far as I am concerned, the code I have written for this software
- * can be used freely for any purpose. Any derived versions of this
- * software must be clearly marked as such, and if the derived work is
- * incompatible with the protocol description in the RFC file, it must be
- * called by a name other than "ssh" or "Secure Shell".
- */
-/*
- * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
- * Copyright 2013 Joyent, Inc. All rights reserved.
- */
-
-#include "includes.h"
-RCSID("$OpenBSD: readconf.c,v 1.100 2002/06/19 00:27:55 deraadt Exp $");
-
-#include "ssh.h"
-#include "xmalloc.h"
-#include "compat.h"
-#include "cipher.h"
-#include "pathnames.h"
-#include "log.h"
-#include "readconf.h"
-#include "match.h"
-#include "misc.h"
-#include "kex.h"
-#include "mac.h"
-
-/* Format of the configuration file:
-
- # Configuration data is parsed as follows:
- # 1. command line options
- # 2. user-specific file
- # 3. system-wide file
- # Any configuration value is only changed the first time it is set.
- # Thus, host-specific definitions should be at the beginning of the
- # configuration file, and defaults at the end.
-
- # Host-specific declarations. These may override anything above. A single
- # host may match multiple declarations; these are processed in the order
- # that they are given in.
-
- Host *.ngs.fi ngs.fi
- User foo
-
- Host fake.com
- HostName another.host.name.real.org
- User blaah
- Port 34289
- ForwardX11 no
- ForwardAgent no
-
- Host books.com
- RemoteForward 9999 shadows.cs.hut.fi:9999
- Cipher 3des
-
- Host fascist.blob.com
- Port 23123
- User tylonen
- RhostsAuthentication no
- PasswordAuthentication no
-
- Host puukko.hut.fi
- User t35124p
- ProxyCommand ssh-proxy %h %p
-
- Host *.fr
- PublicKeyAuthentication no
-
- Host *.su
- Cipher none
- PasswordAuthentication no
-
- # Defaults for various options
- Host *
- ForwardAgent no
- ForwardX11 no
- RhostsAuthentication yes
- PasswordAuthentication yes
- RSAAuthentication yes
- RhostsRSAAuthentication yes
- StrictHostKeyChecking yes
- KeepAlives no
- IdentityFile ~/.ssh/identity
- Port 22
- EscapeChar ~
-
-*/
-
-/* Keyword tokens. */
-
-typedef enum {
- oBadOption,
- oForwardAgent, oForwardX11, oForwardX11Trusted, oGatewayPorts,
- oRhostsAuthentication,
- oPasswordAuthentication, oRSAAuthentication,
- oChallengeResponseAuthentication, oXAuthLocation,
-#if defined(KRB4) || defined(KRB5)
- oKerberosAuthentication,
-#endif
-#ifdef GSSAPI
- oGssKeyEx, oGssAuthentication, oGssDelegateCreds,
-#ifdef GSI
- oGssGlobusDelegateLimitedCreds,
-#endif /* GSI */
-#endif /* GSSAPI */
-#if defined(AFS) || defined(KRB5)
- oKerberosTgtPassing,
-#endif
-#ifdef AFS
- oAFSTokenPassing,
-#endif
- oIdentityFile, oHostName, oPort, oCipher, oRemoteForward, oLocalForward,
- oUser, oHost, oEscapeChar, oRhostsRSAAuthentication, oProxyCommand,
- oGlobalKnownHostsFile, oUserKnownHostsFile, oConnectionAttempts,
- oBatchMode, oCheckHostIP, oStrictHostKeyChecking, oCompression,
- oCompressionLevel, oKeepAlives, oNumberOfPasswordPrompts,
- oUsePrivilegedPort, oLogLevel, oCiphers, oProtocol, oMacs,
- oGlobalKnownHostsFile2, oUserKnownHostsFile2, oPubkeyAuthentication,
- oKbdInteractiveAuthentication, oKbdInteractiveDevices, oHostKeyAlias,
- oDynamicForward, oPreferredAuthentications, oHostbasedAuthentication,
- oHostKeyAlgorithms, oBindAddress, oSmartcardDevice,
- oClearAllForwardings, oNoHostAuthenticationForLocalhost,
- oFallBackToRsh, oUseRsh, oConnectTimeout, oHashKnownHosts,
- oServerAliveInterval, oServerAliveCountMax, oDisableBanner,
- oIgnoreIfUnknown, oRekeyLimit, oUseOpenSSLEngine,
- oDeprecated
-} OpCodes;
-
-/* Textual representations of the tokens. */
-
-static struct {
- const char *name;
- OpCodes opcode;
-} keywords[] = {
- { "forwardagent", oForwardAgent },
- { "forwardx11", oForwardX11 },
- { "forwardx11trusted", oForwardX11Trusted },
- { "xauthlocation", oXAuthLocation },
- { "gatewayports", oGatewayPorts },
- { "useprivilegedport", oUsePrivilegedPort },
- { "rhostsauthentication", oRhostsAuthentication },
- { "passwordauthentication", oPasswordAuthentication },
- { "kbdinteractiveauthentication", oKbdInteractiveAuthentication },
- { "kbdinteractivedevices", oKbdInteractiveDevices },
- { "rsaauthentication", oRSAAuthentication },
- { "pubkeyauthentication", oPubkeyAuthentication },
- { "dsaauthentication", oPubkeyAuthentication }, /* alias */
- { "rhostsrsaauthentication", oRhostsRSAAuthentication },
- { "hostbasedauthentication", oHostbasedAuthentication },
- { "challengeresponseauthentication", oChallengeResponseAuthentication },
- { "skeyauthentication", oChallengeResponseAuthentication }, /* alias */
- { "tisauthentication", oChallengeResponseAuthentication }, /* alias */
-#if defined(KRB4) || defined(KRB5)
- { "kerberosauthentication", oKerberosAuthentication },
-#endif
-#ifdef GSSAPI
- { "gssapikeyexchange", oGssKeyEx },
- { "gssapiauthentication", oGssAuthentication },
- { "gssapidelegatecredentials", oGssDelegateCreds },
- { "gsskeyex", oGssKeyEx }, /* alias */
- { "gssauthentication", oGssAuthentication }, /* alias */
- { "gssdelegatecreds", oGssDelegateCreds }, /* alias */
-#ifdef GSI
- /* For backwards compatability with old 1.2.27 client code */
- { "forwardgssapiglobusproxy", oGssDelegateCreds }, /* alias */
- { "forwardgssapiglobuslimitedproxy", oGssGlobusDelegateLimitedCreds },
-#endif /* GSI */
-#endif /* GSSAPI */
-#if defined(AFS) || defined(KRB5)
- { "kerberostgtpassing", oKerberosTgtPassing },
-#endif
-#ifdef AFS
- { "afstokenpassing", oAFSTokenPassing },
-#endif
- { "fallbacktorsh", oFallBackToRsh },
- { "usersh", oUseRsh },
- { "identityfile", oIdentityFile },
- { "identityfile2", oIdentityFile }, /* alias */
- { "hostname", oHostName },
- { "hostkeyalias", oHostKeyAlias },
- { "proxycommand", oProxyCommand },
- { "port", oPort },
- { "cipher", oCipher },
- { "ciphers", oCiphers },
- { "macs", oMacs },
- { "protocol", oProtocol },
- { "remoteforward", oRemoteForward },
- { "localforward", oLocalForward },
- { "user", oUser },
- { "host", oHost },
- { "escapechar", oEscapeChar },
- { "globalknownhostsfile", oGlobalKnownHostsFile },
- { "userknownhostsfile", oUserKnownHostsFile }, /* obsolete */
- { "globalknownhostsfile2", oGlobalKnownHostsFile2 },
- { "userknownhostsfile2", oUserKnownHostsFile2 }, /* obsolete */
- { "connectionattempts", oConnectionAttempts },
- { "batchmode", oBatchMode },
- { "checkhostip", oCheckHostIP },
- { "stricthostkeychecking", oStrictHostKeyChecking },
- { "compression", oCompression },
- { "compressionlevel", oCompressionLevel },
- { "tcpkeepalive", oKeepAlives },
- { "keepalive", oKeepAlives }, /* obsolete */
- { "numberofpasswordprompts", oNumberOfPasswordPrompts },
- { "loglevel", oLogLevel },
- { "dynamicforward", oDynamicForward },
- { "preferredauthentications", oPreferredAuthentications },
- { "hostkeyalgorithms", oHostKeyAlgorithms },
- { "bindaddress", oBindAddress },
- { "smartcarddevice", oSmartcardDevice },
- { "clearallforwardings", oClearAllForwardings },
- { "nohostauthenticationforlocalhost", oNoHostAuthenticationForLocalhost },
- { "rekeylimit", oRekeyLimit },
- { "connecttimeout", oConnectTimeout },
- { "serveraliveinterval", oServerAliveInterval },
- { "serveralivecountmax", oServerAliveCountMax },
- { "disablebanner", oDisableBanner },
- { "hashknownhosts", oHashKnownHosts },
- { "ignoreifunknown", oIgnoreIfUnknown },
- { "useopensslengine", oUseOpenSSLEngine },
- { NULL, oBadOption }
-};
-
-/*
- * Adds a local TCP/IP port forward to options. Never returns if there is an
- * error.
- */
-
-void
-add_local_forward(Options *options, const Forward *newfwd)
-{
- Forward *fwd;
-#ifndef NO_IPPORT_RESERVED_CONCEPT
- extern uid_t original_real_uid;
- if (newfwd->listen_port < IPPORT_RESERVED && original_real_uid != 0)
- fatal("Privileged ports can only be forwarded by root.");
-#endif
- if (options->num_local_forwards >= SSH_MAX_FORWARDS_PER_DIRECTION)
- fatal("Too many local forwards (max %d).", SSH_MAX_FORWARDS_PER_DIRECTION);
- fwd = &options->local_forwards[options->num_local_forwards++];
-
- fwd->listen_host = (newfwd->listen_host == NULL) ?
- NULL : xstrdup(newfwd->listen_host);
- fwd->listen_port = newfwd->listen_port;
- fwd->connect_host = xstrdup(newfwd->connect_host);
- fwd->connect_port = newfwd->connect_port;
-}
-
-/*
- * Adds a remote TCP/IP port forward to options. Never returns if there is
- * an error.
- */
-
-void
-add_remote_forward(Options *options, const Forward *newfwd)
-{
- Forward *fwd;
- if (options->num_remote_forwards >= SSH_MAX_FORWARDS_PER_DIRECTION)
- fatal("Too many remote forwards (max %d).",
- SSH_MAX_FORWARDS_PER_DIRECTION);
- fwd = &options->remote_forwards[options->num_remote_forwards++];
-
- fwd->listen_host = (newfwd->listen_host == NULL) ?
- NULL : xstrdup(newfwd->listen_host);
- fwd->listen_port = newfwd->listen_port;
- fwd->connect_host = xstrdup(newfwd->connect_host);
- fwd->connect_port = newfwd->connect_port;
-}
-
-static void
-clear_forwardings(Options *options)
-{
- int i;
-
- for (i = 0; i < options->num_local_forwards; i++) {
- if (options->local_forwards[i].listen_host != NULL)
- xfree(options->local_forwards[i].listen_host);
- xfree(options->local_forwards[i].connect_host);
- }
- options->num_local_forwards = 0;
- for (i = 0; i < options->num_remote_forwards; i++) {
- if (options->remote_forwards[i].listen_host != NULL)
- xfree(options->remote_forwards[i].listen_host);
- xfree(options->remote_forwards[i].connect_host);
- }
- options->num_remote_forwards = 0;
-}
-
-/*
- * Returns the number of the token pointed to by cp or oBadOption.
- */
-
-static OpCodes
-parse_token(const char *cp, const char *filename, int linenum)
-{
- u_int i;
-
- for (i = 0; keywords[i].name; i++)
- if (strcasecmp(cp, keywords[i].name) == 0)
- return keywords[i].opcode;
-
- debug("%s: line %d: unknown configuration option: %s",
- filename, linenum, cp);
- return oBadOption;
-}
-
-/*
- * Processes a single option line as used in the configuration files. This
- * only sets those values that have not already been set.
- */
-
-int
-process_config_line(Options *options, const char *host,
- char *line, const char *filename, int linenum,
- int *activep)
-{
- char *s, *string, **charptr, *endofnumber, *keyword, *arg, *arg2, fwdarg[256];
- int opcode, *intptr, value, scale, i;
- long long orig, val64;
- StoredOption *so;
- Forward fwd;
-
- s = line;
- /* Get the keyword. (Each line is supposed to begin with a keyword). */
- keyword = strdelim(&s);
- /* Ignore leading whitespace. */
- if (*keyword == '\0')
- keyword = strdelim(&s);
- if (keyword == NULL || !*keyword || *keyword == '\n' || *keyword == '#')
- return 0;
-
- opcode = parse_token(keyword, filename, linenum);
-
- switch (opcode) {
- case oBadOption:
- if (options->unknown_opts_num == MAX_UNKNOWN_OPTIONS) {
- error("we can't have more than %d unknown options:",
- MAX_UNKNOWN_OPTIONS);
- for (i = 0; i < MAX_UNKNOWN_OPTIONS; ++i) {
- so = &options->unknown_opts[i];
- error("%s:%d:%s",
- so->filename, so->linenum, so->keyword);
- xfree(so->keyword);
- xfree(so->filename);
- }
- fatal("too many unknown options found, can't continue");
- }
-
- /* unknown options will be processed later */
- so = &options->unknown_opts[options->unknown_opts_num];
- so->keyword = xstrdup(keyword);
- so->filename = xstrdup(filename);
- so->linenum = linenum;
- options->unknown_opts_num++;
- return (0);
-
- /* NOTREACHED */
- case oConnectTimeout:
- intptr = &options->connection_timeout;
-parse_time:
- arg = strdelim(&s);
- if (!arg || *arg == '\0')
- fatal("%s line %d: missing time value.",
- filename, linenum);
- if ((value = convtime(arg)) == -1)
- fatal("%s line %d: invalid time value.",
- filename, linenum);
- if (*activep && *intptr == -1)
- *intptr = value;
- break;
-
- case oForwardAgent:
- intptr = &options->forward_agent;
-parse_flag:
- arg = strdelim(&s);
- if (!arg || *arg == '\0')
- fatal("%.200s line %d: Missing yes/no argument.", filename, linenum);
- value = 0; /* To avoid compiler warning... */
- if (strcmp(arg, "yes") == 0 || strcmp(arg, "true") == 0)
- value = 1;
- else if (strcmp(arg, "no") == 0 || strcmp(arg, "false") == 0)
- value = 0;
- else
- fatal("%.200s line %d: Bad yes/no argument.", filename, linenum);
- if (*activep && *intptr == -1)
- *intptr = value;
- break;
-
- case oForwardX11:
- intptr = &options->forward_x11;
- goto parse_flag;
-
- case oForwardX11Trusted:
- intptr = &options->forward_x11_trusted;
- goto parse_flag;
-
- case oGatewayPorts:
- intptr = &options->gateway_ports;
- goto parse_flag;
-
- case oUsePrivilegedPort:
- intptr = &options->use_privileged_port;
- goto parse_flag;
-
- case oRhostsAuthentication:
- intptr = &options->rhosts_authentication;
- goto parse_flag;
-
- case oPasswordAuthentication:
- intptr = &options->password_authentication;
- goto parse_flag;
-
- case oKbdInteractiveAuthentication:
- intptr = &options->kbd_interactive_authentication;
- goto parse_flag;
-
- case oKbdInteractiveDevices:
- charptr = &options->kbd_interactive_devices;
- goto parse_string;
-
- case oPubkeyAuthentication:
- intptr = &options->pubkey_authentication;
- goto parse_flag;
-
- case oRSAAuthentication:
- intptr = &options->rsa_authentication;
- goto parse_flag;
-
- case oRhostsRSAAuthentication:
- intptr = &options->rhosts_rsa_authentication;
- goto parse_flag;
-
- case oHostbasedAuthentication:
- intptr = &options->hostbased_authentication;
- goto parse_flag;
-
- case oChallengeResponseAuthentication:
- intptr = &options->challenge_response_authentication;
- goto parse_flag;
-#if defined(KRB4) || defined(KRB5)
- case oKerberosAuthentication:
- intptr = &options->kerberos_authentication;
- goto parse_flag;
-#endif
-#ifdef GSSAPI
- case oGssKeyEx:
- intptr = &options->gss_keyex;
- goto parse_flag;
-
- case oGssAuthentication:
- intptr = &options->gss_authentication;
- goto parse_flag;
-
- case oGssDelegateCreds:
- intptr = &options->gss_deleg_creds;
- goto parse_flag;
-
-#ifdef GSI
- case oGssGlobusDelegateLimitedCreds:
- intptr = &options->gss_globus_deleg_limited_proxy;
- goto parse_flag;
-#endif /* GSI */
-
-#endif /* GSSAPI */
-
-#if defined(AFS) || defined(KRB5)
- case oKerberosTgtPassing:
- intptr = &options->kerberos_tgt_passing;
- goto parse_flag;
-#endif
-#ifdef AFS
- case oAFSTokenPassing:
- intptr = &options->afs_token_passing;
- goto parse_flag;
-#endif
- case oFallBackToRsh:
- intptr = &options->fallback_to_rsh;
- goto parse_flag;
-
- case oUseRsh:
- intptr = &options->use_rsh;
- goto parse_flag;
-
- case oBatchMode:
- intptr = &options->batch_mode;
- goto parse_flag;
-
- case oCheckHostIP:
- intptr = &options->check_host_ip;
- goto parse_flag;
-
- case oStrictHostKeyChecking:
- intptr = &options->strict_host_key_checking;
- arg = strdelim(&s);
- if (!arg || *arg == '\0')
- fatal("%.200s line %d: Missing yes/no/ask argument.",
- filename, linenum);
- value = 0; /* To avoid compiler warning... */
- if (strcmp(arg, "yes") == 0 || strcmp(arg, "true") == 0)
- value = 1;
- else if (strcmp(arg, "no") == 0 || strcmp(arg, "false") == 0)
- value = 0;
- else if (strcmp(arg, "ask") == 0)
- value = 2;
- else
- fatal("%.200s line %d: Bad yes/no/ask argument.", filename, linenum);
- if (*activep && *intptr == -1)
- *intptr = value;
- break;
-
- case oCompression:
- intptr = &options->compression;
- goto parse_flag;
-
- case oKeepAlives:
- intptr = &options->keepalives;
- goto parse_flag;
-
- case oNoHostAuthenticationForLocalhost:
- intptr = &options->no_host_authentication_for_localhost;
- goto parse_flag;
-
- case oNumberOfPasswordPrompts:
- intptr = &options->number_of_password_prompts;
- goto parse_int;
-
- case oCompressionLevel:
- intptr = &options->compression_level;
- goto parse_int;
-
- case oRekeyLimit:
- arg = strdelim(&s);
- if (!arg || *arg == '\0')
- fatal("%.200s line %d: Missing argument.", filename, linenum);
- if (arg[0] < '0' || arg[0] > '9')
- fatal("%.200s line %d: Bad number.", filename, linenum);
- orig = val64 = strtoll(arg, &endofnumber, 10);
- if (arg == endofnumber)
- fatal("%.200s line %d: Bad number.", filename, linenum);
- switch (toupper(*endofnumber)) {
- case '\0':
- scale = 1;
- break;
- case 'K':
- scale = 1<<10;
- break;
- case 'M':
- scale = 1<<20;
- break;
- case 'G':
- scale = 1<<30;
- break;
- default:
- fatal("%.200s line %d: Invalid RekeyLimit suffix",
- filename, linenum);
- }
- val64 *= scale;
- /* detect integer wrap and too-large limits */
- if ((val64 / scale) != orig || val64 > UINT_MAX)
- fatal("%.200s line %d: RekeyLimit too large",
- filename, linenum);
- if (val64 < 16)
- fatal("%.200s line %d: RekeyLimit too small",
- filename, linenum);
- if (*activep && options->rekey_limit == -1)
- options->rekey_limit = (u_int32_t)val64;
- break;
-
- case oIdentityFile:
- arg = strdelim(&s);
- if (!arg || *arg == '\0')
- fatal("%.200s line %d: Missing argument.", filename, linenum);
- if (*activep) {
- intptr = &options->num_identity_files;
- if (*intptr >= SSH_MAX_IDENTITY_FILES)
- fatal("%.200s line %d: Too many identity files specified (max %d).",
- filename, linenum, SSH_MAX_IDENTITY_FILES);
- charptr = &options->identity_files[*intptr];
- *charptr = xstrdup(arg);
- *intptr = *intptr + 1;
- }
- break;
-
- case oXAuthLocation:
- charptr=&options->xauth_location;
- goto parse_string;
-
- case oUser:
- charptr = &options->user;
-parse_string:
- arg = strdelim(&s);
- if (!arg || *arg == '\0')
- fatal("%.200s line %d: Missing argument.", filename, linenum);
- if (*activep && *charptr == NULL)
- *charptr = xstrdup(arg);
- break;
-
- case oGlobalKnownHostsFile:
- charptr = &options->system_hostfile;
- goto parse_string;
-
- case oUserKnownHostsFile:
- charptr = &options->user_hostfile;
- goto parse_string;
-
- case oGlobalKnownHostsFile2:
- charptr = &options->system_hostfile2;
- goto parse_string;
-
- case oUserKnownHostsFile2:
- charptr = &options->user_hostfile2;
- goto parse_string;
-
- case oHostName:
- charptr = &options->hostname;
- goto parse_string;
-
- case oHostKeyAlias:
- charptr = &options->host_key_alias;
- goto parse_string;
-
- case oPreferredAuthentications:
- charptr = &options->preferred_authentications;
- goto parse_string;
-
- case oBindAddress:
- charptr = &options->bind_address;
- goto parse_string;
-
- case oSmartcardDevice:
- charptr = &options->smartcard_device;
- goto parse_string;
-
- case oProxyCommand:
- charptr = &options->proxy_command;
- string = xstrdup("");
- while ((arg = strdelim(&s)) != NULL && *arg != '\0') {
- string = xrealloc(string, strlen(string) + strlen(arg) + 2);
- strcat(string, " ");
- strcat(string, arg);
- }
- if (*activep && *charptr == NULL)
- *charptr = string;
- else
- xfree(string);
- return 0;
-
- case oPort:
- intptr = &options->port;
-parse_int:
- arg = strdelim(&s);
- if (!arg || *arg == '\0')
- fatal("%.200s line %d: Missing argument.", filename, linenum);
- if (arg[0] < '0' || arg[0] > '9')
- fatal("%.200s line %d: Bad number.", filename, linenum);
-
- /* Octal, decimal, or hex format? */
- value = strtol(arg, &endofnumber, 0);
- if (arg == endofnumber)
- fatal("%.200s line %d: Bad number.", filename, linenum);
- if (*activep && *intptr == -1)
- *intptr = value;
- break;
-
- case oConnectionAttempts:
- intptr = &options->connection_attempts;
- goto parse_int;
-
- case oCipher:
- intptr = &options->cipher;
- arg = strdelim(&s);
- if (!arg || *arg == '\0')
- fatal("%.200s line %d: Missing argument.", filename, linenum);
- value = cipher_number(arg);
- if (value == -1)
- fatal("%.200s line %d: Bad cipher '%s'.",
- filename, linenum, arg ? arg : "<NONE>");
- if (*activep && *intptr == -1)
- *intptr = value;
- break;
-
- case oCiphers:
- arg = strdelim(&s);
- if (!arg || *arg == '\0')
- fatal("%.200s line %d: Missing argument.", filename, linenum);
- if (!ciphers_valid(arg))
- fatal("%.200s line %d: Bad SSH2 cipher spec '%s'.",
- filename, linenum, arg ? arg : "<NONE>");
- if (*activep && options->ciphers == NULL)
- options->ciphers = xstrdup(arg);
- break;
-
- case oMacs:
- arg = strdelim(&s);
- if (!arg || *arg == '\0')
- fatal("%.200s line %d: Missing argument.", filename, linenum);
- if (!mac_valid(arg))
- fatal("%.200s line %d: Bad SSH2 Mac spec '%s'.",
- filename, linenum, arg ? arg : "<NONE>");
- if (*activep && options->macs == NULL)
- options->macs = xstrdup(arg);
- break;
-
- case oHostKeyAlgorithms:
- arg = strdelim(&s);
- if (!arg || *arg == '\0')
- fatal("%.200s line %d: Missing argument.", filename, linenum);
- if (!key_names_valid2(arg))
- fatal("%.200s line %d: Bad protocol 2 host key algorithms '%s'.",
- filename, linenum, arg ? arg : "<NONE>");
- if (*activep && options->hostkeyalgorithms == NULL)
- options->hostkeyalgorithms = xstrdup(arg);
- break;
-
- case oProtocol:
- intptr = &options->protocol;
- arg = strdelim(&s);
- if (!arg || *arg == '\0')
- fatal("%.200s line %d: Missing argument.", filename, linenum);
- value = proto_spec(arg);
- if (value == SSH_PROTO_UNKNOWN)
- fatal("%.200s line %d: Bad protocol spec '%s'.",
- filename, linenum, arg ? arg : "<NONE>");
- if (*activep && *intptr == SSH_PROTO_UNKNOWN)
- *intptr = value;
- break;
-
- case oLogLevel:
- intptr = (int *) &options->log_level;
- arg = strdelim(&s);
- value = log_level_number(arg);
- if (value == SYSLOG_LEVEL_NOT_SET)
- fatal("%.200s line %d: unsupported log level '%s'",
- filename, linenum, arg ? arg : "<NONE>");
- if (*activep && (LogLevel) *intptr == SYSLOG_LEVEL_NOT_SET)
- *intptr = (LogLevel) value;
- break;
-
- case oLocalForward:
- case oRemoteForward:
- arg = strdelim(&s);
- if (arg == NULL || *arg == '\0')
- fatal("%.200s line %d: Missing port argument.",
- filename, linenum);
- arg2 = strdelim(&s);
- if (arg2 == NULL || *arg2 == '\0')
- fatal("%.200s line %d: Missing target argument.",
- filename, linenum);
-
- /* construct a string for parse_forward */
- snprintf(fwdarg, sizeof(fwdarg), "%s:%s", arg, arg2);
-
- if (parse_forward(1, &fwd, fwdarg) == 0)
- fatal("%.200s line %d: Bad forwarding specification.",
- filename, linenum);
-
- if (*activep) {
- if (opcode == oLocalForward)
- add_local_forward(options, &fwd);
- else if (opcode == oRemoteForward)
- add_remote_forward(options, &fwd);
- }
- break;
-
- case oDynamicForward:
- arg = strdelim(&s);
- if (!arg || *arg == '\0')
- fatal("%.200s line %d: Missing port argument.",
- filename, linenum);
-
- if (parse_forward(0, &fwd, arg) == 0) {
- fatal("%.200s line %d: Bad dynamic forwarding specification.",
- filename, linenum);
- }
-
- if (*activep) {
- fwd.connect_host = "socks";
- add_local_forward(options, &fwd);
- }
- break;
-
- case oClearAllForwardings:
- intptr = &options->clear_forwardings;
- goto parse_flag;
-
- case oHost:
- *activep = 0;
- while ((arg = strdelim(&s)) != NULL && *arg != '\0')
- if (match_pattern(host, arg)) {
- debug("Applying options for %.100s", arg);
- *activep = 1;
- break;
- }
- /* Avoid garbage check below, as strdelim is done. */
- return 0;
-
- case oEscapeChar:
- intptr = &options->escape_char;
- arg = strdelim(&s);
- if (!arg || *arg == '\0')
- fatal("%.200s line %d: Missing argument.", filename, linenum);
- if (arg[0] == '^' && arg[2] == 0 &&
- (u_char) arg[1] >= 64 && (u_char) arg[1] < 128)
- value = (u_char) arg[1] & 31;
- else if (strlen(arg) == 1)
- value = (u_char) arg[0];
- else if (strcmp(arg, "none") == 0)
- value = SSH_ESCAPECHAR_NONE;
- else {
- fatal("%.200s line %d: Bad escape character.",
- filename, linenum);
- /* NOTREACHED */
- value = 0; /* Avoid compiler warning. */
- }
- if (*activep && *intptr == -1)
- *intptr = value;
- break;
-
- case oServerAliveInterval:
- intptr = &options->server_alive_interval;
- goto parse_time;
-
- case oServerAliveCountMax:
- intptr = &options->server_alive_count_max;
- goto parse_int;
-
- case oHashKnownHosts:
- intptr = &options->hash_known_hosts;
- goto parse_flag;
-
- case oDisableBanner:
- arg = strdelim(&s);
- if (get_yes_no_flag(&options->disable_banner, arg, filename,
- linenum, *activep) == 1)
- break;
-
- if (strcmp(arg, "in-exec-mode") == 0)
- options->disable_banner = SSH_NO_BANNER_IN_EXEC_MODE;
- else
- fatal("%.200s line %d: Bad yes/no/in-exec-mode "
- "argument.", filename, linenum);
- break;
-
- case oIgnoreIfUnknown:
- charptr = &options->ignore_if_unknown;
- goto parse_string;
-
- case oUseOpenSSLEngine:
- intptr = &options->use_openssl_engine;
- goto parse_flag;
-
- case oDeprecated:
- debug("%s line %d: Deprecated option \"%s\"",
- filename, linenum, keyword);
- return 0;
-
- default:
- fatal("process_config_line: Unimplemented opcode %d", opcode);
- }
-
- /* Check that there is no garbage at end of line. */
- if ((arg = strdelim(&s)) != NULL && *arg != '\0') {
- fatal("%.200s line %d: garbage at end of line; \"%.200s\".",
- filename, linenum, arg);
- }
- return 0;
-}
-
-
-/*
- * Reads the config file and modifies the options accordingly. Options
- * should already be initialized before this call. This never returns if
- * there is an error. If the file does not exist, this returns 0.
- */
-
-int
-read_config_file(const char *filename, const char *host, Options *options)
-{
- FILE *f;
- char line[1024];
- int active, linenum;
-
- /* Open the file. */
- f = fopen(filename, "r");
- if (!f)
- return 0;
-
- debug("Reading configuration data %.200s", filename);
-
- /*
- * Mark that we are now processing the options. This flag is turned
- * on/off by Host specifications.
- */
- active = 1;
- linenum = 0;
- while (fgets(line, sizeof(line), f)) {
- /* Update line number counter. */
- linenum++;
- process_config_line(options, host, line, filename, linenum, &active);
- }
- fclose(f);
- return 1;
-}
-
-/*
- * Initializes options to special values that indicate that they have not yet
- * been set. Read_config_file will only set options with this value. Options
- * are processed in the following order: command line, user config file,
- * system config file. Last, fill_default_options is called.
- */
-
-void
-initialize_options(Options * options)
-{
- memset(options, 'X', sizeof(*options));
- options->forward_agent = -1;
- options->forward_x11 = -1;
- options->forward_x11_trusted = -1;
- options->xauth_location = NULL;
- options->gateway_ports = -1;
- options->use_privileged_port = -1;
- options->rhosts_authentication = -1;
- options->rsa_authentication = -1;
- options->pubkey_authentication = -1;
- options->challenge_response_authentication = -1;
-#ifdef GSSAPI
- options->gss_keyex = -1;
- options->gss_authentication = -1;
- options->gss_deleg_creds = -1;
-#ifdef GSI
- options->gss_globus_deleg_limited_proxy = -1;
-#endif /* GSI */
-#endif /* GSSAPI */
-
-#if defined(KRB4) || defined(KRB5)
- options->kerberos_authentication = -1;
-#endif
-#if defined(AFS) || defined(KRB5)
- options->kerberos_tgt_passing = -1;
-#endif
-#ifdef AFS
- options->afs_token_passing = -1;
-#endif
- options->password_authentication = -1;
- options->kbd_interactive_authentication = -1;
- options->kbd_interactive_devices = NULL;
- options->rhosts_rsa_authentication = -1;
- options->hostbased_authentication = -1;
- options->batch_mode = -1;
- options->check_host_ip = -1;
- options->strict_host_key_checking = -1;
- options->compression = -1;
- options->keepalives = -1;
- options->compression_level = -1;
- options->port = -1;
- options->connection_attempts = -1;
- options->connection_timeout = -1;
- options->number_of_password_prompts = -1;
- options->cipher = -1;
- options->ciphers = NULL;
- options->macs = NULL;
- options->hostkeyalgorithms = NULL;
- options->protocol = SSH_PROTO_UNKNOWN;
- options->num_identity_files = 0;
- options->hostname = NULL;
- options->host_key_alias = NULL;
- options->proxy_command = NULL;
- options->user = NULL;
- options->escape_char = -1;
- options->system_hostfile = NULL;
- options->user_hostfile = NULL;
- options->system_hostfile2 = NULL;
- options->user_hostfile2 = NULL;
- options->num_local_forwards = 0;
- options->num_remote_forwards = 0;
- options->clear_forwardings = -1;
- options->log_level = SYSLOG_LEVEL_NOT_SET;
- options->preferred_authentications = NULL;
- options->bind_address = NULL;
- options->smartcard_device = NULL;
- options->no_host_authentication_for_localhost = -1;
- options->rekey_limit = -1;
- options->fallback_to_rsh = -1;
- options->use_rsh = -1;
- options->server_alive_interval = -1;
- options->server_alive_count_max = -1;
- options->hash_known_hosts = -1;
- options->ignore_if_unknown = NULL;
- options->unknown_opts_num = 0;
- options->disable_banner = -1;
- options->use_openssl_engine = -1;
-}
-
-/*
- * Called after processing other sources of option data, this fills those
- * options for which no value has been specified with their default values.
- */
-
-void
-fill_default_options(Options * options)
-{
- int len;
-
- if (options->forward_agent == -1)
- options->forward_agent = 0;
- if (options->forward_x11 == -1)
- options->forward_x11 = 0;
- /*
- * Unlike OpenSSH, we keep backward compatibility for '-X' option
- * which means that X11 forwarding is trusted by default.
- */
- if (options->forward_x11_trusted == -1)
- options->forward_x11_trusted = 1;
- if (options->xauth_location == NULL)
- options->xauth_location = _PATH_XAUTH;
- if (options->gateway_ports == -1)
- options->gateway_ports = 0;
- if (options->use_privileged_port == -1)
- options->use_privileged_port = 0;
- if (options->rhosts_authentication == -1)
- options->rhosts_authentication = 0;
- if (options->rsa_authentication == -1)
- options->rsa_authentication = 1;
- if (options->pubkey_authentication == -1)
- options->pubkey_authentication = 1;
- if (options->challenge_response_authentication == -1)
- options->challenge_response_authentication = 1;
-#ifdef GSSAPI
- if (options->gss_keyex == -1)
- options->gss_keyex = 1;
- if (options->gss_authentication == -1)
- options->gss_authentication = 1;
- if (options->gss_deleg_creds == -1)
- options->gss_deleg_creds = 0;
-#ifdef GSI
- if (options->gss_globus_deleg_limited_proxy == -1)
- options->gss_globus_deleg_limited_proxy = 0;
-#endif /* GSI */
-#endif /* GSSAPI */
-#if defined(KRB4) || defined(KRB5)
- if (options->kerberos_authentication == -1)
- options->kerberos_authentication = 1;
-#endif
-#if defined(AFS) || defined(KRB5)
- if (options->kerberos_tgt_passing == -1)
- options->kerberos_tgt_passing = 1;
-#endif
-#ifdef AFS
- if (options->afs_token_passing == -1)
- options->afs_token_passing = 1;
-#endif
- if (options->password_authentication == -1)
- options->password_authentication = 1;
- if (options->kbd_interactive_authentication == -1)
- options->kbd_interactive_authentication = 1;
- if (options->rhosts_rsa_authentication == -1)
- options->rhosts_rsa_authentication = 0;
- if (options->hostbased_authentication == -1)
- options->hostbased_authentication = 0;
- if (options->batch_mode == -1)
- options->batch_mode = 0;
- if (options->check_host_ip == -1)
- options->check_host_ip = 1;
- if (options->strict_host_key_checking == -1)
- options->strict_host_key_checking = 2; /* 2 is default */
- if (options->compression == -1)
- options->compression = 0;
- if (options->keepalives == -1)
- options->keepalives = 1;
- if (options->compression_level == -1)
- options->compression_level = 6;
- if (options->port == -1)
- options->port = 0; /* Filled in ssh_connect. */
- if (options->connection_attempts == -1)
- options->connection_attempts = 1;
- if (options->number_of_password_prompts == -1)
- options->number_of_password_prompts = 3;
- /* Selected in ssh_login(). */
- if (options->cipher == -1)
- options->cipher = SSH_CIPHER_NOT_SET;
- /* options->ciphers, default set in myproposals.h */
- /* options->macs, default set in myproposals.h */
- /* options->hostkeyalgorithms, default set in myproposals.h */
- if (options->protocol == SSH_PROTO_UNKNOWN)
- options->protocol = SSH_PROTO_1|SSH_PROTO_2;
- if (options->num_identity_files == 0) {
- if (options->protocol & SSH_PROTO_1) {
- len = 2 + strlen(_PATH_SSH_CLIENT_IDENTITY) + 1;
- options->identity_files[options->num_identity_files] =
- xmalloc(len);
- snprintf(options->identity_files[options->num_identity_files++],
- len, "~/%.100s", _PATH_SSH_CLIENT_IDENTITY);
- }
- if (options->protocol & SSH_PROTO_2) {
- len = 2 + strlen(_PATH_SSH_CLIENT_ID_RSA) + 1;
- options->identity_files[options->num_identity_files] =
- xmalloc(len);
- snprintf(options->identity_files[options->num_identity_files++],
- len, "~/%.100s", _PATH_SSH_CLIENT_ID_RSA);
-
- len = 2 + strlen(_PATH_SSH_CLIENT_ID_DSA) + 1;
- options->identity_files[options->num_identity_files] =
- xmalloc(len);
- snprintf(options->identity_files[options->num_identity_files++],
- len, "~/%.100s", _PATH_SSH_CLIENT_ID_DSA);
- }
- }
- if (options->escape_char == -1)
- options->escape_char = '~';
- if (options->system_hostfile == NULL)
- options->system_hostfile = _PATH_SSH_SYSTEM_HOSTFILE;
- if (options->user_hostfile == NULL)
- options->user_hostfile = _PATH_SSH_USER_HOSTFILE;
- if (options->system_hostfile2 == NULL)
- options->system_hostfile2 = _PATH_SSH_SYSTEM_HOSTFILE2;
- if (options->user_hostfile2 == NULL)
- options->user_hostfile2 = _PATH_SSH_USER_HOSTFILE2;
- if (options->log_level == SYSLOG_LEVEL_NOT_SET)
- options->log_level = SYSLOG_LEVEL_INFO;
- if (options->clear_forwardings == 1)
- clear_forwardings(options);
- if (options->no_host_authentication_for_localhost == -1)
- options->no_host_authentication_for_localhost = 0;
- if (options->rekey_limit == -1)
- options->rekey_limit = 0;
- if (options->fallback_to_rsh == -1)
- options->fallback_to_rsh = 0;
- if (options->use_rsh == -1)
- options->use_rsh = 0;
- if (options->server_alive_interval == -1)
- options->server_alive_interval = 0;
- if (options->server_alive_count_max == -1)
- options->server_alive_count_max = 3;
- if (options->hash_known_hosts == -1)
- options->hash_known_hosts = 0;
- if (options->disable_banner == -1)
- options->disable_banner = 0;
- if (options->use_openssl_engine == -1)
- options->use_openssl_engine = 1;
- /* options->proxy_command should not be set by default */
- /* options->user will be set in the main program if appropriate */
- /* options->hostname will be set in the main program if appropriate */
- /* options->host_key_alias should not be set by default */
- /* options->preferred_authentications will be set in ssh */
- /* options->ignore_if_unknown should not be set by default */
-}
-
-/*
- * Parses a string containing a port forwarding specification of one of the
- * two forms, short or long:
- *
- * [listenhost:]listenport
- * [listenhost:]listenport:connecthost:connectport
- *
- * short forwarding specification is used for dynamic port forwarding and for
- * port forwarding cancelation in process_cmdline(). The function returns number
- * of arguments parsed or zero on any error.
- */
-int
-parse_forward(int long_form, Forward *fwd, const char *fwdspec)
-{
- int i;
- char *p, *cp, *fwdarg[5];
-
- memset(fwd, '\0', sizeof(*fwd));
-
- cp = p = xstrdup(fwdspec);
-
- /* skip leading spaces */
- while (isspace(*cp))
- cp++;
-
- for (i = 0; i < 5; ++i)
- if ((fwdarg[i] = hpdelim(&cp)) == NULL)
- break;
-
- if ((long_form == 0 && i > 2) || (long_form == 1 && i < 3) || (i == 5))
- goto fail_free;
-
- switch (i) {
- case 0:
- goto fail_free;
-
- case 1:
- fwd->listen_host = NULL;
- fwd->listen_port = a2port(fwdarg[0]);
- break;
-
- case 2:
- fwd->listen_host = xstrdup(cleanhostname(fwdarg[0]));
- fwd->listen_port = a2port(fwdarg[1]);
- break;
-
- case 3:
- fwd->listen_host = NULL;
- fwd->listen_port = a2port(fwdarg[0]);
- fwd->connect_host = xstrdup(cleanhostname(fwdarg[1]));
- fwd->connect_port = a2port(fwdarg[2]);
- break;
-
- case 4:
- fwd->listen_host = xstrdup(cleanhostname(fwdarg[0]));
- fwd->listen_port = a2port(fwdarg[1]);
- fwd->connect_host = xstrdup(cleanhostname(fwdarg[2]));
- fwd->connect_port = a2port(fwdarg[3]);
- break;
- }
-
- if (fwd->listen_port == 0 || (fwd->connect_port == 0 && i > 2))
- goto fail_free;
-
- xfree(p);
- return (i);
-
-fail_free:
- if (p != NULL)
- xfree(p);
- if (fwd->connect_host != NULL)
- xfree(fwd->connect_host);
- if (fwd->listen_host != NULL)
- xfree(fwd->listen_host);
- return (0);
-}
-
-/*
- * Process previously stored unknown options. When this function is called we
- * already have IgnoreIfUnknown set so finally we can decide whether each
- * unknown option is to be ignored or not.
- */
-void
-process_unknown_options(Options *options)
-{
- StoredOption *so;
- int m, i, bad_options = 0;
-
- /* if there is no unknown option we are done */
- if (options->unknown_opts_num == 0)
- return;
-
- /*
- * Now go through the list of unknown options and report any one that
- * is not explicitly listed in IgnoreIfUnknown option. If at least one
- * such as that is found it's a show stopper.
- */
- for (i = 0; i < options->unknown_opts_num; ++i) {
- so = &options->unknown_opts[i];
- if (options->ignore_if_unknown == NULL)
- m = 0;
- else
- m = match_pattern_list(tolowercase(so->keyword),
- options->ignore_if_unknown,
- strlen(options->ignore_if_unknown), 1);
- if (m == 1) {
- debug("%s: line %d: ignoring unknown option: %s",
- so->filename, so->linenum, so->keyword);
- }
- else {
- error("%s: line %d: unknown configuration option: %s",
- so->filename, so->linenum, so->keyword);
- bad_options++;
- }
- xfree(so->keyword);
- xfree(so->filename);
- }
-
- /* exit if we found at least one unignored unknown option */
- if (bad_options > 0)
- fatal("terminating, %d bad configuration option(s)",
- bad_options);
-}
diff --git a/usr/src/cmd/ssh/libssh/common/readpass.c b/usr/src/cmd/ssh/libssh/common/readpass.c
deleted file mode 100644
index fa1f1a4982..0000000000
--- a/usr/src/cmd/ssh/libssh/common/readpass.c
+++ /dev/null
@@ -1,163 +0,0 @@
-/*
- * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
- */
-
-/*
- * Copyright (c) 2001 Markus Friedl. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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.
- */
-
-#include "includes.h"
-RCSID("$OpenBSD: readpass.c,v 1.27 2002/03/26 15:58:46 markus Exp $");
-
-#include "xmalloc.h"
-#include "readpass.h"
-#include "pathnames.h"
-#include "log.h"
-#include "ssh.h"
-#include <langinfo.h>
-
-static char *
-ssh_askpass(char *askpass, const char *msg)
-{
- pid_t pid;
- size_t len;
- char *pass;
- int p[2], status, ret;
- char buf[1024];
-
- if (fflush(stdout) != 0)
- error("ssh_askpass: fflush: %s", strerror(errno));
- if (askpass == NULL)
- fatal("internal error: askpass undefined");
- if (pipe(p) < 0) {
- error("ssh_askpass: pipe: %s", strerror(errno));
- return xstrdup("");
- }
- if ((pid = fork()) < 0) {
- error("ssh_askpass: fork: %s", strerror(errno));
- return xstrdup("");
- }
- if (pid == 0) {
- seteuid(getuid());
- setuid(getuid());
- close(p[0]);
- if (dup2(p[1], STDOUT_FILENO) < 0)
- fatal("ssh_askpass: dup2: %s", strerror(errno));
- execlp(askpass, askpass, msg, (char *) 0);
- fatal("ssh_askpass: exec(%s): %s", askpass, strerror(errno));
- }
- close(p[1]);
-
- len = ret = 0;
- do {
- ret = read(p[0], buf + len, sizeof(buf) - 1 - len);
- if (ret == -1 && errno == EINTR)
- continue;
- if (ret <= 0)
- break;
- len += ret;
- } while (sizeof(buf) - 1 - len > 0);
- buf[len] = '\0';
-
- close(p[0]);
- while (waitpid(pid, &status, 0) < 0)
- if (errno != EINTR)
- break;
-
- buf[strcspn(buf, "\r\n")] = '\0';
- pass = xstrdup(buf);
- memset(buf, 0, sizeof(buf));
- return pass;
-}
-
-/*
- * Reads a passphrase from /dev/tty with echo turned off/on. Returns the
- * passphrase (allocated with xmalloc). Exits if EOF is encountered. If
- * RP_ALLOW_STDIN is set, the passphrase will be read from stdin if no
- * tty is available
- */
-char *
-read_passphrase(const char *prompt, int flags)
-{
- char *askpass = NULL, *ret, buf[1024];
- int rppflags, use_askpass = 0, ttyfd;
-
- rppflags = (flags & RP_ECHO) ? RPP_ECHO_ON : RPP_ECHO_OFF;
- if (flags & RP_ALLOW_STDIN) {
- if (!isatty(STDIN_FILENO))
- use_askpass = 1;
- } else {
- rppflags |= RPP_REQUIRE_TTY;
- ttyfd = open(_PATH_TTY, O_RDWR);
- if (ttyfd >= 0)
- close(ttyfd);
- else
- use_askpass = 1;
- }
-
- if (use_askpass && getenv("DISPLAY")) {
- if (getenv(SSH_ASKPASS_ENV))
- askpass = getenv(SSH_ASKPASS_ENV);
- else
- askpass = _PATH_SSH_ASKPASS_DEFAULT;
- return ssh_askpass(askpass, prompt);
- }
-
- if (readpassphrase(prompt, buf, sizeof buf, rppflags) == NULL) {
- if (flags & RP_ALLOW_EOF)
- return NULL;
- return xstrdup("");
- }
-
- ret = xstrdup(buf);
- memset(buf, 'x', sizeof buf);
- return ret;
-}
-
-int
-ask_permission(const char *fmt, ...)
-{
- va_list args;
- char *p, prompt[1024];
- int allowed = 0;
- char *yeschar = nl_langinfo(YESSTR);
-
- va_start(args, fmt);
- vsnprintf(prompt, sizeof(prompt), fmt, args);
- va_end(args);
-
- p = read_passphrase(prompt, RP_USE_ASKPASS|RP_ALLOW_EOF);
- if (p != NULL) {
- /*
- * Accept empty responses and responses consisting
- * of the word "yes" as affirmative.
- */
- if (*p == '\0' || *p == '\n' ||
- strncasecmp(p, yeschar, 1) == 0)
- allowed = 1;
- xfree(p);
- }
-
- return (allowed);
-}
diff --git a/usr/src/cmd/ssh/libssh/common/rsa.c b/usr/src/cmd/ssh/libssh/common/rsa.c
deleted file mode 100644
index f24a44a770..0000000000
--- a/usr/src/cmd/ssh/libssh/common/rsa.c
+++ /dev/null
@@ -1,146 +0,0 @@
-/*
- * Author: Tatu Ylonen <ylo@cs.hut.fi>
- * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
- * All rights reserved
- *
- * As far as I am concerned, the code I have written for this software
- * can be used freely for any purpose. Any derived versions of this
- * software must be clearly marked as such, and if the derived work is
- * incompatible with the protocol description in the RFC file, it must be
- * called by a name other than "ssh" or "Secure Shell".
- *
- *
- * Copyright (c) 1999 Niels Provos. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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.
- *
- *
- * Description of the RSA algorithm can be found e.g. from the following
- * sources:
- *
- * Bruce Schneier: Applied Cryptography. John Wiley & Sons, 1994.
- *
- * Jennifer Seberry and Josed Pieprzyk: Cryptography: An Introduction to
- * Computer Security. Prentice-Hall, 1989.
- *
- * Man Young Rhee: Cryptography and Secure Data Communications. McGraw-Hill,
- * 1994.
- *
- * R. Rivest, A. Shamir, and L. M. Adleman: Cryptographic Communications
- * System and Method. US Patent 4,405,829, 1983.
- *
- * Hans Riesel: Prime Numbers and Computer Methods for Factorization.
- * Birkhauser, 1994.
- *
- * The RSA Frequently Asked Questions document by RSA Data Security,
- * Inc., 1995.
- *
- * RSA in 3 lines of perl by Adam Back <aba@atlax.ex.ac.uk>, 1995, as
- * included below:
- *
- * [gone - had to be deleted - what a pity]
- */
-
-#include "includes.h"
-RCSID("$OpenBSD: rsa.c,v 1.24 2001/12/27 18:22:16 markus Exp $");
-
-#pragma ident "%Z%%M% %I% %E% SMI"
-
-#include "rsa.h"
-#include "log.h"
-#include "xmalloc.h"
-
-void
-rsa_public_encrypt(BIGNUM *out, BIGNUM *in, RSA *key)
-{
- u_char *inbuf, *outbuf;
- int len, ilen, olen;
-
- if (BN_num_bits(key->e) < 2 || !BN_is_odd(key->e))
- fatal("rsa_public_encrypt() exponent too small or not odd");
-
- olen = BN_num_bytes(key->n);
- outbuf = xmalloc(olen);
-
- ilen = BN_num_bytes(in);
- inbuf = xmalloc(ilen);
- BN_bn2bin(in, inbuf);
-
- if ((len = RSA_public_encrypt(ilen, inbuf, outbuf, key,
- RSA_PKCS1_PADDING)) <= 0)
- fatal("rsa_public_encrypt() failed");
-
- BN_bin2bn(outbuf, len, out);
-
- memset(outbuf, 0, olen);
- memset(inbuf, 0, ilen);
- xfree(outbuf);
- xfree(inbuf);
-}
-
-int
-rsa_private_decrypt(BIGNUM *out, BIGNUM *in, RSA *key)
-{
- u_char *inbuf, *outbuf;
- int len, ilen, olen;
-
- olen = BN_num_bytes(key->n);
- outbuf = xmalloc(olen);
-
- ilen = BN_num_bytes(in);
- inbuf = xmalloc(ilen);
- BN_bn2bin(in, inbuf);
-
- if ((len = RSA_private_decrypt(ilen, inbuf, outbuf, key,
- RSA_PKCS1_PADDING)) <= 0) {
- error("rsa_private_decrypt() failed");
- } else {
- BN_bin2bn(outbuf, len, out);
- }
- memset(outbuf, 0, olen);
- memset(inbuf, 0, ilen);
- xfree(outbuf);
- xfree(inbuf);
- return len;
-}
-
-/* calculate p-1 and q-1 */
-void
-rsa_generate_additional_parameters(RSA *rsa)
-{
- BIGNUM *aux;
- BN_CTX *ctx;
-
- if ((aux = BN_new()) == NULL)
- fatal("rsa_generate_additional_parameters: BN_new failed");
- if ((ctx = BN_CTX_new()) == NULL)
- fatal("rsa_generate_additional_parameters: BN_CTX_new failed");
-
- BN_sub(aux, rsa->q, BN_value_one());
- BN_mod(rsa->dmq1, rsa->d, aux, ctx);
-
- BN_sub(aux, rsa->p, BN_value_one());
- BN_mod(rsa->dmp1, rsa->d, aux, ctx);
-
- BN_clear_free(aux);
- BN_CTX_free(ctx);
-}
-
diff --git a/usr/src/cmd/ssh/libssh/common/sftp-common.c b/usr/src/cmd/ssh/libssh/common/sftp-common.c
deleted file mode 100644
index ead9e2406f..0000000000
--- a/usr/src/cmd/ssh/libssh/common/sftp-common.c
+++ /dev/null
@@ -1,227 +0,0 @@
-/*
- * Copyright (c) 2001 Markus Friedl. All rights reserved.
- * Copyright (c) 2001 Damien Miller. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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.
- */
-
-/* $OpenBSD: sftp-common.c,v 1.20 2006/08/03 03:34:42 deraadt Exp $ */
-
-#pragma ident "%Z%%M% %I% %E% SMI"
-
-#include "includes.h"
-
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <sys/param.h>
-
-#include <grp.h>
-#include <pwd.h>
-#include <stdio.h>
-#include <string.h>
-#include <time.h>
-#include <stdarg.h>
-
-#include "xmalloc.h"
-#include "buffer.h"
-#include "bufaux.h"
-#include "log.h"
-
-#include "sftp.h"
-#include "sftp-common.h"
-
-/* Clear contents of attributes structure */
-void
-attrib_clear(Attrib *a)
-{
- a->flags = 0;
- a->size = 0;
- a->uid = 0;
- a->gid = 0;
- a->perm = 0;
- a->atime = 0;
- a->mtime = 0;
-}
-
-/* Convert from struct stat to filexfer attribs */
-void
-stat_to_attrib(const struct stat *st, Attrib *a)
-{
- attrib_clear(a);
- a->flags = 0;
- a->flags |= SSH2_FILEXFER_ATTR_SIZE;
- a->size = st->st_size;
- a->flags |= SSH2_FILEXFER_ATTR_UIDGID;
- a->uid = st->st_uid;
- a->gid = st->st_gid;
- a->flags |= SSH2_FILEXFER_ATTR_PERMISSIONS;
- a->perm = st->st_mode;
- a->flags |= SSH2_FILEXFER_ATTR_ACMODTIME;
- a->atime = st->st_atime;
- a->mtime = st->st_mtime;
-}
-
-/* Convert from filexfer attribs to struct stat */
-void
-attrib_to_stat(const Attrib *a, struct stat *st)
-{
- memset(st, 0, sizeof(*st));
-
- if (a->flags & SSH2_FILEXFER_ATTR_SIZE)
- st->st_size = a->size;
- if (a->flags & SSH2_FILEXFER_ATTR_UIDGID) {
- st->st_uid = a->uid;
- st->st_gid = a->gid;
- }
- if (a->flags & SSH2_FILEXFER_ATTR_PERMISSIONS)
- st->st_mode = a->perm;
- if (a->flags & SSH2_FILEXFER_ATTR_ACMODTIME) {
- st->st_atime = a->atime;
- st->st_mtime = a->mtime;
- }
-}
-
-/* Decode attributes in buffer */
-Attrib *
-decode_attrib(Buffer *b)
-{
- static Attrib a;
-
- attrib_clear(&a);
- a.flags = buffer_get_int(b);
- if (a.flags & SSH2_FILEXFER_ATTR_SIZE)
- a.size = buffer_get_int64(b);
- if (a.flags & SSH2_FILEXFER_ATTR_UIDGID) {
- a.uid = buffer_get_int(b);
- a.gid = buffer_get_int(b);
- }
- if (a.flags & SSH2_FILEXFER_ATTR_PERMISSIONS)
- a.perm = buffer_get_int(b);
- if (a.flags & SSH2_FILEXFER_ATTR_ACMODTIME) {
- a.atime = buffer_get_int(b);
- a.mtime = buffer_get_int(b);
- }
- /* vendor-specific extensions */
- if (a.flags & SSH2_FILEXFER_ATTR_EXTENDED) {
- char *type, *data;
- int i, count;
-
- count = buffer_get_int(b);
- for (i = 0; i < count; i++) {
- type = buffer_get_string(b, NULL);
- data = buffer_get_string(b, NULL);
- debug3("Got file attribute \"%s\"", type);
- xfree(type);
- xfree(data);
- }
- }
- return &a;
-}
-
-/* Encode attributes to buffer */
-void
-encode_attrib(Buffer *b, const Attrib *a)
-{
- buffer_put_int(b, a->flags);
- if (a->flags & SSH2_FILEXFER_ATTR_SIZE)
- buffer_put_int64(b, a->size);
- if (a->flags & SSH2_FILEXFER_ATTR_UIDGID) {
- buffer_put_int(b, a->uid);
- buffer_put_int(b, a->gid);
- }
- if (a->flags & SSH2_FILEXFER_ATTR_PERMISSIONS)
- buffer_put_int(b, a->perm);
- if (a->flags & SSH2_FILEXFER_ATTR_ACMODTIME) {
- buffer_put_int(b, a->atime);
- buffer_put_int(b, a->mtime);
- }
-}
-
-/* Convert from SSH2_FX_ status to text error message */
-const char *
-fx2txt(int status)
-{
- switch (status) {
- case SSH2_FX_OK:
- return(gettext("No error"));
- case SSH2_FX_EOF:
- return(gettext("End of file"));
- case SSH2_FX_NO_SUCH_FILE:
- return(gettext("No such file or directory"));
- case SSH2_FX_PERMISSION_DENIED:
- return(gettext("Permission denied"));
- case SSH2_FX_FAILURE:
- return(gettext("Failure"));
- case SSH2_FX_BAD_MESSAGE:
- return(gettext("Bad message"));
- case SSH2_FX_NO_CONNECTION:
- return(gettext("No connection"));
- case SSH2_FX_CONNECTION_LOST:
- return(gettext("Connection lost"));
- case SSH2_FX_OP_UNSUPPORTED:
- return(gettext("Operation unsupported"));
- default:
- return(gettext("Unknown status"));
- }
- /* NOTREACHED */
-}
-
-/*
- * drwxr-xr-x 5 markus markus 1024 Jan 13 18:39 .ssh
- */
-char *
-ls_file(const char *name, const struct stat *st, int remote)
-{
- int ulen, glen, sz = 0;
- struct passwd *pw;
- struct group *gr;
- struct tm *ltime = localtime(&st->st_mtime);
- char *user, *group;
- char buf[1024], mode[11+1], tbuf[12+1], ubuf[11+1], gbuf[11+1];
-
- strmode(st->st_mode, mode);
- if (!remote && (pw = getpwuid(st->st_uid)) != NULL) {
- user = pw->pw_name;
- } else {
- snprintf(ubuf, sizeof ubuf, "%u", (u_int)st->st_uid);
- user = ubuf;
- }
- if (!remote && (gr = getgrgid(st->st_gid)) != NULL) {
- group = gr->gr_name;
- } else {
- snprintf(gbuf, sizeof gbuf, "%u", (u_int)st->st_gid);
- group = gbuf;
- }
- if (ltime != NULL) {
- if (time(NULL) - st->st_mtime < (365*24*60*60)/2)
- sz = strftime(tbuf, sizeof tbuf, "%b %e %H:%M", ltime);
- else
- sz = strftime(tbuf, sizeof tbuf, "%b %e %Y", ltime);
- }
- if (sz == 0)
- tbuf[0] = '\0';
- ulen = MAX(strlen(user), 8);
- glen = MAX(strlen(group), 8);
- snprintf(buf, sizeof buf, "%s %3u %-*s %-*s %8llu %s %s", mode,
- (u_int)st->st_nlink, ulen, user, glen, group,
- (unsigned long long)st->st_size, tbuf, name);
- return xstrdup(buf);
-}
diff --git a/usr/src/cmd/ssh/libssh/common/ssh-dss.c b/usr/src/cmd/ssh/libssh/common/ssh-dss.c
deleted file mode 100644
index f73a91672f..0000000000
--- a/usr/src/cmd/ssh/libssh/common/ssh-dss.c
+++ /dev/null
@@ -1,183 +0,0 @@
-/*
- * Copyright (c) 2000 Markus Friedl. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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.
- */
-
-#include "includes.h"
-RCSID("$OpenBSD: ssh-dss.c,v 1.17 2002/07/04 10:41:47 markus Exp $");
-
-#pragma ident "%Z%%M% %I% %E% SMI"
-
-#include <openssl/bn.h>
-#include <openssl/evp.h>
-
-#include "xmalloc.h"
-#include "buffer.h"
-#include "bufaux.h"
-#include "compat.h"
-#include "log.h"
-#include "key.h"
-#include "ssh-dss.h"
-
-#define INTBLOB_LEN 20
-#define SIGBLOB_LEN (2*INTBLOB_LEN)
-
-int
-ssh_dss_sign(Key *key, u_char **sigp, u_int *lenp,
- u_char *data, u_int datalen)
-{
- DSA_SIG *sig;
- const EVP_MD *evp_md = EVP_sha1();
- EVP_MD_CTX md;
- u_char digest[EVP_MAX_MD_SIZE], sigblob[SIGBLOB_LEN];
- u_int rlen, slen, len, dlen;
- Buffer b;
-
- if (key == NULL || key->type != KEY_DSA || key->dsa == NULL) {
- error("ssh_dss_sign: no DSA key");
- return -1;
- }
- EVP_DigestInit(&md, evp_md);
- EVP_DigestUpdate(&md, data, datalen);
- EVP_DigestFinal(&md, digest, &dlen);
-
- sig = DSA_do_sign(digest, dlen, key->dsa);
- memset(digest, 'd', sizeof(digest));
-
- if (sig == NULL) {
- error("ssh_dss_sign: sign failed");
- return -1;
- }
-
- rlen = BN_num_bytes(sig->r);
- slen = BN_num_bytes(sig->s);
- if (rlen > INTBLOB_LEN || slen > INTBLOB_LEN) {
- error("bad sig size %u %u", rlen, slen);
- DSA_SIG_free(sig);
- return -1;
- }
- memset(sigblob, 0, SIGBLOB_LEN);
- BN_bn2bin(sig->r, sigblob+ SIGBLOB_LEN - INTBLOB_LEN - rlen);
- BN_bn2bin(sig->s, sigblob+ SIGBLOB_LEN - slen);
- DSA_SIG_free(sig);
-
- if (datafellows & SSH_BUG_SIGBLOB) {
- if (lenp != NULL)
- *lenp = SIGBLOB_LEN;
- if (sigp != NULL) {
- *sigp = xmalloc(SIGBLOB_LEN);
- memcpy(*sigp, sigblob, SIGBLOB_LEN);
- }
- } else {
- /* ietf-drafts */
- buffer_init(&b);
- buffer_put_cstring(&b, "ssh-dss");
- buffer_put_string(&b, sigblob, SIGBLOB_LEN);
- len = buffer_len(&b);
- if (lenp != NULL)
- *lenp = len;
- if (sigp != NULL) {
- *sigp = xmalloc(len);
- memcpy(*sigp, buffer_ptr(&b), len);
- }
- buffer_free(&b);
- }
- return 0;
-}
-int
-ssh_dss_verify(Key *key, u_char *signature, u_int signaturelen,
- u_char *data, u_int datalen)
-{
- DSA_SIG *sig;
- const EVP_MD *evp_md = EVP_sha1();
- EVP_MD_CTX md;
- u_char digest[EVP_MAX_MD_SIZE], *sigblob;
- u_int len, dlen;
- int rlen, ret;
- Buffer b;
-
- if (key == NULL || key->type != KEY_DSA || key->dsa == NULL) {
- error("ssh_dss_verify: no DSA key");
- return -1;
- }
-
- /* fetch signature */
- if (datafellows & SSH_BUG_SIGBLOB) {
- sigblob = signature;
- len = signaturelen;
- } else {
- /* ietf-drafts */
- char *ktype;
- buffer_init(&b);
- buffer_append(&b, signature, signaturelen);
- ktype = buffer_get_string(&b, NULL);
- if (strcmp("ssh-dss", ktype) != 0) {
- error("ssh_dss_verify: cannot handle type %s", ktype);
- buffer_free(&b);
- xfree(ktype);
- return -1;
- }
- xfree(ktype);
- sigblob = buffer_get_string(&b, &len);
- rlen = buffer_len(&b);
- buffer_free(&b);
- if (rlen != 0) {
- error("ssh_dss_verify: "
- "remaining bytes in signature %d", rlen);
- xfree(sigblob);
- return -1;
- }
- }
-
- if (len != SIGBLOB_LEN) {
- fatal("bad sigbloblen %u != SIGBLOB_LEN", len);
- }
-
- /* parse signature */
- if ((sig = DSA_SIG_new()) == NULL)
- fatal("ssh_dss_verify: DSA_SIG_new failed");
- if ((sig->r = BN_new()) == NULL)
- fatal("ssh_dss_verify: BN_new failed");
- if ((sig->s = BN_new()) == NULL)
- fatal("ssh_dss_verify: BN_new failed");
- BN_bin2bn(sigblob, INTBLOB_LEN, sig->r);
- BN_bin2bn(sigblob+ INTBLOB_LEN, INTBLOB_LEN, sig->s);
-
- if (!(datafellows & SSH_BUG_SIGBLOB)) {
- memset(sigblob, 0, len);
- xfree(sigblob);
- }
-
- /* sha1 the data */
- EVP_DigestInit(&md, evp_md);
- EVP_DigestUpdate(&md, data, datalen);
- EVP_DigestFinal(&md, digest, &dlen);
-
- ret = DSA_do_verify(digest, dlen, sig, key->dsa);
- memset(digest, 'd', sizeof(digest));
-
- DSA_SIG_free(sig);
-
- debug("ssh_dss_verify: signature %s",
- ret == 1 ? "correct" : ret == 0 ? "incorrect" : "error");
- return ret;
-}
diff --git a/usr/src/cmd/ssh/libssh/common/ssh-gss.c b/usr/src/cmd/ssh/libssh/common/ssh-gss.c
deleted file mode 100644
index 37aeb04873..0000000000
--- a/usr/src/cmd/ssh/libssh/common/ssh-gss.c
+++ /dev/null
@@ -1,782 +0,0 @@
-/*
- * Copyright (c) 2001-2003 Simon Wilkinson. All rights reserved. *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR `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.
- */
-/*
- * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
- */
-
-#include "includes.h"
-
-#ifdef GSSAPI
-
-#include "ssh.h"
-#include "ssh2.h"
-#include "xmalloc.h"
-#include "buffer.h"
-#include "bufaux.h"
-#include "packet.h"
-#include "compat.h"
-#include <openssl/evp.h>
-#include "cipher.h"
-#include "kex.h"
-#include "log.h"
-#include "compat.h"
-#include "xlist.h"
-
-#include <netdb.h>
-
-#include "ssh-gss.h"
-
-#ifdef HAVE_GSS_OID_TO_MECH
-#include <gssapi/gssapi_ext.h>
-#endif /* HAVE_GSS_OID_TO_MECH */
-
-typedef struct {
- char *encoded;
- gss_OID oid;
-} ssh_gss_kex_mapping;
-
-static ssh_gss_kex_mapping **gss_enc2oid = NULL;
-
-static void ssh_gssapi_encode_oid_for_kex(const gss_OID oid, char **enc_name);
-static char *ssh_gssapi_make_kexalgs_list(gss_OID_set mechs,
- const char *old_kexalgs);
-
-/*
- * Populate gss_enc2oid table and return list of kexnames.
- *
- * If called with both mechs == GSS_C_NULL_OID_SET and kexname_list == NULL
- * then cached gss_enc2oid table is cleaned up.
- */
-void
-ssh_gssapi_mech_oids_to_kexnames(const gss_OID_set mechs, char **kexname_list)
-{
- ssh_gss_kex_mapping **new_gss_enc2oid, **p;
- Buffer buf;
- char *enc_name;
- int i;
-
- if (kexname_list != NULL)
- *kexname_list = NULL; /* default to failed */
-
- if (mechs != GSS_C_NULL_OID_SET || kexname_list == NULL) {
- /* Cleanup gss_enc2oid table */
- for (p = gss_enc2oid; p != NULL && *p != NULL; p++) {
- if ((*p)->encoded)
- xfree((*p)->encoded);
- ssh_gssapi_release_oid(&(*p)->oid);
- xfree(*p);
- }
- if (gss_enc2oid)
- xfree(gss_enc2oid);
- }
-
- if (mechs == GSS_C_NULL_OID_SET && kexname_list == NULL)
- return; /* nothing left to do */
-
- if (mechs) {
- gss_OID mech;
- /* Populate gss_enc2oid table */
- new_gss_enc2oid = xmalloc(sizeof (ssh_gss_kex_mapping *) *
- (mechs->count + 1));
- memset(new_gss_enc2oid, 0,
- sizeof (ssh_gss_kex_mapping *) * (mechs->count + 1));
-
- for (i = 0; i < mechs->count; i++) {
- mech = &mechs->elements[i];
- ssh_gssapi_encode_oid_for_kex((const gss_OID)mech,
- &enc_name);
-
- if (!enc_name)
- continue;
-
- new_gss_enc2oid[i] =
- xmalloc(sizeof (ssh_gss_kex_mapping));
- (new_gss_enc2oid[i])->encoded = enc_name;
- (new_gss_enc2oid[i])->oid =
- ssh_gssapi_dup_oid(&mechs->elements[i]);
- }
-
- /* Do this last to avoid run-ins with fatal_cleanups */
- gss_enc2oid = new_gss_enc2oid;
- }
-
- if (!kexname_list)
- return; /* nothing left to do */
-
- /* Make kex name list */
- buffer_init(&buf);
- for (p = gss_enc2oid; p && *p; p++) {
- buffer_put_char(&buf, ',');
- buffer_append(&buf, (*p)->encoded, strlen((*p)->encoded));
- }
-
- if (buffer_len(&buf) == 0) {
- buffer_free(&buf);
- return;
- }
-
- buffer_consume(&buf, 1); /* consume leading ',' */
- buffer_put_char(&buf, '\0');
-
- *kexname_list = xstrdup(buffer_ptr(&buf));
- buffer_free(&buf);
-}
-
-void
-ssh_gssapi_mech_oid_to_kexname(const gss_OID mech, char **kexname)
-{
- ssh_gss_kex_mapping **p;
-
- if (mech == GSS_C_NULL_OID || !kexname)
- return;
-
- *kexname = NULL; /* default to not found */
- if (gss_enc2oid) {
- for (p = gss_enc2oid; p && *p; p++) {
- if (mech->length == (*p)->oid->length &&
- memcmp(mech->elements, (*p)->oid->elements,
- mech->length) == 0)
- *kexname = xstrdup((*p)->encoded);
- }
- }
-
- if (*kexname)
- return; /* found */
-
- ssh_gssapi_encode_oid_for_kex(mech, kexname);
-}
-
-void
-ssh_gssapi_oid_of_kexname(const char *kexname, gss_OID *mech)
-{
- ssh_gss_kex_mapping **p;
-
- if (!mech || !kexname || !*kexname)
- return;
-
- *mech = GSS_C_NULL_OID; /* default to not found */
-
- if (!gss_enc2oid)
- return;
-
- for (p = gss_enc2oid; p && *p; p++) {
- if (strcmp(kexname, (*p)->encoded) == 0) {
- *mech = (*p)->oid;
- return;
- }
- }
-}
-
-static
-void
-ssh_gssapi_encode_oid_for_kex(const gss_OID oid, char **enc_name)
-{
- Buffer buf;
- OM_uint32 oidlen;
- uint_t enclen;
- const EVP_MD *evp_md = EVP_md5();
- EVP_MD_CTX md;
- uchar_t digest[EVP_MAX_MD_SIZE];
- char *encoded;
-
- if (oid == GSS_C_NULL_OID || !enc_name)
- return;
-
- *enc_name = NULL;
-
- oidlen = oid->length;
-
- /* No GSS mechs have OIDs as long as 128 -- simplify DER encoding */
- if (oidlen > 128)
- return; /* fail gracefully */
-
- /*
- * NOTE: If we need to support SSH_BUG_GSSAPI_BER this is where
- * we'd do it.
- *
- * That means using "Se3H81ismmOC3OE+FwYCiQ==" for the Kerberos
- * V mech and "N3+k7/4wGxHyuP8Yxi4RhA==" for the GSI mech. Ick.
- */
-
- buffer_init(&buf);
-
- /* UNIVERSAL class tag for OBJECT IDENTIFIER */
- buffer_put_char(&buf, 0x06);
- buffer_put_char(&buf, oidlen); /* one octet DER length -- see above */
-
- /* OID elements */
- buffer_append(&buf, oid->elements, oidlen);
-
- /* Make digest */
- EVP_DigestInit(&md, evp_md);
- EVP_DigestUpdate(&md, buffer_ptr(&buf), buffer_len(&buf));
- EVP_DigestFinal(&md, digest, NULL);
- buffer_free(&buf);
-
- /* Base 64 encoding */
- encoded = xmalloc(EVP_MD_size(evp_md)*2);
- enclen = __b64_ntop(digest, EVP_MD_size(evp_md),
- encoded, EVP_MD_size(evp_md) * 2);
- buffer_init(&buf);
- buffer_append(&buf, KEX_GSS_SHA1, sizeof (KEX_GSS_SHA1) - 1);
- buffer_append(&buf, encoded, enclen);
- buffer_put_char(&buf, '\0');
-
- debug2("GSS-API Mechanism encoded as %s", encoded);
- xfree(encoded);
-
- *enc_name = xstrdup(buffer_ptr(&buf));
- buffer_free(&buf);
-}
-
-static char *
-ssh_gssapi_make_kexalgs_list(gss_OID_set mechs, const char *old_kexalgs)
-{
- char *gss_kexalgs, *new_kexalgs;
- int len;
-
- if (mechs == GSS_C_NULL_OID_SET)
- return (xstrdup(old_kexalgs)); /* never null */
-
- ssh_gssapi_mech_oids_to_kexnames(mechs, &gss_kexalgs);
-
- if (gss_kexalgs == NULL || *gss_kexalgs == '\0')
- return (xstrdup(old_kexalgs)); /* never null */
-
- if (old_kexalgs == NULL || *old_kexalgs == '\0')
- return (gss_kexalgs);
-
- len = strlen(old_kexalgs) + strlen(gss_kexalgs) + 2;
- new_kexalgs = xmalloc(len);
- (void) snprintf(new_kexalgs, len, "%s,%s", gss_kexalgs, old_kexalgs);
- xfree(gss_kexalgs);
-
- return (new_kexalgs);
-}
-
-void
-ssh_gssapi_modify_kex(Kex *kex, gss_OID_set mechs, char **proposal)
-{
- char *kexalgs, *orig_kexalgs, *p;
- char **hostalg, *orig_hostalgs, *new_hostalgs;
- char **hostalgs;
- gss_OID_set dup_mechs;
- OM_uint32 maj, min;
- int i;
-
- if (kex == NULL || proposal == NULL ||
- proposal[PROPOSAL_KEX_ALGS] == NULL) {
- fatal("INTERNAL ERROR (%s)", __func__);
- }
-
- orig_hostalgs = proposal[PROPOSAL_SERVER_HOST_KEY_ALGS];
-
- if (kex->mechs == GSS_C_NULL_OID_SET && mechs == GSS_C_NULL_OID_SET)
- return; /* didn't offer GSS last time, not offering now */
-
- if (kex->mechs == GSS_C_NULL_OID_SET || mechs == GSS_C_NULL_OID_SET)
- goto mod_offer; /* didn't offer last time or not offering now */
-
- /* Check if mechs is congruent to kex->mechs (last offered) */
- if (kex->mechs->count == mechs->count) {
- int present, matches = 0;
-
- for (i = 0; i < mechs->count; i++) {
- maj = gss_test_oid_set_member(&min,
- &kex->mechs->elements[i], mechs, &present);
-
- if (GSS_ERROR(maj)) {
- mechs = GSS_C_NULL_OID_SET;
- break;
- }
-
- matches += (present) ? 1 : 0;
- }
-
- if (matches == kex->mechs->count)
- return; /* no change in offer from last time */
- }
-
-mod_offer:
- /*
- * Remove previously offered mechs from PROPOSAL_KEX_ALGS proposal
- *
- * ASSUMPTION: GSS-API kex algs always go in front, so removing
- * them is a matter of skipping them.
- */
- p = kexalgs = orig_kexalgs = proposal[PROPOSAL_KEX_ALGS];
- while (p != NULL && *p != '\0' &&
- strncmp(p, KEX_GSS_SHA1, strlen(KEX_GSS_SHA1)) == 0) {
-
- if ((p = strchr(p, ',')) == NULL)
- break;
- p++;
- kexalgs = p;
-
- }
- kexalgs = proposal[PROPOSAL_KEX_ALGS] = xstrdup(kexalgs);
- xfree(orig_kexalgs);
-
- (void) gss_release_oid_set(&min, &kex->mechs); /* ok if !kex->mechs */
-
- /* Not offering GSS kex algorithms now -> all done */
- if (mechs == GSS_C_NULL_OID_SET)
- return;
-
- /* Remember mechs we're offering */
- maj = gss_create_empty_oid_set(&min, &dup_mechs);
- if (GSS_ERROR(maj))
- return;
- for (i = 0; i < mechs->count; i++) {
- maj = gss_add_oid_set_member(&min, &mechs->elements[i],
- &dup_mechs);
-
- if (GSS_ERROR(maj)) {
- (void) gss_release_oid_set(&min, &dup_mechs);
- return;
- }
- }
-
- /* Add mechs to kex algorithms ... */
- proposal[PROPOSAL_KEX_ALGS] = ssh_gssapi_make_kexalgs_list(mechs,
- kexalgs);
- xfree(kexalgs);
- kex->mechs = dup_mechs; /* remember what we offer now */
-
- /*
- * ... and add null host key alg, if it wasn't there before, but
- * not if we're the server and we have other host key algs to
- * offer.
- *
- * NOTE: Never remove "null" host key alg once added.
- */
- if (orig_hostalgs == NULL || *orig_hostalgs == '\0') {
- proposal[PROPOSAL_SERVER_HOST_KEY_ALGS] = xstrdup("null");
- } else if (!kex->server) {
- hostalgs = xsplit(orig_hostalgs, ',');
- for (hostalg = hostalgs; *hostalg != NULL; hostalg++) {
- if (strcmp(*hostalg, "null") == 0) {
- xfree_split_list(hostalgs);
- return;
- }
- }
- xfree_split_list(hostalgs);
-
- if (kex->mechs != GSS_C_NULL_OID_SET) {
- int len;
-
- len = strlen(orig_hostalgs) + sizeof (",null");
- new_hostalgs = xmalloc(len);
- (void) snprintf(new_hostalgs, len, "%s,null",
- orig_hostalgs);
- proposal[PROPOSAL_SERVER_HOST_KEY_ALGS] = new_hostalgs;
- }
-
- xfree(orig_hostalgs);
- }
-}
-
-/*
- * Yes, we harcode OIDs for some things, for now it's all we can do.
- *
- * We have to reference particular mechanisms due to lack of generality
- * in the GSS-API in several areas: authorization, mapping principal
- * names to usernames, "storing" delegated credentials, and discovering
- * whether a mechanism is a pseudo-mechanism that negotiates mechanisms.
- *
- * Even if they were in some header file or if __gss_mech_to_oid()
- * and/or __gss_oid_to_mech() were standard we'd still have to hardcode
- * the mechanism names, and since the mechanisms have no standard names
- * other than their OIDs it's actually worse [less portable] to hardcode
- * names than OIDs, so we hardcode OIDs.
- *
- * SPNEGO is a difficult problem though -- it MUST NOT be used in SSHv2,
- * but that's true of all possible pseudo-mechanisms that can perform
- * mechanism negotiation, and SPNEGO could have new OIDs in the future.
- * Ideally we could query each mechanism for its feature set and then
- * ignore any mechanisms that negotiate mechanisms, but, alas, there's
- * no interface to do that.
- *
- * In the future, if the necessary generic GSS interfaces for the issues
- * listed above are made available (even if they differ by platform, as
- * we can expect authorization interfaces will), then we can stop
- * referencing specific mechanism OIDs here.
- */
-int
-ssh_gssapi_is_spnego(gss_OID oid)
-{
- return (oid->length == 6 &&
- memcmp("\053\006\001\005\005\002", oid->elements, 6) == 0);
-}
-
-int
-ssh_gssapi_is_krb5(gss_OID oid)
-{
- return (oid->length == 9 &&
- memcmp("\x2A\x86\x48\x86\xF7\x12\x01\x02\x02",
- oid->elements, 9) == 0);
-}
-
-int
-ssh_gssapi_is_dh(gss_OID oid)
-{
- return (oid->length == 9 &&
- memcmp("\053\006\004\001\052\002\032\002\005",
- oid->elements, 9) == 0);
-}
-
-int
-ssh_gssapi_is_gsi(gss_OID oid)
-{
- return (oid->length == 9 &&
- memcmp("\x2B\x06\x01\x04\x01\x9B\x50\x01\x01",
- oid->elements, 9) == 0);
-}
-
-const char *
-ssh_gssapi_oid_to_name(gss_OID oid)
-{
-#ifdef HAVE_GSS_OID_TO_MECH
- return (__gss_oid_to_mech(oid));
-#else
- if (ssh_gssapi_is_krb5(oid))
- return ("Kerberos");
- if (ssh_gssapi_is_gsi(oid))
- return ("GSI");
- return ("(unknown)");
-#endif /* HAVE_GSS_OID_TO_MECH */
-}
-
-char *
-ssh_gssapi_oid_to_str(gss_OID oid)
-{
-#ifdef HAVE_GSS_OID_TO_STR
- gss_buffer_desc str_buf;
- char *str;
- OM_uint32 maj, min;
-
- maj = gss_oid_to_str(&min, oid, &str_buf);
-
- if (GSS_ERROR(maj))
- return (xstrdup("<gss_oid_to_str() failed>"));
-
- str = xmalloc(str_buf.length + 1);
- memset(str, 0, str_buf.length + 1);
- strlcpy(str, str_buf.value, str_buf.length + 1);
- (void) gss_release_buffer(&min, &str_buf);
-
- return (str);
-#else
- return (xstrdup("<gss_oid_to_str() unsupported>"));
-#endif /* HAVE_GSS_OID_TO_STR */
-}
-
-/* Check that the OID in a data stream matches that in the context */
-int
-ssh_gssapi_check_mech_oid(Gssctxt *ctx, void *data, size_t len)
-{
-
- return (ctx != NULL && ctx->desired_mech != GSS_C_NULL_OID &&
- ctx->desired_mech->length == len &&
- memcmp(ctx->desired_mech->elements, data, len) == 0);
-}
-
-/* Set the contexts OID from a data stream */
-void
-ssh_gssapi_set_oid_data(Gssctxt *ctx, void *data, size_t len)
-{
- if (ctx->actual_mech != GSS_C_NULL_OID) {
- xfree(ctx->actual_mech->elements);
- xfree(ctx->actual_mech);
- }
- ctx->actual_mech = xmalloc(sizeof (gss_OID_desc));
- ctx->actual_mech->length = len;
- ctx->actual_mech->elements = xmalloc(len);
- memcpy(ctx->actual_mech->elements, data, len);
-}
-
-/* Set the contexts OID */
-void
-ssh_gssapi_set_oid(Gssctxt *ctx, gss_OID oid)
-{
- ssh_gssapi_set_oid_data(ctx, oid->elements, oid->length);
-}
-
-/* All this effort to report an error ... */
-
-void
-ssh_gssapi_error(Gssctxt *ctxt, const char *where)
-{
- char *errmsg = ssh_gssapi_last_error(ctxt, NULL, NULL);
-
- if (where != NULL)
- debug("GSS-API error while %s: %s", where, errmsg);
- else
- debug("GSS-API error: %s", errmsg);
-
- /* ssh_gssapi_last_error() can't return NULL */
- xfree(errmsg);
-}
-
-char *
-ssh_gssapi_last_error(Gssctxt *ctxt, OM_uint32 *major_status,
- OM_uint32 *minor_status)
-{
- OM_uint32 lmin, more;
- OM_uint32 maj, min;
- gss_OID mech = GSS_C_NULL_OID;
- gss_buffer_desc msg;
- Buffer b;
- char *ret;
-
- buffer_init(&b);
-
- if (ctxt) {
- /* Get status codes from the Gssctxt */
- maj = ctxt->major;
- min = ctxt->minor;
- /* Output them if desired */
- if (major_status)
- *major_status = maj;
- if (minor_status)
- *minor_status = min;
- /* Get mechanism for minor status display */
- mech = (ctxt->actual_mech != GSS_C_NULL_OID) ?
- ctxt->actual_mech : ctxt->desired_mech;
- } else if (major_status && minor_status) {
- maj = *major_status;
- min = *major_status;
- } else {
- maj = GSS_S_COMPLETE;
- min = 0;
- }
-
- more = 0;
- /* The GSSAPI error */
- do {
- gss_display_status(&lmin, maj, GSS_C_GSS_CODE,
- GSS_C_NULL_OID, &more, &msg);
-
- buffer_append(&b, msg.value, msg.length);
- buffer_put_char(&b, '\n');
- gss_release_buffer(&lmin, &msg);
- } while (more != 0);
-
- /* The mechanism specific error */
- do {
- /*
- * If mech == GSS_C_NULL_OID we may get the default
- * mechanism, whatever that is, and that may not be
- * useful.
- */
- gss_display_status(&lmin, min, GSS_C_MECH_CODE, mech, &more,
- &msg);
-
- buffer_append(&b, msg.value, msg.length);
- buffer_put_char(&b, '\n');
-
- gss_release_buffer(&lmin, &msg);
- } while (more != 0);
-
- buffer_put_char(&b, '\0');
- ret = xstrdup(buffer_ptr(&b));
- buffer_free(&b);
-
- return (ret);
-}
-
-/*
- * Initialise our GSSAPI context. We use this opaque structure to contain all
- * of the data which both the client and server need to persist across
- * {accept,init}_sec_context calls, so that when we do it from the userauth
- * stuff life is a little easier
- */
-void
-ssh_gssapi_build_ctx(Gssctxt **ctx, int client, gss_OID mech)
-{
- Gssctxt *newctx;
-
-
- newctx = (Gssctxt*)xmalloc(sizeof (Gssctxt));
- memset(newctx, 0, sizeof (Gssctxt));
-
-
- newctx->local = client;
- newctx->desired_mech = ssh_gssapi_dup_oid(mech);
-
- /* This happens to be redundant given the memset() above */
- newctx->major = GSS_S_COMPLETE;
- newctx->context = GSS_C_NO_CONTEXT;
- newctx->actual_mech = GSS_C_NULL_OID;
- newctx->desired_name = GSS_C_NO_NAME;
- newctx->src_name = GSS_C_NO_NAME;
- newctx->dst_name = GSS_C_NO_NAME;
- newctx->creds = GSS_C_NO_CREDENTIAL;
- newctx->deleg_creds = GSS_C_NO_CREDENTIAL;
-
- newctx->default_creds = (*ctx != NULL) ? (*ctx)->default_creds : 0;
-
- ssh_gssapi_delete_ctx(ctx);
-
- *ctx = newctx;
-}
-
-gss_OID
-ssh_gssapi_dup_oid(gss_OID oid)
-{
- gss_OID new_oid;
-
- new_oid = xmalloc(sizeof (gss_OID_desc));
-
- new_oid->elements = xmalloc(oid->length);
- new_oid->length = oid->length;
- memcpy(new_oid->elements, oid->elements, oid->length);
-
- return (new_oid);
-}
-
-gss_OID
-ssh_gssapi_make_oid(size_t length, void *elements)
-{
- gss_OID_desc oid;
-
- oid.length = length;
- oid.elements = elements;
-
- return (ssh_gssapi_dup_oid(&oid));
-}
-
-void
-ssh_gssapi_release_oid(gss_OID *oid)
-{
- OM_uint32 min;
-
- if (oid && *oid == GSS_C_NULL_OID)
- return;
- (void) gss_release_oid(&min, oid);
-
- if (*oid == GSS_C_NULL_OID)
- return; /* libgss did own this gss_OID and released it */
-
- xfree((*oid)->elements);
- xfree(*oid);
- *oid = GSS_C_NULL_OID;
-}
-
-struct gss_name {
- gss_OID name_type;
- gss_buffer_t external_name;
- gss_OID mech_type;
- void *mech_name;
-};
-
-/* Delete our context, providing it has been built correctly */
-void
-ssh_gssapi_delete_ctx(Gssctxt **ctx)
-{
- OM_uint32 ms;
-
- if ((*ctx) == NULL)
- return;
-
- if ((*ctx)->context != GSS_C_NO_CONTEXT)
- gss_delete_sec_context(&ms, &(*ctx)->context, GSS_C_NO_BUFFER);
-#if 0
- /* XXX */
- if ((*ctx)->desired_mech != GSS_C_NULL_OID)
- ssh_gssapi_release_oid(&(*ctx)->desired_mech);
-#endif
- if ((*ctx)->actual_mech != GSS_C_NULL_OID)
- (void) ssh_gssapi_release_oid(&(*ctx)->actual_mech);
- if ((*ctx)->desired_name != GSS_C_NO_NAME)
- gss_release_name(&ms, &(*ctx)->desired_name);
-#if 0
- if ((*ctx)->src_name != GSS_C_NO_NAME)
- gss_release_name(&ms, &(*ctx)->src_name);
-#endif
- if ((*ctx)->dst_name != GSS_C_NO_NAME)
- gss_release_name(&ms, &(*ctx)->dst_name);
- if ((*ctx)->creds != GSS_C_NO_CREDENTIAL)
- gss_release_cred(&ms, &(*ctx)->creds);
- if ((*ctx)->deleg_creds != GSS_C_NO_CREDENTIAL)
- gss_release_cred(&ms, &(*ctx)->deleg_creds);
-
- xfree(*ctx);
- *ctx = NULL;
-}
-
-/* Create a GSS hostbased service principal name for a given server hostname */
-int
-ssh_gssapi_import_name(Gssctxt *ctx, const char *server_host)
-{
- gss_buffer_desc name_buf;
- int ret;
-
- /* Build target principal */
- name_buf.length = strlen(SSH_GSS_HOSTBASED_SERVICE) +
- strlen(server_host) + 1; /* +1 for '@' */
- name_buf.value = xmalloc(name_buf.length + 1); /* +1 for NUL */
- ret = snprintf(name_buf.value, name_buf.length + 1, "%s@%s",
- SSH_GSS_HOSTBASED_SERVICE, server_host);
-
- debug3("%s: snprintf() returned %d, expected %d", __func__, ret,
- name_buf.length);
-
- ctx->major = gss_import_name(&ctx->minor, &name_buf,
- GSS_C_NT_HOSTBASED_SERVICE, &ctx->desired_name);
-
- if (GSS_ERROR(ctx->major)) {
- ssh_gssapi_error(ctx, "calling GSS_Import_name()");
- return (0);
- }
-
- xfree(name_buf.value);
-
- return (1);
-}
-
-OM_uint32
-ssh_gssapi_get_mic(Gssctxt *ctx, gss_buffer_desc *buffer, gss_buffer_desc *hash)
-{
-
- ctx->major = gss_get_mic(&ctx->minor, ctx->context,
- GSS_C_QOP_DEFAULT, buffer, hash);
- if (GSS_ERROR(ctx->major))
- ssh_gssapi_error(ctx, "while getting MIC");
- return (ctx->major);
-}
-
-OM_uint32
-ssh_gssapi_verify_mic(Gssctxt *ctx, gss_buffer_desc *buffer,
- gss_buffer_desc *hash)
-{
- gss_qop_t qop;
-
- ctx->major = gss_verify_mic(&ctx->minor, ctx->context, buffer,
- hash, &qop);
- if (GSS_ERROR(ctx->major))
- ssh_gssapi_error(ctx, "while verifying MIC");
- return (ctx->major);
-}
-#endif /* GSSAPI */
diff --git a/usr/src/cmd/ssh/libssh/common/ssh-rsa.c b/usr/src/cmd/ssh/libssh/common/ssh-rsa.c
deleted file mode 100644
index bc89d41da1..0000000000
--- a/usr/src/cmd/ssh/libssh/common/ssh-rsa.c
+++ /dev/null
@@ -1,270 +0,0 @@
-/*
- * Copyright (c) 2000 Markus Friedl. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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.
- */
-
-#include "includes.h"
-RCSID("$OpenBSD: ssh-rsa.c,v 1.26 2002/08/27 17:13:56 stevesk Exp $");
-
-#pragma ident "%Z%%M% %I% %E% SMI"
-
-#include <openssl/evp.h>
-#include <openssl/err.h>
-
-#include "xmalloc.h"
-#include "log.h"
-#include "buffer.h"
-#include "bufaux.h"
-#include "key.h"
-#include "ssh-rsa.h"
-#include "compat.h"
-#include "ssh.h"
-
-static int openssh_RSA_verify(int, u_char *, u_int, u_char *, u_int , RSA *);
-
-/* RSASSA-PKCS1-v1_5 (PKCS #1 v2.0 signature) with SHA1 */
-int
-ssh_rsa_sign(Key *key, u_char **sigp, u_int *lenp,
- u_char *data, u_int datalen)
-{
- const EVP_MD *evp_md;
- EVP_MD_CTX md;
- u_char digest[EVP_MAX_MD_SIZE], *sig;
- u_int slen, dlen, len;
- int ok, nid;
- Buffer b;
-
- if (key == NULL || key->type != KEY_RSA || key->rsa == NULL) {
- error("ssh_rsa_sign: no RSA key");
- return -1;
- }
- nid = (datafellows & SSH_BUG_RSASIGMD5) ? NID_md5 : NID_sha1;
- if ((evp_md = EVP_get_digestbynid(nid)) == NULL) {
- error("ssh_rsa_sign: EVP_get_digestbynid %d failed", nid);
- return -1;
- }
- EVP_DigestInit(&md, evp_md);
- EVP_DigestUpdate(&md, data, datalen);
- EVP_DigestFinal(&md, digest, &dlen);
-
- slen = RSA_size(key->rsa);
- sig = xmalloc(slen);
-
- ok = RSA_sign(nid, digest, dlen, sig, &len, key->rsa);
- memset(digest, 'd', sizeof(digest));
-
- if (ok != 1) {
- int ecode = ERR_get_error();
- error("ssh_rsa_sign: RSA_sign failed: %s",
- ERR_error_string(ecode, NULL));
- xfree(sig);
- return -1;
- }
- if (len < slen) {
- u_int diff = slen - len;
- debug("slen %u > len %u", slen, len);
- memmove(sig + diff, sig, len);
- memset(sig, 0, diff);
- } else if (len > slen) {
- error("ssh_rsa_sign: slen %u slen2 %u", slen, len);
- xfree(sig);
- return -1;
- }
- /* encode signature */
- buffer_init(&b);
- buffer_put_cstring(&b, "ssh-rsa");
- buffer_put_string(&b, sig, slen);
- len = buffer_len(&b);
- if (lenp != NULL)
- *lenp = len;
- if (sigp != NULL) {
- *sigp = xmalloc(len);
- memcpy(*sigp, buffer_ptr(&b), len);
- }
- buffer_free(&b);
- memset(sig, 's', slen);
- xfree(sig);
-
- return 0;
-}
-
-int
-ssh_rsa_verify(Key *key, u_char *signature, u_int signaturelen,
- u_char *data, u_int datalen)
-{
- Buffer b;
- const EVP_MD *evp_md;
- EVP_MD_CTX md;
- char *ktype;
- u_char digest[EVP_MAX_MD_SIZE], *sigblob;
- u_int len, dlen, modlen;
- int rlen, ret, nid;
-
- if (key == NULL || key->type != KEY_RSA || key->rsa == NULL) {
- error("ssh_rsa_verify: no RSA key");
- return -1;
- }
- if (BN_num_bits(key->rsa->n) < SSH_RSA_MINIMUM_MODULUS_SIZE) {
- error("ssh_rsa_verify: RSA modulus too small: %d < minimum %d bits",
- BN_num_bits(key->rsa->n), SSH_RSA_MINIMUM_MODULUS_SIZE);
- return -1;
- }
- buffer_init(&b);
- buffer_append(&b, signature, signaturelen);
- ktype = buffer_get_string(&b, NULL);
- if (strcmp("ssh-rsa", ktype) != 0) {
- error("ssh_rsa_verify: cannot handle type %s", ktype);
- buffer_free(&b);
- xfree(ktype);
- return -1;
- }
- xfree(ktype);
- sigblob = buffer_get_string(&b, &len);
- rlen = buffer_len(&b);
- buffer_free(&b);
- if (rlen != 0) {
- error("ssh_rsa_verify: remaining bytes in signature %d", rlen);
- xfree(sigblob);
- return -1;
- }
- /* RSA_verify expects a signature of RSA_size */
- modlen = RSA_size(key->rsa);
- if (len > modlen) {
- error("ssh_rsa_verify: len %u > modlen %u", len, modlen);
- xfree(sigblob);
- return -1;
- } else if (len < modlen) {
- u_int diff = modlen - len;
- debug("ssh_rsa_verify: add padding: modlen %u > len %u",
- modlen, len);
- sigblob = xrealloc(sigblob, modlen);
- memmove(sigblob + diff, sigblob, len);
- memset(sigblob, 0, diff);
- len = modlen;
- }
- nid = (datafellows & SSH_BUG_RSASIGMD5) ? NID_md5 : NID_sha1;
- if ((evp_md = EVP_get_digestbynid(nid)) == NULL) {
- error("ssh_rsa_verify: EVP_get_digestbynid %d failed", nid);
- xfree(sigblob);
- return -1;
- }
- EVP_DigestInit(&md, evp_md);
- EVP_DigestUpdate(&md, data, datalen);
- EVP_DigestFinal(&md, digest, &dlen);
-
- ret = openssh_RSA_verify(nid, digest, dlen, sigblob, len, key->rsa);
- memset(digest, 'd', sizeof(digest));
- memset(sigblob, 's', len);
- xfree(sigblob);
- debug("ssh_rsa_verify: signature %scorrect", (ret==0) ? "in" : "");
- return ret;
-}
-
-/*
- * See:
- * http://www.rsasecurity.com/rsalabs/pkcs/pkcs-1/
- * ftp://ftp.rsasecurity.com/pub/pkcs/pkcs-1/pkcs-1v2-1.asn
- */
-/*
- * id-sha1 OBJECT IDENTIFIER ::= { iso(1) identified-organization(3)
- * oiw(14) secsig(3) algorithms(2) 26 }
- */
-static const u_char id_sha1[] = {
- 0x30, 0x21, /* type Sequence, length 0x21 (33) */
- 0x30, 0x09, /* type Sequence, length 0x09 */
- 0x06, 0x05, /* type OID, length 0x05 */
- 0x2b, 0x0e, 0x03, 0x02, 0x1a, /* id-sha1 OID */
- 0x05, 0x00, /* NULL */
- 0x04, 0x14 /* Octet string, length 0x14 (20), followed by sha1 hash */
-};
-/*
- * id-md5 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840)
- * rsadsi(113549) digestAlgorithm(2) 5 }
- */
-static const u_char id_md5[] = {
- 0x30, 0x20, /* type Sequence, length 0x20 (32) */
- 0x30, 0x0c, /* type Sequence, length 0x09 */
- 0x06, 0x08, /* type OID, length 0x05 */
- 0x2a, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x02, 0x05, /* id-md5 */
- 0x05, 0x00, /* NULL */
- 0x04, 0x10 /* Octet string, length 0x10 (16), followed by md5 hash */
-};
-
-static int
-openssh_RSA_verify(int type, u_char *hash, u_int hashlen,
- u_char *sigbuf, u_int siglen, RSA *rsa)
-{
- u_int ret, rsasize, oidlen = 0, hlen = 0;
- int len;
- const u_char *oid = NULL;
- u_char *decrypted = NULL;
-
- ret = 0;
- switch (type) {
- case NID_sha1:
- oid = id_sha1;
- oidlen = sizeof(id_sha1);
- hlen = 20;
- break;
- case NID_md5:
- oid = id_md5;
- oidlen = sizeof(id_md5);
- hlen = 16;
- break;
- default:
- goto done;
- break;
- }
- if (hashlen != hlen) {
- error("bad hashlen");
- goto done;
- }
- rsasize = RSA_size(rsa);
- if (siglen == 0 || siglen > rsasize) {
- error("bad siglen");
- goto done;
- }
- decrypted = xmalloc(rsasize);
- if ((len = RSA_public_decrypt(siglen, sigbuf, decrypted, rsa,
- RSA_PKCS1_PADDING)) < 0) {
- error("RSA_public_decrypt failed: %s",
- ERR_error_string(ERR_get_error(), NULL));
- goto done;
- }
- if (len != hlen + oidlen) {
- error("bad decrypted len: %d != %d + %d", len, hlen, oidlen);
- goto done;
- }
- if (memcmp(decrypted, oid, oidlen) != 0) {
- error("oid mismatch");
- goto done;
- }
- if (memcmp(decrypted + oidlen, hash, hlen) != 0) {
- error("hash mismatch");
- goto done;
- }
- ret = 1;
-done:
- if (decrypted)
- xfree(decrypted);
- return ret;
-}
diff --git a/usr/src/cmd/ssh/libssh/common/tildexpand.c b/usr/src/cmd/ssh/libssh/common/tildexpand.c
deleted file mode 100644
index 5fcd07ebe6..0000000000
--- a/usr/src/cmd/ssh/libssh/common/tildexpand.c
+++ /dev/null
@@ -1,95 +0,0 @@
-/*
- * Author: Tatu Ylonen <ylo@cs.hut.fi>
- * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
- * All rights reserved
- *
- * As far as I am concerned, the code I have written for this software
- * can be used freely for any purpose. Any derived versions of this
- * software must be clearly marked as such, and if the derived work is
- * incompatible with the protocol description in the RFC file, it must be
- * called by a name other than "ssh" or "Secure Shell".
- */
-/*
- * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
- */
-
-#include "includes.h"
-RCSID("$OpenBSD: tildexpand.c,v 1.13 2002/06/23 03:25:50 deraadt Exp $");
-
-#include <libgen.h>
-
-#include "xmalloc.h"
-#include "log.h"
-#include "tildexpand.h"
-
-/*
- * Expands tildes in the file name. Returns data allocated by xmalloc.
- * Warning: this calls getpw*.
- */
-char *
-tilde_expand_filename(const char *filename, uid_t my_uid)
-{
- const char *cp;
- uint_t userlen;
- char *expanded;
- struct passwd *pw;
- char *pw_dir;
- char user[100];
- int len;
-
- /* Return immediately if no tilde. */
- if (filename[0] != '~')
- return (xstrdup(filename));
-
- /* Skip the tilde. */
- filename++;
-
- /* Find where the username ends. */
- cp = strchr(filename, '/');
- if (cp)
- userlen = cp - filename; /* Something after username. */
- else
- userlen = strlen(filename); /* Nothing after username. */
-
- /* This is the ~/xyz case with no ~username specification. */
- if (userlen == 0)
- pw = getpwuid(my_uid);
- else {
- /* Tilde refers to someone elses home directory. */
- if (userlen > sizeof (user) - 1)
- fatal("User name after tilde too long.");
- memcpy(user, filename, userlen);
- user[userlen] = 0;
- pw = getpwnam(user);
- }
-
- /* Use the HOME variable now. */
- if (pw == NULL) {
- debug("User account's password entry not found, trying to use "
- "the HOME variable.");
- if ((pw_dir = getenv("HOME")) == NULL) {
- fatal("User account's password entry not found and "
- "the HOME variable not set.");
- }
- } else {
- pw_dir = pw->pw_dir;
- }
-
- /* If referring to someones home directory, return it now. */
- if (cp == NULL) {
- /* Only home directory specified */
- return (xstrdup(pw_dir));
- }
-
- /* Build a path combining the specified directory and path. */
- len = strlen(pw_dir) + strlen(cp + 1) + 2;
- if (len > MAXPATHLEN)
- fatal("Home directory too long (%d > %d)", len - 1,
- MAXPATHLEN - 1);
-
- expanded = xmalloc(len);
- snprintf(expanded, len, "%s%s%s", pw_dir,
- strcmp(pw_dir, "/") ? "/" : "", cp + 1);
- return (expanded);
-}
diff --git a/usr/src/cmd/ssh/libssh/common/ttymodes.c b/usr/src/cmd/ssh/libssh/common/ttymodes.c
deleted file mode 100644
index b20ab34ff3..0000000000
--- a/usr/src/cmd/ssh/libssh/common/ttymodes.c
+++ /dev/null
@@ -1,480 +0,0 @@
-/*
- * Author: Tatu Ylonen <ylo@cs.hut.fi>
- * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
- * All rights reserved
- *
- * As far as I am concerned, the code I have written for this software
- * can be used freely for any purpose. Any derived versions of this
- * software must be clearly marked as such, and if the derived work is
- * incompatible with the protocol description in the RFC file, it must be
- * called by a name other than "ssh" or "Secure Shell".
- */
-
-/*
- * SSH2 tty modes support by Kevin Steves.
- * Copyright (c) 2001 Kevin Steves. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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.
- */
-
-/*
- * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
- */
-
-/*
- * Encoding and decoding of terminal modes in a portable way.
- * Much of the format is defined in ttymodes.h; it is included multiple times
- * into this file with the appropriate macro definitions to generate the
- * suitable code.
- */
-
-#include "includes.h"
-RCSID("$OpenBSD: ttymodes.c,v 1.18 2002/06/19 00:27:55 deraadt Exp $");
-
-#include "packet.h"
-#include "log.h"
-#include "ssh1.h"
-#include "compat.h"
-#include "buffer.h"
-#include "bufaux.h"
-
-#define TTY_OP_END 0
-/*
- * uint32 (u_int) follows speed in SSH1 and SSH2
- */
-#define TTY_OP_ISPEED_PROTO1 192
-#define TTY_OP_OSPEED_PROTO1 193
-#define TTY_OP_ISPEED_PROTO2 128
-#define TTY_OP_OSPEED_PROTO2 129
-
-/*
- * Converts POSIX speed_t to a baud rate. The values of the
- * constants for speed_t are not themselves portable.
- */
-static int
-speed_to_baud(speed_t speed)
-{
- switch (speed) {
- case B0:
- return 0;
- case B50:
- return 50;
- case B75:
- return 75;
- case B110:
- return 110;
- case B134:
- return 134;
- case B150:
- return 150;
- case B200:
- return 200;
- case B300:
- return 300;
- case B600:
- return 600;
- case B1200:
- return 1200;
- case B1800:
- return 1800;
- case B2400:
- return 2400;
- case B4800:
- return 4800;
- case B9600:
- return 9600;
-
-#ifdef B19200
- case B19200:
- return 19200;
-#else /* B19200 */
-#ifdef EXTA
- case EXTA:
- return 19200;
-#endif /* EXTA */
-#endif /* B19200 */
-
-#ifdef B38400
- case B38400:
- return 38400;
-#else /* B38400 */
-#ifdef EXTB
- case EXTB:
- return 38400;
-#endif /* EXTB */
-#endif /* B38400 */
-
-#ifdef B7200
- case B7200:
- return 7200;
-#endif /* B7200 */
-#ifdef B14400
- case B14400:
- return 14400;
-#endif /* B14400 */
-#ifdef B28800
- case B28800:
- return 28800;
-#endif /* B28800 */
-#ifdef B57600
- case B57600:
- return 57600;
-#endif /* B57600 */
-#ifdef B76800
- case B76800:
- return 76800;
-#endif /* B76800 */
-#ifdef B115200
- case B115200:
- return 115200;
-#endif /* B115200 */
-#ifdef B230400
- case B230400:
- return 230400;
-#endif /* B230400 */
-#ifdef B460800
- case B460800:
- return 460800;
-#endif /* B460800 */
-#ifdef B921600
- case B921600:
- return 921600;
-#endif /* B921600 */
- default:
- return 9600;
- }
-}
-
-/*
- * Converts a numeric baud rate to a POSIX speed_t.
- */
-static speed_t
-baud_to_speed(int baud)
-{
- switch (baud) {
- case 0:
- return B0;
- case 50:
- return B50;
- case 75:
- return B75;
- case 110:
- return B110;
- case 134:
- return B134;
- case 150:
- return B150;
- case 200:
- return B200;
- case 300:
- return B300;
- case 600:
- return B600;
- case 1200:
- return B1200;
- case 1800:
- return B1800;
- case 2400:
- return B2400;
- case 4800:
- return B4800;
- case 9600:
- return B9600;
-
-#ifdef B19200
- case 19200:
- return B19200;
-#else /* B19200 */
-#ifdef EXTA
- case 19200:
- return EXTA;
-#endif /* EXTA */
-#endif /* B19200 */
-
-#ifdef B38400
- case 38400:
- return B38400;
-#else /* B38400 */
-#ifdef EXTB
- case 38400:
- return EXTB;
-#endif /* EXTB */
-#endif /* B38400 */
-
-#ifdef B7200
- case 7200:
- return B7200;
-#endif /* B7200 */
-#ifdef B14400
- case 14400:
- return B14400;
-#endif /* B14400 */
-#ifdef B28800
- case 28800:
- return B28800;
-#endif /* B28800 */
-#ifdef B57600
- case 57600:
- return B57600;
-#endif /* B57600 */
-#ifdef B76800
- case 76800:
- return B76800;
-#endif /* B76800 */
-#ifdef B115200
- case 115200:
- return B115200;
-#endif /* B115200 */
-#ifdef B230400
- case 230400:
- return B230400;
-#endif /* B230400 */
-#ifdef B460800
- case 460800:
- return B460800;
-#endif /* B460800 */
-#ifdef B921600
- case 921600:
- return B921600;
-#endif /* B921600 */
- default:
- return B9600;
- }
-}
-
-/*
- * Encodes terminal modes for the terminal referenced by fd
- * or tiop in a portable manner, and appends the modes to a packet
- * being constructed.
- */
-void
-tty_make_modes(int fd, struct termios *tiop)
-{
- struct termios tio;
- int baud;
- Buffer buf;
- int tty_op_ospeed, tty_op_ispeed;
- void (*put_arg)(Buffer *, u_int);
-
- buffer_init(&buf);
- if (compat20) {
- tty_op_ospeed = TTY_OP_OSPEED_PROTO2;
- tty_op_ispeed = TTY_OP_ISPEED_PROTO2;
- put_arg = buffer_put_int;
- } else {
- tty_op_ospeed = TTY_OP_OSPEED_PROTO1;
- tty_op_ispeed = TTY_OP_ISPEED_PROTO1;
- put_arg = (void (*)(Buffer *, u_int)) buffer_put_char;
- }
-
- if (tiop == NULL) {
- if (tcgetattr(fd, &tio) == -1) {
- log("tcgetattr: %.100s", strerror(errno));
- goto end;
- }
- } else
- tio = *tiop;
-
- /* Store input and output baud rates. */
- baud = speed_to_baud(cfgetospeed(&tio));
- debug3("tty_make_modes: ospeed %d", baud);
- buffer_put_char(&buf, tty_op_ospeed);
- buffer_put_int(&buf, baud);
- baud = speed_to_baud(cfgetispeed(&tio));
- debug3("tty_make_modes: ispeed %d", baud);
- buffer_put_char(&buf, tty_op_ispeed);
- buffer_put_int(&buf, baud);
-
- /* Store values of mode flags. */
-#define TTYCHAR(NAME, OP) \
- debug3("tty_make_modes: %d %d", OP, tio.c_cc[NAME]); \
- buffer_put_char(&buf, OP); \
- put_arg(&buf, tio.c_cc[NAME]);
-
-#define TTYMODE(NAME, FIELD, OP) \
- debug3("tty_make_modes: %d %d", OP, ((tio.FIELD & NAME) != 0)); \
- buffer_put_char(&buf, OP); \
- put_arg(&buf, ((tio.FIELD & NAME) != 0));
-
-#include "ttymodes.h"
-
-#undef TTYCHAR
-#undef TTYMODE
-
-end:
- /* Mark end of mode data. */
- buffer_put_char(&buf, TTY_OP_END);
- if (compat20)
- packet_put_string(buffer_ptr(&buf), buffer_len(&buf));
- else
- packet_put_raw(buffer_ptr(&buf), buffer_len(&buf));
- buffer_free(&buf);
-}
-
-/*
- * Decodes terminal modes for the terminal referenced by fd in a portable
- * manner from a packet being read.
- */
-void
-tty_parse_modes(int fd, int *n_bytes_ptr)
-{
- struct termios tio;
- int opcode, baud;
- int n_bytes = 0;
- int failure = 0;
- u_int (*get_arg)(void);
- int arg, arg_size;
-
- if (compat20) {
- *n_bytes_ptr = packet_get_int();
- debug3("tty_parse_modes: SSH2 n_bytes %d", *n_bytes_ptr);
- if (*n_bytes_ptr == 0)
- return;
- get_arg = packet_get_int;
- arg_size = 4;
- } else {
- get_arg = packet_get_char;
- arg_size = 1;
- }
-
- /*
- * Get old attributes for the terminal. We will modify these
- * flags. I am hoping that if there are any machine-specific
- * modes, they will initially have reasonable values.
- */
- if (tcgetattr(fd, &tio) == -1) {
- log("tcgetattr: %.100s", strerror(errno));
- failure = -1;
- }
-
- for (;;) {
- n_bytes += 1;
- opcode = packet_get_char();
- switch (opcode) {
- case TTY_OP_END:
- goto set;
-
- /* XXX: future conflict possible */
- case TTY_OP_ISPEED_PROTO1:
- case TTY_OP_ISPEED_PROTO2:
- n_bytes += 4;
- baud = packet_get_int();
- debug3("tty_parse_modes: ispeed %d", baud);
- if (failure != -1 && cfsetispeed(&tio, baud_to_speed(baud)) == -1)
- error("cfsetispeed failed for %d", baud);
- break;
-
- /* XXX: future conflict possible */
- case TTY_OP_OSPEED_PROTO1:
- case TTY_OP_OSPEED_PROTO2:
- n_bytes += 4;
- baud = packet_get_int();
- debug3("tty_parse_modes: ospeed %d", baud);
- if (failure != -1 && cfsetospeed(&tio, baud_to_speed(baud)) == -1)
- error("cfsetospeed failed for %d", baud);
- break;
-
-#define TTYCHAR(NAME, OP) \
- case OP: \
- n_bytes += arg_size; \
- tio.c_cc[NAME] = get_arg(); \
- debug3("tty_parse_modes: %d %d", OP, tio.c_cc[NAME]); \
- break;
-#define TTYMODE(NAME, FIELD, OP) \
- case OP: \
- n_bytes += arg_size; \
- if ((arg = get_arg())) \
- tio.FIELD |= NAME; \
- else \
- tio.FIELD &= ~NAME; \
- debug3("tty_parse_modes: %d %d", OP, arg); \
- break;
-
-#include "ttymodes.h"
-
-#undef TTYCHAR
-#undef TTYMODE
-
- default:
- debug("Ignoring unsupported tty mode opcode %d (0x%x)",
- opcode, opcode);
- if (!compat20) {
- /*
- * SSH1:
- * Opcodes 1 to 127 are defined to have
- * a one-byte argument.
- * Opcodes 128 to 159 are defined to have
- * an integer argument.
- */
- if (opcode > 0 && opcode < 128) {
- n_bytes += 1;
- (void) packet_get_char();
- break;
- } else if (opcode >= 128 && opcode < 160) {
- n_bytes += 4;
- (void) packet_get_int();
- break;
- } else {
- /*
- * It is a truly undefined opcode (160 to 255).
- * We have no idea about its arguments. So we
- * must stop parsing. Note that some data may be
- * left in the packet; hopefully there is nothing
- * more coming after the mode data.
- */
- log("parse_tty_modes: unknown opcode %d", opcode);
- goto set;
- }
- } else {
- /*
- * SSH2:
- * Opcodes 1 to 159 are defined to have
- * a uint32 argument.
- * Opcodes 160 to 255 are undefined and
- * cause parsing to stop.
- */
- if (opcode > 0 && opcode < 160) {
- n_bytes += 4;
- (void) packet_get_int();
- break;
- } else {
- log("parse_tty_modes: unknown opcode %d", opcode);
- goto set;
- }
- }
- }
- }
-
-set:
- if (*n_bytes_ptr != n_bytes) {
- *n_bytes_ptr = n_bytes;
- log("parse_tty_modes: n_bytes_ptr != n_bytes: %d %d",
- *n_bytes_ptr, n_bytes);
- return; /* Don't process bytes passed */
- }
- if (failure == -1)
- return; /* Packet parsed ok but tcgetattr() failed */
-
- /* Set the new modes for the terminal. */
- if (tcsetattr(fd, TCSANOW, &tio) == -1)
- log("Setting tty modes failed: %.100s", strerror(errno));
-}
diff --git a/usr/src/cmd/ssh/libssh/common/uidswap.c b/usr/src/cmd/ssh/libssh/common/uidswap.c
deleted file mode 100644
index 942b22a749..0000000000
--- a/usr/src/cmd/ssh/libssh/common/uidswap.c
+++ /dev/null
@@ -1,257 +0,0 @@
-/*
- * Author: Tatu Ylonen <ylo@cs.hut.fi>
- * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
- * All rights reserved
- * Code for uid-swapping.
- *
- * As far as I am concerned, the code I have written for this software
- * can be used freely for any purpose. Any derived versions of this
- * software must be clearly marked as such, and if the derived work is
- * incompatible with the protocol description in the RFC file, it must be
- * called by a name other than "ssh" or "Secure Shell".
- */
-/*
- * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
- */
-
-#include "includes.h"
-RCSID("$OpenBSD: uidswap.c,v 1.23 2002/07/15 17:15:31 stevesk Exp $");
-
-#include <priv.h>
-
-#include "log.h"
-#include "uidswap.h"
-#include "buffer.h"
-#include "servconf.h"
-
-/*
- * Note: all these functions must work in all of the following cases:
- * 1. euid=0, ruid=0
- * 2. euid=0, ruid!=0
- * 3. euid!=0, ruid!=0
- * Additionally, they must work regardless of whether the system has
- * POSIX saved uids or not.
- */
-
-#if defined(_POSIX_SAVED_IDS) && !defined(BROKEN_SAVED_UIDS)
-/* Lets assume that posix saved ids also work with seteuid, even though that
- is not part of the posix specification. */
-#define SAVED_IDS_WORK
-/* Saved effective uid. */
-static uid_t saved_euid = 0;
-static gid_t saved_egid = 0;
-#endif
-
-/* Saved effective uid. */
-static int privileged = 0;
-static int temporarily_use_uid_effective = 0;
-static int ngroups_max = -1;
-static gid_t *saved_egroups, *user_groups;
-static int saved_egroupslen = -1, user_groupslen = -1;
-
-/*
- * Temporarily changes to the given uid. If the effective user
- * id is not root, this does nothing. This call cannot be nested.
- */
-void
-temporarily_use_uid(struct passwd *pw)
-{
- /* Save the current euid, and egroups. */
-#ifdef SAVED_IDS_WORK
- saved_euid = geteuid();
- saved_egid = getegid();
- debug("temporarily_use_uid: %u/%u (e=%u/%u)",
- (u_int)pw->pw_uid, (u_int)pw->pw_gid,
- (u_int)saved_euid, (u_int)saved_egid);
- if (saved_euid != 0) {
- privileged = 0;
- return;
- }
-#else
- if (geteuid() != 0) {
- privileged = 0;
- return;
- }
-#endif /* SAVED_IDS_WORK */
-
- privileged = 1;
- temporarily_use_uid_effective = 1;
-
- if (ngroups_max < 0) {
- ngroups_max = sysconf(_SC_NGROUPS_MAX);
- saved_egroups = malloc(ngroups_max * sizeof (gid_t));
- user_groups = malloc(ngroups_max * sizeof (gid_t));
- if (saved_egroups == NULL || user_groups == NULL)
- fatal("malloc(gid array): %.100s", strerror(errno));
- }
-
- saved_egroupslen = getgroups(ngroups_max, saved_egroups);
- if (saved_egroupslen < 0)
- fatal("getgroups: %.100s", strerror(errno));
-
- /* set and save the user's groups */
- if (user_groupslen == -1) {
- if (initgroups(pw->pw_name, pw->pw_gid) < 0)
- fatal("initgroups: %s: %.100s", pw->pw_name,
- strerror(errno));
- user_groupslen = getgroups(ngroups_max, user_groups);
- if (user_groupslen < 0)
- fatal("getgroups: %.100s", strerror(errno));
- }
- /* Set the effective uid to the given (unprivileged) uid. */
- if (setgroups(user_groupslen, user_groups) < 0)
- fatal("setgroups: %.100s", strerror(errno));
-#ifdef SAVED_IDS_WORK
- /* Set saved gid and set real gid */
- if (setregid(pw->pw_gid, -1) == -1)
- debug("setregid(%u, -1): %.100s", (uint_t)pw->pw_gid, strerror(errno));
- /* Set saved uid and set real uid */
- if (setreuid(pw->pw_uid, -1) == -1)
- debug("setreuid(%u, -1): %.100s", (uint_t)pw->pw_uid, strerror(errno));
-#else
- /* Propagate the privileged gid to all of our gids. */
- if (setgid(getegid()) < 0)
- debug("setgid %u: %.100s", (u_int) getegid(), strerror(errno));
- /* Propagate the privileged uid to all of our uids. */
- if (setuid(geteuid()) < 0)
- debug("setuid %u: %.100s", (u_int) geteuid(), strerror(errno));
-#endif /* SAVED_IDS_WORK */
- /* Set effective gid */
- if (setegid(pw->pw_gid) == -1)
- fatal("setegid %u: %.100s", (u_int)pw->pw_uid,
- strerror(errno));
- /* Set effective uid */
- if (seteuid(pw->pw_uid) == -1)
- fatal("seteuid %u: %.100s", (u_int)pw->pw_uid,
- strerror(errno));
- /*
- * If saved set ids work then
- *
- * ruid == euid == pw->pw_uid
- * saved uid = previous euid
- * rgid == egid == pw->pw_gid
- * saved gid = previous egid
- */
-}
-
-/*
- * Restores to the original (privileged) uid.
- */
-void
-restore_uid(void)
-{
- /* it's a no-op unless privileged */
- if (!privileged) {
- debug("restore_uid: (unprivileged)");
- return;
- }
- if (!temporarily_use_uid_effective)
- fatal("restore_uid: temporarily_use_uid not effective");
-
-#ifdef SAVED_IDS_WORK
- debug("restore_uid: %u/%u", (u_int)saved_euid, (u_int)saved_egid);
- /* Set the effective uid back to the saved privileged uid. */
- if (seteuid(saved_euid) < 0)
- fatal("seteuid %u: %.100s", (u_int)saved_euid, strerror(errno));
- if (setuid(saved_euid) < 0)
- fatal("setuid %u: %.100s", (u_int)saved_euid, strerror(errno));
- if (setegid(saved_egid) < 0)
- fatal("setegid %u: %.100s", (u_int)saved_egid, strerror(errno));
- if (setgid(saved_egid) < 0)
- fatal("setgid %u: %.100s", (u_int)saved_egid, strerror(errno));
-#else /* SAVED_IDS_WORK */
- /*
- * We are unable to restore the real uid to its unprivileged value.
- * Propagate the real uid (usually more privileged) to effective uid
- * as well.
- */
- setuid(getuid());
- setgid(getgid());
-#endif /* SAVED_IDS_WORK */
-
- if (setgroups(saved_egroupslen, saved_egroups) < 0)
- fatal("setgroups: %.100s", strerror(errno));
- temporarily_use_uid_effective = 0;
-}
-
-/*
- * Permanently sets all uids to the given uid. This cannot be called while
- * temporarily_use_uid is effective. Note that when the ChrootDirectory option
- * is in use we keep a few privileges so that we can call chroot(2) later while
- * already running under UIDs of a connecting user.
- */
-void
-permanently_set_uid(struct passwd *pw, char *chroot_directory)
-{
- priv_set_t *pset;
-
- if (temporarily_use_uid_effective)
- fatal("%s: temporarily_use_uid effective", __func__);
-
- debug("%s: %u/%u", __func__, (u_int)pw->pw_uid, (u_int)pw->pw_gid);
-
- if (initgroups(pw->pw_name, pw->pw_gid) < 0)
- fatal("initgroups: %s: %.100s", pw->pw_name,
- strerror(errno));
-
- if (setgid(pw->pw_gid) < 0)
- fatal("setgid %u: %.100s", (u_int)pw->pw_gid, strerror(errno));
-
- /*
- * If root is connecting we are done now. Note that we must have called
- * setgid() in case that the SSH server was run under a group other than
- * root.
- */
- if (pw->pw_uid == 0)
- return;
-
- /*
- * This means we will keep all privileges after the UID change.
- */
- if (setpflags(PRIV_AWARE, 1) != 0)
- fatal("setpflags: %s", strerror(errno));
-
- /* Now we are running under UID of the user. */
- if (setuid(pw->pw_uid) < 0)
- fatal("setuid %u: %.100s", (u_int)pw->pw_uid, strerror(errno));
-
- /*
- * We will run with the privileges from the Inheritable set as
- * we would have after exec(2) if we had stayed in NPA mode
- * before setuid(2) call (see privileges(5), user_attr(4), and
- * pam_unix_cred(5)). We want to run with P = E = I, with I as
- * set by pam_unix_cred(5). We also add PRIV_PROC_CHROOT,
- * obviously, and then PRIV_PROC_FORK and PRIV_PROC_EXEC, since
- * those two might have been removed from the I set. Note that
- * we are expected to finish the login process without them in
- * the I set, the important thing is that those not be passed on
- * to a shell or a subsystem later if they were not set in
- * pam_unix_cred(5).
- */
- if ((pset = priv_allocset()) == NULL)
- fatal("priv_allocset: %s", strerror(errno));
- if (getppriv(PRIV_INHERITABLE, pset) != 0)
- fatal("getppriv: %s", strerror(errno));
-
- /* We do not need PRIV_PROC_CHROOT unless chroot()ing. */
- if (chroot_requested(chroot_directory) &&
- priv_addset(pset, PRIV_PROC_CHROOT) == -1) {
- fatal("%s: priv_addset failed", __func__);
- }
-
- if (priv_addset(pset, PRIV_PROC_FORK) == -1 ||
- priv_addset(pset, PRIV_PROC_EXEC) == -1) {
- fatal("%s: priv_addset failed", __func__);
- }
-
- /* Set only P; this will also set E. */
- if (setppriv(PRIV_SET, PRIV_PERMITTED, pset) == -1)
- fatal("setppriv: %s", strerror(errno));
-
- /* We don't need the PA flag anymore. */
- if (setpflags(PRIV_AWARE, 0) == -1)
- fatal("setpflags: %s", strerror(errno));
-
- priv_freeset(pset);
-}
diff --git a/usr/src/cmd/ssh/libssh/common/uuencode.c b/usr/src/cmd/ssh/libssh/common/uuencode.c
deleted file mode 100644
index 432f5c4369..0000000000
--- a/usr/src/cmd/ssh/libssh/common/uuencode.c
+++ /dev/null
@@ -1,75 +0,0 @@
-/*
- * Copyright (c) 2000 Markus Friedl. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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.
- */
-
-#include "includes.h"
-RCSID("$OpenBSD: uuencode.c,v 1.16 2002/09/09 14:54:15 markus Exp $");
-
-#pragma ident "%Z%%M% %I% %E% SMI"
-
-#include "xmalloc.h"
-#include "uuencode.h"
-
-int
-uuencode(u_char *src, u_int srclength,
- char *target, size_t targsize)
-{
- return __b64_ntop(src, srclength, target, targsize);
-}
-
-int
-uudecode(const char *src, u_char *target, size_t targsize)
-{
- int len;
- char *encoded, *p;
-
- /* copy the 'readonly' source */
- encoded = xstrdup(src);
- /* 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((u_char *) encoded, target, targsize);
- xfree(encoded);
- return len;
-}
-
-void
-dump_base64(FILE *fp, u_char *data, u_int len)
-{
- char *buf = xmalloc(2*len);
- int i, n;
-
- n = uuencode(data, len, buf, 2*len);
- for (i = 0; i < n; i++) {
- fprintf(fp, "%c", buf[i]);
- if (i % 70 == 69)
- fprintf(fp, "\n");
- }
- if (i % 70 != 69)
- fprintf(fp, "\n");
- xfree(buf);
-}
diff --git a/usr/src/cmd/ssh/libssh/common/xlist.c b/usr/src/cmd/ssh/libssh/common/xlist.c
deleted file mode 100644
index c44e420eeb..0000000000
--- a/usr/src/cmd/ssh/libssh/common/xlist.c
+++ /dev/null
@@ -1,85 +0,0 @@
-/*
- * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
- */
-
-#pragma ident "%Z%%M% %I% %E% SMI"
-
-#include <stdio.h>
-#include <strings.h>
-#include "xmalloc.h"
-#include "xlist.h"
-
-char **
-xsplit(char *list, char sep)
-{
- char **a;
- char *p, *q;
- uint_t n = 0;
-
- for (n = 0, p = list; p && *p; ) {
- while (p && *p && *p == sep)
- p++;
- if (!*p)
- break;
- n++;
- p = strchr(p, sep);
- }
- a = (char **)xmalloc(sizeof (char *) * (n + 2));
- for (n = 0, p = list; p && *p; ) {
- while (*p == sep)
- p++;
- if (!*p)
- break;
- q = strchr(p, sep);
- if (!q)
- q = p + strlen(p);
- a[n] = (char *)xmalloc((q - p + 2));
- (void) strncpy(a[n], p, q - p);
- a[n][q - p] = '\0';
- n++;
- if (!*q)
- break;
- p = q + 1;
- }
- a[n] = NULL;
- return (a);
-}
-
-void
-xfree_split_list(char **list)
-{
- char **p;
- for (p = list; p && *p; p++) {
- xfree(*p);
- }
- xfree(list);
-}
-
-char *
-xjoin(char **alist, char sep)
-{
- char **p;
- char *list;
- char sep_str[2];
- uint_t n;
-
- for (n = 1, p = alist; p && *p; p++) {
- if (!*p || !**p)
- continue;
- n += strlen(*p) + 1;
- }
- list = (char *)xmalloc(n);
- *list = '\0';
-
- sep_str[0] = sep;
- sep_str[1] = '\0';
- for (p = alist; p && *p; p++) {
- if (!*p || !**p)
- continue;
- if (*list != '\0')
- (void) strlcat(list, sep_str, n);
- (void) strlcat(list, *p, n);
- }
- return (list);
-}
diff --git a/usr/src/cmd/ssh/libssh/common/xmalloc.c b/usr/src/cmd/ssh/libssh/common/xmalloc.c
deleted file mode 100644
index b9ae011d3c..0000000000
--- a/usr/src/cmd/ssh/libssh/common/xmalloc.c
+++ /dev/null
@@ -1,86 +0,0 @@
-/*
- * Author: Tatu Ylonen <ylo@cs.hut.fi>
- * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
- * All rights reserved
- * Versions of malloc and friends that check their results, and never return
- * failure (they call fatal if they encounter an error).
- *
- * As far as I am concerned, the code I have written for this software
- * can be used freely for any purpose. Any derived versions of this
- * software must be clearly marked as such, and if the derived work is
- * incompatible with the protocol description in the RFC file, it must be
- * called by a name other than "ssh" or "Secure Shell".
- */
-
-#include "includes.h"
-RCSID("$OpenBSD: xmalloc.c,v 1.16 2001/07/23 18:21:46 stevesk Exp $");
-
-#pragma ident "%Z%%M% %I% %E% SMI"
-
-#include "xmalloc.h"
-#include "log.h"
-
-void *
-xmalloc(size_t size)
-{
- void *ptr;
-
- if (size == 0)
- fatal("xmalloc: zero size");
- ptr = malloc(size);
- if (ptr == NULL)
- fatal("xmalloc: out of memory (allocating %lu bytes)", (u_long) size);
- return ptr;
-}
-
-void *
-xcalloc(size_t nmemb, size_t size)
-{
- void *ptr;
-
- if (size == 0 || nmemb == 0)
- fatal("xcalloc: zero size");
- if (SIZE_T_MAX / nmemb < size)
- fatal("xcalloc: nmemb * size > SIZE_T_MAX");
- ptr = calloc(nmemb, size);
- if (ptr == NULL)
- fatal("xcalloc: out of memory (allocating %lu bytes)",
- (u_long)(size * nmemb));
- return ptr;
-}
-
-void *
-xrealloc(void *ptr, size_t new_size)
-{
- void *new_ptr;
-
- if (new_size == 0)
- fatal("xrealloc: zero size");
- if (ptr == NULL)
- new_ptr = malloc(new_size);
- else
- new_ptr = realloc(ptr, new_size);
- if (new_ptr == NULL)
- fatal("xrealloc: out of memory (new_size %lu bytes)", (u_long) new_size);
- return new_ptr;
-}
-
-void
-xfree(void *ptr)
-{
- if (ptr == NULL)
- fatal("xfree: NULL pointer given as argument");
- free(ptr);
-}
-
-char *
-xstrdup(const char *str)
-{
- size_t len;
- char *cp;
-
- len = strlen(str) + 1;
- cp = xmalloc(len);
- strlcpy(cp, str, len);
- return cp;
-}