- Merged more OpenBSD changes:

- [atomicio.c authfd.c scp.c serverloop.c ssh.h sshconnect.c sshd.c]
     move atomicio into it's own file.  wrap all socket write()s which
     were doing write(sock, buf, len) != len, with atomicio() calls.
   - [auth-skey.c]
     fd leak
   - [authfile.c]
     properly name fd variable
   - [channels.c]
     display great hatred towards strcpy
   - [pty.c pty.h sshd.c]
     use openpty() if it exists (it does on BSD4_4)
   - [tildexpand.c]
     check for ~ expansion past MAXPATHLEN
 - Modified helper.c to use new atomicio function.
 - Reformat Makefile a little
 - Moved RC4 routines from rc4.[ch] into helper.c
 - Added autoconf code to detect /dev/ptmx (Solaris) and /dev/ptc (AIX)
This commit is contained in:
Damien Miller 1999-12-07 15:38:31 +11:00
parent eabf3417bc
commit 037a0dc083
21 changed files with 263 additions and 361 deletions

View File

@ -4,6 +4,24 @@
- Fixed default SSH_ASKPASS
- Fix PAM account and session being called multiple times. Problem
reported by Adrian Baugh <adrian@merlin.keble.ox.ac.uk>
- Merged more OpenBSD changes:
- [atomicio.c authfd.c scp.c serverloop.c ssh.h sshconnect.c sshd.c]
move atomicio into it's own file. wrap all socket write()s which
were doing write(sock, buf, len) != len, with atomicio() calls.
- [auth-skey.c]
fd leak
- [authfile.c]
properly name fd variable
- [channels.c]
display great hatred towards strcpy
- [pty.c pty.h sshd.c]
use openpty() if it exists (it does on BSD4_4)
- [tildexpand.c]
check for ~ expansion past MAXPATHLEN
- Modified helper.c to use new atomicio function.
- Reformat Makefile a little
- Moved RC4 routines from rc4.[ch] into helper.c
- Added autoconf code to detect /dev/ptmx (Solaris) and /dev/ptc (AIX)
19991204
- Small cleanup of PAM code in sshd.c

View File

@ -23,25 +23,31 @@ LFLAGS=@LDFLAGS@
GNOME_CFLAGS=`gnome-config --cflags gnome gnomeui`
GNOME_LIBS=`gnome-config --libs gnome gnomeui`
OBJS= authfd.o authfile.o auth-passwd.o auth-rhosts.o auth-rh-rsa.o \
auth-rsa.o auth-skey.o bufaux.o buffer.o canohost.o channels.o \
cipher.o clientloop.o compress.o crc32.o deattack.o helper.o \
hostfile.o log-client.o login.o log-server.o match.o mpaux.o \
packet.o pty.o readconf.o readpass.o rsa.o servconf.o serverloop.o \
sshconnect.o tildexpand.o ttymodes.o uidswap.o xmalloc.o \
helper.o bsd-mktemp.o bsd-strlcpy.o bsd-strlcat.o bsd-daemon.o \
bsd-login.o bsd-snprintf.o rc4.o md5crypt.o
OBJS= atomicio.o authfd.o authfile.o auth-passwd.o auth-rhosts.o \
auth-rh-rsa.o auth-rsa.o auth-skey.o bsd-daemon.o bsd-login.o \
bsd-mktemp.o bsd-snprintf.o bsd-strlcat.o bsd-strlcpy.o bufaux.o \
buffer.o canohost.o channels.o cipher.o clientloop.o compress.o \
crc32.o deattack.o helper.o helper.o hostfile.o log-client.o \
login.o log-server.o match.o md5crypt.o mpaux.o packet.o pty.o \
readconf.o readpass.o rsa.o servconf.o serverloop.o \
sshconnect.o tildexpand.o ttymodes.o uidswap.o xmalloc.o
all: $(OBJS) $(TARGETS)
libssh.a: authfd.o authfile.o bufaux.o buffer.o canohost.o channels.o cipher.o compat.o compress.o crc32.o deattack.o hostfile.o match.o mpaux.o nchan.o packet.o readpass.o rsa.o tildexpand.o ttymodes.o uidswap.o xmalloc.o helper.o rc4.o bsd-mktemp.o bsd-strlcpy.o bsd-strlcat.o bsd-snprintf.o bsd-daemon.o log.o fingerprint.o
libssh.a: atomicio.o authfd.o authfile.o bsd-daemon.o bsd-mktemp.o \
bsd-snprintf.o bsd-strlcat.o bsd-strlcpy.o bufaux.o \
buffer.o canohost.o channels.o cipher.o compat.o \
compress.o crc32.o deattack.o fingerprint.o helper.o \
hostfile.o log.o match.o mpaux.o nchan.o packet.o \
readpass.o rsa.o tildexpand.o ttymodes.o uidswap.o xmalloc.o
$(AR) rv $@ $^
$(RANLIB) $@
ssh: ssh.o sshconnect.o log-client.o readconf.o clientloop.o libssh.a
$(CC) -o $@ $^ $(LFLAGS) $(LIBS)
sshd: sshd.o auth-rhosts.o auth-passwd.o auth-rsa.o auth-rh-rsa.o pty.o log-server.o login.o servconf.o serverloop.o bsd-login.o md5crypt.o libssh.a
sshd: sshd.o auth-rhosts.o auth-passwd.o auth-rsa.o auth-rh-rsa.o \
pty.o log-server.o login.o servconf.o serverloop.o bsd-login.o \
md5crypt.o libssh.a
$(CC) -o $@ $^ $(LFLAGS) $(LIBS)
scp: scp.o libssh.a

