summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog18
-rw-r--r--Makefile.in28
-rw-r--r--acconfig.h6
-rw-r--r--atomicio.c57
-rw-r--r--auth-skey.c5
-rw-r--r--authfd.c24
-rw-r--r--authfile.c51
-rw-r--r--channels.c7
-rw-r--r--clientloop.c20
-rw-r--r--configure.in5
-rw-r--r--helper.c64
-rw-r--r--pty.c20
-rw-r--r--pty.h4
-rw-r--r--rc4.c109
-rw-r--r--rc4.h115
-rw-r--r--scp.c28
-rw-r--r--serverloop.c6
-rw-r--r--ssh.h9
-rw-r--r--sshconnect.c19
-rw-r--r--sshd.c19
-rw-r--r--tildexpand.c10
21 files changed, 263 insertions, 361 deletions
diff --git a/ChangeLog b/ChangeLog
index f475f188..fc6b3f37 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -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
diff --git a/Makefile.in b/Makefile.in
index c2c3261b..80b0a6d4 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -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
diff --git a/acconfig.h b/acconfig.h
index 25f49141..29ec0782 100644
--- a/acconfig.h
+++ b/acconfig.h
@@ -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 ************** */
diff --git a/atomicio.c b/atomicio.c
new file mode 100644
index 00000000..03d635cb
--- /dev/null
+++ b/atomicio.c
@@ -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);
+}
diff --git a/auth-skey.c b/auth-skey.c
index cc5f4510..88291599 100644
--- a/auth-skey.c
+++ b/auth-skey.c
@@ -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 */
diff --git a/authfd.c b/authfd.c
index ee6473d3..1a62c3ed 100644
--- a/authfd.c
+++ b/authfd.c
@@ -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;
}
diff --git a/authfile.c b/authfile.c
index 97d0a878..b0e832a0 100644
--- a/authfile.c
+++ b/authfile.c
@@ -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) {
diff --git a/channels.c b/channels.c
index 01382365..6c2fb73a 100644
--- a/channels.c
+++ b/channels.c
@@ -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. */
diff --git a/clientloop.c b/clientloop.c
index 679180f5..bfa3019b 100644
--- a/clientloop.c
+++ b/clientloop.c
@@ -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;
diff --git a/configure.in b/configure.in
index 86f2dde7..62e68317 100644
--- a/configure.in
+++ b/configure.in
@@ -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);],
diff --git a/helper.c b/helper.c
index 91a78b57..bf4e145b 100644
--- a/helper.c
+++ b/helper.c
@@ -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);
}
diff --git a/pty.c b/pty.c
index e4684213..4f8fbd21 100644
--- a/pty.c
+++ b/pty.c
@@ -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);
diff --git a/pty.h b/pty.h
index 0601e69f..186cb3c9 100644
--- a/pty.h
+++ b/pty.h
@@ -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
diff --git a/rc4.c b/rc4.c
deleted file mode 100644
index 998a1077..00000000
--- a/rc4.c
+++ /dev/null
@@ -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 */
diff --git a/rc4.h b/rc4.h
deleted file mode 100644
index 1be64aca..00000000
--- a/rc4.h
+++ /dev/null
@@ -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 */
diff --git a/scp.c b/scp.c
index fec2f432..5a3ec447 100644
--- a/scp.c
+++ b/scp.c
@@ -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)
diff --git a/serverloop.c b/serverloop.c
index 94c21157..a5ecfe97 100644
--- a/serverloop.c
+++ b/serverloop.c
@@ -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);
diff --git a/ssh.h b/ssh.h
index 0b66264f..facd88a0 100644
--- a/ssh.h
+++ b/ssh.h
@@ -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
diff --git a/sshconnect.c b/sshconnect.c
index 593eade0..e6175f11 100644
--- a/sshconnect.c
+++ b/sshconnect.c
@@ -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;
}
diff --git a/sshd.c b/sshd.c
index 60d34d8b..0c15e283 100644
--- a/sshd.c
+++ b/sshd.c
@@ -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;
}
diff --git a/tildexpand.c b/tildexpand.c
index 8ee551f1..f615362f 100644
--- a/tildexpand.c
+++ b/tildexpand.c
@@ -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;
}