openssh/bufaux.c

407 lines
9.4 KiB
C
Raw Normal View History

/* $OpenBSD: bufaux.c,v 1.41 2006/03/30 09:58:15 djm Exp $ */
1999-10-27 03:42:43 +00:00
/*
* 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.
*
- (djm) Merge OpenBSD changes: - markus@cvs.openbsd.org 2000/09/05 02:59:57 [session.c] print hostname (not hushlogin) - markus@cvs.openbsd.org 2000/09/05 13:18:48 [authfile.c ssh-add.c] enable ssh-add -d for DSA keys - markus@cvs.openbsd.org 2000/09/05 13:20:49 [sftp-server.c] cleanup - markus@cvs.openbsd.org 2000/09/06 03:46:41 [authfile.h] prototype - deraadt@cvs.openbsd.org 2000/09/07 14:27:56 [ALL] cleanup copyright notices on all files. I have attempted to be accurate with the details. everything is now under Tatu's licence (which I copied from his readme), and/or the core-sdi bsd-ish thing for deattack, or various openbsd developers under a 2-term bsd licence. We're not changing any rules, just being accurate. - markus@cvs.openbsd.org 2000/09/07 14:40:30 [channels.c channels.h clientloop.c serverloop.c ssh.c] cleanup window and packet sizes for ssh2 flow control; ok niels - markus@cvs.openbsd.org 2000/09/07 14:53:00 [scp.c] typo - markus@cvs.openbsd.org 2000/09/07 15:13:37 [auth-options.c auth-options.h auth-rh-rsa.c auth-rsa.c auth.c] [authfile.h canohost.c channels.h compat.c hostfile.h log.c match.h] [pty.c readconf.c] some more Copyright fixes - markus@cvs.openbsd.org 2000/09/08 03:02:51 [README.openssh2] bye bye - deraadt@cvs.openbsd.org 2000/09/11 18:38:33 [LICENCE cipher.c] a few more comments about it being ARC4 not RC4 - markus@cvs.openbsd.org 2000/09/12 14:53:11 [log-client.c log-server.c log.c ssh.1 ssh.c ssh.h sshd.8 sshd.c] multiple debug levels - markus@cvs.openbsd.org 2000/09/14 14:25:15 [clientloop.c] typo - deraadt@cvs.openbsd.org 2000/09/15 01:13:51 [ssh-agent.c] check return value for setenv(3) for failure, and deal appropriately
2000-09-16 02:29:08 +00:00
* 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
- (djm) Merge OpenBSD changes: - markus@cvs.openbsd.org 2000/09/05 02:59:57 [session.c] print hostname (not hushlogin) - markus@cvs.openbsd.org 2000/09/05 13:18:48 [authfile.c ssh-add.c] enable ssh-add -d for DSA keys - markus@cvs.openbsd.org 2000/09/05 13:20:49 [sftp-server.c] cleanup - markus@cvs.openbsd.org 2000/09/06 03:46:41 [authfile.h] prototype - deraadt@cvs.openbsd.org 2000/09/07 14:27:56 [ALL] cleanup copyright notices on all files. I have attempted to be accurate with the details. everything is now under Tatu's licence (which I copied from his readme), and/or the core-sdi bsd-ish thing for deattack, or various openbsd developers under a 2-term bsd licence. We're not changing any rules, just being accurate. - markus@cvs.openbsd.org 2000/09/07 14:40:30 [channels.c channels.h clientloop.c serverloop.c ssh.c] cleanup window and packet sizes for ssh2 flow control; ok niels - markus@cvs.openbsd.org 2000/09/07 14:53:00 [scp.c] typo - markus@cvs.openbsd.org 2000/09/07 15:13:37 [auth-options.c auth-options.h auth-rh-rsa.c auth-rsa.c auth.c] [authfile.h canohost.c channels.h compat.c hostfile.h log.c match.h] [pty.c readconf.c] some more Copyright fixes - markus@cvs.openbsd.org 2000/09/08 03:02:51 [README.openssh2] bye bye - deraadt@cvs.openbsd.org 2000/09/11 18:38:33 [LICENCE cipher.c] a few more comments about it being ARC4 not RC4 - markus@cvs.openbsd.org 2000/09/12 14:53:11 [log-client.c log-server.c log.c ssh.1 ssh.c ssh.h sshd.8 sshd.c] multiple debug levels - markus@cvs.openbsd.org 2000/09/14 14:25:15 [clientloop.c] typo - deraadt@cvs.openbsd.org 2000/09/15 01:13:51 [ssh-agent.c] check return value for setenv(3) for failure, and deal appropriately
2000-09-16 02:29:08 +00:00
* 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.
*
- (djm) Merge OpenBSD changes: - markus@cvs.openbsd.org 2000/09/05 02:59:57 [session.c] print hostname (not hushlogin) - markus@cvs.openbsd.org 2000/09/05 13:18:48 [authfile.c ssh-add.c] enable ssh-add -d for DSA keys - markus@cvs.openbsd.org 2000/09/05 13:20:49 [sftp-server.c] cleanup - markus@cvs.openbsd.org 2000/09/06 03:46:41 [authfile.h] prototype - deraadt@cvs.openbsd.org 2000/09/07 14:27:56 [ALL] cleanup copyright notices on all files. I have attempted to be accurate with the details. everything is now under Tatu's licence (which I copied from his readme), and/or the core-sdi bsd-ish thing for deattack, or various openbsd developers under a 2-term bsd licence. We're not changing any rules, just being accurate. - markus@cvs.openbsd.org 2000/09/07 14:40:30 [channels.c channels.h clientloop.c serverloop.c ssh.c] cleanup window and packet sizes for ssh2 flow control; ok niels - markus@cvs.openbsd.org 2000/09/07 14:53:00 [scp.c] typo - markus@cvs.openbsd.org 2000/09/07 15:13:37 [auth-options.c auth-options.h auth-rh-rsa.c auth-rsa.c auth.c] [authfile.h canohost.c channels.h compat.c hostfile.h log.c match.h] [pty.c readconf.c] some more Copyright fixes - markus@cvs.openbsd.org 2000/09/08 03:02:51 [README.openssh2] bye bye - deraadt@cvs.openbsd.org 2000/09/11 18:38:33 [LICENCE cipher.c] a few more comments about it being ARC4 not RC4 - markus@cvs.openbsd.org 2000/09/12 14:53:11 [log-client.c log-server.c log.c ssh.1 ssh.c ssh.h sshd.8 sshd.c] multiple debug levels - markus@cvs.openbsd.org 2000/09/14 14:25:15 [clientloop.c] typo - deraadt@cvs.openbsd.org 2000/09/15 01:13:51 [ssh-agent.c] check return value for setenv(3) for failure, and deal appropriately
2000-09-16 02:29:08 +00:00
* 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.
*/
1999-10-27 03:42:43 +00:00
#include "includes.h"
#include <openssl/bn.h>
#include "bufaux.h"
#include "xmalloc.h"
Hopefully things did not get mixed around too much. It compiles under Linux and works. So that is at least a good sign. =) 20010122 - (bal) OpenBSD Resync - markus@cvs.openbsd.org 2001/01/19 12:45:26 GMT 2001 by markus [servconf.c ssh.h sshd.c] only auth-chall.c needs #ifdef SKEY - markus@cvs.openbsd.org 2001/01/19 15:55:10 GMT 2001 by markus [auth-krb4.c auth-options.c auth-rh-rsa.c auth-rhosts.c auth-rsa.c auth1.c auth2.c channels.c clientloop.c dh.c dispatch.c nchan.c packet.c pathname.h readconf.c scp.c servconf.c serverloop.c session.c ssh-add.c ssh-keygen.c ssh-keyscan.c ssh.c ssh.h ssh1.h sshconnect1.c sshd.c ttymodes.c] move ssh1 definitions to ssh1.h, pathnames to pathnames.h - markus@cvs.openbsd.org 2001/01/19 16:48:14 [sshd.8] fix typo; from stevesk@ - markus@cvs.openbsd.org 2001/01/19 16:50:58 [ssh-dss.c] clear and free digest, make consistent with other code (use dlen); from stevesk@ - markus@cvs.openbsd.org 2001/01/20 15:55:20 GMT 2001 by markus [auth-options.c auth-options.h auth-rsa.c auth2.c] pass the filename to auth_parse_options() - markus@cvs.openbsd.org 2001/01/20 17:59:40 GMT 2001 [readconf.c] fix SIGSEGV from -o ""; problem noted by jehsom@togetherweb.com - stevesk@cvs.openbsd.org 2001/01/20 18:20:29 [sshconnect2.c] dh_new_group() does not return NULL. ok markus@ - markus@cvs.openbsd.org 2001/01/20 21:33:42 [ssh-add.c] do not loop forever if askpass does not exist; from andrew@pimlott.ne.mediaone.net - djm@cvs.openbsd.org 2001/01/20 23:00:56 [servconf.c] Check for NULL return from strdelim; ok markus - djm@cvs.openbsd.org 2001/01/20 23:02:07 [readconf.c] KNF; ok markus - jakob@cvs.openbsd.org 2001/01/21 9:00:33 [ssh-keygen.1] remove -R flag; ok markus@ - markus@cvs.openbsd.org 2001/01/21 19:05:40 [atomicio.c automicio.h auth-chall.c auth-krb4.c auth-options.c auth-options.h auth-passwd.c auth-rh-rsa.c auth-rhosts.c auth-rsa.c auth.c auth.h auth1.c auth2-chall.c auth2.c authfd.c authfile.c bufaux.c bufaux.h buffer.c canahost.c canahost.h channels.c cipher.c cli.c clientloop.c clientloop.h compat.c compress.c deattack.c dh.c dispatch.c groupaccess.c hmac.c hostfile.c kex.c key.c key.h log-client.c log-server.c log.c log.h login.c login.h match.c misc.c misc.h nchan.c packet.c pty.c radix.h readconf.c readpass.c readpass.h rsa.c scp.c servconf.c serverloop.c serverloop.h session.c sftp-server.c ssh-add.c ssh-agent.c ssh-dss.c ssh-keygen.c ssh-keyscan.c ssh-rsa.c ssh.c ssh.h sshconnect.c sshconnect.h sshconnect1.c sshconnect2.c sshd.c tildexpand.c tildexpand.h ttysmodes.c uidswap.c xmalloc.c] split ssh.h and try to cleanup the #include mess. remove unnecessary #includes. rename util.[ch] -> misc.[ch] - (bal) renamed 'PIDDIR' to '_PATH_SSH_PIDDIR' to match OpenBSD tree - (bal) Moved #ifdef KRB4 in auth-krb4.c above the #include to resolve conflict when compiling for non-kerb install - (bal) removed the #ifdef SKEY in auth1.c to match Markus' changes on 1/19.
2001-01-22 05:34:40 +00:00
#include "log.h"
#include "misc.h"
1999-10-27 03:42:43 +00:00
/*
* 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)
1999-10-27 03:42:43 +00:00
{
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_u16(msg, bits);
buffer_append(buffer, msg, 2);
/* Store the binary data. */
buffer_append(buffer, 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");
1999-10-27 03:42:43 +00:00
}
/*
* Retrieves an BIGNUM from the buffer.
*/
int
buffer_get_bignum_ret(Buffer *buffer, BIGNUM *value)
1999-10-27 03:42:43 +00:00
{
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_u16(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");
1999-10-27 03:42:43 +00:00
}
/*
* 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");
}
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_u16(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_u32(buf);
return (0);
}
u_int
buffer_get_int(Buffer *buffer)
1999-10-27 03:42:43 +00:00
{
u_int ret;
if (buffer_get_int_ret(&ret, buffer) == -1)
fatal("buffer_get_int: buffer error");
return (ret);
}
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_u64(buf);
return (0);
1999-10-27 03:42:43 +00:00
}
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);
}
/*
* Stores integers in the buffer, msb first.
*/
void
buffer_put_short(Buffer *buffer, u_short value)
{
char buf[2];
put_u16(buf, value);
buffer_append(buffer, buf, 2);
}
void
buffer_put_int(Buffer *buffer, u_int value)
1999-10-27 03:42:43 +00:00
{
char buf[4];
put_u32(buf, value);
buffer_append(buffer, buf, 4);
1999-10-27 03:42:43 +00:00
}
void
buffer_put_int64(Buffer *buffer, u_int64_t value)
{
char buf[8];
put_u64(buf, value);
buffer_append(buffer, buf, 8);
}
/*
* 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)
1999-10-27 03:42:43 +00:00
{
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);
1999-10-27 03:42:43 +00:00
}
/*
* Stores and arbitrary binary string in the buffer.
*/
void
buffer_put_string(Buffer *buffer, const void *buf, u_int len)
1999-10-27 03:42:43 +00:00
{
buffer_put_int(buffer, len);
buffer_append(buffer, buf, len);
1999-10-27 03:42:43 +00:00
}
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));
}
1999-10-27 03:42:43 +00:00
/*
* 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)
1999-10-27 03:42:43 +00:00
{
char ch;
if (buffer_get_char_ret(&ch, buffer) == -1)
fatal("buffer_get_char: buffer error");
return (u_char) ch;
1999-10-27 03:42:43 +00:00
}
/*
* Stores a character in the buffer.
*/
void
buffer_put_char(Buffer *buffer, int value)
1999-10-27 03:42:43 +00:00
{
char ch = value;
buffer_append(buffer, &ch, 1);
1999-10-27 03:42:43 +00:00
}