View File

@ -64,6 +64,12 @@
#undef HAVE_U_INTXX_T
#undef HAVE_UINTXX_T
/* Define if you have /dev/ptmx */
#undef HAVE_DEV_PTMX
/* Define if you have /dev/ptc */
#undef HAVE_DEV_PTS_AND_PTC
@BOTTOM@
/* ******************* Shouldn't need to edit below this line ************** */

57
atomicio.c Normal file
View File

@ -0,0 +1,57 @@
/*
* 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.
*/
#include "includes.h"
RCSID("$Id: atomicio.c,v 1.1 1999/12/07 04:38:31 damien Exp $");
#include "xmalloc.h"
#include "ssh.h"
/*
* ensure all of data on socket comes through. f==read || f==write
*/
int
atomicio(f, fd, s, n)
int (*f) ();
int fd;
void *s;
size_t n;
{
int res, pos = 0;
while (n > pos) {
res = (f) (fd, s + pos, n - pos);
switch (res) {
case -1:
if (errno == EINTR || errno == EAGAIN)
continue;
case 0:
return (res);
default:
pos += res;
}
}
return (pos);
}

View File

@ -1,7 +1,7 @@
#include "includes.h"
#ifdef SKEY
RCSID("$Id: auth-skey.c,v 1.4 1999/12/01 16:54:35 markus Exp $");
RCSID("$Id: auth-skey.c,v 1.5 1999/12/06 19:04:57 deraadt Exp $");
#include "ssh.h"
#include "packet.h"
@ -114,6 +114,7 @@ skey_fake_keyinfo(char *username)
SEEK_SET) != -1 && read(fd, hseed,
SKEY_MAX_SEED_LEN) == SKEY_MAX_SEED_LEN) {
close(fd);
fd = -1;
secret = hseed;
secretlen = SKEY_MAX_SEED_LEN;
flg = 0;
@ -123,6 +124,8 @@ skey_fake_keyinfo(char *username)
secretlen = strlen(secret);
flg = 0;
}
if (fd != -1)
close(fd);
}
/* Put that in your pipe and smoke it */

View File

