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 f475f188d..fc6b3f37b 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -4,6 +4,24 @@
4 - Fixed default SSH_ASKPASS 4 - Fixed default SSH_ASKPASS
5 - Fix PAM account and session being called multiple times. Problem 5 - Fix PAM account and session being called multiple times. Problem
6 reported by Adrian Baugh <adrian@merlin.keble.ox.ac.uk> 6 reported by Adrian Baugh <adrian@merlin.keble.ox.ac.uk>
7 - Merged more OpenBSD changes:
8 - [atomicio.c authfd.c scp.c serverloop.c ssh.h sshconnect.c sshd.c]
9 move atomicio into it's own file. wrap all socket write()s which
10 were doing write(sock, buf, len) != len, with atomicio() calls.
11 - [auth-skey.c]
12 fd leak
13 - [authfile.c]
14 properly name fd variable
15 - [channels.c]
16 display great hatred towards strcpy
17 - [pty.c pty.h sshd.c]
18 use openpty() if it exists (it does on BSD4_4)
19 - [tildexpand.c]
20 check for ~ expansion past MAXPATHLEN
21 - Modified helper.c to use new atomicio function.
22 - Reformat Makefile a little
23 - Moved RC4 routines from rc4.[ch] into helper.c
24 - Added autoconf code to detect /dev/ptmx (Solaris) and /dev/ptc (AIX)
7 25
819991204 2619991204
9 - Small cleanup of PAM code in sshd.c 27 - Small cleanup of PAM code in sshd.c
diff --git a/Makefile.in b/Makefile.in
index c2c3261b5..80b0a6d42 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -23,25 +23,31 @@ LFLAGS=@LDFLAGS@
23GNOME_CFLAGS=`gnome-config --cflags gnome gnomeui` 23GNOME_CFLAGS=`gnome-config --cflags gnome gnomeui`
24GNOME_LIBS=`gnome-config --libs gnome gnomeui` 24GNOME_LIBS=`gnome-config --libs gnome gnomeui`
25 25
26OBJS= authfd.o authfile.o auth-passwd.o auth-rhosts.o auth-rh-rsa.o \ 26OBJS= atomicio.o authfd.o authfile.o auth-passwd.o auth-rhosts.o \
27 auth-rsa.o auth-skey.o bufaux.o buffer.o canohost.o channels.o \ 27 auth-rh-rsa.o auth-rsa.o auth-skey.o bsd-daemon.o bsd-login.o \
28 cipher.o clientloop.o compress.o crc32.o deattack.o helper.o \ 28 bsd-mktemp.o bsd-snprintf.o bsd-strlcat.o bsd-strlcpy.o bufaux.o \
29 hostfile.o log-client.o login.o log-server.o match.o mpaux.o \ 29 buffer.o canohost.o channels.o cipher.o clientloop.o compress.o \
30 packet.o pty.o readconf.o readpass.o rsa.o servconf.o serverloop.o \ 30 crc32.o deattack.o helper.o helper.o hostfile.o log-client.o \
31 sshconnect.o tildexpand.o ttymodes.o uidswap.o xmalloc.o \ 31 login.o log-server.o match.o md5crypt.o mpaux.o packet.o pty.o \
32 helper.o bsd-mktemp.o bsd-strlcpy.o bsd-strlcat.o bsd-daemon.o \ 32 readconf.o readpass.o rsa.o servconf.o serverloop.o \
33 bsd-login.o bsd-snprintf.o rc4.o md5crypt.o 33 sshconnect.o tildexpand.o ttymodes.o uidswap.o xmalloc.o
34
35all: $(OBJS) $(TARGETS) 34all: $(OBJS) $(TARGETS)
36 35
37libssh.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 36libssh.a: atomicio.o authfd.o authfile.o bsd-daemon.o bsd-mktemp.o \
37 bsd-snprintf.o bsd-strlcat.o bsd-strlcpy.o bufaux.o \
38 buffer.o canohost.o channels.o cipher.o compat.o \
39 compress.o crc32.o deattack.o fingerprint.o helper.o \
40 hostfile.o log.o match.o mpaux.o nchan.o packet.o \
41 readpass.o rsa.o tildexpand.o ttymodes.o uidswap.o xmalloc.o
38 $(AR) rv $@ $^ 42 $(AR) rv $@ $^
39 $(RANLIB) $@ 43 $(RANLIB) $@
40 44
41ssh: ssh.o sshconnect.o log-client.o readconf.o clientloop.o libssh.a 45ssh: ssh.o sshconnect.o log-client.o readconf.o clientloop.o libssh.a
42 $(CC) -o $@ $^ $(LFLAGS) $(LIBS) 46 $(CC) -o $@ $^ $(LFLAGS) $(LIBS)
43 47
44sshd: 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 48sshd: sshd.o auth-rhosts.o auth-passwd.o auth-rsa.o auth-rh-rsa.o \
49 pty.o log-server.o login.o servconf.o serverloop.o bsd-login.o \
50 md5crypt.o libssh.a
45 $(CC) -o $@ $^ $(LFLAGS) $(LIBS) 51 $(CC) -o $@ $^ $(LFLAGS) $(LIBS)
46 52
47scp: scp.o libssh.a 53scp: scp.o libssh.a
diff --git a/acconfig.h b/acconfig.h
index 25f491414..29ec07821 100644
--- a/acconfig.h
+++ b/acconfig.h
@@ -64,6 +64,12 @@
64#undef HAVE_U_INTXX_T 64#undef HAVE_U_INTXX_T
65#undef HAVE_UINTXX_T 65#undef HAVE_UINTXX_T
66 66
67/* Define if you have /dev/ptmx */
68#undef HAVE_DEV_PTMX
69
70/* Define if you have /dev/ptc */
71#undef HAVE_DEV_PTS_AND_PTC
72
67@BOTTOM@ 73@BOTTOM@
68 74
69/* ******************* Shouldn't need to edit below this line ************** */ 75/* ******************* Shouldn't need to edit below this line ************** */
diff --git a/atomicio.c b/atomicio.c
new file mode 100644
index 000000000..03d635cb3
--- /dev/null
+++ b/atomicio.c
@@ -0,0 +1,57 @@
1/*
2 * Copyright (c) 1999 Theo de Raadt
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
15 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
16 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
17 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
18 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
19 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
20 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
21 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
23 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 */
25
26#include "includes.h"
27RCSID("$Id: atomicio.c,v 1.1 1999/12/07 04:38:31 damien Exp $");
28
29#include "xmalloc.h"
30#include "ssh.h"
31
32/*
33 * ensure all of data on socket comes through. f==read || f==write
34 */
35int
36atomicio(f, fd, s, n)
37 int (*f) ();
38 int fd;
39 void *s;
40 size_t n;
41{
42 int res, pos = 0;
43
44 while (n > pos) {
45 res = (f) (fd, s + pos, n - pos);
46 switch (res) {
47 case -1:
48 if (errno == EINTR || errno == EAGAIN)
49 continue;
50 case 0:
51 return (res);
52 default:
53 pos += res;
54 }
55 }
56 return (pos);
57}
diff --git a/auth-skey.c b/auth-skey.c
index cc5f45101..882915992 100644
--- a/auth-skey.c
+++ b/auth-skey.c
@@ -1,7 +1,7 @@
1#include "includes.h" 1#include "includes.h"
2 2
3#ifdef SKEY 3#ifdef SKEY
4RCSID("$Id: auth-skey.c,v 1.4 1999/12/01 16:54:35 markus Exp $"); 4RCSID("$Id: auth-skey.c,v 1.5 1999/12/06 19:04:57 deraadt Exp $");
5 5
6#include "ssh.h" 6#include "ssh.h"
7#include "packet.h" 7#include "packet.h"
@@ -114,6 +114,7 @@ skey_fake_keyinfo(char *username)
114 SEEK_SET) != -1 && read(fd, hseed, 114 SEEK_SET) != -1 && read(fd, hseed,
115 SKEY_MAX_SEED_LEN) == SKEY_MAX_SEED_LEN) { 115 SKEY_MAX_SEED_LEN) == SKEY_MAX_SEED_LEN) {
116 close(fd); 116 close(fd);
117 fd = -1;
117 secret = hseed; 118 secret = hseed;
118 secretlen = SKEY_MAX_SEED_LEN; 119 secretlen = SKEY_MAX_SEED_LEN;
119 flg = 0; 120 flg = 0;
@@ -123,6 +124,8 @@ skey_fake_keyinfo(char *username)
123 secretlen = strlen(secret); 124 secretlen = strlen(secret);
124 flg = 0; 125 flg = 0;
125 } 126 }
127 if (fd != -1)
128 close(fd);
126 } 129 }
127 130
128 /* Put that in your pipe and smoke it */ 131 /* Put that in your pipe and smoke it */
diff --git a/authfd.c b/authfd.c
index ee6473d32..1a62c3ed0 100644
--- a/authfd.c
+++ b/authfd.c
@@ -14,7 +14,7 @@
14 */ 14 */
15 15
16#include "includes.h" 16#include "includes.h"
17RCSID("$Id: authfd.c,v 1.8 1999/11/25 00:54:57 damien Exp $"); 17RCSID("$Id: authfd.c,v 1.9 1999/12/07 04:38:32 damien Exp $");
18 18
19#include "ssh.h" 19#include "ssh.h"
20#include "rsa.h" 20#include "rsa.h"
@@ -145,7 +145,7 @@ ssh_get_first_identity(AuthenticationConnection *auth,
145 msg[2] = 0; 145 msg[2] = 0;
146 msg[3] = 1; 146 msg[3] = 1;
147 msg[4] = SSH_AGENTC_REQUEST_RSA_IDENTITIES; 147 msg[4] = SSH_AGENTC_REQUEST_RSA_IDENTITIES;
148 if (write(auth->fd, msg, 5) != 5) { 148 if (atomicio(write, auth->fd, msg, 5) != 5) {
149 error("write auth->fd: %.100s", strerror(errno)); 149 error("write auth->fd: %.100s", strerror(errno));
150 return 0; 150 return 0;
151 } 151 }
@@ -270,9 +270,9 @@ ssh_decrypt_challenge(AuthenticationConnection *auth,
270 PUT_32BIT(buf, len); 270 PUT_32BIT(buf, len);
271 271
272 /* Send the length and then the packet to the agent. */ 272 /* Send the length and then the packet to the agent. */
273 if (write(auth->fd, buf, 4) != 4 || 273 if (atomicio(write, auth->fd, buf, 4) != 4 ||
274 write(auth->fd, buffer_ptr(&buffer), buffer_len(&buffer)) != 274 atomicio(write, auth->fd, buffer_ptr(&buffer),
275 buffer_len(&buffer)) { 275 buffer_len(&buffer)) != buffer_len(&buffer)) {
276 error("Error writing to authentication socket."); 276 error("Error writing to authentication socket.");
277error_cleanup: 277error_cleanup:
278 buffer_free(&buffer); 278 buffer_free(&buffer);
@@ -369,9 +369,9 @@ ssh_add_identity(AuthenticationConnection *auth,
369 PUT_32BIT(buf, len); 369 PUT_32BIT(buf, len);
370 370
371 /* Send the length and then the packet to the agent. */ 371 /* Send the length and then the packet to the agent. */
372 if (write(auth->fd, buf, 4) != 4 || 372 if (atomicio(write, auth->fd, buf, 4) != 4 ||
373 write(auth->fd, buffer_ptr(&buffer), buffer_len(&buffer)) != 373 atomicio(write, auth->fd, buffer_ptr(&buffer),
374 buffer_len(&buffer)) { 374 buffer_len(&buffer)) != buffer_len(&buffer)) {
375 error("Error writing to authentication socket."); 375 error("Error writing to authentication socket.");
376error_cleanup: 376error_cleanup:
377 buffer_free(&buffer); 377 buffer_free(&buffer);
@@ -450,9 +450,9 @@ ssh_remove_identity(AuthenticationConnection *auth, RSA *key)
450 PUT_32BIT(buf, len); 450 PUT_32BIT(buf, len);
451 451
452 /* Send the length and then the packet to the agent. */ 452 /* Send the length and then the packet to the agent. */
453 if (write(auth->fd, buf, 4) != 4 || 453 if (atomicio(write, auth->fd, buf, 4) != 4 ||
454 write(auth->fd, buffer_ptr(&buffer), buffer_len(&buffer)) != 454 atomicio(write, auth->fd, buffer_ptr(&buffer),
455 buffer_len(&buffer)) { 455 buffer_len(&buffer)) != buffer_len(&buffer)) {
456 error("Error writing to authentication socket."); 456 error("Error writing to authentication socket.");
457error_cleanup: 457error_cleanup:
458 buffer_free(&buffer); 458 buffer_free(&buffer);
@@ -526,7 +526,7 @@ ssh_remove_all_identities(AuthenticationConnection *auth)
526 buf[4] = SSH_AGENTC_REMOVE_ALL_RSA_IDENTITIES; 526 buf[4] = SSH_AGENTC_REMOVE_ALL_RSA_IDENTITIES;
527 527
528 /* Send the length and then the packet to the agent. */ 528 /* Send the length and then the packet to the agent. */
529 if (write(auth->fd, buf, 5) != 5) { 529 if (atomicio(write, auth->fd, buf, 5) != 5) {
530 error("Error writing to authentication socket."); 530 error("Error writing to authentication socket.");
531 return 0; 531 return 0;
532 } 532 }
diff --git a/authfile.c b/authfile.c
index 97d0a8783..b0e832a04 100644
--- a/authfile.c
+++ b/authfile.c
@@ -15,7 +15,7 @@
15 */ 15 */
16 16
17#include "includes.h" 17#include "includes.h"
18RCSID("$Id: authfile.c,v 1.5 1999/11/25 00:54:58 damien Exp $"); 18RCSID("$Id: authfile.c,v 1.6 1999/12/07 04:38:32 damien Exp $");
19 19
20#ifdef HAVE_OPENSSL 20#ifdef HAVE_OPENSSL
21#include <openssl/bn.h> 21#include <openssl/bn.h>
@@ -46,7 +46,7 @@ save_private_key(const char *filename, const char *passphrase,
46{ 46{
47 Buffer buffer, encrypted; 47 Buffer buffer, encrypted;
48 char buf[100], *cp; 48 char buf[100], *cp;
49 int f, i; 49 int fd, i;
50 CipherContext cipher; 50 CipherContext cipher;
51 int cipher_type; 51 int cipher_type;
52 u_int32_t rand; 52 u_int32_t rand;
@@ -117,19 +117,19 @@ save_private_key(const char *filename, const char *passphrase,
117 memset(buf, 0, sizeof(buf)); 117 memset(buf, 0, sizeof(buf));
118 buffer_free(&buffer); 118 buffer_free(&buffer);
119 119
120 f = open(filename, O_WRONLY | O_CREAT | O_TRUNC, 0600); 120 fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC, 0600);
121 if (f < 0) 121 if (fd < 0)
122 return 0; 122 return 0;
123 if (write(f, buffer_ptr(&encrypted), buffer_len(&encrypted)) != 123 if (write(fd, buffer_ptr(&encrypted), buffer_len(&encrypted)) !=
124 buffer_len(&encrypted)) { 124 buffer_len(&encrypted)) {
125 debug("Write to key file %.200s failed: %.100s", filename, 125 debug("Write to key file %.200s failed: %.100s", filename,
126 strerror(errno)); 126 strerror(errno));
127 buffer_free(&encrypted); 127 buffer_free(&encrypted);
128 close(f); 128 close(fd);
129 remove(filename); 129 remove(filename);
130 return 0; 130 return 0;
131 } 131 }
132 close(f); 132 close(fd);
133 buffer_free(&encrypted); 133 buffer_free(&encrypted);
134 return 1; 134 return 1;
135} 135}
@@ -144,28 +144,28 @@ int
144load_public_key(const char *filename, RSA * pub, 144load_public_key(const char *filename, RSA * pub,
145 char **comment_return) 145 char **comment_return)
146{ 146{
147 int f, i; 147 int fd, i;
148 off_t len; 148 off_t len;
149 Buffer buffer; 149 Buffer buffer;
150 char *cp; 150 char *cp;
151 151
152 f = open(filename, O_RDONLY); 152 fd = open(filename, O_RDONLY);
153 if (f < 0) 153 if (fd < 0)
154 return 0; 154 return 0;
155 len = lseek(f, (off_t) 0, SEEK_END); 155 len = lseek(fd, (off_t) 0, SEEK_END);
156 lseek(f, (off_t) 0, SEEK_SET); 156 lseek(fd, (off_t) 0, SEEK_SET);
157 157
158 buffer_init(&buffer); 158 buffer_init(&buffer);
159 buffer_append_space(&buffer, &cp, len); 159 buffer_append_space(&buffer, &cp, len);
160 160
161 if (read(f, cp, (size_t) len) != (size_t) len) { 161 if (read(fd, cp, (size_t) len) != (size_t) len) {
162 debug("Read from key file %.200s failed: %.100s", filename, 162 debug("Read from key file %.200s failed: %.100s", filename,
163 strerror(errno)); 163 strerror(errno));
164 buffer_free(&buffer); 164 buffer_free(&buffer);
165 close(f); 165 close(fd);
166 return 0; 166 return 0;
167 } 167 }
168 close(f); 168 close(fd);
169 169
170 /* Check that it is at least big enought to contain the ID string. */ 170 /* Check that it is at least big enought to contain the ID string. */
171 if (len < strlen(AUTHFILE_ID_STRING) + 1) { 171 if (len < strlen(AUTHFILE_ID_STRING) + 1) {
@@ -178,7 +178,7 @@ load_public_key(const char *filename, RSA * pub,
178 * from the buffer. 178 * from the buffer.
179 */ 179 */
180 for (i = 0; i < (unsigned int) strlen(AUTHFILE_ID_STRING) + 1; i++) 180 for (i = 0; i < (unsigned int) strlen(AUTHFILE_ID_STRING) + 1; i++)
181 if (buffer_get_char(&buffer) != (unsigned char) AUTHFILE_ID_STRING[i]) { 181 if (buffer_get_char(&buffer) != (u_char) AUTHFILE_ID_STRING[i]) {
182 debug("Bad key file %.200s.", filename); 182 debug("Bad key file %.200s.", filename);
183 buffer_free(&buffer); 183 buffer_free(&buffer);
184 return 0; 184 return 0;
@@ -213,7 +213,7 @@ int
213load_private_key(const char *filename, const char *passphrase, 213load_private_key(const char *filename, const char *passphrase,
214 RSA * prv, char **comment_return) 214 RSA * prv, char **comment_return)
215{ 215{
216 int f, i, check1, check2, cipher_type; 216 int fd, i, check1, check2, cipher_type;
217 off_t len; 217 off_t len;
218 Buffer buffer, decrypted; 218 Buffer buffer, decrypted;
219 char *cp; 219 char *cp;
@@ -222,14 +222,15 @@ load_private_key(const char *filename, const char *passphrase,
222 BIGNUM *aux; 222 BIGNUM *aux;
223 struct stat st; 223 struct stat st;
224 224
225 f = open(filename, O_RDONLY); 225 fd = open(filename, O_RDONLY);
226 if (f < 0) 226 if (fd < 0)
227 return 0; 227 return 0;
228 228
229 /* check owner and modes */ 229 /* check owner and modes */
230 if (fstat(f, &st) < 0 || 230 if (fstat(fd, &st) < 0 ||
231 (st.st_uid != 0 && st.st_uid != getuid()) || 231 (st.st_uid != 0 && st.st_uid != getuid()) ||
232 (st.st_mode & 077) != 0) { 232 (st.st_mode & 077) != 0) {
233 close(fd);
233 error("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@"); 234 error("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@");
234 error("@ WARNING: UNPROTECTED PRIVATE KEY FILE! @"); 235 error("@ WARNING: UNPROTECTED PRIVATE KEY FILE! @");
235 error("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@"); 236 error("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@");
@@ -238,20 +239,20 @@ load_private_key(const char *filename, const char *passphrase,
238 error("It is recommended that your private key files are NOT accessible by others."); 239 error("It is recommended that your private key files are NOT accessible by others.");
239 return 0; 240 return 0;
240 } 241 }
241 len = lseek(f, (off_t) 0, SEEK_END); 242 len = lseek(fd, (off_t) 0, SEEK_END);
242 lseek(f, (off_t) 0, SEEK_SET); 243 lseek(fd, (off_t) 0, SEEK_SET);
243 244
244 buffer_init(&buffer); 245 buffer_init(&buffer);
245 buffer_append_space(&buffer, &cp, len); 246 buffer_append_space(&buffer, &cp, len);
246 247
247 if (read(f, cp, (size_t) len) != (size_t) len) { 248 if (read(fd, cp, (size_t) len) != (size_t) len) {
248 debug("Read from key file %.200s failed: %.100s", filename, 249 debug("Read from key file %.200s failed: %.100s", filename,
249 strerror(errno)); 250 strerror(errno));
250 buffer_free(&buffer); 251 buffer_free(&buffer);
251 close(f); 252 close(fd);
252 return 0; 253 return 0;
253 } 254 }
254 close(f); 255 close(fd);
255 256
256 /* Check that it is at least big enought to contain the ID string. */ 257 /* Check that it is at least big enought to contain the ID string. */
257 if (len < strlen(AUTHFILE_ID_STRING) + 1) { 258 if (len < strlen(AUTHFILE_ID_STRING) + 1) {
diff --git a/channels.c b/channels.c
index 013823659..6c2fb73aa 100644
--- a/channels.c
+++ b/channels.c
@@ -16,7 +16,7 @@
16 */ 16 */
17 17
18#include "includes.h" 18#include "includes.h"
19RCSID("$Id: channels.c,v 1.9 1999/12/06 00:47:29 damien Exp $"); 19RCSID("$Id: channels.c,v 1.10 1999/12/07 04:38:32 damien Exp $");
20 20
21#include "ssh.h" 21#include "ssh.h"
22#include "packet.h" 22#include "packet.h"
@@ -921,7 +921,7 @@ channel_request_local_forwarding(u_short port, const char *host,
921 /* Allocate a channel number for the socket. */ 921 /* Allocate a channel number for the socket. */
922 ch = channel_allocate(SSH_CHANNEL_PORT_LISTENER, sock, 922 ch = channel_allocate(SSH_CHANNEL_PORT_LISTENER, sock,
923 xstrdup("port listener")); 923 xstrdup("port listener"));
924 strcpy(channels[ch].path, host); 924 strlcpy(channels[ch].path, host, sizeof(channels[ch].path));
925 channels[ch].host_port = host_port; 925 channels[ch].host_port = host_port;
926 channels[ch].listening_port = port; 926 channels[ch].listening_port = port;
927} 927}
@@ -1498,7 +1498,8 @@ auth_input_request_forwarding(struct passwd * pw)
1498 /* Allocate a channel for the authentication agent socket. */ 1498 /* Allocate a channel for the authentication agent socket. */
1499 newch = channel_allocate(SSH_CHANNEL_AUTH_SOCKET, sock, 1499 newch = channel_allocate(SSH_CHANNEL_AUTH_SOCKET, sock,
1500 xstrdup("auth socket")); 1500 xstrdup("auth socket"));
1501 strcpy(channels[newch].path, channel_forwarded_auth_socket_name); 1501 strlcpy(channels[newch].path, channel_forwarded_auth_socket_name,
1502 sizeof(channels[newch].path));
1502} 1503}
1503 1504
1504/* This is called to process an SSH_SMSG_AGENT_OPEN message. */ 1505/* This is called to process an SSH_SMSG_AGENT_OPEN message. */
diff --git a/clientloop.c b/clientloop.c
index 679180f58..bfa3019b6 100644
--- a/clientloop.c
+++ b/clientloop.c
@@ -15,7 +15,7 @@
15 */ 15 */
16 16
17#include "includes.h" 17#include "includes.h"
18RCSID("$Id: clientloop.c,v 1.6 1999/11/25 00:54:58 damien Exp $"); 18RCSID("$Id: clientloop.c,v 1.7 1999/12/07 04:38:32 damien Exp $");
19 19
20#include "xmalloc.h" 20#include "xmalloc.h"
21#include "ssh.h" 21#include "ssh.h"
@@ -466,13 +466,11 @@ client_suspend_self()
466 466
467 /* Flush stdout and stderr buffers. */ 467 /* Flush stdout and stderr buffers. */
468 if (buffer_len(&stdout_buffer) > 0) 468 if (buffer_len(&stdout_buffer) > 0)
469 write(fileno(stdout), 469 atomicio(write, fileno(stdout), buffer_ptr(&stdout_buffer),
470 buffer_ptr(&stdout_buffer), 470 buffer_len(&stdout_buffer));
471 buffer_len(&stdout_buffer));
472 if (buffer_len(&stderr_buffer) > 0) 471 if (buffer_len(&stderr_buffer) > 0)
473 write(fileno(stderr), 472 atomicio(write, fileno(stderr), buffer_ptr(&stderr_buffer),
474 buffer_ptr(&stderr_buffer), 473 buffer_len(&stderr_buffer));
475 buffer_len(&stderr_buffer));
476 474
477 leave_raw_mode(); 475 leave_raw_mode();
478 476
@@ -739,7 +737,7 @@ client_process_output(fd_set * writeset)
739 if (FD_ISSET(fileno(stdout), writeset)) { 737 if (FD_ISSET(fileno(stdout), writeset)) {
740 /* Write as much data as possible. */ 738 /* Write as much data as possible. */
741 len = write(fileno(stdout), buffer_ptr(&stdout_buffer), 739 len = write(fileno(stdout), buffer_ptr(&stdout_buffer),
742 buffer_len(&stdout_buffer)); 740 buffer_len(&stdout_buffer));
743 if (len <= 0) { 741 if (len <= 0) {
744 if (errno == EAGAIN) 742 if (errno == EAGAIN)
745 len = 0; 743 len = 0;
@@ -762,7 +760,7 @@ client_process_output(fd_set * writeset)
762 if (FD_ISSET(fileno(stderr), writeset)) { 760 if (FD_ISSET(fileno(stderr), writeset)) {
763 /* Write as much data as possible. */ 761 /* Write as much data as possible. */
764 len = write(fileno(stderr), buffer_ptr(&stderr_buffer), 762 len = write(fileno(stderr), buffer_ptr(&stderr_buffer),
765 buffer_len(&stderr_buffer)); 763 buffer_len(&stderr_buffer));
766 if (len <= 0) { 764 if (len <= 0) {
767 if (errno == EAGAIN) 765 if (errno == EAGAIN)
768 len = 0; 766 len = 0;
@@ -911,7 +909,7 @@ client_loop(int have_pty, int escape_char_arg)
911 /* Output any buffered data for stdout. */ 909 /* Output any buffered data for stdout. */
912 while (buffer_len(&stdout_buffer) > 0) { 910 while (buffer_len(&stdout_buffer) > 0) {
913 len = write(fileno(stdout), buffer_ptr(&stdout_buffer), 911 len = write(fileno(stdout), buffer_ptr(&stdout_buffer),
914 buffer_len(&stdout_buffer)); 912 buffer_len(&stdout_buffer));
915 if (len <= 0) { 913 if (len <= 0) {
916 error("Write failed flushing stdout buffer."); 914 error("Write failed flushing stdout buffer.");
917 break; 915 break;
@@ -922,7 +920,7 @@ client_loop(int have_pty, int escape_char_arg)
922 /* Output any buffered data for stderr. */ 920 /* Output any buffered data for stderr. */
923 while (buffer_len(&stderr_buffer) > 0) { 921 while (buffer_len(&stderr_buffer) > 0) {
924 len = write(fileno(stderr), buffer_ptr(&stderr_buffer), 922 len = write(fileno(stderr), buffer_ptr(&stderr_buffer),
925 buffer_len(&stderr_buffer)); 923 buffer_len(&stderr_buffer));
926 if (len <= 0) { 924 if (len <= 0) {
927 error("Write failed flushing stderr buffer."); 925 error("Write failed flushing stderr buffer.");
928 break; 926 break;
diff --git a/configure.in b/configure.in
index 86f2dde7c..62e68317e 100644
--- a/configure.in
+++ b/configure.in
@@ -59,7 +59,7 @@ dnl Checks for header files.
59AC_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) 59AC_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)
60 60
61dnl Checks for library functions. 61dnl Checks for library functions.
62AC_CHECK_FUNCS(arc4random mkdtemp openpty setenv setlogin setproctitle snprintf strlcat strlcpy vsnprintf) 62AC_CHECK_FUNCS(arc4random mkdtemp openpty _getpty setenv setlogin setproctitle snprintf strlcat strlcpy vsnprintf)
63 63
64AC_CHECK_FUNC(login, 64AC_CHECK_FUNC(login,
65 [AC_DEFINE(HAVE_LOGIN)], 65 [AC_DEFINE(HAVE_LOGIN)],
@@ -221,6 +221,9 @@ else
221 AC_DEFINE_UNQUOTED(LASTLOG_LOCATION, "$lastlog") 221 AC_DEFINE_UNQUOTED(LASTLOG_LOCATION, "$lastlog")
222fi 222fi
223 223
224AC_CHECK_FILE("/dev/ptmx", AC_DEFINE_UNQUOTED(HAVE_DEV_PTMX))
225AC_CHECK_FILE("/dev/ptc", AC_DEFINE_UNQUOTED(HAVE_DEV_PTS_AND_PTC))
226
224AC_MSG_CHECKING([whether libc defines __progname]) 227AC_MSG_CHECKING([whether libc defines __progname])
225AC_TRY_LINK([], 228AC_TRY_LINK([],
226 [extern char *__progname; printf("%s", __progname);], 229 [extern char *__progname; printf("%s", __progname);],
diff --git a/helper.c b/helper.c
index 91a78b577..bf4e145b2 100644
--- a/helper.c
+++ b/helper.c
@@ -45,7 +45,6 @@
45#include <sys/un.h> 45#include <sys/un.h>
46#include <fcntl.h> 46#include <fcntl.h>
47 47
48#include "rc4.h"
49#include "xmalloc.h" 48#include "xmalloc.h"
50#include "ssh.h" 49#include "ssh.h"
51#include "config.h" 50#include "config.h"
@@ -57,10 +56,58 @@
57 56
58#ifndef HAVE_ARC4RANDOM 57#ifndef HAVE_ARC4RANDOM
59 58
59typedef struct
60{
61 unsigned int s[256];
62 int i;
63 int j;
64} rc4_t;
65
60void get_random_bytes(unsigned char *buf, int len); 66void get_random_bytes(unsigned char *buf, int len);
67void rc4_key(rc4_t *r, unsigned char *key, int len);
68void rc4_getbytes(rc4_t *r, unsigned char *buffer, int len);
61 69
62static rc4_t *rc4 = NULL; 70static rc4_t *rc4 = NULL;
63 71
72void rc4_key(rc4_t *r, unsigned char *key, int len)
73{
74 int t;
75
76 for(r->i = 0; r->i < 256; r->i++)
77 r->s[r->i] = r->i;
78
79 r->j = 0;
80 for(r->i = 0; r->i < 256; r->i++)
81 {
82 r->j = (r->j + r->s[r->i] + key[r->i % len]) % 256;
83 t = r->s[r->i];
84 r->s[r->i] = r->s[r->j];
85 r->s[r->j] = t;
86 }
87 r->i = r->j = 0;
88}
89
90void rc4_getbytes(rc4_t *r, unsigned char *buffer, int len)
91{
92 int t;
93 int c;
94
95 c = 0;
96 while(c < len)
97 {
98 r->i = (r->i + 1) % 256;
99 r->j = (r->j + r->s[r->i]) % 256;
100 t = r->s[r->i];
101 r->s[r->i] = r->s[r->j];
102 r->s[r->j] = t;
103
104 t = (r->s[r->i] + r->s[r->j]) % 256;
105
106 buffer[c] = r->s[t];
107 c++;
108 }
109}
110
64unsigned int arc4random(void) 111unsigned int arc4random(void)
65{ 112{
66 unsigned int r; 113 unsigned int r;
@@ -117,7 +164,8 @@ void get_random_bytes(unsigned char *buf, int len)
117 164
118 /* Send blocking read request to EGD */ 165 /* Send blocking read request to EGD */
119 egd_message[1] = len; 166 egd_message[1] = len;
120 c = write(random_pool, egd_message, sizeof(egd_message)); 167
168 c = atomicio(write, random_pool, egd_message, sizeof(egd_message));
121 if (c == -1) 169 if (c == -1)
122 fatal("Couldn't write to EGD socket \"%s\": %s", RANDOM_POOL, strerror(errno)); 170 fatal("Couldn't write to EGD socket \"%s\": %s", RANDOM_POOL, strerror(errno));
123 171
@@ -129,15 +177,9 @@ void get_random_bytes(unsigned char *buf, int len)
129 177
130#endif /* HAVE_EGD */ 178#endif /* HAVE_EGD */
131 179
132 do { 180 c = atomicio(read, random_pool, buf, len);
133 c = read(random_pool, buf, len); 181 if (c <= 0)
134 182 fatal("Couldn't read from random pool \"%s\": %s", RANDOM_POOL, strerror(errno));
135 if ((c == -1) && (errno != EINTR))
136 fatal("Couldn't read from random pool \"%s\": %s", RANDOM_POOL, strerror(errno));
137 } while (c == -1);
138
139 if (c != len)
140 fatal("Short read from random pool \"%s\"", RANDOM_POOL);
141 183
142 close(random_pool); 184 close(random_pool);
143} 185}
diff --git a/pty.c b/pty.c
index e46842138..4f8fbd21b 100644
--- a/pty.c
+++ b/pty.c
@@ -14,7 +14,7 @@
14 */ 14 */
15 15
16#include "includes.h" 16#include "includes.h"
17RCSID("$Id: pty.c,v 1.5 1999/11/25 00:54:59 damien Exp $"); 17RCSID("$Id: pty.c,v 1.6 1999/12/07 04:38:32 damien Exp $");
18 18
19#include "pty.h" 19#include "pty.h"
20#include "ssh.h" 20#include "ssh.h"
@@ -40,17 +40,19 @@ RCSID("$Id: pty.c,v 1.5 1999/11/25 00:54:59 damien Exp $");
40 */ 40 */
41 41
42int 42int
43pty_allocate(int *ptyfd, int *ttyfd, char *namebuf) 43pty_allocate(int *ptyfd, int *ttyfd, char *namebuf, int namebuflen)
44{ 44{
45#ifdef HAVE_OPENPTY 45#if defined(HAVE_OPENPTY) || defined(BSD4_4)
46 /* openpty(3) exists in OSF/1 and some other os'es */ 46 /* openpty(3) exists in OSF/1 and some other os'es */
47 char buf[64];
47 int i; 48 int i;
48 49
49 i = openpty(ptyfd, ttyfd, namebuf, NULL, NULL); 50 i = openpty(ptyfd, ttyfd, buf, NULL, NULL);
50 if (i < 0) { 51 if (i < 0) {
51 error("openpty: %.100s", strerror(errno)); 52 error("openpty: %.100s", strerror(errno));
52 return 0; 53 return 0;
53 } 54 }
55 strlcpy(namebuf, buf, namebuflen); /* possible truncation */
54 return 1; 56 return 1;
55#else /* HAVE_OPENPTY */ 57#else /* HAVE_OPENPTY */
56#ifdef HAVE__GETPTY 58#ifdef HAVE__GETPTY
@@ -65,7 +67,7 @@ pty_allocate(int *ptyfd, int *ttyfd, char *namebuf)
65 error("_getpty: %.100s", strerror(errno)); 67 error("_getpty: %.100s", strerror(errno));
66 return 0; 68 return 0;
67 } 69 }
68 strcpy(namebuf, slave); 70 strlcpy(namebuf, slave, namebuflen);
69 /* Open the slave side. */ 71 /* Open the slave side. */
70 *ttyfd = open(namebuf, O_RDWR | O_NOCTTY); 72 *ttyfd = open(namebuf, O_RDWR | O_NOCTTY);
71 if (*ttyfd < 0) { 73 if (*ttyfd < 0) {
@@ -99,7 +101,7 @@ pty_allocate(int *ptyfd, int *ttyfd, char *namebuf)
99 pts = ptsname(ptm); 101 pts = ptsname(ptm);
100 if (pts == NULL) 102 if (pts == NULL)
101 error("Slave pty side name could not be obtained."); 103 error("Slave pty side name could not be obtained.");
102 strcpy(namebuf, pts); 104 strlcpy(namebuf, pts, namebuflen);
103 *ptyfd = ptm; 105 *ptyfd = ptm;
104 106
105 /* Open the slave side. */ 107 /* Open the slave side. */
@@ -130,7 +132,7 @@ pty_allocate(int *ptyfd, int *ttyfd, char *namebuf)
130 name = ttyname(*ptyfd); 132 name = ttyname(*ptyfd);
131 if (!name) 133 if (!name)
132 fatal("Open of /dev/ptc returns device for which ttyname fails."); 134 fatal("Open of /dev/ptc returns device for which ttyname fails.");
133 strcpy(namebuf, name); 135 strlcpy(namebuf, name, namebuflen);
134 *ttyfd = open(name, O_RDWR | O_NOCTTY); 136 *ttyfd = open(name, O_RDWR | O_NOCTTY);
135 if (*ttyfd < 0) { 137 if (*ttyfd < 0) {
136 error("Could not open pty slave side %.100s: %.100s", 138 error("Could not open pty slave side %.100s: %.100s",
@@ -154,8 +156,8 @@ pty_allocate(int *ptyfd, int *ttyfd, char *namebuf)
154 *ptyfd = open(buf, O_RDWR | O_NOCTTY); 156 *ptyfd = open(buf, O_RDWR | O_NOCTTY);
155 if (*ptyfd < 0) 157 if (*ptyfd < 0)
156 continue; 158 continue;
157 snprintf(namebuf, sizeof buf, "/dev/tty%c%c", ptymajors[i / num_minors], 159 snprintf(namebuf, sizeof namebuflen, "/dev/tty%c%c",
158 ptyminors[i % num_minors]); 160 ptymajors[i / num_minors], ptyminors[i % num_minors]);
159 161
160 /* Open the slave side. */ 162 /* Open the slave side. */
161 *ttyfd = open(namebuf, O_RDWR | O_NOCTTY); 163 *ttyfd = open(namebuf, O_RDWR | O_NOCTTY);
diff --git a/pty.h b/pty.h
index 0601e69fc..186cb3c98 100644
--- a/pty.h
+++ b/pty.h
@@ -13,7 +13,7 @@
13 * tty. 13 * tty.
14 */ 14 */
15 15
16/* RCSID("$Id: pty.h,v 1.3 1999/11/25 00:54:59 damien Exp $"); */ 16/* RCSID("$Id: pty.h,v 1.4 1999/12/07 04:38:32 damien Exp $"); */
17 17
18#ifndef PTY_H 18#ifndef PTY_H
19#define PTY_H 19#define PTY_H
@@ -24,7 +24,7 @@
24 * descriptors for the pty and tty sides and the name of the tty side are 24 * descriptors for the pty and tty sides and the name of the tty side are
25 * returned (the buffer must be able to hold at least 64 characters). 25 * returned (the buffer must be able to hold at least 64 characters).
26 */ 26 */
27int pty_allocate(int *ptyfd, int *ttyfd, char *ttyname); 27int pty_allocate(int *ptyfd, int *ttyfd, char *ttyname, int ttynamelen);
28 28
29/* 29/*
30 * Releases the tty. Its ownership is returned to root, and permissions to 30 * 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 998a10774..000000000
--- a/rc4.c
+++ /dev/null
@@ -1,109 +0,0 @@
1/*! \file rc4.c
2 \brief Source file for RC4 stream cipher routines
3 \author Damien Miller <djm@mindrot.org>
4 \version 0.0.0
5 \date 1999
6
7 A simple implementation of the RC4 stream cipher, based on the
8 description given in _Bruce Schneier's_ "Applied Cryptography"
9 2nd edition.
10
11 Copyright 1999 Damien Miller
12
13 Permission is hereby granted, free of charge, to any person
14 obtaining a copy of this software and associated documentation
15 files (the "Software"), to deal in the Software without
16 restriction, including without limitation the rights to use, copy,
17 modify, merge, publish, distribute, sublicense, and/or sell copies
18 of the Software, and to permit persons to whom the Software is
19 furnished to do so, subject to the following conditions:
20
21 The above copyright notice and this permission notice shall be
22 included in all copies or substantial portions of the Software.
23
24 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
25 KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
26 WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE
27 AND NONINFRINGEMENT. IN NO EVENT SHALL DAMIEN MILLER BE LIABLE
28 FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
29 CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
30 WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
31
32 \warning None of these functions clears its memory after use. It
33 \warning is the responsability of the calling routines to ensure
34 \warning that any sensitive data (keystream, key or plaintext) is
35 \warning properly erased after use.
36
37 \warning The name "RC4" is trademarked in the United States,
38 \warning you may need to use "RC4 compatible" or "ARC4"
39 \warning (Alleged RC4).
40*/
41
42/* $Id: rc4.c,v 1.1.1.1 1999/10/26 05:48:13 damien Exp $ */
43
44#include "config.h"
45
46#ifndef HAVE_ARC4RANDOM
47#include "rc4.h"
48
49
50void rc4_key(rc4_t *r, unsigned char *key, int len)
51{
52 int t;
53
54 for(r->i = 0; r->i < 256; r->i++)
55 r->s[r->i] = r->i;
56
57 r->j = 0;
58 for(r->i = 0; r->i < 256; r->i++)
59 {
60 r->j = (r->j + r->s[r->i] + key[r->i % len]) % 256;
61 t = r->s[r->i];
62 r->s[r->i] = r->s[r->j];
63 r->s[r->j] = t;
64 }
65 r->i = r->j = 0;
66}
67
68void rc4_crypt(rc4_t *r, unsigned char *plaintext, int len)
69{
70 int t;
71 int c;
72
73 c = 0;
74 while(c < len)
75 {
76 r->i = (r->i + 1) % 256;
77 r->j = (r->j + r->s[r->i]) % 256;
78 t = r->s[r->i];
79 r->s[r->i] = r->s[r->j];
80 r->s[r->j] = t;
81
82 t = (r->s[r->i] + r->s[r->j]) % 256;
83
84 plaintext[c] ^= r->s[t];
85 c++;
86 }
87}
88
89void rc4_getbytes(rc4_t *r, unsigned char *buffer, int len)
90{
91 int t;
92 int c;
93
94 c = 0;
95 while(c < len)
96 {
97 r->i = (r->i + 1) % 256;
98 r->j = (r->j + r->s[r->i]) % 256;
99 t = r->s[r->i];
100 r->s[r->i] = r->s[r->j];
101 r->s[r->j] = t;
102
103 t = (r->s[r->i] + r->s[r->j]) % 256;
104
105 buffer[c] = r->s[t];
106 c++;
107 }
108}
109#endif /* !HAVE_ARC4RANDOM */
diff --git a/rc4.h b/rc4.h
deleted file mode 100644
index 1be64acac..000000000
--- a/rc4.h
+++ /dev/null
@@ -1,115 +0,0 @@
1/*! \file rc4.h
2 \brief Header file for RC4 stream cipher routines
3 \author Damien Miller <djm@mindrot.org>
4 \version 0.0.0
5 \date 1999
6
7 A simple implementation of the RC4 stream cipher, based on the
8 description given in _Bruce Schneier's_ "Applied Cryptography"
9 2nd edition.
10
11 Copyright 1999 Damien Miller
12
13 Permission is hereby granted, free of charge, to any person
14 obtaining a copy of this software and associated documentation
15 files (the "Software"), to deal in the Software without
16 restriction, including without limitation the rights to use, copy,
17 modify, merge, publish, distribute, sublicense, and/or sell copies
18 of the Software, and to permit persons to whom the Software is
19 furnished to do so, subject to the following conditions:
20
21 The above copyright notice and this permission notice shall be
22 included in all copies or substantial portions of the Software.
23
24 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
25 KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
26 WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE
27 AND NONINFRINGEMENT. IN NO EVENT SHALL DAMIEN MILLER BE LIABLE
28 FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
29 CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
30 WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
31
32 \warning None of these functions clears its memory after use. It
33 \warning is the responsability of the calling routines to ensure
34 \warning that any sensitive data (keystream, key or plaintext) is
35 \warning properly erased after use.
36
37 \warning The name "RC4" is trademarked in the United States,
38 \warning you may need to use "RC4 compatible" or "ARC4"
39 \warning (Alleged RC4).
40*/
41
42/* $Id: rc4.h,v 1.1.1.1 1999/10/26 05:48:13 damien Exp $ */
43
44#ifndef _RC4_H
45#define _RC4_H
46
47#include "config.h"
48#ifndef HAVE_ARC4RANDOM
49
50/*! \struct rc4_t
51 \brief RC4 stream cipher state object
52 \var s State array
53 \var i Monotonic index
54 \var j Randomised index
55
56 \warning This structure should not be accessed directly. To
57 \warning initialise a rc4_t object, you should use the rc4_key()
58 \warning function
59
60 This structure holds the current state of the RC4 algorithm.
61*/
62typedef struct
63{
64 unsigned int s[256];
65 int i;
66 int j;
67} rc4_t;
68
69/*! \fn void rc4_key(rc4_t *r, unsigned char *key, int len);
70 \brief Set up key structure of RC4 stream cipher
71 \param r pointer to RC4 structure to be seeded
72 \param key pointer to buffer containing raw key
73 \param len length of key
74
75 This function set the internal state of the RC4 data structure
76 pointed to by \a r using the specified \a key of length \a len.
77
78 This function can use up to 256 bytes of key, any more are ignored.
79
80 \warning Stream ciphers (such as RC4) can be insecure if the same
81 \warning key is used repeatedly. Ensure that any key specified has
82 \warning an reasonably sized Initialisation Vector component.
83*/
84void rc4_key(rc4_t *r, unsigned char *key, int len);
85
86/*! \fn rc4_crypt(rc4_t *r, unsigned char *plaintext, int len);
87 \brief Crypt bytes using RC4 algorithm
88 \param r pointer to RC4 structure to be used
89 \param plaintext Pointer to bytes to encrypt
90 \param len number of bytes to crypt
91
92 This function encrypts one or more bytes (pointed to by \a plaintext)
93 using the RC4 algorithm. \a r is a state structure that must be
94 initialiased using the rc4_key() function prior to use.
95
96 Since RC4 XORs each byte of plaintext with a byte of keystream,
97 this function can be used for both encryption and decryption.
98*/
99void rc4_crypt(rc4_t *r, unsigned char *plaintext, int len);
100
101/*! \fn rc4_getbytes(rc4_t *r, unsigned char *buffer, int len);
102 \brief Generate key stream using the RC4 stream cipher
103 \param r pointer to RC4 structure to be used
104 \param buffer pointer to buffer in which to deposit keystream
105 \param len number of bytes to deposit
106
107 This function gives access to the raw RC4 key stream. In this
108 consiguration RC4 can be used as a fast, strong pseudo-random
109 number generator with a very long period.
110*/
111void rc4_getbytes(rc4_t *r, unsigned char *buffer, int len);
112
113#endif /* !HAVE_ARC4RANDOM */
114
115#endif /* _RC4_H */
diff --git a/scp.c b/scp.c
index fec2f4328..5a3ec4470 100644
--- a/scp.c
+++ b/scp.c
@@ -45,7 +45,7 @@
45 */ 45 */
46 46
47#include "includes.h" 47#include "includes.h"
48RCSID("$Id: scp.c,v 1.11 1999/11/25 01:31:26 damien Exp $"); 48RCSID("$Id: scp.c,v 1.12 1999/12/07 04:38:32 damien Exp $");
49 49
50#include "ssh.h" 50#include "ssh.h"
51#include "xmalloc.h" 51#include "xmalloc.h"
@@ -974,7 +974,7 @@ run_err(const char *fmt,...)
974 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 974 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
975 * SUCH DAMAGE. 975 * SUCH DAMAGE.
976 * 976 *
977 * $Id: scp.c,v 1.11 1999/11/25 01:31:26 damien Exp $ 977 * $Id: scp.c,v 1.12 1999/12/07 04:38:32 damien Exp $
978 */ 978 */
979 979
980char * 980char *
@@ -1065,30 +1065,6 @@ lostconn(signo)
1065 exit(1); 1065 exit(1);
1066} 1066}
1067 1067
1068/*
1069 * ensure all of data on socket comes through. f==read || f==write
1070 */
1071int
1072atomicio(f, fd, s, n)
1073 int (*f) ();
1074 char *s;
1075{
1076 int res, pos = 0;
1077
1078 while (n > pos) {
1079 res = (f) (fd, s + pos, n - pos);
1080 switch (res) {
1081 case -1:
1082 if (errno == EINTR || errno == EAGAIN)
1083 continue;
1084 case 0:
1085 return (res);
1086 default:
1087 pos += res;
1088 }
1089 }
1090 return (pos);
1091}
1092 1068
1093void 1069void
1094alarmtimer(int wait) 1070alarmtimer(int wait)
diff --git a/serverloop.c b/serverloop.c
index 94c211571..a5ecfe97d 100644
--- a/serverloop.c
+++ b/serverloop.c
@@ -170,7 +170,7 @@ make_packets_from_stderr_data()
170 170
171 /* Send buffered stderr data to the client. */ 171 /* Send buffered stderr data to the client. */
172 while (buffer_len(&stderr_buffer) > 0 && 172 while (buffer_len(&stderr_buffer) > 0 &&
173 packet_not_very_much_data_to_write()) { 173 packet_not_very_much_data_to_write()) {
174 len = buffer_len(&stderr_buffer); 174 len = buffer_len(&stderr_buffer);
175 if (packet_is_interactive()) { 175 if (packet_is_interactive()) {
176 if (len > 512) 176 if (len > 512)
@@ -199,7 +199,7 @@ make_packets_from_stdout_data()
199 199
200 /* Send buffered stdout data to the client. */ 200 /* Send buffered stdout data to the client. */
201 while (buffer_len(&stdout_buffer) > 0 && 201 while (buffer_len(&stdout_buffer) > 0 &&
202 packet_not_very_much_data_to_write()) { 202 packet_not_very_much_data_to_write()) {
203 len = buffer_len(&stdout_buffer); 203 len = buffer_len(&stdout_buffer);
204 if (packet_is_interactive()) { 204 if (packet_is_interactive()) {
205 if (len > 512) 205 if (len > 512)
@@ -364,7 +364,7 @@ process_output(fd_set * writeset)
364 /* Write buffered data to program stdin. */ 364 /* Write buffered data to program stdin. */
365 if (fdin != -1 && FD_ISSET(fdin, writeset)) { 365 if (fdin != -1 && FD_ISSET(fdin, writeset)) {
366 len = write(fdin, buffer_ptr(&stdin_buffer), 366 len = write(fdin, buffer_ptr(&stdin_buffer),
367 buffer_len(&stdin_buffer)); 367 buffer_len(&stdin_buffer));
368 if (len <= 0) { 368 if (len <= 0) {
369#ifdef USE_PIPES 369#ifdef USE_PIPES
370 close(fdin); 370 close(fdin);
diff --git a/ssh.h b/ssh.h
index 0b66264f6..facd88a09 100644
--- a/ssh.h
+++ b/ssh.h
@@ -13,7 +13,7 @@
13 * 13 *
14 */ 14 */
15 15
16/* RCSID("$Id: ssh.h,v 1.18 1999/12/07 03:54:53 damien Exp $"); */ 16/* RCSID("$Id: ssh.h,v 1.19 1999/12/07 04:38:32 damien Exp $"); */
17 17
18#ifndef SSH_H 18#ifndef SSH_H
19#define SSH_H 19#define SSH_H
@@ -702,9 +702,14 @@ struct envstring {
702 struct envstring *next; 702 struct envstring *next;
703 char *s; 703 char *s;
704}; 704};
705
706/*
707 * Ensure all of data on socket comes through. f==read || f==write
708 */
709int atomicio(int (*f)(), int fd, void *s, size_t n);
710
705#ifdef KRB4 711#ifdef KRB4
706#include <krb.h> 712#include <krb.h>
707
708/* 713/*
709 * Performs Kerberos v4 mutual authentication with the client. This returns 0 714 * Performs Kerberos v4 mutual authentication with the client. This returns 0
710 * if the client could not be authenticated, and 1 if authentication was 715 * if the client could not be authenticated, and 1 if authentication was
diff --git a/sshconnect.c b/sshconnect.c
index 593eade03..e6175f11b 100644
--- a/sshconnect.c
+++ b/sshconnect.c
@@ -8,7 +8,7 @@
8 */ 8 */
9 9
10#include "includes.h" 10#include "includes.h"
11RCSID("$Id: sshconnect.c,v 1.16 1999/12/06 00:47:29 damien Exp $"); 11RCSID("$Id: sshconnect.c,v 1.17 1999/12/07 04:38:32 damien Exp $");
12 12
13#ifdef HAVE_OPENSSL 13#ifdef HAVE_OPENSSL
14#include <openssl/bn.h> 14#include <openssl/bn.h>
@@ -537,7 +537,7 @@ try_rsa_authentication(const char *authfile)
537 if (!load_private_key(authfile, "", private_key, NULL)) { 537 if (!load_private_key(authfile, "", private_key, NULL)) {
538 char buf[300]; 538 char buf[300];
539 snprintf(buf, sizeof buf, "Enter passphrase for RSA key '%.100s': ", 539 snprintf(buf, sizeof buf, "Enter passphrase for RSA key '%.100s': ",
540 comment); 540 comment);
541 if (!options.batch_mode) 541 if (!options.batch_mode)
542 passphrase = read_passphrase(buf, 0); 542 passphrase = read_passphrase(buf, 0);
543 else { 543 else {
@@ -1036,8 +1036,8 @@ ssh_exchange_identification()
1036 1036
1037 /* Send our own protocol version identification. */ 1037 /* Send our own protocol version identification. */
1038 snprintf(buf, sizeof buf, "SSH-%d.%d-%.100s\n", 1038 snprintf(buf, sizeof buf, "SSH-%d.%d-%.100s\n",
1039 PROTOCOL_MAJOR, PROTOCOL_MINOR, SSH_VERSION); 1039 PROTOCOL_MAJOR, PROTOCOL_MINOR, SSH_VERSION);
1040 if (write(connection_out, buf, strlen(buf)) != strlen(buf)) 1040 if (atomicio(write, connection_out, buf, strlen(buf)) != strlen(buf))
1041 fatal("write: %.100s", strerror(errno)); 1041 fatal("write: %.100s", strerror(errno));
1042} 1042}
1043 1043
@@ -1292,10 +1292,10 @@ ssh_login(int host_key_valid,
1292 char prompt[1024]; 1292 char prompt[1024];
1293 char *fp = fingerprint(host_key->e, host_key->n); 1293 char *fp = fingerprint(host_key->e, host_key->n);
1294 snprintf(prompt, sizeof(prompt), 1294 snprintf(prompt, sizeof(prompt),
1295 "The authenticity of host '%.200s' can't be established.\n" 1295 "The authenticity of host '%.200s' can't be established.\n"
1296 "Key fingerprint is %d %s.\n" 1296 "Key fingerprint is %d %s.\n"
1297 "Are you sure you want to continue connecting (yes/no)? ", 1297 "Are you sure you want to continue connecting (yes/no)? ",
1298 host, BN_num_bits(host_key->n), fp); 1298 host, BN_num_bits(host_key->n), fp);
1299 if (!read_yes_or_no(prompt, -1)) 1299 if (!read_yes_or_no(prompt, -1))
1300 fatal("Aborted by user!\n"); 1300 fatal("Aborted by user!\n");
1301 } 1301 }
@@ -1599,8 +1599,9 @@ ssh_login(int host_key_valid,
1599 if ((supported_authentications & (1 << SSH_AUTH_PASSWORD)) && 1599 if ((supported_authentications & (1 << SSH_AUTH_PASSWORD)) &&
1600 options.password_authentication && !options.batch_mode) { 1600 options.password_authentication && !options.batch_mode) {
1601 char prompt[80]; 1601 char prompt[80];
1602
1602 snprintf(prompt, sizeof(prompt), "%.30s@%.40s's password: ", 1603 snprintf(prompt, sizeof(prompt), "%.30s@%.40s's password: ",
1603 server_user, host); 1604 server_user, host);
1604 if (try_password_authentication(prompt)) 1605 if (try_password_authentication(prompt))
1605 return; 1606 return;
1606 } 1607 }
diff --git a/sshd.c b/sshd.c
index 60d34d8b6..0c15e2837 100644
--- a/sshd.c
+++ b/sshd.c
@@ -11,7 +11,7 @@
11 */ 11 */
12 12
13#include "includes.h" 13#include "includes.h"
14RCSID("$Id: sshd.c,v 1.34 1999/12/07 03:56:27 damien Exp $"); 14RCSID("$Id: sshd.c,v 1.35 1999/12/07 04:38:32 damien Exp $");
15 15
16#include "xmalloc.h" 16#include "xmalloc.h"
17#include "rsa.h" 17#include "rsa.h"
@@ -812,7 +812,7 @@ main(int ac, char **av)
812 /* Send our protocol version identification. */ 812 /* Send our protocol version identification. */
813 snprintf(buf, sizeof buf, "SSH-%d.%d-%.100s\n", 813 snprintf(buf, sizeof buf, "SSH-%d.%d-%.100s\n",
814 PROTOCOL_MAJOR, PROTOCOL_MINOR, SSH_VERSION); 814 PROTOCOL_MAJOR, PROTOCOL_MINOR, SSH_VERSION);
815 if (write(sock_out, buf, strlen(buf)) != strlen(buf)) 815 if (atomicio(write, sock_out, buf, strlen(buf)) != strlen(buf))
816 fatal("Could not write ident string to %s.", get_remote_ipaddr()); 816 fatal("Could not write ident string to %s.", get_remote_ipaddr());
817 817
818 /* Read other side\'s version identification. */ 818 /* Read other side\'s version identification. */
@@ -838,9 +838,10 @@ main(int ac, char **av)
838 * several versions and set appropriate flags to handle them. 838 * several versions and set appropriate flags to handle them.
839 */ 839 */
840 if (sscanf(buf, "SSH-%d.%d-%[^\n]\n", &remote_major, &remote_minor, 840 if (sscanf(buf, "SSH-%d.%d-%[^\n]\n", &remote_major, &remote_minor,
841 remote_version) != 3) { 841 remote_version) != 3) {
842 const char *s = "Protocol mismatch.\n"; 842 char *s = "Protocol mismatch.\n";
843 (void) write(sock_out, s, strlen(s)); 843
844 (void) atomicio(write, sock_out, s, strlen(s));
844 close(sock_in); 845 close(sock_in);
845 close(sock_out); 846 close(sock_out);
846 fatal("Bad protocol version identification '%.100s' from %s", 847 fatal("Bad protocol version identification '%.100s' from %s",
@@ -849,8 +850,9 @@ main(int ac, char **av)
849 debug("Client protocol version %d.%d; client software version %.100s", 850 debug("Client protocol version %d.%d; client software version %.100s",
850 remote_major, remote_minor, remote_version); 851 remote_major, remote_minor, remote_version);
851 if (remote_major != PROTOCOL_MAJOR) { 852 if (remote_major != PROTOCOL_MAJOR) {
852 const char *s = "Protocol major versions differ.\n"; 853 char *s = "Protocol major versions differ.\n";
853 (void) write(sock_out, s, strlen(s)); 854
855 (void) atomicio(write, sock_out, s, strlen(s));
854 close(sock_in); 856 close(sock_in);
855 close(sock_out); 857 close(sock_out);
856 fatal("Protocol major versions differ for %s: %d vs. %d", 858 fatal("Protocol major versions differ for %s: %d vs. %d",
@@ -1737,7 +1739,8 @@ do_authenticated(struct passwd * pw)
1737 debug("Allocating pty."); 1739 debug("Allocating pty.");
1738 1740
1739 /* Allocate a pty and open it. */ 1741 /* Allocate a pty and open it. */
1740 if (!pty_allocate(&ptyfd, &ttyfd, ttyname)) { 1742 if (!pty_allocate(&ptyfd, &ttyfd, ttyname,
1743 sizeof(ttyname))) {
1741 error("Failed to allocate pty."); 1744 error("Failed to allocate pty.");
1742 goto fail; 1745 goto fail;
1743 } 1746 }
diff --git a/tildexpand.c b/tildexpand.c
index 8ee551f13..f615362f9 100644
--- a/tildexpand.c
+++ b/tildexpand.c
@@ -6,7 +6,7 @@
6 */ 6 */
7 7
8#include "includes.h" 8#include "includes.h"
9RCSID("$Id: tildexpand.c,v 1.3 1999/11/25 00:54:59 damien Exp $"); 9RCSID("$Id: tildexpand.c,v 1.4 1999/12/07 04:38:32 damien Exp $");
10 10
11#include "xmalloc.h" 11#include "xmalloc.h"
12#include "ssh.h" 12#include "ssh.h"
@@ -23,6 +23,7 @@ tilde_expand_filename(const char *filename, uid_t my_uid)
23 char *expanded; 23 char *expanded;
24 struct passwd *pw; 24 struct passwd *pw;
25 char user[100]; 25 char user[100];
26 int len;
26 27
27 /* Return immediately if no tilde. */ 28 /* Return immediately if no tilde. */
28 if (filename[0] != '~') 29 if (filename[0] != '~')
@@ -56,7 +57,10 @@ tilde_expand_filename(const char *filename, uid_t my_uid)
56 return xstrdup(pw->pw_dir); 57 return xstrdup(pw->pw_dir);
57 } 58 }
58 /* Build a path combining the specified directory and path. */ 59 /* Build a path combining the specified directory and path. */
59 expanded = xmalloc(strlen(pw->pw_dir) + strlen(cp + 1) + 2); 60 len = strlen(pw->pw_dir) + strlen(cp + 1) + 2;
60 sprintf(expanded, "%s/%s", pw->pw_dir, cp + 1); 61 if (len > MAXPATHLEN)
62 fatal("Home directory too long (%d > %d", len-1, MAXPATHLEN-1);
63 expanded = xmalloc(len);
64 snprintf(expanded, len, "%s/%s", pw->pw_dir, cp + 1);
61 return expanded; 65 return expanded;
62} 66}