@ -14,7 +14,7 @@
*/
#include "includes.h"
RCSID("$Id: authfd.c,v 1.8 1999/11/25 00:54:57 damien Exp $");
RCSID("$Id: authfd.c,v 1.9 1999/12/07 04:38:32 damien Exp $");
#include "ssh.h"
#include "rsa.h"
@ -145,7 +145,7 @@ ssh_get_first_identity(AuthenticationConnection *auth,
msg[2] = 0;
msg[3] = 1;
msg[4] = SSH_AGENTC_REQUEST_RSA_IDENTITIES;
if (write(auth->fd, msg, 5) != 5) {
if (atomicio(write, auth->fd, msg, 5) != 5) {
error("write auth->fd: %.100s", strerror(errno));
return 0;
}
@ -270,9 +270,9 @@ ssh_decrypt_challenge(AuthenticationConnection *auth,
PUT_32BIT(buf, len);
/* Send the length and then the packet to the agent. */
if (write(auth->fd, buf, 4) != 4 ||
write(auth->fd, buffer_ptr(&buffer), buffer_len(&buffer)) !=
buffer_len(&buffer)) {
if (atomicio(write, auth->fd, buf, 4) != 4 ||
atomicio(write, auth->fd, buffer_ptr(&buffer),
buffer_len(&buffer)) != buffer_len(&buffer)) {
error("Error writing to authentication socket.");
error_cleanup:
buffer_free(&buffer);
@ -369,9 +369,9 @@ ssh_add_identity(AuthenticationConnection *auth,
PUT_32BIT(buf, len);
/* Send the length and then the packet to the agent. */
if (write(auth->fd, buf, 4) != 4 ||
write(auth->fd, buffer_ptr(&buffer), buffer_len(&buffer)) !=
buffer_len(&buffer)) {
if (atomicio(write, auth->fd, buf, 4) != 4 ||
atomicio(write, auth->fd, buffer_ptr(&buffer),
buffer_len(&buffer)) != buffer_len(&buffer)) {
error("Error writing to authentication socket.");
error_cleanup:
buffer_free(&buffer);
@ -450,9 +450,9 @@ ssh_remove_identity(AuthenticationConnection *auth, RSA *key)
PUT_32BIT(buf, len);
/* Send the length and then the packet to the agent. */
if (write(auth->fd, buf, 4) != 4 ||
write(auth->fd, buffer_ptr(&buffer), buffer_len(&buffer)) !=
buffer_len(&buffer)) {
if (atomicio(write, auth->fd, buf, 4) != 4 ||
atomicio(write, auth->fd, buffer_ptr(&buffer),
buffer_len(&buffer)) != buffer_len(&buffer)) {
error("Error writing to authentication socket.");
error_cleanup:
buffer_free(&buffer);
@ -526,7 +526,7 @@ ssh_remove_all_identities(AuthenticationConnection *auth)
buf[4] = SSH_AGENTC_REMOVE_ALL_RSA_IDENTITIES;
/* Send the length and then the packet to the agent. */
if (write(auth->fd, buf, 5) != 5) {
if (atomicio(write, auth->fd, buf, 5) != 5) {
error("Error writing to authentication socket.");
return 0;
}

View File

@ -15,7 +15,7 @@
*/
#include "includes.h"
RCSID("$Id: authfile.c,v 1.5 1999/11/25 00:54:58 damien Exp $");
RCSID("$Id: authfile.c,v 1.6 1999/12/07 04:38:32 damien Exp $");
#ifdef HAVE_OPENSSL
#include <openssl/bn.h>
@ -46,7 +46,7 @@ save_private_key(const char *filename, const char *passphrase,
{
Buffer buffer, encrypted;
char buf[100], *cp;
int f, i;
int fd, i;
CipherContext cipher;
int cipher_type;
u_int32_t rand;
@ -117,19 +117,19 @@ save_private_key(const char *filename, const char *passphrase,
memset(buf, 0, sizeof(buf));
buffer_free(&buffer);
f = open(filename, O_WRONLY | O_CREAT | O_TRUNC, 0600);
if (f < 0)
fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC, 0600);
if (fd < 0)
return 0;
if (write(f, buffer_ptr(&encrypted), buffer_len(&encrypted)) !=
if (write(fd, buffer_ptr(&encrypted), buffer_len(&encrypted)) !=
buffer_len(&encrypted)) {
debug("Write to key file %.200s failed: %.100s", filename,
strerror(errno));
buffer_free(&encrypted);
close(f);
close(fd);
remove(filename);
return 0;
}
close(f);
close(fd);
buffer_free(&encrypted);
return 1;
}
@ -144,28 +144,28 @@ int
load_public_key(const char *filename, RSA * pub,
char **comment_return)
{
int f, i;
int fd, i;
off_t len;
Buffer buffer;
char *cp;
f = open(filename, O_RDONLY);
if (f < 0)
fd = open(filename, O_RDONLY);
if (fd < 0)
return 0;
len = lseek(f, (off_t) 0, SEEK_END);
lseek(f, (off_t) 0, SEEK_SET);
len = lseek(fd, (off_t) 0, SEEK_END);
lseek(fd, (off_t) 0, SEEK_SET);
buffer_init(&buffer);
buffer_append_space(&buffer, &cp, len);
if (read(f, cp, (size_t) len) != (size_t) 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(f);
close(fd);
return 0;
}
close(f);
close(fd);
/* Check that it is at least big enought to contain the ID string. */
if (len < strlen(AUTHFILE_ID_STRING) + 1) {
@ -178,7 +178,7 @@ load_public_key(const char *filename, RSA * pub,
* from the buffer.
*/
for (i = 0; i < (unsigned int) strlen(AUTHFILE_ID_STRING) + 1; i++)
if (buffer_get_char(&buffer) != (unsigned char) AUTHFILE_ID_STRING[i]) {
if (buffer_get_char(&buffer) != (u_char) AUTHFILE_ID_STRING[i]) {
debug("Bad key file %.200s.", filename);
buffer_free(&buffer);
return 0;
@ -213,7 +213,7 @@ int
load_private_key(const char *filename, const char *passphrase,
RSA * prv, char **comment_return)
{
int f, i, check1, check2, cipher_type;
int fd, i, check1, check2, cipher_type;
off_t len;
Buffer buffer, decrypted;
char *cp;
@ -222,14 +222,15 @@ load_private_key(const char *filename, const char *passphrase,
BIGNUM *aux;
struct stat st;
f = open(filename, O_RDONLY);
if (f < 0)
fd = open(filename, O_RDONLY);
if (fd < 0)
return 0;
/* check owner and modes */
if (fstat(f, &st) < 0 ||
if (fstat(fd, &st) < 0 ||
(st.st_uid != 0 && st.st_uid != getuid()) ||
(st.st_mode & 077) != 0) {
close(fd);
error("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@");
error("@ WARNING: UNPROTECTED PRIVATE KEY FILE! @");
error("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@");
@ -238,20 +239,20 @@ load_private_key(const char *filename, const char *passphrase,
error("It is recommended that your private key files are NOT accessible by others.");
return 0;
}
len = lseek(f, (off_t) 0, SEEK_END);
lseek(f, (off_t) 0, SEEK_SET);
len = lseek(fd, (off_t) 0, SEEK_END);
lseek(fd, (off_t) 0, SEEK_SET);
buffer_init(&buffer);
buffer_append_space(&buffer, &cp, len);
if (read(f, cp, (size_t) len) != (size_t) 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(f);
close(fd);
return 0;
}
close(f);
close(fd);
/* Check that it is at least big enought to contain the ID string. */
if (len < strlen(AUTHFILE_ID_STRING) + 1) {

View File

@ -16,7 +16,7 @@
*/
#include "includes.h"
RCSID("$Id: channels.c,v 1.9 1999/12/06 00:47:29 damien Exp $");
RCSID("$Id: channels.c,v 1.10 1999/12/07 04:38:32 damien Exp $");
#include "ssh.h"
#include "packet.h"
@ -921,7 +921,7 @@ channel_request_local_forwarding(u_short port, const char *host,
/* Allocate a channel number for the socket. */
ch = channel_allocate(SSH_CHANNEL_PORT_LISTENER, sock,
xstrdup("port listener"));
strcpy(channels[ch].path, host);
strlcpy(channels[ch].path, host, sizeof(channels[ch].path));
channels[ch].host_port = host_port;
channels[ch].listening_port = port;
}
@ -1498,7 +1498,8 @@ auth_input_request_forwarding(struct passwd * pw)
/* Allocate a channel for the authentication agent socket. */
newch = channel_allocate(SSH_CHANNEL_AUTH_SOCKET, sock,
xstrdup("auth socket"));
strcpy(channels[newch].path, channel_forwarded_auth_socket_name);
strlcpy(channels[newch].path, channel_forwarded_auth_socket_name,
sizeof(channels[newch].path));
}
/* This is called to process an SSH_SMSG_AGENT_OPEN message. */

View File

@ -15,7 +15,7 @@
*/
#include "includes.h"
RCSID("$Id: clientloop.c,v 1.6 1999/11/25 00:54:58 damien Exp $");
RCSID("$Id: clientloop.c,v 1.7 1999/12/07 04:38:32 damien Exp $");
#include "xmalloc.h"
#include "ssh.h"
@ -466,13 +466,11 @@ client_suspend_self()
/* Flush stdout and stderr buffers. */
if (buffer_len(&stdout_buffer) > 0)
write(fileno(stdout),
buffer_ptr(&stdout_buffer),
buffer_len(&stdout_buffer));
atomicio(write, fileno(stdout), buffer_ptr(&stdout_buffer),
buffer_len(&stdout_buffer));
if (buffer_len(&stderr_buffer) > 0)
write(fileno(stderr),
buffer_ptr(&stderr_buffer),
buffer_len(&stderr_buffer));
atomicio(write, fileno(stderr), buffer_ptr(&stderr_buffer),
buffer_len(&stderr_buffer));
leave_raw_mode();
@ -739,7 +737,7 @@ client_process_output(fd_set * writeset)
if (FD_ISSET(fileno(stdout), writeset)) {
/* Write as much data as possible. */
len = write(fileno(stdout), buffer_ptr(&stdout_buffer),
buffer_len(&stdout_buffer));
buffer_len(&stdout_buffer));
if (len <= 0) {
if (errno == EAGAIN)
len = 0;
@ -762,7 +760,7 @@ client_process_output(fd_set * writeset)
if (FD_ISSET(fileno(stderr), writeset)) {
/* Write as much data as possible. */
len = write(fileno(stderr), buffer_ptr(&stderr_buffer),
buffer_len(&stderr_buffer));
buffer_len(&stderr_buffer));
if (len <= 0) {
if (errno == EAGAIN)
len = 0;
@ -911,7 +909,7 @@ client_loop(int have_pty, int escape_char_arg)
/* Output any buffered data for stdout. */
while (buffer_len(&stdout_buffer) > 0) {
len = write(fileno(stdout), buffer_ptr(&stdout_buffer),
buffer_len(&stdout_buffer));
buffer_len(&stdout_buffer));
if (len <= 0) {
error("Write failed flushing stdout buffer.");
break;
@ -922,7 +920,7 @@ client_loop(int have_pty, int escape_char_arg)
/* Output any buffered data for stderr. */
while (buffer_len(&stderr_buffer) > 0) {
len = write(fileno(stderr), buffer_ptr(&stderr_buffer),
buffer_len(&stderr_buffer));
buffer_len(&stderr_buffer));
if (len <= 0) {
error("Write failed flushing stderr buffer.");
break;

View File

@ -59,7 +59,7 @@ dnl Checks for header files.
AC_CHECK_HEADERS(endian.h lastlog.h login.h maillock.h netgroup.h paths.h pty.h shadow.h util.h utmp.h sys/select.h sys/time.h)
dnl Checks for library functions.
AC_CHECK_FUNCS(arc4random mkdtemp openpty setenv setlogin setproctitle snprintf strlcat strlcpy vsnprintf)
AC_CHECK_FUNCS(arc4random mkdtemp openpty _getpty setenv setlogin setproctitle snprintf strlcat strlcpy vsnprintf)
AC_CHECK_FUNC(login,
[AC_DEFINE(HAVE_LOGIN)],
@ -221,6 +221,9 @@ else
AC_DEFINE_UNQUOTED(LASTLOG_LOCATION, "$lastlog")
fi
AC_CHECK_FILE("/dev/ptmx", AC_DEFINE_UNQUOTED(HAVE_DEV_PTMX))
AC_CHECK_FILE("/dev/ptc", AC_DEFINE_UNQUOTED(HAVE_DEV_PTS_AND_PTC))
AC_MSG_CHECKING([whether libc defines __progname])
AC_TRY_LINK([],
[extern char *__progname; printf("%s", __progname);],

View File

@ -45,7 +45,6 @@
#include <sys/un.h>
#include <fcntl.h>
#include "rc4.h"
#include "xmalloc.h"
#include "ssh.h"
#include "config.h"
@ -57,10 +56,58 @@
#ifndef HAVE_ARC4RANDOM
typedef struct
{
unsigned int s[256];
int i;
int j;
} rc4_t;
void get_random_bytes(unsigned char *buf, int len);
void rc4_key(rc4_t *r, unsigned char *key, int len);
void rc4_getbytes(rc4_t *r, unsigned char *buffer, int len);
static rc4_t *rc4 = NULL;
void rc4_key(rc4_t *r, unsigned char *key, int len)
{
int t;
for(r->i = 0; r->i < 256; r->i++)
r->s[r->i] = r->i;
r->j = 0;
for(r->i = 0; r->i < 256; r->i++)
{
r->j = (r->j + r->s[r->i] + key[r->i % len]) % 256;
t = r->s[r->i];
r->s[r->i] = r->s[r->j];
r->s[r->j] = t;
}
r->i = r->j = 0;
}
void rc4_getbytes(rc4_t *r, unsigned char *buffer, int len)
{
int t;
int c;
c = 0;
while(c < len)
{
r->i = (r->i + 1) % 256;
r->j = (r->j + r->s[r->i]) % 256;
t = r->s[r->i];
r->s[r->i] = r->s[r->j];
r->s[r->j] = t;
t = (r->s[r->i] + r->s[r->j]) % 256;
buffer[c] = r->s[t];
c++;
}
}
unsigned int arc4random(void)
{
unsigned int r;
@ -117,7 +164,8 @@ void get_random_bytes(unsigned char *buf, int len)
/* Send blocking read request to EGD */
egd_message[1] = len;
c = write(random_pool, egd_message, sizeof(egd_message));
c = atomicio(write, random_pool, egd_message, sizeof(egd_message));
if (c == -1)
fatal("Couldn't write to EGD socket \"%s\": %s", RANDOM_POOL, strerror(errno));
@ -129,15 +177,9 @@ void get_random_bytes(unsigned char *buf, int len)
#endif /* HAVE_EGD */
do {
c = read(random_pool, buf, len);
if ((c == -1) && (errno != EINTR))
fatal("Couldn't read from random pool \"%s\": %s", RANDOM_POOL, strerror(errno));
} while (c == -1);
if (c != len)
fatal("Short read from random pool \"%s\"", RANDOM_POOL);
c = atomicio(read, random_pool, buf, len);
if (c <= 0)
fatal("Couldn't read from random pool \"%s\": %s", RANDOM_POOL, strerror(errno));
close(random_pool);
}

20
pty.c
View File

@ -14,7 +14,7 @@
*/
#include "includes.h"
RCSID("$Id: pty.c,v 1.5 1999/11/25 00:54:59 damien Exp $");
RCSID("$Id: pty.c,v 1.6 1999/12/07 04:38:32 damien Exp $");
#include "pty.h"
#include "ssh.h"
@ -40,17 +40,19 @@ RCSID("$Id: pty.c,v 1.5 1999/11/25 00:54:59 damien Exp $");
*/
int
pty_allocate(int *ptyfd, int *ttyfd, char *namebuf)
pty_allocate(int *ptyfd, int *ttyfd, char *namebuf, int namebuflen)
{
#ifdef HAVE_OPENPTY
#if defined(HAVE_OPENPTY) || defined(BSD4_4)
/* openpty(3) exists in OSF/1 and some other os'es */
char buf[64];
int i;
i = openpty(ptyfd, ttyfd, namebuf, NULL, NULL);
i = openpty(ptyfd, ttyfd, buf, NULL, NULL);
if (i < 0) {
error("openpty: %.100s", strerror(errno));
return 0;
}
strlcpy(namebuf, buf, namebuflen); /* possible truncation */
return 1;
#else /* HAVE_OPENPTY */
#ifdef HAVE__GETPTY
@ -65,7 +67,7 @@ pty_allocate(int *ptyfd, int *ttyfd, char *namebuf)
error("_getpty: %.100s", strerror(errno));
return 0;
}
strcpy(namebuf, slave);
strlcpy(namebuf, slave, namebuflen);
/* Open the slave side. */
*ttyfd = open(namebuf, O_RDWR | O_NOCTTY);
if (*ttyfd < 0) {
@ -99,7 +101,7 @@ pty_allocate(int *ptyfd, int *ttyfd, char *namebuf)
pts = ptsname(ptm);
if (pts == NULL)
error("Slave pty side name could not be obtained.");
strcpy(namebuf, pts);
strlcpy(namebuf, pts, namebuflen);
*ptyfd = ptm;
/* Open the slave side. */
@ -130,7 +132,7 @@ pty_allocate(int *ptyfd, int *ttyfd, char *namebuf)
name = ttyname(*ptyfd);
if (!name)
fatal("Open of /dev/ptc returns device for which ttyname fails.");
strcpy(namebuf, name);
strlcpy(namebuf, name, namebuflen);
*ttyfd = open(name, O_RDWR | O_NOCTTY);
if (*ttyfd < 0) {
error("Could not open pty slave side %.100s: %.100s",
@ -154,8 +156,8 @@ pty_allocate(int *ptyfd, int *ttyfd, char *namebuf)
*ptyfd = open(buf, O_RDWR | O_NOCTTY);
if (*ptyfd < 0)
continue;
snprintf(namebuf, sizeof buf, "/dev/tty%c%c", ptymajors[i / num_minors],
ptyminors[i % num_minors]);
snprintf(namebuf, sizeof namebuflen, "/dev/tty%c%c",
ptymajors[i / num_minors], ptyminors[i % num_minors]);
/* Open the slave side. */
*ttyfd = open(namebuf, O_RDWR | O_NOCTTY);

4
pty.h
View File

@ -13,7 +13,7 @@
* tty.
*/
/* RCSID("$Id: pty.h,v 1.3 1999/11/25 00:54:59 damien Exp $"); */
/* RCSID("$Id: pty.h,v 1.4 1999/12/07 04:38:32 damien Exp $"); */
#ifndef PTY_H
#define PTY_H
@ -24,7 +24,7 @@
* descriptors for the pty and tty sides and the name of the tty side are
* returned (the buffer must be able to hold at least 64 characters).
*/
int pty_allocate(int *ptyfd, int *ttyfd, char *ttyname);
int pty_allocate(int *ptyfd, int *ttyfd, char *ttyname, int ttynamelen);
/*
* Releases the tty. Its ownership is returned to root, and permissions to

109
rc4.c
View File

@ -1,109 +0,0 @@
/*! \file rc4.c
\brief Source file for RC4 stream cipher routines
\author Damien Miller <djm@mindrot.org>
\version 0.0.0
\date 1999
A simple implementation of the RC4 stream cipher, based on the
description given in _Bruce Schneier's_ "Applied Cryptography"
2nd edition.
Copyright 1999 Damien Miller
Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation
files (the "Software"), to deal in the Software without
restriction, including without limitation the rights to use, copy,
modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE
AND NONINFRINGEMENT. IN NO EVENT SHALL DAMIEN MILLER BE LIABLE
FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
\warning None of these functions clears its memory after use. It
\warning is the responsability of the calling routines to ensure
\warning that any sensitive data (keystream, key or plaintext) is
\warning properly erased after use.
\warning The name "RC4" is trademarked in the United States,
\warning you may need to use "RC4 compatible" or "ARC4"
\warning (Alleged RC4).
*/
/* $Id: rc4.c,v 1.1.1.1 1999/10/26 05:48:13 damien Exp $ */
#include "config.h"
#ifndef HAVE_ARC4RANDOM
#include "rc4.h"
void rc4_key(rc4_t *r, unsigned char *key, int len)
{
int t;
for(r->i = 0; r->i < 256; r->i++)
r->s[r->i] = r->i;
r->j = 0;
for(r->i = 0; r->i < 256; r->i++)
{
r->j = (r->j + r->s[r->i] + key[r->i % len]) % 256;
t = r->s[r->i];
r->s[r->i] = r->s[r->j];
r->s[r->j] = t;
}
r->i = r->j = 0;
}
void rc4_crypt(rc4_t *r, unsigned char *plaintext, int len)
{
int t;
int c;
c = 0;
while(c < len)
{
r->i = (r->i + 1) % 256;
r->j = (r->j + r->s[r->i]) % 256;
t = r->s[r->i];
r->s[r->i] = r->s[r->j];
r->s[r->j] = t;
t = (r->s[r->i] + r->s[r->j]) % 256;
plaintext[c] ^= r->s[t];
c++;
}
}
void rc4_getbytes(rc4_t *r, unsigned char *buffer, int len)
{
int t;
int c;
c = 0;
while(c < len)
{
r->i = (r->i + 1) % 256;
r->j = (r->j + r->s[r->i]) % 256;
t = r->s[r->i];
r->s[r->i] = r->s[r->j];
r->s[r->j] = t;
t = (r->s[r->i] + r->s[r->j]) % 256;
buffer[c] = r->s[t];
c++;
}
}
#endif /* !HAVE_ARC4RANDOM */

115
rc4.h
View File

@ -1,115 +0,0 @@
/*! \file rc4.h
\brief Header file for RC4 stream cipher routines
\author Damien Miller <djm@mindrot.org>
\version 0.0.0
\date 1999
A simple implementation of the RC4 stream cipher, based on the
description given in _Bruce Schneier's_ "Applied Cryptography"
2nd edition.
Copyright 1999 Damien Miller
Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation
files (the "Software"), to deal in the Software without
restriction, including without limitation the rights to use, copy,
modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE
AND NONINFRINGEMENT. IN NO EVENT SHALL DAMIEN MILLER BE LIABLE
FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
\warning None of these functions clears its memory after use. It
\warning is the responsability of the calling routines to ensure
\warning that any sensitive data (keystream, key or plaintext) is
\warning properly erased after use.
\warning The name "RC4" is trademarked in the United States,
\warning you may need to use "RC4 compatible" or "ARC4"
\warning (Alleged RC4).
*/
/* $Id: rc4.h,v 1.1.1.1 1999/10/26 05:48:13 damien Exp $ */
#ifndef _RC4_H
#define _RC4_H
#include "config.h"
#ifndef HAVE_ARC4RANDOM
/*! \struct rc4_t
\brief RC4 stream cipher state object
\var s State array
\var i Monotonic index
\var j Randomised index
\warning This structure should not be accessed directly. To
\warning initialise a rc4_t object, you should use the rc4_key()
\warning function
This structure holds the current state of the RC4 algorithm.
*/
typedef struct
{
unsigned int s[256];
int i;
int j;
} rc4_t;
/*! \fn void rc4_key(rc4_t *r, unsigned char *key, int len);
\brief Set up key structure of RC4 stream cipher
\param r pointer to RC4 structure to be seeded
\param key pointer to buffer containing raw key
\param len length of key
This function set the internal state of the RC4 data structure
pointed to by \a r using the specified \a key of length \a len.
This function can use up to 256 bytes of key, any more are ignored.
\warning Stream ciphers (such as RC4) can be insecure if the same
\warning key is used repeatedly. Ensure that any key specified has
\warning an reasonably sized Initialisation Vector component.
*/
void rc4_key(rc4_t *r, unsigned char *key, int len);
/*! \fn rc4_crypt(rc4_t *r, unsigned char *plaintext, int len);
\brief Crypt bytes using RC4 algorithm
\param r pointer to RC4 structure to be used
\param plaintext Pointer to bytes to encrypt
\param len number of bytes to crypt
This function encrypts one or more bytes (pointed to by \a plaintext)
using the RC4 algorithm. \a r is a state structure that must be
initialiased using the rc4_key() function prior to use.
Since RC4 XORs each byte of plaintext with a byte of keystream,
this function can be used for both encryption and decryption.
*/
void rc4_crypt(rc4_t *r, unsigned char *plaintext, int len);
/*! \fn rc4_getbytes(rc4_t *r, unsigned char *buffer, int len);
\brief Generate key stream using the RC4 stream cipher
\param r pointer to RC4 structure to be used
\param buffer pointer to buffer in which to deposit keystream
\param len number of bytes to deposit
This function gives access to the raw RC4 key stream. In this
consiguration RC4 can be used as a fast, strong pseudo-random
number generator with a very long period.
*/
void rc4_getbytes(rc4_t *r, unsigned char *buffer, int len);
#endif /* !HAVE_ARC4RANDOM */
#endif /* _RC4_H */

28
scp.c
View File

@ -45,7 +45,7 @@
*/
#include "includes.h"
RCSID("$Id: scp.c,v 1.11 1999/11/25 01:31:26 damien Exp $");
RCSID("$Id: scp.c,v 1.12 1999/12/07 04:38:32 damien Exp $");
#include "ssh.h"
#include "xmalloc.h"
@ -974,7 +974,7 @@ run_err(const char *fmt,...)
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $Id: scp.c,v 1.11 1999/11/25 01:31:26 damien Exp $
* $Id: scp.c,v 1.12 1999/12/07 04:38:32 damien Exp $
*/
char *
@ -1065,30 +1065,6 @@ lostconn(signo)
exit(1);
}
/*
* ensure all of data on socket comes through. f==read || f==write
*/
int
atomicio(f, fd, s, n)
int (*f) ();
char *s;
{
int res, pos = 0;
while (n > pos) {
res = (f) (fd, s + pos, n - pos);
switch (res) {
case -1:
if (errno == EINTR || errno == EAGAIN)
continue;
case 0:
return (res);
default:
pos += res;
}
}
return (pos);
}
void
alarmtimer(int wait)

View File

@ -170,7 +170,7 @@ make_packets_from_stderr_data()
/* Send buffered stderr data to the client. */
while (buffer_len(&stderr_buffer) > 0 &&
packet_not_very_much_data_to_write()) {
packet_not_very_much_data_to_write()) {
len = buffer_len(&stderr_buffer);
if (packet_is_interactive()) {
if (len > 512)
@ -199,7 +199,7 @@ make_packets_from_stdout_data()
/* Send buffered stdout data to the client. */
while (buffer_len(&stdout_buffer) > 0 &&
packet_not_very_much_data_to_write()) {
packet_not_very_much_data_to_write()) {
len = buffer_len(&stdout_buffer);
if (packet_is_interactive()) {
if (len > 512)
@ -364,7 +364,7 @@ process_output(fd_set * writeset)
/* Write buffered data to program stdin. */
if (fdin != -1 && FD_ISSET(fdin, writeset)) {
len = write(fdin, buffer_ptr(&stdin_buffer),
buffer_len(&stdin_buffer));
buffer_len(&stdin_buffer));
if (len <= 0) {
#ifdef USE_PIPES
close(fdin);

9
ssh.h
View File

@ -13,7 +13,7 @@
*
*/
/* RCSID("$Id: ssh.h,v 1.18 1999/12/07 03:54:53 damien Exp $"); */
/* RCSID("$Id: ssh.h,v 1.19 1999/12/07 04:38:32 damien Exp $"); */
#ifndef SSH_H
#define SSH_H
@ -702,9 +702,14 @@ struct envstring {
struct envstring *next;
char *s;
};
/*
* Ensure all of data on socket comes through. f==read || f==write
*/
int atomicio(int (*f)(), int fd, void *s, size_t n);
#ifdef KRB4
#include <krb.h>
/*
* Performs Kerberos v4 mutual authentication with the client. This returns 0
* if the client could not be authenticated, and 1 if authentication was

View File

@ -8,7 +8,7 @@
*/
#include "includes.h"
RCSID("$Id: sshconnect.c,v 1.16 1999/12/06 00:47:29 damien Exp $");
RCSID("$Id: sshconnect.c,v 1.17 1999/12/07 04:38:32 damien Exp $");
#ifdef HAVE_OPENSSL
#include <openssl/bn.h>
@ -537,7 +537,7 @@ try_rsa_authentication(const char *authfile)
if (!load_private_key(authfile, "", private_key, NULL)) {
char buf[300];
snprintf(buf, sizeof buf, "Enter passphrase for RSA key '%.100s': ",
comment);
comment);
if (!options.batch_mode)
passphrase = read_passphrase(buf, 0);
else {
@ -1036,8 +1036,8 @@ ssh_exchange_identification()
/* Send our own protocol version identification. */
snprintf(buf, sizeof buf, "SSH-%d.%d-%.100s\n",
PROTOCOL_MAJOR, PROTOCOL_MINOR, SSH_VERSION);
if (write(connection_out, buf, strlen(buf)) != strlen(buf))
PROTOCOL_MAJOR, PROTOCOL_MINOR, SSH_VERSION);
if (atomicio(write, connection_out, buf, strlen(buf)) != strlen(buf))
fatal("write: %.100s", strerror(errno));
}
@ -1292,10 +1292,10 @@ ssh_login(int host_key_valid,
char prompt[1024];
char *fp = fingerprint(host_key->e, host_key->n);
snprintf(prompt, sizeof(prompt),
"The authenticity of host '%.200s' can't be established.\n"
"Key fingerprint is %d %s.\n"
"Are you sure you want to continue connecting (yes/no)? ",
host, BN_num_bits(host_key->n), fp);
"The authenticity of host '%.200s' can't be established.\n"
"Key fingerprint is %d %s.\n"
"Are you sure you want to continue connecting (yes/no)? ",
host, BN_num_bits(host_key->n), fp);
if (!read_yes_or_no(prompt, -1))
fatal("Aborted by user!\n");
}
@ -1599,8 +1599,9 @@ ssh_login(int host_key_valid,
if ((supported_authentications & (1 << SSH_AUTH_PASSWORD)) &&
options.password_authentication && !options.batch_mode) {
char prompt[80];
snprintf(prompt, sizeof(prompt), "%.30s@%.40s's password: ",
server_user, host);
server_user, host);
if (try_password_authentication(prompt))
return;
}

19
sshd.c
View File

@ -11,7 +11,7 @@
*/
#include "includes.h"
RCSID("$Id: sshd.c,v 1.34 1999/12/07 03:56:27 damien Exp $");
RCSID("$Id: sshd.c,v 1.35 1999/12/07 04:38:32 damien Exp $");
#include "xmalloc.h"
#include "rsa.h"
@ -812,7 +812,7 @@ main(int ac, char **av)
/* Send our protocol version identification. */
snprintf(buf, sizeof buf, "SSH-%d.%d-%.100s\n",
PROTOCOL_MAJOR, PROTOCOL_MINOR, SSH_VERSION);
if (write(sock_out, buf, strlen(buf)) != strlen(buf))
if (atomicio(write, sock_out, buf, strlen(buf)) != strlen(buf))
fatal("Could not write ident string to %s.", get_remote_ipaddr());
/* Read other side\'s version identification. */
@ -838,9 +838,10 @@ main(int ac, char **av)
* several versions and set appropriate flags to handle them.
*/
if (sscanf(buf, "SSH-%d.%d-%[^\n]\n", &remote_major, &remote_minor,
remote_version) != 3) {
const char *s = "Protocol mismatch.\n";
(void) write(sock_out, s, strlen(s));
remote_version) != 3) {
char *s = "Protocol mismatch.\n";
(void) atomicio(write, sock_out, s, strlen(s));
close(sock_in);
close(sock_out);
fatal("Bad protocol version identification '%.100s' from %s",
@ -849,8 +850,9 @@ main(int ac, char **av)
debug("Client protocol version %d.%d; client software version %.100s",
remote_major, remote_minor, remote_version);
if (remote_major != PROTOCOL_MAJOR) {
const char *s = "Protocol major versions differ.\n";
(void) write(sock_out, s, strlen(s));
char *s = "Protocol major versions differ.\n";
(void) atomicio(write, sock_out, s, strlen(s));
close(sock_in);
close(sock_out);
fatal("Protocol major versions differ for %s: %d vs. %d",
@ -1737,7 +1739,8 @@ do_authenticated(struct passwd * pw)
debug("Allocating pty.");
/* Allocate a pty and open it. */
if (!pty_allocate(&ptyfd, &ttyfd, ttyname)) {
if (!pty_allocate(&ptyfd, &ttyfd, ttyname,
sizeof(ttyname))) {
error("Failed to allocate pty.");
goto fail;
}

View File

@ -6,7 +6,7 @@
*/
#include "includes.h"
RCSID("$Id: tildexpand.c,v 1.3 1999/11/25 00:54:59 damien Exp $");
RCSID("$Id: tildexpand.c,v 1.4 1999/12/07 04:38:32 damien Exp $");
#include "xmalloc.h"
#include "ssh.h"
@ -23,6 +23,7 @@ tilde_expand_filename(const char *filename, uid_t my_uid)
char *expanded;
struct passwd *pw;
char user[100];
int len;
/* Return immediately if no tilde. */
if (filename[0] != '~')
@ -56,7 +57,10 @@ tilde_expand_filename(const char *filename, uid_t my_uid)
return xstrdup(pw->pw_dir);
}
/* Build a path combining the specified directory and path. */
expanded = xmalloc(strlen(pw->pw_dir) + strlen(cp + 1) + 2);
sprintf(expanded, "%s/%s", pw->pw_dir, cp + 1);
len = strlen(pw->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", pw->pw_dir, cp + 1);
return expanded;
}