summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDamien Miller <djm@mindrot.org>2000-08-23 10:46:23 +1000
committerDamien Miller <djm@mindrot.org>2000-08-23 10:46:23 +1000
commitad833b3e65c1887674714d514eb818d862bb499a (patch)
tree16fa75fe42aede072c5d3edac562c2870d1bb0e5
parentb078567bf5de1dcf12d265d98acb4dc9eba8b325 (diff)
- (djm) Pick up LOGIN_PROGRAM from environment or PATH if not set by headers
- (djm) OpenBSD CVS updates: - deraadt@cvs.openbsd.org 2000/08/18 20:07:23 [ssh.c] accept remsh as a valid name as well; roman@buildpoint.com - deraadt@cvs.openbsd.org 2000/08/18 20:17:13 [deattack.c crc32.c packet.c] rename crc32() to ssh_crc32() to avoid zlib name clash. do not move to libz crc32 function yet, because it has ugly "long"'s in it; oneill@cs.sfu.ca - deraadt@cvs.openbsd.org 2000/08/18 20:26:08 [scp.1 scp.c] -S prog support; tv@debian.org - deraadt@cvs.openbsd.org 2000/08/18 20:50:07 [scp.c] knf - deraadt@cvs.openbsd.org 2000/08/18 20:57:33 [log-client.c] shorten - markus@cvs.openbsd.org 2000/08/19 12:48:11 [channels.c channels.h clientloop.c ssh.c ssh.h] support for ~. in ssh2 - deraadt@cvs.openbsd.org 2000/08/19 15:29:40 [crc32.h] proper prototype - markus@cvs.openbsd.org 2000/08/19 15:34:44 [authfd.c authfd.h key.c key.h ssh-add.1 ssh-add.c ssh-agent.1] [ssh-agent.c ssh-keygen.c sshconnect1.c sshconnect2.c Makefile] [fingerprint.c fingerprint.h] add SSH2/DSA support to the agent and some other DSA related cleanups. (note that we cannot talk to ssh.com's ssh2 agents) - markus@cvs.openbsd.org 2000/08/19 15:55:52 [channels.c channels.h clientloop.c] more ~ support for ssh2 - markus@cvs.openbsd.org 2000/08/19 16:21:19 [clientloop.c] oops - millert@cvs.openbsd.org 2000/08/20 12:25:53 [session.c] We have to stash the result of get_remote_name_or_ip() before we close our socket or getpeername() will get EBADF and the process will exit. Only a problem for "UseLogin yes". - millert@cvs.openbsd.org 2000/08/20 12:30:59 [session.c] Only check /etc/nologin if "UseLogin no" since login(1) may have its own policy on determining who is allowed to login when /etc/nologin is present. Also use the _PATH_NOLOGIN define. - millert@cvs.openbsd.org 2000/08/20 12:42:43 [auth1.c auth2.c session.c ssh.c] Add calls to setusercontext() and login_get*(). We basically call setusercontext() in most places where previously we did a setlogin(). Add default login.conf file and put root in the "daemon" login class. - millert@cvs.openbsd.org 2000/08/21 10:23:31 [session.c] Fix incorrect PATH setting; noted by Markus.
-rw-r--r--ChangeLog55
-rw-r--r--Makefile.in2
-rw-r--r--TODO2
-rw-r--r--acconfig.h7
-rw-r--r--auth1.c5
-rw-r--r--auth2.c5
-rw-r--r--authfd.c235
-rw-r--r--authfd.h53
-rw-r--r--channels.c22
-rw-r--r--channels.h14
-rw-r--r--clientloop.c340
-rw-r--r--configure.in41
-rw-r--r--crc32.c4
-rw-r--r--crc32.h4
-rw-r--r--deattack.c4
-rw-r--r--defines.h8
-rw-r--r--fingerprint.c69
-rw-r--r--fingerprint.h34
-rw-r--r--key.c14
-rw-r--r--log-client.c5
-rw-r--r--packet.c8
-rw-r--r--scp.112
-rw-r--r--scp.c137
-rw-r--r--session.c120
-rw-r--r--ssh-add.18
-rw-r--r--ssh-add.c81
-rw-r--r--ssh-agent.111
-rw-r--r--ssh-agent.c514
-rw-r--r--ssh-keygen.c19
-rw-r--r--ssh.c28
-rw-r--r--ssh.h10
-rw-r--r--sshconnect1.c40
-rw-r--r--sshconnect2.c78
33 files changed, 1178 insertions, 811 deletions
diff --git a/ChangeLog b/ChangeLog
index 4463cf2bb..9d3dd02e2 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -3,6 +3,61 @@
3 Avoids "scp never exits" problem. Reports from Lutz Jaenicke 3 Avoids "scp never exits" problem. Reports from Lutz Jaenicke
4 <Lutz.Jaenicke@aet.TU-Cottbus.DE> and Tamito KAJIYAMA 4 <Lutz.Jaenicke@aet.TU-Cottbus.DE> and Tamito KAJIYAMA
5 <kajiyama@grad.sccs.chukyo-u.ac.jp> 5 <kajiyama@grad.sccs.chukyo-u.ac.jp>
6 - (djm) Pick up LOGIN_PROGRAM from environment or PATH if not set by headers
7 - (djm) OpenBSD CVS updates:
8 - deraadt@cvs.openbsd.org 2000/08/18 20:07:23
9 [ssh.c]
10 accept remsh as a valid name as well; roman@buildpoint.com
11 - deraadt@cvs.openbsd.org 2000/08/18 20:17:13
12 [deattack.c crc32.c packet.c]
13 rename crc32() to ssh_crc32() to avoid zlib name clash. do not move to
14 libz crc32 function yet, because it has ugly "long"'s in it;
15 oneill@cs.sfu.ca
16 - deraadt@cvs.openbsd.org 2000/08/18 20:26:08
17 [scp.1 scp.c]
18 -S prog support; tv@debian.org
19 - deraadt@cvs.openbsd.org 2000/08/18 20:50:07
20 [scp.c]
21 knf
22 - deraadt@cvs.openbsd.org 2000/08/18 20:57:33
23 [log-client.c]
24 shorten
25 - markus@cvs.openbsd.org 2000/08/19 12:48:11
26 [channels.c channels.h clientloop.c ssh.c ssh.h]
27 support for ~. in ssh2
28 - deraadt@cvs.openbsd.org 2000/08/19 15:29:40
29 [crc32.h]
30 proper prototype
31 - markus@cvs.openbsd.org 2000/08/19 15:34:44
32 [authfd.c authfd.h key.c key.h ssh-add.1 ssh-add.c ssh-agent.1]
33 [ssh-agent.c ssh-keygen.c sshconnect1.c sshconnect2.c Makefile]
34 [fingerprint.c fingerprint.h]
35 add SSH2/DSA support to the agent and some other DSA related cleanups.
36 (note that we cannot talk to ssh.com's ssh2 agents)
37 - markus@cvs.openbsd.org 2000/08/19 15:55:52
38 [channels.c channels.h clientloop.c]
39 more ~ support for ssh2
40 - markus@cvs.openbsd.org 2000/08/19 16:21:19
41 [clientloop.c]
42 oops
43 - millert@cvs.openbsd.org 2000/08/20 12:25:53
44 [session.c]
45 We have to stash the result of get_remote_name_or_ip() before we
46 close our socket or getpeername() will get EBADF and the process
47 will exit. Only a problem for "UseLogin yes".
48 - millert@cvs.openbsd.org 2000/08/20 12:30:59
49 [session.c]
50 Only check /etc/nologin if "UseLogin no" since login(1) may have its
51 own policy on determining who is allowed to login when /etc/nologin
52 is present. Also use the _PATH_NOLOGIN define.
53 - millert@cvs.openbsd.org 2000/08/20 12:42:43
54 [auth1.c auth2.c session.c ssh.c]
55 Add calls to setusercontext() and login_get*(). We basically call
56 setusercontext() in most places where previously we did a setlogin().
57 Add default login.conf file and put root in the "daemon" login class.
58 - millert@cvs.openbsd.org 2000/08/21 10:23:31
59 [session.c]
60 Fix incorrect PATH setting; noted by Markus.
6 61
720000818 6220000818
8 - (djm) OpenBSD CVS changes: 63 - (djm) OpenBSD CVS changes:
diff --git a/Makefile.in b/Makefile.in
index ff34c4932..4ceef7043 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -34,7 +34,7 @@ INSTALL_SSH_PRNG_CMDS=@INSTALL_SSH_PRNG_CMDS@
34 34
35TARGETS=ssh sshd ssh-add ssh-keygen ssh-agent scp $(EXTRA_TARGETS) 35TARGETS=ssh sshd ssh-add ssh-keygen ssh-agent scp $(EXTRA_TARGETS)
36 36
37LIBSSH_OBJS=atomicio.o authfd.o authfile.o bufaux.o buffer.o canohost.o channels.o cipher.o compat.o compress.o crc32.o deattack.o dispatch.o dsa.o fingerprint.o hmac.o hostfile.o key.o kex.o log.o match.o mpaux.o nchan.o packet.o radix.o entropy.o readpass.o rsa.o tildexpand.o ttymodes.o uidswap.o util.o uuencode.o xmalloc.o 37LIBSSH_OBJS=atomicio.o authfd.o authfile.o bufaux.o buffer.o canohost.o channels.o cipher.o compat.o compress.o crc32.o deattack.o dispatch.o dsa.o hmac.o hostfile.o key.o kex.o log.o match.o mpaux.o nchan.o packet.o radix.o entropy.o readpass.o rsa.o tildexpand.o ttymodes.o uidswap.o util.o uuencode.o xmalloc.o
38 38
39LIBOPENBSD_COMPAT_OBJS=bsd-arc4random.o bsd-base64.o bsd-bindresvport.o bsd-daemon.o bsd-inet_aton.o bsd-inet_ntoa.o bsd-misc.o bsd-mktemp.o bsd-rresvport.o bsd-setenv.o bsd-sigaction.o bsd-snprintf.o bsd-strlcat.o bsd-strlcpy.o bsd-strsep.o fake-getaddrinfo.o fake-getnameinfo.o next-posix.o 39LIBOPENBSD_COMPAT_OBJS=bsd-arc4random.o bsd-base64.o bsd-bindresvport.o bsd-daemon.o bsd-inet_aton.o bsd-inet_ntoa.o bsd-misc.o bsd-mktemp.o bsd-rresvport.o bsd-setenv.o bsd-sigaction.o bsd-snprintf.o bsd-strlcat.o bsd-strlcpy.o bsd-strsep.o fake-getaddrinfo.o fake-getnameinfo.o next-posix.o
40 40
diff --git a/TODO b/TODO
index 1d46ae1c3..ecfd21e33 100644
--- a/TODO
+++ b/TODO
@@ -14,3 +14,5 @@
14 underlying shell. 14 underlying shell.
15 15
16- utmp/wtmp logging does not work on NeXT 16- utmp/wtmp logging does not work on NeXT
17
18- Complete Tru64 SIA support
diff --git a/acconfig.h b/acconfig.h
index 601dc16f7..eeee4eaf1 100644
--- a/acconfig.h
+++ b/acconfig.h
@@ -6,6 +6,13 @@
6 6
7@TOP@ 7@TOP@
8 8
9/* If your header files don't define LOGIN_PROGRAM, then use this (detected) */
10/* from environment and PATH */
11#undef LOGIN_PROGRAM_FALLBACK
12
13/* Define if your password has a pw_class field */
14#undef HAVE_PW_CLASS_IN_PASSWD
15
9/* Define if your socketpair() has bugs */ 16/* Define if your socketpair() has bugs */
10#undef USE_PIPES 17#undef USE_PIPES
11 18
diff --git a/auth1.c b/auth1.c
index d8f2652e3..b043e8a95 100644
--- a/auth1.c
+++ b/auth1.c
@@ -4,7 +4,7 @@
4 */ 4 */
5 5
6#include "includes.h" 6#include "includes.h"
7RCSID("$OpenBSD: auth1.c,v 1.2 2000/04/29 18:11:52 markus Exp $"); 7RCSID("$OpenBSD: auth1.c,v 1.3 2000/08/20 18:42:40 millert Exp $");
8 8
9#include "xmalloc.h" 9#include "xmalloc.h"
10#include "rsa.h" 10#include "rsa.h"
@@ -480,6 +480,9 @@ do_authentication()
480 pwcopy.pw_passwd = xstrdup(pw->pw_passwd); 480 pwcopy.pw_passwd = xstrdup(pw->pw_passwd);
481 pwcopy.pw_uid = pw->pw_uid; 481 pwcopy.pw_uid = pw->pw_uid;
482 pwcopy.pw_gid = pw->pw_gid; 482 pwcopy.pw_gid = pw->pw_gid;
483#ifdef HAVE_PW_CLASS_IN_PASSWD
484 pwcopy.pw_class = xstrdup(pw->pw_class);
485#endif
483 pwcopy.pw_dir = xstrdup(pw->pw_dir); 486 pwcopy.pw_dir = xstrdup(pw->pw_dir);
484 pwcopy.pw_shell = xstrdup(pw->pw_shell); 487 pwcopy.pw_shell = xstrdup(pw->pw_shell);
485 pw = &pwcopy; 488 pw = &pwcopy;
diff --git a/auth2.c b/auth2.c
index 4926ff8a0..7769046fb 100644
--- a/auth2.c
+++ b/auth2.c
@@ -27,7 +27,7 @@
27 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 */ 28 */
29#include "includes.h" 29#include "includes.h"
30RCSID("$OpenBSD: auth2.c,v 1.12 2000/07/07 03:55:03 todd Exp $"); 30RCSID("$OpenBSD: auth2.c,v 1.13 2000/08/20 18:42:40 millert Exp $");
31 31
32#include <openssl/dsa.h> 32#include <openssl/dsa.h>
33#include <openssl/rsa.h> 33#include <openssl/rsa.h>
@@ -411,6 +411,9 @@ auth_set_user(char *u, char *s)
411 copy->pw_passwd = xstrdup(pw->pw_passwd); 411 copy->pw_passwd = xstrdup(pw->pw_passwd);
412 copy->pw_uid = pw->pw_uid; 412 copy->pw_uid = pw->pw_uid;
413 copy->pw_gid = pw->pw_gid; 413 copy->pw_gid = pw->pw_gid;
414#ifdef HAVE_PW_CLASS_IN_PASSWD
415 copy->pw_class = xstrdup(pw->pw_class);
416#endif
414 copy->pw_dir = xstrdup(pw->pw_dir); 417 copy->pw_dir = xstrdup(pw->pw_dir);
415 copy->pw_shell = xstrdup(pw->pw_shell); 418 copy->pw_shell = xstrdup(pw->pw_shell);
416 authctxt->valid = 1; 419 authctxt->valid = 1;
diff --git a/authfd.c b/authfd.c
index a34e111ac..d9427d377 100644
--- a/authfd.c
+++ b/authfd.c
@@ -11,10 +11,13 @@
11 * 11 *
12 * Functions for connecting the local authentication agent. 12 * Functions for connecting the local authentication agent.
13 * 13 *
14 * SSH2 implementation,
15 * Copyright (c) 2000 Markus Friedl. All rights reserved.
16 *
14 */ 17 */
15 18
16#include "includes.h" 19#include "includes.h"
17RCSID("$OpenBSD: authfd.c,v 1.24 2000/08/15 19:20:46 markus Exp $"); 20RCSID("$OpenBSD: authfd.c,v 1.25 2000/08/19 21:34:42 markus Exp $");
18 21
19#include "ssh.h" 22#include "ssh.h"
20#include "rsa.h" 23#include "rsa.h"
@@ -29,6 +32,7 @@ RCSID("$OpenBSD: authfd.c,v 1.24 2000/08/15 19:20:46 markus Exp $");
29#include "key.h" 32#include "key.h"
30#include "authfd.h" 33#include "authfd.h"
31#include "kex.h" 34#include "kex.h"
35#include "dsa.h"
32 36
33/* helper */ 37/* helper */
34int decode_reply(int type); 38int decode_reply(int type);
@@ -71,8 +75,7 @@ ssh_get_authentication_socket()
71} 75}
72 76
73int 77int
74ssh_request_reply(AuthenticationConnection *auth, 78ssh_request_reply(AuthenticationConnection *auth, Buffer *request, Buffer *reply)
75 Buffer *request, Buffer *reply)
76{ 79{
77 int l, len; 80 int l, len;
78 char buf[1024]; 81 char buf[1024];
@@ -162,7 +165,6 @@ ssh_get_authentication_connection()
162 165
163 auth = xmalloc(sizeof(*auth)); 166 auth = xmalloc(sizeof(*auth));
164 auth->fd = sock; 167 auth->fd = sock;
165 buffer_init(&auth->packet);
166 buffer_init(&auth->identities); 168 buffer_init(&auth->identities);
167 auth->howmany = 0; 169 auth->howmany = 0;
168 170
@@ -175,46 +177,57 @@ ssh_get_authentication_connection()
175 */ 177 */
176 178
177void 179void
178ssh_close_authentication_connection(AuthenticationConnection *ac) 180ssh_close_authentication_connection(AuthenticationConnection *auth)
179{ 181{
180 buffer_free(&ac->packet); 182 buffer_free(&auth->identities);
181 buffer_free(&ac->identities); 183 close(auth->fd);
182 close(ac->fd); 184 xfree(auth);
183 xfree(ac);
184} 185}
185 186
186/* 187/*
187 * Returns the first authentication identity held by the agent. 188 * Returns the first authentication identity held by the agent.
188 * Returns true if an identity is available, 0 otherwise.
189 * The caller must initialize the integers before the call, and free the
190 * comment after a successful call (before calling ssh_get_next_identity).
191 */ 189 */
192 190
193int 191Key *
194ssh_get_first_identity(AuthenticationConnection *auth, 192ssh_get_first_identity(AuthenticationConnection *auth, char **comment, int version)
195 BIGNUM *e, BIGNUM *n, char **comment)
196{ 193{
194 int type, code1 = 0, code2 = 0;
197 Buffer request; 195 Buffer request;
198 int type; 196
197 switch(version){
198 case 1:
199 code1 = SSH_AGENTC_REQUEST_RSA_IDENTITIES;
200 code2 = SSH_AGENT_RSA_IDENTITIES_ANSWER;
201 break;
202 case 2:
203 code1 = SSH2_AGENTC_REQUEST_IDENTITIES;
204 code2 = SSH2_AGENT_IDENTITIES_ANSWER;
205 break;
206 default:
207 return NULL;
208 }
199 209
200 /* 210 /*
201 * Send a message to the agent requesting for a list of the 211 * Send a message to the agent requesting for a list of the
202 * identities it can represent. 212 * identities it can represent.
203 */ 213 */
204 buffer_init(&request); 214 buffer_init(&request);
205 buffer_put_char(&request, SSH_AGENTC_REQUEST_RSA_IDENTITIES); 215 buffer_put_char(&request, code1);
206 216
207 buffer_clear(&auth->identities); 217 buffer_clear(&auth->identities);
208 if (ssh_request_reply(auth, &request, &auth->identities) == 0) { 218 if (ssh_request_reply(auth, &request, &auth->identities) == 0) {
209 buffer_free(&request); 219 buffer_free(&request);
210 return 0; 220 return NULL;
211 } 221 }
212 buffer_free(&request); 222 buffer_free(&request);
213 223
214 /* Get message type, and verify that we got a proper answer. */ 224 /* Get message type, and verify that we got a proper answer. */
215 type = buffer_get_char(&auth->identities); 225 type = buffer_get_char(&auth->identities);
216 if (type != SSH_AGENT_RSA_IDENTITIES_ANSWER) 226 if (type == SSH_AGENT_FAILURE) {
227 return NULL;
228 } else if (type != code2) {
217 fatal("Bad authentication reply message type: %d", type); 229 fatal("Bad authentication reply message type: %d", type);
230 }
218 231
219 /* Get the number of entries in the response and check it for sanity. */ 232 /* Get the number of entries in the response and check it for sanity. */
220 auth->howmany = buffer_get_int(&auth->identities); 233 auth->howmany = buffer_get_int(&auth->identities);
@@ -223,43 +236,49 @@ ssh_get_first_identity(AuthenticationConnection *auth,
223 auth->howmany); 236 auth->howmany);
224 237
225 /* Return the first entry (if any). */ 238 /* Return the first entry (if any). */
226 return ssh_get_next_identity(auth, e, n, comment); 239 return ssh_get_next_identity(auth, comment, version);
227} 240}
228 241
229/* 242Key *
230 * Returns the next authentication identity for the agent. Other functions 243ssh_get_next_identity(AuthenticationConnection *auth, char **comment, int version)
231 * can be called between this and ssh_get_first_identity or two calls of this
232 * function. This returns 0 if there are no more identities. The caller
233 * must free comment after a successful return.
234 */
235
236int
237ssh_get_next_identity(AuthenticationConnection *auth,
238 BIGNUM *e, BIGNUM *n, char **comment)
239{ 244{
240 unsigned int bits; 245 unsigned int bits;
246 unsigned char *blob;
247 unsigned int blen;
248 Key *key = NULL;
241 249
242 /* Return failure if no more entries. */ 250 /* Return failure if no more entries. */
243 if (auth->howmany <= 0) 251 if (auth->howmany <= 0)
244 return 0; 252 return NULL;
245 253
246 /* 254 /*
247 * Get the next entry from the packet. These will abort with a fatal 255 * Get the next entry from the packet. These will abort with a fatal
248 * error if the packet is too short or contains corrupt data. 256 * error if the packet is too short or contains corrupt data.
249 */ 257 */
250 bits = buffer_get_int(&auth->identities); 258 switch(version){
251 buffer_get_bignum(&auth->identities, e); 259 case 1:
252 buffer_get_bignum(&auth->identities, n); 260 key = key_new(KEY_RSA);
253 *comment = buffer_get_string(&auth->identities, NULL); 261 bits = buffer_get_int(&auth->identities);
254 262 buffer_get_bignum(&auth->identities, key->rsa->e);
255 if (bits != BN_num_bits(n)) 263 buffer_get_bignum(&auth->identities, key->rsa->n);
256 log("Warning: identity keysize mismatch: actual %d, announced %u", 264 *comment = buffer_get_string(&auth->identities, NULL);
257 BN_num_bits(n), bits); 265 if (bits != BN_num_bits(key->rsa->n))
258 266 log("Warning: identity keysize mismatch: actual %d, announced %u",
267 BN_num_bits(key->rsa->n), bits);
268 break;
269 case 2:
270 blob = buffer_get_string(&auth->identities, &blen);
271 *comment = buffer_get_string(&auth->identities, NULL);
272 key = dsa_key_from_blob(blob, blen);
273 xfree(blob);
274 break;
275 default:
276 return NULL;
277 break;
278 }
259 /* Decrement the number of remaining entries. */ 279 /* Decrement the number of remaining entries. */
260 auth->howmany--; 280 auth->howmany--;
261 281 return key;
262 return 1;
263} 282}
264 283
265/* 284/*
@@ -272,7 +291,7 @@ ssh_get_next_identity(AuthenticationConnection *auth,
272 291
273int 292int
274ssh_decrypt_challenge(AuthenticationConnection *auth, 293ssh_decrypt_challenge(AuthenticationConnection *auth,
275 BIGNUM* e, BIGNUM *n, BIGNUM *challenge, 294 Key* key, BIGNUM *challenge,
276 unsigned char session_id[16], 295 unsigned char session_id[16],
277 unsigned int response_type, 296 unsigned int response_type,
278 unsigned char response[16]) 297 unsigned char response[16])
@@ -282,15 +301,17 @@ ssh_decrypt_challenge(AuthenticationConnection *auth,
282 int i; 301 int i;
283 int type; 302 int type;
284 303
285 if (response_type == 0) 304 if (key->type != KEY_RSA)
286 fatal("Compatibility with ssh protocol version " 305 return 0;
287 "1.0 no longer supported."); 306 if (response_type == 0) {
288 307 log("Compatibility with ssh protocol version 1.0 no longer supported.");
308 return 0;
309 }
289 buffer_init(&buffer); 310 buffer_init(&buffer);
290 buffer_put_char(&buffer, SSH_AGENTC_RSA_CHALLENGE); 311 buffer_put_char(&buffer, SSH_AGENTC_RSA_CHALLENGE);
291 buffer_put_int(&buffer, BN_num_bits(n)); 312 buffer_put_int(&buffer, BN_num_bits(key->rsa->n));
292 buffer_put_bignum(&buffer, e); 313 buffer_put_bignum(&buffer, key->rsa->e);
293 buffer_put_bignum(&buffer, n); 314 buffer_put_bignum(&buffer, key->rsa->n);
294 buffer_put_bignum(&buffer, challenge); 315 buffer_put_bignum(&buffer, challenge);
295 buffer_append(&buffer, (char *) session_id, 16); 316 buffer_append(&buffer, (char *) session_id, 16);
296 buffer_put_int(&buffer, response_type); 317 buffer_put_int(&buffer, response_type);
@@ -318,6 +339,45 @@ ssh_decrypt_challenge(AuthenticationConnection *auth,
318 return success; 339 return success;
319} 340}
320 341
342/* ask agent to sign data, returns -1 on error, 0 on success */
343int
344ssh_agent_sign(AuthenticationConnection *auth,
345 Key *key,
346 unsigned char **sigp, int *lenp,
347 unsigned char *data, int datalen)
348{
349 Buffer msg;
350 unsigned char *blob;
351 unsigned int blen;
352 int type;
353 int ret = -1;
354
355 if (dsa_make_key_blob(key, &blob, &blen) == 0)
356 return -1;
357
358 buffer_init(&msg);
359 buffer_put_char(&msg, SSH2_AGENTC_SIGN_REQUEST);
360 buffer_put_string(&msg, blob, blen);
361 buffer_put_string(&msg, data, datalen);
362 xfree(blob);
363
364 if (ssh_request_reply(auth, &msg, &msg) == 0) {
365 buffer_free(&msg);
366 return -1;
367 }
368 type = buffer_get_char(&msg);
369 if (type == SSH_AGENT_FAILURE) {
370 log("Agent admitted failure to sign using the key.");
371 } else if (type != SSH2_AGENT_SIGN_RESPONSE) {
372 fatal("Bad authentication response: %d", type);
373 } else {
374 ret = 0;
375 *sigp = buffer_get_string(&msg, lenp);
376 }
377 buffer_free(&msg);
378 return ret;
379}
380
321/* Encode key for a message to the agent. */ 381/* Encode key for a message to the agent. */
322 382
323void 383void
@@ -358,29 +418,29 @@ ssh_encode_identity_dsa(Buffer *b, DSA *key, const char *comment)
358int 418int
359ssh_add_identity(AuthenticationConnection *auth, Key *key, const char *comment) 419ssh_add_identity(AuthenticationConnection *auth, Key *key, const char *comment)
360{ 420{
361 Buffer buffer; 421 Buffer msg;
362 int type; 422 int type;
363 423
364 buffer_init(&buffer); 424 buffer_init(&msg);
365 425
366 switch (key->type) { 426 switch (key->type) {
367 case KEY_RSA: 427 case KEY_RSA:
368 ssh_encode_identity_rsa(&buffer, key->rsa, comment); 428 ssh_encode_identity_rsa(&msg, key->rsa, comment);
369 break; 429 break;
370 case KEY_DSA: 430 case KEY_DSA:
371 ssh_encode_identity_dsa(&buffer, key->dsa, comment); 431 ssh_encode_identity_dsa(&msg, key->dsa, comment);
372 break; 432 break;
373 default: 433 default:
374 buffer_free(&buffer); 434 buffer_free(&msg);
375 return 0; 435 return 0;
376 break; 436 break;
377 } 437 }
378 if (ssh_request_reply(auth, &buffer, &buffer) == 0) { 438 if (ssh_request_reply(auth, &msg, &msg) == 0) {
379 buffer_free(&buffer); 439 buffer_free(&msg);
380 return 0; 440 return 0;
381 } 441 }
382 type = buffer_get_char(&buffer); 442 type = buffer_get_char(&msg);
383 buffer_free(&buffer); 443 buffer_free(&msg);
384 return decode_reply(type); 444 return decode_reply(type);
385} 445}
386 446
@@ -390,23 +450,35 @@ ssh_add_identity(AuthenticationConnection *auth, Key *key, const char *comment)
390 */ 450 */
391 451
392int 452int
393ssh_remove_identity(AuthenticationConnection *auth, RSA *key) 453ssh_remove_identity(AuthenticationConnection *auth, Key *key)
394{ 454{
395 Buffer buffer; 455 Buffer msg;
396 int type; 456 int type;
397 457 unsigned char *blob;
398 buffer_init(&buffer); 458 unsigned int blen;
399 buffer_put_char(&buffer, SSH_AGENTC_REMOVE_RSA_IDENTITY); 459
400 buffer_put_int(&buffer, BN_num_bits(key->n)); 460 buffer_init(&msg);
401 buffer_put_bignum(&buffer, key->e); 461
402 buffer_put_bignum(&buffer, key->n); 462 if (key->type == KEY_RSA) {
403 463 buffer_put_char(&msg, SSH_AGENTC_REMOVE_RSA_IDENTITY);
404 if (ssh_request_reply(auth, &buffer, &buffer) == 0) { 464 buffer_put_int(&msg, BN_num_bits(key->rsa->n));
405 buffer_free(&buffer); 465 buffer_put_bignum(&msg, key->rsa->e);
466 buffer_put_bignum(&msg, key->rsa->n);
467 } else if (key->type == KEY_DSA) {
468 dsa_make_key_blob(key, &blob, &blen);
469 buffer_put_char(&msg, SSH2_AGENTC_REMOVE_IDENTITY);
470 buffer_put_string(&msg, blob, blen);
471 xfree(blob);
472 } else {
473 buffer_free(&msg);
406 return 0; 474 return 0;
407 } 475 }
408 type = buffer_get_char(&buffer); 476 if (ssh_request_reply(auth, &msg, &msg) == 0) {
409 buffer_free(&buffer); 477 buffer_free(&msg);
478 return 0;
479 }
480 type = buffer_get_char(&msg);
481 buffer_free(&msg);
410 return decode_reply(type); 482 return decode_reply(type);
411} 483}
412 484
@@ -416,20 +488,23 @@ ssh_remove_identity(AuthenticationConnection *auth, RSA *key)
416 */ 488 */
417 489
418int 490int
419ssh_remove_all_identities(AuthenticationConnection *auth) 491ssh_remove_all_identities(AuthenticationConnection *auth, int version)
420{ 492{
421 Buffer buffer; 493 Buffer msg;
422 int type; 494 int type;
495 int code = (version==1) ?
496 SSH_AGENTC_REMOVE_ALL_RSA_IDENTITIES :
497 SSH2_AGENTC_REMOVE_ALL_IDENTITIES;
423 498
424 buffer_init(&buffer); 499 buffer_init(&msg);
425 buffer_put_char(&buffer, SSH_AGENTC_REMOVE_ALL_RSA_IDENTITIES); 500 buffer_put_char(&msg, code);
426 501
427 if (ssh_request_reply(auth, &buffer, &buffer) == 0) { 502 if (ssh_request_reply(auth, &msg, &msg) == 0) {
428 buffer_free(&buffer); 503 buffer_free(&msg);
429 return 0; 504 return 0;
430 } 505 }
431 type = buffer_get_char(&buffer); 506 type = buffer_get_char(&msg);
432 buffer_free(&buffer); 507 buffer_free(&msg);
433 return decode_reply(type); 508 return decode_reply(type);
434} 509}
435 510
diff --git a/authfd.h b/authfd.h
index 14b9bee94..5819b9139 100644
--- a/authfd.h
+++ b/authfd.h
@@ -13,7 +13,7 @@
13 * 13 *
14 */ 14 */
15 15
16/* RCSID("$OpenBSD: authfd.h,v 1.9 2000/07/16 08:27:21 markus Exp $"); */ 16/* RCSID("$OpenBSD: authfd.h,v 1.10 2000/08/19 21:34:43 markus Exp $"); */
17 17
18#ifndef AUTHFD_H 18#ifndef AUTHFD_H
19#define AUTHFD_H 19#define AUTHFD_H
@@ -35,18 +35,16 @@
35#define SSH2_AGENT_IDENTITIES_ANSWER 12 35#define SSH2_AGENT_IDENTITIES_ANSWER 12
36#define SSH2_AGENTC_SIGN_REQUEST 13 36#define SSH2_AGENTC_SIGN_REQUEST 13
37#define SSH2_AGENT_SIGN_RESPONSE 14 37#define SSH2_AGENT_SIGN_RESPONSE 14
38#define SSH2_AGENT_FAILURE SSH_AGENT_FAILURE
39#define SSH2_AGENT_SUCCESS SSH_AGENT_SUCCESS
40#define SSH2_AGENTC_ADD_IDENTITY 17 38#define SSH2_AGENTC_ADD_IDENTITY 17
41#define SSH2_AGENTC_REMOVE_IDENTITY 18 39#define SSH2_AGENTC_REMOVE_IDENTITY 18
42#define SSH2_AGENTC_REMOVE_ALL_IDENTITIES 19 40#define SSH2_AGENTC_REMOVE_ALL_IDENTITIES 19
43 41
44typedef struct { 42typedef struct {
45 int fd; 43 int fd;
46 Buffer packet;
47 Buffer identities; 44 Buffer identities;
48 int howmany; 45 int howmany;
49} AuthenticationConnection; 46} AuthenticationConnection;
47
50/* Returns the number of the authentication fd, or -1 if there is none. */ 48/* Returns the number of the authentication fd, or -1 if there is none. */
51int ssh_get_authentication_socket(); 49int ssh_get_authentication_socket();
52 50
@@ -69,44 +67,48 @@ AuthenticationConnection *ssh_get_authentication_connection();
69 * Closes the connection to the authentication agent and frees any associated 67 * Closes the connection to the authentication agent and frees any associated
70 * memory. 68 * memory.
71 */ 69 */
72void ssh_close_authentication_connection(AuthenticationConnection * ac); 70void ssh_close_authentication_connection(AuthenticationConnection *auth);
73 71
74/* 72/*
75 * Returns the first authentication identity held by the agent. Returns true 73 * Returns the first authentication identity held by the agent or NULL if
76 * if an identity is available, 0 otherwise. The caller must initialize the 74 * no identies are available. Caller must free comment and key.
77 * integers before the call, and free the comment after a successful call 75 * Note that you cannot mix calls with different versions.
78 * (before calling ssh_get_next_identity).
79 */ 76 */
80int 77Key *ssh_get_first_identity(AuthenticationConnection *auth, char **comment, int version);
81ssh_get_first_identity(AuthenticationConnection * connection,
82 BIGNUM * e, BIGNUM * n, char **comment);
83 78
84/* 79/*
85 * Returns the next authentication identity for the agent. Other functions 80 * Returns the next authentication identity for the agent. Other functions
86 * can be called between this and ssh_get_first_identity or two calls of this 81 * can be called between this and ssh_get_first_identity or two calls of this
87 * function. This returns 0 if there are no more identities. The caller 82 * function. This returns NULL if there are no more identities. The caller
88 * must free comment after a successful return. 83 * must free key and comment after a successful return.
89 */ 84 */
90int 85Key *ssh_get_next_identity(AuthenticationConnection *auth, char **comment, int version);
91ssh_get_next_identity(AuthenticationConnection * connection,
92 BIGNUM * e, BIGNUM * n, char **comment);
93 86
94/* Requests the agent to decrypt the given challenge. Returns true if 87/*
95 the agent claims it was able to decrypt it. */ 88 * Requests the agent to decrypt the given challenge. Returns true if the
89 * agent claims it was able to decrypt it.
90 */
96int 91int
97ssh_decrypt_challenge(AuthenticationConnection * auth, 92ssh_decrypt_challenge(AuthenticationConnection *auth,
98 BIGNUM * e, BIGNUM * n, BIGNUM * challenge, 93 Key *key, BIGNUM * challenge,
99 unsigned char session_id[16], 94 unsigned char session_id[16],
100 unsigned int response_type, 95 unsigned int response_type,
101 unsigned char response[16]); 96 unsigned char response[16]);
102 97
98/* Requests the agent to sign data using key */
99int
100ssh_agent_sign(AuthenticationConnection *auth,
101 Key *key,
102 unsigned char **sigp, int *lenp,
103 unsigned char *data, int datalen);
104
103/* 105/*
104 * Adds an identity to the authentication server. This call is not meant to 106 * Adds an identity to the authentication server. This call is not meant to
105 * be used by normal applications. This returns true if the identity was 107 * be used by normal applications. This returns true if the identity was
106 * successfully added. 108 * successfully added.
107 */ 109 */
108int 110int
109ssh_add_identity(AuthenticationConnection * connection, Key *key, 111ssh_add_identity(AuthenticationConnection *auth, Key *key,
110 const char *comment); 112 const char *comment);
111 113
112/* 114/*
@@ -114,16 +116,13 @@ ssh_add_identity(AuthenticationConnection * connection, Key *key,
114 * meant to be used by normal applications. This returns true if the 116 * meant to be used by normal applications. This returns true if the
115 * identity was successfully added. 117 * identity was successfully added.
116 */ 118 */
117int ssh_remove_identity(AuthenticationConnection * connection, RSA * key); 119int ssh_remove_identity(AuthenticationConnection *auth, Key *key);
118 120
119/* 121/*
120 * Removes all identities from the authentication agent. This call is not 122 * Removes all identities from the authentication agent. This call is not
121 * meant to be used by normal applications. This returns true if the 123 * meant to be used by normal applications. This returns true if the
122 * operation was successful. 124 * operation was successful.
123 */ 125 */
124int ssh_remove_all_identities(AuthenticationConnection * connection); 126int ssh_remove_all_identities(AuthenticationConnection *auth, int version);
125
126/* Closes the connection to the authentication agent. */
127void ssh_close_authentication(AuthenticationConnection * connection);
128 127
129#endif /* AUTHFD_H */ 128#endif /* AUTHFD_H */
diff --git a/channels.c b/channels.c
index ea395293a..c77f6b96a 100644
--- a/channels.c
+++ b/channels.c
@@ -17,7 +17,7 @@
17 */ 17 */
18 18
19#include "includes.h" 19#include "includes.h"
20RCSID("$OpenBSD: channels.c,v 1.64 2000/07/16 08:27:21 markus Exp $"); 20RCSID("$OpenBSD: channels.c,v 1.66 2000/08/19 21:55:51 markus Exp $");
21 21
22#include "ssh.h" 22#include "ssh.h"
23#include "packet.h" 23#include "packet.h"
@@ -244,6 +244,7 @@ channel_new(char *ctype, int type, int rfd, int wfd, int efd,
244 c->cb_arg = NULL; 244 c->cb_arg = NULL;
245 c->cb_event = 0; 245 c->cb_event = 0;
246 c->dettach_user = NULL; 246 c->dettach_user = NULL;
247 c->input_filter = NULL;
247 debug("channel %d: new [%s]", found, remote_name); 248 debug("channel %d: new [%s]", found, remote_name);
248 return found; 249 return found;
249} 250}
@@ -665,7 +666,14 @@ channel_handle_rfd(Channel *c, fd_set * readset, fd_set * writeset)
665 } 666 }
666 return -1; 667 return -1;
667 } 668 }
668 buffer_append(&c->input, buf, len); 669 if(c->input_filter != NULL) {
670 if (c->input_filter(c, buf, len) == -1) {
671 debug("filter stops channel %d", c->self);
672 chan_read_failed(c);
673 }
674 } else {
675 buffer_append(&c->input, buf, len);
676 }
669 } 677 }
670 return 1; 678 return 1;
671} 679}
@@ -2309,6 +2317,16 @@ channel_cancel_cleanup(int id)
2309 } 2317 }
2310 c->dettach_user = NULL; 2318 c->dettach_user = NULL;
2311} 2319}
2320void
2321channel_register_filter(int id, channel_filter_fn *fn)
2322{
2323 Channel *c = channel_lookup(id);
2324 if (c == NULL) {
2325 log("channel_register_filter: %d: bad id", id);
2326 return;
2327 }
2328 c->input_filter = fn;
2329}
2312 2330
2313void 2331void
2314channel_set_fds(int id, int rfd, int wfd, int efd, int extusage) 2332channel_set_fds(int id, int rfd, int wfd, int efd, int extusage)
diff --git a/channels.h b/channels.h
index 9629124b9..9acdf5810 100644
--- a/channels.h
+++ b/channels.h
@@ -1,4 +1,4 @@
1/* RCSID("$OpenBSD: channels.h,v 1.14 2000/06/20 01:39:40 markus Exp $"); */ 1/* RCSID("$OpenBSD: channels.h,v 1.16 2000/08/19 21:55:51 markus Exp $"); */
2 2
3#ifndef CHANNELS_H 3#ifndef CHANNELS_H
4#define CHANNELS_H 4#define CHANNELS_H
@@ -21,9 +21,13 @@
21 * Data structure for channel data. This is iniailized in channel_allocate 21 * Data structure for channel data. This is iniailized in channel_allocate
22 * and cleared in channel_free. 22 * and cleared in channel_free.
23 */ 23 */
24struct Channel;
25typedef struct Channel Channel;
26
24typedef void channel_callback_fn(int id, void *arg); 27typedef void channel_callback_fn(int id, void *arg);
28typedef int channel_filter_fn(struct Channel *c, char *buf, int len);
25 29
26typedef struct Channel { 30struct Channel {
27 int type; /* channel type/state */ 31 int type; /* channel type/state */
28 int self; /* my own channel identifier */ 32 int self; /* my own channel identifier */
29 int remote_id; /* channel identifier for remote peer */ 33 int remote_id; /* channel identifier for remote peer */
@@ -61,7 +65,10 @@ typedef struct Channel {
61 void *cb_arg; 65 void *cb_arg;
62 int cb_event; 66 int cb_event;
63 channel_callback_fn *dettach_user; 67 channel_callback_fn *dettach_user;
64} Channel; 68
69 /* filter */
70 channel_filter_fn *input_filter;
71};
65 72
66#define CHAN_EXTENDED_IGNORE 0 73#define CHAN_EXTENDED_IGNORE 0
67#define CHAN_EXTENDED_READ 1 74#define CHAN_EXTENDED_READ 1
@@ -73,6 +80,7 @@ void channel_request(int id, char *service, int wantconfirm);
73void channel_request_start(int id, char *service, int wantconfirm); 80void channel_request_start(int id, char *service, int wantconfirm);
74void channel_register_callback(int id, int mtype, channel_callback_fn *fn, void *arg); 81void channel_register_callback(int id, int mtype, channel_callback_fn *fn, void *arg);
75void channel_register_cleanup(int id, channel_callback_fn *fn); 82void channel_register_cleanup(int id, channel_callback_fn *fn);
83void channel_register_filter(int id, channel_filter_fn *fn);
76void channel_cancel_cleanup(int id); 84void channel_cancel_cleanup(int id);
77Channel *channel_lookup(int id); 85Channel *channel_lookup(int id);
78 86
diff --git a/clientloop.c b/clientloop.c
index 67fa36d91..d339e1274 100644
--- a/clientloop.c
+++ b/clientloop.c
@@ -16,7 +16,7 @@
16 */ 16 */
17 17
18#include "includes.h" 18#include "includes.h"
19RCSID("$OpenBSD: clientloop.c,v 1.29 2000/07/16 08:27:21 markus Exp $"); 19RCSID("$OpenBSD: clientloop.c,v 1.32 2000/08/19 22:21:19 markus Exp $");
20 20
21#include "xmalloc.h" 21#include "xmalloc.h"
22#include "ssh.h" 22#include "ssh.h"
@@ -29,6 +29,9 @@ RCSID("$OpenBSD: clientloop.c,v 1.29 2000/07/16 08:27:21 markus Exp $");
29#include "channels.h" 29#include "channels.h"
30#include "dispatch.h" 30#include "dispatch.h"
31 31
32#include "buffer.h"
33#include "bufaux.h"
34
32/* Flag indicating that stdin should be redirected from /dev/null. */ 35/* Flag indicating that stdin should be redirected from /dev/null. */
33extern int stdin_null_flag; 36extern int stdin_null_flag;
34 37
@@ -60,6 +63,8 @@ static int in_raw_mode = 0;
60static int in_non_blocking_mode = 0; 63static int in_non_blocking_mode = 0;
61 64
62/* Common data for the client loop code. */ 65/* Common data for the client loop code. */
66static int quit_pending; /* Set to non-zero to quit the client loop. */
67static int escape_char; /* Escape character. */
63static int escape_pending; /* Last character was the escape character */ 68static int escape_pending; /* Last character was the escape character */
64static int last_was_cr; /* Last character was a newline. */ 69static int last_was_cr; /* Last character was a newline. */
65static int exit_status; /* Used to store the exit status of the command. */ 70static int exit_status; /* Used to store the exit status of the command. */
@@ -67,13 +72,11 @@ static int stdin_eof; /* EOF has been encountered on standard error. */
67static Buffer stdin_buffer; /* Buffer for stdin data. */ 72static Buffer stdin_buffer; /* Buffer for stdin data. */
68static Buffer stdout_buffer; /* Buffer for stdout data. */ 73static Buffer stdout_buffer; /* Buffer for stdout data. */
69static Buffer stderr_buffer; /* Buffer for stderr data. */ 74static Buffer stderr_buffer; /* Buffer for stderr data. */
75static unsigned long stdin_bytes, stdout_bytes, stderr_bytes;
70static unsigned int buffer_high;/* Soft max buffer size. */ 76static unsigned int buffer_high;/* Soft max buffer size. */
71static int max_fd; /* Maximum file descriptor number in select(). */ 77static int max_fd; /* Maximum file descriptor number in select(). */
72static int connection_in; /* Connection to server (input). */ 78static int connection_in; /* Connection to server (input). */
73static int connection_out; /* Connection to server (output). */ 79static int connection_out; /* Connection to server (output). */
74static unsigned long stdin_bytes, stdout_bytes, stderr_bytes;
75static int quit_pending; /* Set to non-zero to quit the client loop. */
76static int escape_char; /* Escape character. */
77 80
78 81
79void client_init_dispatch(void); 82void client_init_dispatch(void);
@@ -379,17 +382,15 @@ client_wait_until_can_do_something(fd_set * readset, fd_set * writeset)
379} 382}
380 383
381void 384void
382client_suspend_self() 385client_suspend_self(Buffer *bin, Buffer *bout, Buffer *berr)
383{ 386{
384 struct winsize oldws, newws; 387 struct winsize oldws, newws;
385 388
386 /* Flush stdout and stderr buffers. */ 389 /* Flush stdout and stderr buffers. */
387 if (buffer_len(&stdout_buffer) > 0) 390 if (buffer_len(bout) > 0)
388 atomicio(write, fileno(stdout), buffer_ptr(&stdout_buffer), 391 atomicio(write, fileno(stdout), buffer_ptr(bout), buffer_len(bout));
389 buffer_len(&stdout_buffer)); 392 if (buffer_len(berr) > 0)
390 if (buffer_len(&stderr_buffer) > 0) 393 atomicio(write, fileno(stderr), buffer_ptr(berr), buffer_len(berr));
391 atomicio(write, fileno(stderr), buffer_ptr(&stderr_buffer),
392 buffer_len(&stderr_buffer));
393 394
394 leave_raw_mode(); 395 leave_raw_mode();
395 396
@@ -397,9 +398,9 @@ client_suspend_self()
397 * Free (and clear) the buffer to reduce the amount of data that gets 398 * Free (and clear) the buffer to reduce the amount of data that gets
398 * written to swap. 399 * written to swap.
399 */ 400 */
400 buffer_free(&stdin_buffer); 401 buffer_free(bin);
401 buffer_free(&stdout_buffer); 402 buffer_free(bout);
402 buffer_free(&stderr_buffer); 403 buffer_free(berr);
403 404
404 /* Save old window size. */ 405 /* Save old window size. */
405 ioctl(fileno(stdin), TIOCGWINSZ, &oldws); 406 ioctl(fileno(stdin), TIOCGWINSZ, &oldws);
@@ -416,9 +417,9 @@ client_suspend_self()
416 received_window_change_signal = 1; 417 received_window_change_signal = 1;
417 418
418 /* OK, we have been continued by the user. Reinitialize buffers. */ 419 /* OK, we have been continued by the user. Reinitialize buffers. */
419 buffer_init(&stdin_buffer); 420 buffer_init(bin);
420 buffer_init(&stdout_buffer); 421 buffer_init(bout);
421 buffer_init(&stderr_buffer); 422 buffer_init(berr);
422 423
423 enter_raw_mode(); 424 enter_raw_mode();
424} 425}
@@ -466,12 +467,155 @@ client_process_net_input(fd_set * readset)
466 } 467 }
467} 468}
468 469
470/* process the characters one by one */
471int
472process_escapes(Buffer *bin, Buffer *bout, Buffer *berr, char *buf, int len)
473{
474 char string[1024];
475 pid_t pid;
476 int bytes = 0;
477 unsigned int i;
478 unsigned char ch;
479 char *s;
480
481 for (i = 0; i < len; i++) {
482 /* Get one character at a time. */
483 ch = buf[i];
484
485 if (escape_pending) {
486 /* We have previously seen an escape character. */
487 /* Clear the flag now. */
488 escape_pending = 0;
489
490 /* Process the escaped character. */
491 switch (ch) {
492 case '.':
493 /* Terminate the connection. */
494 snprintf(string, sizeof string, "%c.\r\n", escape_char);
495 buffer_append(berr, string, strlen(string));
496 /*stderr_bytes += strlen(string); XXX*/
497
498 quit_pending = 1;
499 return -1;
500
501 case 'Z' - 64:
502 /* Suspend the program. */
503 /* Print a message to that effect to the user. */
504 snprintf(string, sizeof string, "%c^Z [suspend ssh]\r\n", escape_char);
505 buffer_append(berr, string, strlen(string));
506 /*stderr_bytes += strlen(string); XXX*/
507
508 /* Restore terminal modes and suspend. */
509 client_suspend_self(bin, bout, berr);
510
511 /* We have been continued. */
512 continue;
513
514 case '&':
515 /* XXX does not work yet with proto 2 */
516 if (compat20)
517 continue;
518 /*
519 * Detach the program (continue to serve connections,
520 * but put in background and no more new connections).
521 */
522 if (!stdin_eof) {
523 /*
524 * Sending SSH_CMSG_EOF alone does not always appear
525 * to be enough. So we try to send an EOF character
526 * first.
527 */
528 packet_start(SSH_CMSG_STDIN_DATA);
529 packet_put_string("\004", 1);
530 packet_send();
531 /* Close stdin. */
532 stdin_eof = 1;
533 if (buffer_len(bin) == 0) {
534 packet_start(SSH_CMSG_EOF);
535 packet_send();
536 }
537 }
538 /* Restore tty modes. */
539 leave_raw_mode();
540
541 /* Stop listening for new connections. */
542 channel_stop_listening();
543
544 printf("%c& [backgrounded]\n", escape_char);
545
546 /* Fork into background. */
547 pid = fork();
548 if (pid < 0) {
549 error("fork: %.100s", strerror(errno));
550 continue;
551 }
552 if (pid != 0) { /* This is the parent. */
553 /* The parent just exits. */
554 exit(0);
555 }
556 /* The child continues serving connections. */
557 continue; /*XXX ? */
558
559 case '?':
560 snprintf(string, sizeof string,
561"%c?\r\n\
562Supported escape sequences:\r\n\
563~. - terminate connection\r\n\
564~^Z - suspend ssh\r\n\
565~# - list forwarded connections\r\n\
566~& - background ssh (when waiting for connections to terminate)\r\n\
567~? - this message\r\n\
568~~ - send the escape character by typing it twice\r\n\
569(Note that escapes are only recognized immediately after newline.)\r\n",
570 escape_char);
571 buffer_append(berr, string, strlen(string));
572 continue;
573
574 case '#':
575 snprintf(string, sizeof string, "%c#\r\n", escape_char);
576 buffer_append(berr, string, strlen(string));
577 s = channel_open_message();
578 buffer_append(berr, s, strlen(s));
579 xfree(s);
580 continue;
581
582 default:
583 if (ch != escape_char) {
584 buffer_put_char(bin, escape_char);
585 bytes++;
586 }
587 /* Escaped characters fall through here */
588 break;
589 }
590 } else {
591 /*
592 * The previous character was not an escape char. Check if this
593 * is an escape.
594 */
595 if (last_was_cr && ch == escape_char) {
596 /* It is. Set the flag and continue to next character. */
597 escape_pending = 1;
598 continue;
599 }
600 }
601
602 /*
603 * Normal character. Record whether it was a newline,
604 * and append it to the buffer.
605 */
606 last_was_cr = (ch == '\r' || ch == '\n');
607 buffer_put_char(bin, ch);
608 bytes++;
609 }
610 return bytes;
611}
612
469void 613void
470client_process_input(fd_set * readset) 614client_process_input(fd_set * readset)
471{ 615{
616 int ret;
472 int len; 617 int len;
473 pid_t pid; 618 char buf[8192];
474 char buf[8192], *s;
475 619
476 /* Read input from stdin. */ 620 /* Read input from stdin. */
477 if (FD_ISSET(fileno(stdin), readset)) { 621 if (FD_ISSET(fileno(stdin), readset)) {
@@ -513,145 +657,10 @@ client_process_input(fd_set * readset)
513 * Normal, successful read. But we have an escape character 657 * Normal, successful read. But we have an escape character
514 * and have to process the characters one by one. 658 * and have to process the characters one by one.
515 */ 659 */
516 unsigned int i; 660 ret = process_escapes(&stdin_buffer, &stdout_buffer, &stderr_buffer, buf, len);
517 for (i = 0; i < len; i++) { 661 if (ret == -1)
518 unsigned char ch; 662 return;
519 /* Get one character at a time. */ 663 stdout_bytes += ret;
520 ch = buf[i];
521
522 if (escape_pending) {
523 /* We have previously seen an escape character. */
524 /* Clear the flag now. */
525 escape_pending = 0;
526 /* Process the escaped character. */
527 switch (ch) {
528 case '.':
529 /* Terminate the connection. */
530 snprintf(buf, sizeof buf, "%c.\r\n", escape_char);
531 buffer_append(&stderr_buffer, buf, strlen(buf));
532 stderr_bytes += strlen(buf);
533 quit_pending = 1;
534 return;
535
536 case 'Z' - 64:
537 /* Suspend the program. */
538 /* Print a message to that effect to the user. */
539 snprintf(buf, sizeof buf, "%c^Z\r\n", escape_char);
540 buffer_append(&stderr_buffer, buf, strlen(buf));
541 stderr_bytes += strlen(buf);
542
543 /* Restore terminal modes and suspend. */
544 client_suspend_self();
545
546 /* We have been continued. */
547 continue;
548
549 case '&':
550 /*
551 * Detach the program (continue to serve connections,
552 * but put in background and no more new connections).
553 */
554 if (!stdin_eof) {
555 /*
556 * Sending SSH_CMSG_EOF alone does not always appear
557 * to be enough. So we try to send an EOF character
558 * first.
559 */
560 packet_start(SSH_CMSG_STDIN_DATA);
561 packet_put_string("\004", 1);
562 packet_send();
563 /* Close stdin. */
564 stdin_eof = 1;
565 if (buffer_len(&stdin_buffer) == 0) {
566 packet_start(SSH_CMSG_EOF);
567 packet_send();
568 }
569 }
570 /* Restore tty modes. */
571 leave_raw_mode();
572
573 /* Stop listening for new connections. */
574 channel_stop_listening();
575
576 printf("%c& [backgrounded]\n", escape_char);
577
578 /* Fork into background. */
579 pid = fork();
580 if (pid < 0) {
581 error("fork: %.100s", strerror(errno));
582 continue;
583 }
584 if (pid != 0) { /* This is the parent. */
585 /* The parent just exits. */
586 exit(0);
587 }
588 /* The child continues serving connections. */
589 continue;
590
591 case '?':
592 snprintf(buf, sizeof buf,
593"%c?\r\n\
594Supported escape sequences:\r\n\
595~. - terminate connection\r\n\
596~^Z - suspend ssh\r\n\
597~# - list forwarded connections\r\n\
598~& - background ssh (when waiting for connections to terminate)\r\n\
599~? - this message\r\n\
600~~ - send the escape character by typing it twice\r\n\
601(Note that escapes are only recognized immediately after newline.)\r\n",
602 escape_char);
603 buffer_append(&stderr_buffer, buf, strlen(buf));
604 continue;
605
606 case '#':
607 snprintf(buf, sizeof buf, "%c#\r\n", escape_char);
608 buffer_append(&stderr_buffer, buf, strlen(buf));
609 s = channel_open_message();
610 buffer_append(&stderr_buffer, s, strlen(s));
611 xfree(s);
612 continue;
613
614 default:
615 if (ch != escape_char) {
616 /*
617 * Escape character followed by non-special character.
618 * Append both to the input buffer.
619 */
620 buf[0] = escape_char;
621 buf[1] = ch;
622 buffer_append(&stdin_buffer, buf, 2);
623 stdin_bytes += 2;
624 continue;
625 }
626 /*
627 * Note that escape character typed twice
628 * falls through here; the latter gets processed
629 * as a normal character below.
630 */
631 break;
632 }
633 } else {
634 /*
635 * The previous character was not an escape char. Check if this
636 * is an escape.
637 */
638 if (last_was_cr && ch == escape_char) {
639 /* It is. Set the flag and continue to next character. */
640 escape_pending = 1;
641 continue;
642 }
643 }
644
645 /*
646 * Normal character. Record whether it was a newline,
647 * and append it to the buffer.
648 */
649 last_was_cr = (ch == '\r' || ch == '\n');
650 buf[0] = ch;
651 buffer_append(&stdin_buffer, buf, 1);
652 stdin_bytes += 1;
653 continue;
654 }
655 } 664 }
656 } 665 }
657} 666}
@@ -722,6 +731,15 @@ client_process_buffered_input_packets()
722 dispatch_run(DISPATCH_NONBLOCK, &quit_pending); 731 dispatch_run(DISPATCH_NONBLOCK, &quit_pending);
723} 732}
724 733
734/* scan buf[] for '~' before sending data to the peer */
735
736int
737simple_escape_filter(Channel *c, char *buf, int len)
738{
739 /* XXX we assume c->extended is writeable */
740 return process_escapes(&c->input, &c->output, &c->extended, buf, len);
741}
742
725/* 743/*
726 * Implements the interactive session with the server. This is called after 744 * Implements the interactive session with the server. This is called after
727 * the user has been authenticated, and a command has been started on the 745 * the user has been authenticated, and a command has been started on the
@@ -730,7 +748,7 @@ client_process_buffered_input_packets()
730 */ 748 */
731 749
732int 750int
733client_loop(int have_pty, int escape_char_arg) 751client_loop(int have_pty, int escape_char_arg, int ssh2_chan_id)
734{ 752{
735 extern Options options; 753 extern Options options;
736 double start_time, total_time; 754 double start_time, total_time;
@@ -780,6 +798,9 @@ client_loop(int have_pty, int escape_char_arg)
780 if (!compat20) 798 if (!compat20)
781 client_check_initial_eof_on_stdin(); 799 client_check_initial_eof_on_stdin();
782 800
801 if (compat20 && escape_char != -1)
802 channel_register_filter(ssh2_chan_id, simple_escape_filter);
803
783 /* Main loop of the client for the interactive session mode. */ 804 /* Main loop of the client for the interactive session mode. */
784 while (!quit_pending) { 805 while (!quit_pending) {
785 fd_set readset, writeset; 806 fd_set readset, writeset;
@@ -989,6 +1010,7 @@ client_input_channel_open(int type, int plen)
989 /* XXX move to channels.c */ 1010 /* XXX move to channels.c */
990 sock = x11_connect_display(); 1011 sock = x11_connect_display();
991 if (sock >= 0) { 1012 if (sock >= 0) {
1013/*XXX MAXPACK */
992 id = channel_new("x11", SSH_CHANNEL_X11_OPEN, 1014 id = channel_new("x11", SSH_CHANNEL_X11_OPEN,
993 sock, sock, -1, 4*1024, 32*1024, 0, 1015 sock, sock, -1, 4*1024, 32*1024, 0,
994 xstrdup("x11")); 1016 xstrdup("x11"));
diff --git a/configure.in b/configure.in
index f048b000d..02287b802 100644
--- a/configure.in
+++ b/configure.in
@@ -14,6 +14,17 @@ AC_SUBST(PERL)
14AC_PATH_PROG(ENT, ent) 14AC_PATH_PROG(ENT, ent)
15AC_SUBST(ENT) 15AC_SUBST(ENT)
16 16
17# Use LOGIN_PROGRAM from environment if possible
18if test ! -z "$LOGIN_PROGRAM" ; then
19 AC_DEFINE_UNQUOTED(LOGIN_PROGRAM_FALLBACK, "$LOGIN_PROGRAM")
20else
21 # Search for login
22 AC_PATH_PROG(LOGIN_PROGRAM_FALLBACK, login)
23 if test ! -z "$LOGIN_PROGRAM_FALLBACK" ; then
24 AC_DEFINE_UNQUOTED(LOGIN_PROGRAM_FALLBACK, "$LOGIN_PROGRAM_FALLBACK")
25 fi
26fi
27
17if test -z "$LD" ; then 28if test -z "$LD" ; then
18 LD=$CC 29 LD=$CC
19fi 30fi
@@ -225,18 +236,18 @@ if test -z "$no_libnsl" ; then
225fi 236fi
226 237
227# Checks for header files. 238# Checks for header files.
228AC_CHECK_HEADERS(bstring.h endian.h floatingpoint.h lastlog.h limits.h login.h maillock.h netdb.h netgroup.h netinet/in_systm.h paths.h poll.h pty.h shadow.h security/pam_appl.h sys/bitypes.h sys/bsdtty.h sys/cdefs.h sys/poll.h sys/select.h sys/stat.h sys/stropts.h sys/sysmacros.h sys/time.h sys/ttcompat.h stddef.h time.h ttyent.h usersec.h util.h utmp.h utmpx.h) 239AC_CHECK_HEADERS(bstring.h endian.h floatingpoint.h lastlog.h limits.h login.h login_cap.h maillock.h netdb.h netgroup.h netinet/in_systm.h paths.h poll.h pty.h shadow.h security/pam_appl.h sys/bitypes.h sys/bsdtty.h sys/cdefs.h sys/poll.h sys/select.h sys/stat.h sys/stropts.h sys/sysmacros.h sys/time.h sys/ttcompat.h stddef.h time.h ttyent.h usersec.h util.h utmp.h utmpx.h)
229 240
230# Checks for library functions. 241dnl Checks for library functions.
231AC_CHECK_FUNCS(arc4random atexit b64_ntop bcopy bindresvport_af clock freeaddrinfo gai_strerror getaddrinfo getnameinfo getrusage getttyent inet_aton inet_ntoa innetgr md5_crypt memmove mkdtemp on_exit openpty rresvport_af setenv seteuid setlogin setproctitle setreuid sigaction sigvec snprintf strerror strlcat strlcpy strsep vsnprintf vhangup _getpty __b64_ntop) 242AC_CHECK_FUNCS(arc4random atexit b64_ntop bcopy bindresvport_af clock freeaddrinfo gai_strerror getaddrinfo getnameinfo getrusage getttyent inet_aton inet_ntoa innetgr login_getcapbool md5_crypt memmove mkdtemp on_exit openpty rresvport_af setenv seteuid setlogin setproctitle setreuid sigaction sigvec snprintf strerror strlcat strlcpy strsep vsnprintf vhangup _getpty __b64_ntop)
232dnl checks for time functions 243dnl Checks for time functions
233AC_CHECK_FUNCS(gettimeofday time) 244AC_CHECK_FUNCS(gettimeofday time)
234dnl checks for libutil functions 245dnl Checks for libutil functions
235AC_CHECK_FUNCS(login logout updwtmp logwtmp) 246AC_CHECK_FUNCS(login logout updwtmp logwtmp)
236dnl checks for utmp functions 247dnl Checks for utmp functions
237AC_CHECK_FUNCS(entutent getutent getutid getutline pututline setutent) 248AC_CHECK_FUNCS(entutent getutent getutid getutline pututline setutent)
238AC_CHECK_FUNCS(utmpname) 249AC_CHECK_FUNCS(utmpname)
239dnl checks for utmpx functions 250dnl Checks for utmpx functions
240AC_CHECK_FUNCS(entutxent getutxent getutxid getutxline pututxline ) 251AC_CHECK_FUNCS(entutxent getutxent getutxid getutxline pututxline )
241AC_CHECK_FUNCS(setutxent utmpxname) 252AC_CHECK_FUNCS(setutxent utmpxname)
242 253
@@ -736,6 +747,22 @@ if test "x$ac_cv_have___ss_family_in_struct_ss" = "xyes" ; then
736 AC_DEFINE(HAVE___SS_FAMILY_IN_SS) 747 AC_DEFINE(HAVE___SS_FAMILY_IN_SS)
737fi 748fi
738 749
750AC_CACHE_CHECK([for pw_class field in struct passwd],
751 ac_cv_have_pw_class_in_struct_passwd, [
752 AC_TRY_COMPILE(
753 [
754#include <sys/types.h>
755#include <pwd.h>
756 ],
757 [ struct passwd p s; p.pw_class = NULL; ],
758 [ ac_cv_have_pw_class_in_struct_passwd="yes" ],
759 [ ac_cv_have_pw_class_in_struct_passwd="no" ]
760 )
761])
762if test "x$ac_cv_have_pw_class_in_struct_passwd" = "xyes" ; then
763 AC_DEFINE(HAVE_PW_CLASS_IN_PASSWD)
764fi
765
739 766
740AC_CACHE_CHECK([if libc defines __progname], ac_cv_libc_defines___progname, [ 767AC_CACHE_CHECK([if libc defines __progname], ac_cv_libc_defines___progname, [
741 AC_TRY_LINK([], 768 AC_TRY_LINK([],
diff --git a/crc32.c b/crc32.c
index 05a1af7b3..eb9b2dcd4 100644
--- a/crc32.c
+++ b/crc32.c
@@ -6,7 +6,7 @@
6 */ 6 */
7 7
8#include "includes.h" 8#include "includes.h"
9RCSID("$OpenBSD: crc32.c,v 1.5 2000/06/20 01:39:40 markus Exp $"); 9RCSID("$OpenBSD: crc32.c,v 1.6 2000/08/19 02:17:12 deraadt Exp $");
10 10
11#include "crc32.h" 11#include "crc32.h"
12 12
@@ -108,7 +108,7 @@ static unsigned int crc32_tab[] = {
108/* Return a 32-bit CRC of the contents of the buffer. */ 108/* Return a 32-bit CRC of the contents of the buffer. */
109 109
110unsigned int 110unsigned int
111crc32(const unsigned char *s, unsigned int len) 111ssh_crc32(const unsigned char *s, unsigned int len)
112{ 112{
113 unsigned int i; 113 unsigned int i;
114 unsigned int crc32val; 114 unsigned int crc32val;
diff --git a/crc32.h b/crc32.h
index 45495b422..2c84a8017 100644
--- a/crc32.h
+++ b/crc32.h
@@ -13,7 +13,7 @@
13 * 13 *
14 */ 14 */
15 15
16/* RCSID("$OpenBSD: crc32.h,v 1.6 2000/06/20 01:39:40 markus Exp $"); */ 16/* RCSID("$OpenBSD: crc32.h,v 1.7 2000/08/19 21:29:40 deraadt Exp $"); */
17 17
18#ifndef CRC32_H 18#ifndef CRC32_H
19#define CRC32_H 19#define CRC32_H
@@ -22,6 +22,6 @@
22 * This computes a 32 bit CRC of the data in the buffer, and returns the CRC. 22 * This computes a 32 bit CRC of the data in the buffer, and returns the CRC.
23 * The polynomial used is 0xedb88320. 23 * The polynomial used is 0xedb88320.
24 */ 24 */
25unsigned int crc32(const unsigned char *buf, unsigned int len); 25unsigned int ssh_crc32(const unsigned char *buf, unsigned int len);
26 26
27#endif /* CRC32_H */ 27#endif /* CRC32_H */
diff --git a/deattack.c b/deattack.c
index 7f95eca31..72e7f1e06 100644
--- a/deattack.c
+++ b/deattack.c
@@ -1,5 +1,5 @@
1/* 1/*
2 * $OpenBSD: deattack.c,v 1.7 2000/06/20 01:39:41 markus Exp $ 2 * $OpenBSD: deattack.c,v 1.8 2000/08/19 02:17:12 deraadt Exp $
3 * Cryptographic attack detector for ssh - source code 3 * Cryptographic attack detector for ssh - source code
4 * 4 *
5 * Copyright (c) 1998 CORE SDI S.A., Buenos Aires, Argentina. 5 * Copyright (c) 1998 CORE SDI S.A., Buenos Aires, Argentina.
@@ -50,7 +50,7 @@ void
50crc_update(u_int32_t *a, u_int32_t b) 50crc_update(u_int32_t *a, u_int32_t b)
51{ 51{
52 b ^= *a; 52 b ^= *a;
53 *a = crc32((unsigned char *) &b, sizeof(b)); 53 *a = ssh_crc32((unsigned char *) &b, sizeof(b));
54} 54}
55 55
56/* detect if a block is used in a particular pattern */ 56/* detect if a block is used in a particular pattern */
diff --git a/defines.h b/defines.h
index cd322f9b8..1fe74a92b 100644
--- a/defines.h
+++ b/defines.h
@@ -246,8 +246,16 @@ typedef int mode_t;
246# endif /* RSH_PATH */ 246# endif /* RSH_PATH */
247#endif /* _PATH_RSH */ 247#endif /* _PATH_RSH */
248 248
249#ifndef _PATH_NOLOGIN
250# define _PATH_NOLOGIN "/etc/nologin"
251#endif
252
249/* Macros */ 253/* Macros */
250 254
255#if defined(HAVE_LOGIN_GETCAPBOOL) && defined(HAVE_LOGIN_CAP_H)
256# define HAVE_LOGIN_CAP
257#endif
258
251#ifndef MAX 259#ifndef MAX
252# define MAX(a,b) (((a)>(b))?(a):(b)) 260# define MAX(a,b) (((a)>(b))?(a):(b))
253# define MIN(a,b) (((a)<(b))?(a):(b)) 261# define MIN(a,b) (((a)<(b))?(a):(b))
diff --git a/fingerprint.c b/fingerprint.c
deleted file mode 100644
index 801f6a6e2..000000000
--- a/fingerprint.c
+++ /dev/null
@@ -1,69 +0,0 @@
1/*
2 * Copyright (c) 1999 Markus Friedl. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * 3. All advertising materials mentioning features or use of this software
13 * must display the following acknowledgement:
14 * This product includes software developed by Markus Friedl.
15 * 4. The name of the author may not be used to endorse or promote products
16 * derived from this software without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 */
29
30#include "includes.h"
31RCSID("$OpenBSD: fingerprint.c,v 1.7 2000/06/20 01:39:41 markus Exp $");
32
33#include "ssh.h"
34#include "xmalloc.h"
35#include <openssl/md5.h>
36
37#define FPRINT "%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x"
38
39/*
40 * Generate key fingerprint in ascii format.
41 * Based on ideas and code from Bjoern Groenvall <bg@sics.se>
42 */
43char *
44fingerprint(BIGNUM *e, BIGNUM *n)
45{
46 static char retval[80];
47 MD5_CTX md;
48 unsigned char d[16];
49 unsigned char *buf;
50 int nlen, elen;
51
52 nlen = BN_num_bytes(n);
53 elen = BN_num_bytes(e);
54
55 buf = xmalloc(nlen + elen);
56
57 BN_bn2bin(n, buf);
58 BN_bn2bin(e, buf + nlen);
59
60 MD5_Init(&md);
61 MD5_Update(&md, buf, nlen + elen);
62 MD5_Final(d, &md);
63 snprintf(retval, sizeof(retval), FPRINT,
64 d[0], d[1], d[2], d[3], d[4], d[5], d[6], d[7],
65 d[8], d[9], d[10], d[11], d[12], d[13], d[14], d[15]);
66 memset(buf, 0, nlen + elen);
67 xfree(buf);
68 return retval;
69}
diff --git a/fingerprint.h b/fingerprint.h
deleted file mode 100644
index 3d7bcb32c..000000000
--- a/fingerprint.h
+++ /dev/null
@@ -1,34 +0,0 @@
1/*
2 * Copyright (c) 1999 Markus Friedl. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * 3. All advertising materials mentioning features or use of this software
13 * must display the following acknowledgement:
14 * This product includes software developed by Markus Friedl.
15 * 4. The name of the author may not be used to endorse or promote products
16 * derived from this software without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 */
29/* RCSID("$OpenBSD: fingerprint.h,v 1.4 2000/06/20 01:39:41 markus Exp $"); */
30
31#ifndef FINGERPRINT_H
32#define FINGERPRINT_H
33char *fingerprint(BIGNUM * e, BIGNUM * n);
34#endif
diff --git a/key.c b/key.c
index 764f1f227..f2ce75e7f 100644
--- a/key.c
+++ b/key.c
@@ -41,7 +41,7 @@
41#include "dsa.h" 41#include "dsa.h"
42#include "uuencode.h" 42#include "uuencode.h"
43 43
44RCSID("$OpenBSD: key.c,v 1.9 2000/06/22 23:55:00 djm Exp $"); 44RCSID("$OpenBSD: key.c,v 1.10 2000/08/19 21:34:43 markus Exp $");
45 45
46#define SSH_DSS "ssh-dss" 46#define SSH_DSS "ssh-dss"
47 47
@@ -335,3 +335,15 @@ key_type(Key *k)
335 } 335 }
336 return "unknown"; 336 return "unknown";
337} 337}
338unsigned int
339key_size(Key *k){
340 switch (k->type) {
341 case KEY_RSA:
342 return BN_num_bits(k->rsa->n);
343 break;
344 case KEY_DSA:
345 return BN_num_bits(k->dsa->p);
346 break;
347 }
348 return 0;
349}
diff --git a/log-client.c b/log-client.c
index 7e9fd61e7..7615a94f0 100644
--- a/log-client.c
+++ b/log-client.c
@@ -15,7 +15,7 @@
15 */ 15 */
16 16
17#include "includes.h" 17#include "includes.h"
18RCSID("$OpenBSD: log-client.c,v 1.9 2000/06/20 01:39:42 markus Exp $"); 18RCSID("$OpenBSD: log-client.c,v 1.10 2000/08/19 02:57:33 deraadt Exp $");
19 19
20#include "xmalloc.h" 20#include "xmalloc.h"
21#include "ssh.h" 21#include "ssh.h"
@@ -57,6 +57,5 @@ do_log(LogLevel level, const char *fmt, va_list args)
57 if (level == SYSLOG_LEVEL_DEBUG) 57 if (level == SYSLOG_LEVEL_DEBUG)
58 fprintf(stderr, "debug: "); 58 fprintf(stderr, "debug: ");
59 vsnprintf(msgbuf, sizeof(msgbuf), fmt, args); 59 vsnprintf(msgbuf, sizeof(msgbuf), fmt, args);
60 fprintf(stderr, "%s", msgbuf); 60 fprintf(stderr, "%s\r\n", msgbuf);
61 fprintf(stderr, "\r\n");
62} 61}
diff --git a/packet.c b/packet.c
index 56080cbb1..8f9311074 100644
--- a/packet.c
+++ b/packet.c
@@ -17,7 +17,7 @@
17 */ 17 */
18 18
19#include "includes.h" 19#include "includes.h"
20RCSID("$OpenBSD: packet.c,v 1.33 2000/06/20 01:39:43 markus Exp $"); 20RCSID("$OpenBSD: packet.c,v 1.34 2000/08/19 02:17:12 deraadt Exp $");
21 21
22#include "xmalloc.h" 22#include "xmalloc.h"
23#include "buffer.h" 23#include "buffer.h"
@@ -479,8 +479,8 @@ packet_send1()
479 buffer_consume(&outgoing_packet, 8 - padding); 479 buffer_consume(&outgoing_packet, 8 - padding);
480 480
481 /* Add check bytes. */ 481 /* Add check bytes. */
482 checksum = crc32((unsigned char *) buffer_ptr(&outgoing_packet), 482 checksum = ssh_crc32((unsigned char *) buffer_ptr(&outgoing_packet),
483 buffer_len(&outgoing_packet)); 483 buffer_len(&outgoing_packet));
484 PUT_32BIT(buf, checksum); 484 PUT_32BIT(buf, checksum);
485 buffer_append(&outgoing_packet, buf, 4); 485 buffer_append(&outgoing_packet, buf, 4);
486 486
@@ -764,7 +764,7 @@ packet_read_poll1(int *payload_len_ptr)
764#endif 764#endif
765 765
766 /* Compute packet checksum. */ 766 /* Compute packet checksum. */
767 checksum = crc32((unsigned char *) buffer_ptr(&incoming_packet), 767 checksum = ssh_crc32((unsigned char *) buffer_ptr(&incoming_packet),
768 buffer_len(&incoming_packet) - 4); 768 buffer_len(&incoming_packet) - 4);
769 769
770 /* Skip padding. */ 770 /* Skip padding. */
diff --git a/scp.1 b/scp.1
index d2fa546af..b7b247624 100644
--- a/scp.1
+++ b/scp.1
@@ -9,7 +9,7 @@
9.\" 9.\"
10.\" Created: Sun May 7 00:14:37 1995 ylo 10.\" Created: Sun May 7 00:14:37 1995 ylo
11.\" 11.\"
12.\" $Id: scp.1,v 1.8 2000/07/11 07:31:38 djm Exp $ 12.\" $Id: scp.1,v 1.9 2000/08/23 00:46:24 djm Exp $
13.\" 13.\"
14.Dd September 25, 1999 14.Dd September 25, 1999
15.Dt SCP 1 15.Dt SCP 1
@@ -68,6 +68,11 @@ This option is directly passed to
68.It Fl p 68.It Fl p
69Preserves modification times, access times, and modes from the 69Preserves modification times, access times, and modes from the
70original file. 70original file.
71.It Fl S
72Name of program to use for the encrypted connection.
73The program must understand
74.Xr ssh 1
75options.
71.It Fl r 76.It Fl r
72Recursively copy entire directories. 77Recursively copy entire directories.
73.It Fl v 78.It Fl v
@@ -98,6 +103,11 @@ because
98.Fl p 103.Fl p
99is already reserved for preserving the times and modes of the file in 104is already reserved for preserving the times and modes of the file in
100.Xr rcp 1 . 105.Xr rcp 1 .
106.It Fl S
107Name of program to use for the encrypted connection. The program must
108understand
109.Xr ssh 1
110options.
101.It Fl 4 111.It Fl 4
102Forces 112Forces
103.Nm 113.Nm
diff --git a/scp.c b/scp.c
index 02feba9c1..d2e4224bb 100644
--- a/scp.c
+++ b/scp.c
@@ -11,6 +11,8 @@
11*/ 11*/
12 12
13/* 13/*
14 * Parts from:
15 *
14 * Copyright (c) 1983, 1990, 1992, 1993, 1995 16 * Copyright (c) 1983, 1990, 1992, 1993, 1995
15 * The Regents of the University of California. All rights reserved. 17 * The Regents of the University of California. All rights reserved.
16 * 18 *
@@ -45,7 +47,7 @@
45 */ 47 */
46 48
47#include "includes.h" 49#include "includes.h"
48RCSID("$OpenBSD: scp.c,v 1.33 2000/07/13 23:19:31 provos Exp $"); 50RCSID("$OpenBSD: scp.c,v 1.35 2000/08/19 02:50:07 deraadt Exp $");
49 51
50#include "ssh.h" 52#include "ssh.h"
51#include "xmalloc.h" 53#include "xmalloc.h"
@@ -69,6 +71,7 @@ void progressmeter(int);
69 71
70/* Returns width of the terminal (for progress meter calculations). */ 72/* Returns width of the terminal (for progress meter calculations). */
71int getttywidth(void); 73int getttywidth(void);
74int do_cmd(char *host, char *remuser, char *cmd, int *fdin, int *fdout, int argc);
72 75
73/* Time a transfer started. */ 76/* Time a transfer started. */
74static struct timeval start; 77static struct timeval start;
@@ -111,6 +114,9 @@ char *identity = NULL;
111/* This is the port to use in contacting the remote site (is non-NULL). */ 114/* This is the port to use in contacting the remote site (is non-NULL). */
112char *port = NULL; 115char *port = NULL;
113 116
117/* This is the program to execute for the secured connection. ("ssh" or -S) */
118char *ssh_program = SSH_PROGRAM;
119
114/* 120/*
115 * This function executes the given command as the specified user on the 121 * This function executes the given command as the specified user on the
116 * given host. This returns < 0 if execution fails, and >= 0 otherwise. This 122 * given host. This returns < 0 if execution fails, and >= 0 otherwise. This
@@ -118,13 +124,13 @@ char *port = NULL;
118 */ 124 */
119 125
120int 126int
121do_cmd(char *host, char *remuser, char *cmd, int *fdin, int *fdout) 127do_cmd(char *host, char *remuser, char *cmd, int *fdin, int *fdout, int argc)
122{ 128{
123 int pin[2], pout[2], reserved[2]; 129 int pin[2], pout[2], reserved[2];
124 130
125 if (verbose_mode) 131 if (verbose_mode)
126 fprintf(stderr, "Executing: host %s, user %s, command %s\n", 132 fprintf(stderr, "Executing: host %s, user %s, command %s\n",
127 host, remuser ? remuser : "(unspecified)", cmd); 133 host, remuser ? remuser : "(unspecified)", cmd);
128 134
129 /* 135 /*
130 * Reserve two descriptors so that the real pipes won't get 136 * Reserve two descriptors so that the real pipes won't get
@@ -144,7 +150,7 @@ do_cmd(char *host, char *remuser, char *cmd, int *fdin, int *fdout)
144 150
145 /* For a child to execute the command on the remote host using ssh. */ 151 /* For a child to execute the command on the remote host using ssh. */
146 if (fork() == 0) { 152 if (fork() == 0) {
147 char *args[100]; 153 char *args[100]; /* XXX careful */
148 unsigned int i; 154 unsigned int i;
149 155
150 /* Child. */ 156 /* Child. */
@@ -156,7 +162,7 @@ do_cmd(char *host, char *remuser, char *cmd, int *fdin, int *fdout)
156 close(pout[1]); 162 close(pout[1]);
157 163
158 i = 0; 164 i = 0;
159 args[i++] = SSH_PROGRAM; 165 args[i++] = ssh_program;
160 args[i++] = "-x"; 166 args[i++] = "-x";
161 args[i++] = "-oFallBackToRsh no"; 167 args[i++] = "-oFallBackToRsh no";
162 if (IPv4) 168 if (IPv4)
@@ -189,8 +195,8 @@ do_cmd(char *host, char *remuser, char *cmd, int *fdin, int *fdout)
189 args[i++] = cmd; 195 args[i++] = cmd;
190 args[i++] = NULL; 196 args[i++] = NULL;
191 197
192 execvp(SSH_PROGRAM, args); 198 execvp(ssh_program, args);
193 perror(SSH_PROGRAM); 199 perror(ssh_program);
194 exit(1); 200 exit(1);
195 } 201 }
196 /* Parent. Close the other side, and return the local side. */ 202 /* Parent. Close the other side, and return the local side. */
@@ -214,8 +220,6 @@ fatal(const char *fmt,...)
214 exit(255); 220 exit(255);
215} 221}
216 222
217/* This stuff used to be in BSD rcp extern.h. */
218
219typedef struct { 223typedef struct {
220 int cnt; 224 int cnt;
221 char *buf; 225 char *buf;
@@ -231,8 +235,6 @@ int okname(char *);
231void run_err(const char *,...); 235void run_err(const char *,...);
232void verifydir(char *); 236void verifydir(char *);
233 237
234/* Stuff from BSD rcp.c continues. */
235
236struct passwd *pwd; 238struct passwd *pwd;
237uid_t userid; 239uid_t userid;
238int errs, remin, remout; 240int errs, remin, remout;
@@ -260,7 +262,7 @@ main(argc, argv)
260 extern int optind; 262 extern int optind;
261 263
262 fflag = tflag = 0; 264 fflag = tflag = 0;
263 while ((ch = getopt(argc, argv, "dfprtvBCc:i:P:q46")) != EOF) 265 while ((ch = getopt(argc, argv, "dfprtvBCc:i:P:q46S")) != EOF)
264 switch (ch) { 266 switch (ch) {
265 /* User-visible flags. */ 267 /* User-visible flags. */
266 case '4': 268 case '4':
@@ -278,6 +280,10 @@ main(argc, argv)
278 case 'r': 280 case 'r':
279 iamrecursive = 1; 281 iamrecursive = 1;
280 break; 282 break;
283 case 'S':
284 ssh_program = optarg;
285 break;
286
281 /* Server options. */ 287 /* Server options. */
282 case 'd': 288 case 'd':
283 targetshouldbedirectory = 1; 289 targetshouldbedirectory = 1;
@@ -343,8 +349,8 @@ main(argc, argv)
343 remin = remout = -1; 349 remin = remout = -1;
344 /* Command to be executed on remote system using "ssh". */ 350 /* Command to be executed on remote system using "ssh". */
345 (void) sprintf(cmd, "scp%s%s%s%s", verbose_mode ? " -v" : "", 351 (void) sprintf(cmd, "scp%s%s%s%s", verbose_mode ? " -v" : "",
346 iamrecursive ? " -r" : "", pflag ? " -p" : "", 352 iamrecursive ? " -r" : "", pflag ? " -p" : "",
347 targetshouldbedirectory ? " -d" : ""); 353 targetshouldbedirectory ? " -d" : "");
348 354
349 (void) signal(SIGPIPE, lostconn); 355 (void) signal(SIGPIPE, lostconn);
350 356
@@ -401,9 +407,9 @@ toremote(targ, argc, argv)
401 if (*src == 0) 407 if (*src == 0)
402 src = "."; 408 src = ".";
403 host = strchr(argv[i], '@'); 409 host = strchr(argv[i], '@');
404 len = strlen(SSH_PROGRAM) + strlen(argv[i]) + 410 len = strlen(ssh_program) + strlen(argv[i]) +
405 strlen(src) + (tuser ? strlen(tuser) : 0) + 411 strlen(src) + (tuser ? strlen(tuser) : 0) +
406 strlen(thost) + strlen(targ) + CMDNEEDS + 32; 412 strlen(thost) + strlen(targ) + CMDNEEDS + 32;
407 bp = xmalloc(len); 413 bp = xmalloc(len);
408 if (host) { 414 if (host) {
409 *host++ = 0; 415 *host++ = 0;
@@ -414,19 +420,19 @@ toremote(targ, argc, argv)
414 else if (!okname(suser)) 420 else if (!okname(suser))
415 continue; 421 continue;
416 (void) sprintf(bp, 422 (void) sprintf(bp,
417 "%s%s -x -o'FallBackToRsh no' -n -l %s %s %s %s '%s%s%s:%s'", 423 "%s%s -x -o'FallBackToRsh no' -n -l %s %s %s %s '%s%s%s:%s'",
418 SSH_PROGRAM, verbose_mode ? " -v" : "", 424 ssh_program, verbose_mode ? " -v" : "",
419 suser, host, cmd, src, 425 suser, host, cmd, src,
420 tuser ? tuser : "", tuser ? "@" : "", 426 tuser ? tuser : "", tuser ? "@" : "",
421 thost, targ); 427 thost, targ);
422 } else { 428 } else {
423 host = cleanhostname(argv[i]); 429 host = cleanhostname(argv[i]);
424 (void) sprintf(bp, 430 (void) sprintf(bp,
425 "exec %s%s -x -o'FallBackToRsh no' -n %s %s %s '%s%s%s:%s'", 431 "exec %s%s -x -o'FallBackToRsh no' -n %s %s %s '%s%s%s:%s'",
426 SSH_PROGRAM, verbose_mode ? " -v" : "", 432 ssh_program, verbose_mode ? " -v" : "",
427 host, cmd, src, 433 host, cmd, src,
428 tuser ? tuser : "", tuser ? "@" : "", 434 tuser ? tuser : "", tuser ? "@" : "",
429 thost, targ); 435 thost, targ);
430 } 436 }
431 if (verbose_mode) 437 if (verbose_mode)
432 fprintf(stderr, "Executing: %s\n", bp); 438 fprintf(stderr, "Executing: %s\n", bp);
@@ -438,8 +444,8 @@ toremote(targ, argc, argv)
438 bp = xmalloc(len); 444 bp = xmalloc(len);
439 (void) sprintf(bp, "%s -t %s", cmd, targ); 445 (void) sprintf(bp, "%s -t %s", cmd, targ);
440 host = cleanhostname(thost); 446 host = cleanhostname(thost);
441 if (do_cmd(host, tuser, 447 if (do_cmd(host, tuser, bp, &remin,
442 bp, &remin, &remout) < 0) 448 &remout, argc) < 0)
443 exit(1); 449 exit(1);
444 if (response() < 0) 450 if (response() < 0)
445 exit(1); 451 exit(1);
@@ -461,11 +467,11 @@ tolocal(argc, argv)
461 for (i = 0; i < argc - 1; i++) { 467 for (i = 0; i < argc - 1; i++) {
462 if (!(src = colon(argv[i]))) { /* Local to local. */ 468 if (!(src = colon(argv[i]))) { /* Local to local. */
463 len = strlen(_PATH_CP) + strlen(argv[i]) + 469 len = strlen(_PATH_CP) + strlen(argv[i]) +
464 strlen(argv[argc - 1]) + 20; 470 strlen(argv[argc - 1]) + 20;
465 bp = xmalloc(len); 471 bp = xmalloc(len);
466 (void) sprintf(bp, "exec %s%s%s %s %s", _PATH_CP, 472 (void) sprintf(bp, "exec %s%s%s %s %s", _PATH_CP,
467 iamrecursive ? " -r" : "", pflag ? " -p" : "", 473 iamrecursive ? " -r" : "", pflag ? " -p" : "",
468 argv[i], argv[argc - 1]); 474 argv[i], argv[argc - 1]);
469 if (verbose_mode) 475 if (verbose_mode)
470 fprintf(stderr, "Executing: %s\n", bp); 476 fprintf(stderr, "Executing: %s\n", bp);
471 if (system(bp)) 477 if (system(bp))
@@ -491,7 +497,7 @@ tolocal(argc, argv)
491 len = strlen(src) + CMDNEEDS + 20; 497 len = strlen(src) + CMDNEEDS + 20;
492 bp = xmalloc(len); 498 bp = xmalloc(len);
493 (void) sprintf(bp, "%s -f %s", cmd, src); 499 (void) sprintf(bp, "%s -f %s", cmd, src);
494 if (do_cmd(host, suser, bp, &remin, &remout) < 0) { 500 if (do_cmd(host, suser, bp, &remin, &remout, argc) < 0) {
495 (void) xfree(bp); 501 (void) xfree(bp);
496 ++errs; 502 ++errs;
497 continue; 503 continue;
@@ -548,8 +554,8 @@ syserr: run_err("%s: %s", name, strerror(errno));
548 * versions expecting microseconds. 554 * versions expecting microseconds.
549 */ 555 */
550 (void) sprintf(buf, "T%lu 0 %lu 0\n", 556 (void) sprintf(buf, "T%lu 0 %lu 0\n",
551 (unsigned long) stb.st_mtime, 557 (unsigned long) stb.st_mtime,
552 (unsigned long) stb.st_atime); 558 (unsigned long) stb.st_atime);
553 (void) atomicio(write, remout, buf, strlen(buf)); 559 (void) atomicio(write, remout, buf, strlen(buf));
554 if (response() < 0) 560 if (response() < 0)
555 goto next; 561 goto next;
@@ -626,8 +632,8 @@ rsource(name, statp)
626 last++; 632 last++;
627 if (pflag) { 633 if (pflag) {
628 (void) sprintf(path, "T%lu 0 %lu 0\n", 634 (void) sprintf(path, "T%lu 0 %lu 0\n",
629 (unsigned long) statp->st_mtime, 635 (unsigned long) statp->st_mtime,
630 (unsigned long) statp->st_atime); 636 (unsigned long) statp->st_atime);
631 (void) atomicio(write, remout, path, strlen(path)); 637 (void) atomicio(write, remout, path, strlen(path));
632 if (response() < 0) { 638 if (response() < 0) {
633 closedir(dirp); 639 closedir(dirp);
@@ -635,8 +641,7 @@ rsource(name, statp)
635 } 641 }
636 } 642 }
637 (void) sprintf(path, "D%04o %d %.1024s\n", 643 (void) sprintf(path, "D%04o %d %.1024s\n",
638 (unsigned int) (statp->st_mode & FILEMODEMASK), 644 (unsigned int) (statp->st_mode & FILEMODEMASK), 0, last);
639 0, last);
640 if (verbose_mode) 645 if (verbose_mode)
641 fprintf(stderr, "Entering directory: %s", path); 646 fprintf(stderr, "Entering directory: %s", path);
642 (void) atomicio(write, remout, path, strlen(path)); 647 (void) atomicio(write, remout, path, strlen(path));
@@ -783,7 +788,7 @@ sink(argc, argv)
783 if (need > cursize) 788 if (need > cursize)
784 namebuf = xmalloc(need); 789 namebuf = xmalloc(need);
785 (void) sprintf(namebuf, "%s%s%s", targ, 790 (void) sprintf(namebuf, "%s%s%s", targ,
786 *targ ? "/" : "", cp); 791 *targ ? "/" : "", cp);
787 np = namebuf; 792 np = namebuf;
788 } else 793 } else
789 np = targ; 794 np = targ;
@@ -954,8 +959,9 @@ response()
954void 959void
955usage() 960usage()
956{ 961{
957 (void) fprintf(stderr, 962 (void) fprintf(stderr, "usage: scp "
958 "usage: scp [-pqrvC46] [-P port] [-c cipher] [-i identity] f1 f2; or:\n scp [options] f1 ... fn directory\n"); 963 "[-pqrvC46] [-S ssh] [-P port] [-c cipher] [-i identity] f1 f2; or:\n"
964 " scp [options] f1 ... fn directory\n");
959 exit(1); 965 exit(1);
960} 966}
961 967
@@ -984,43 +990,6 @@ run_err(const char *fmt,...)
984 } 990 }
985} 991}
986 992
987/* Stuff below is from BSD rcp util.c. */
988
989/*-
990 * Copyright (c) 1992, 1993
991 * The Regents of the University of California. All rights reserved.
992 *
993 * Redistribution and use in source and binary forms, with or without
994 * modification, are permitted provided that the following conditions
995 * are met:
996 * 1. Redistributions of source code must retain the above copyright
997 * notice, this list of conditions and the following disclaimer.
998 * 2. Redistributions in binary form must reproduce the above copyright
999 * notice, this list of conditions and the following disclaimer in the
1000 * documentation and/or other materials provided with the distribution.
1001 * 3. All advertising materials mentioning features or use of this software
1002 * must display the following acknowledgement:
1003 * This product includes software developed by the University of
1004 * California, Berkeley and its contributors.
1005 * 4. Neither the name of the University nor the names of its contributors
1006 * may be used to endorse or promote products derived from this software
1007 * without specific prior written permission.
1008 *
1009 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
1010 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1011 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
1012 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
1013 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
1014 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
1015 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
1016 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
1017 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
1018 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
1019 * SUCH DAMAGE.
1020 *
1021 * $OpenBSD: scp.c,v 1.33 2000/07/13 23:19:31 provos Exp $
1022 */
1023
1024char * 993char *
1025colon(cp) 994colon(cp)
1026 char *cp; 995 char *cp;
@@ -1097,7 +1066,7 @@ allocbuf(bp, fd, blksize)
1097 size = blksize; 1066 size = blksize;
1098 else 1067 else
1099 size = blksize + (stb.st_blksize - blksize % stb.st_blksize) % 1068 size = blksize + (stb.st_blksize - blksize % stb.st_blksize) %
1100 stb.st_blksize; 1069 stb.st_blksize;
1101 if (bp->cnt >= size) 1070 if (bp->cnt >= size)
1102 return (bp); 1071 return (bp);
1103 if (bp->buf == NULL) 1072 if (bp->buf == NULL)
@@ -1228,14 +1197,14 @@ progressmeter(int flag)
1228 i = remaining / 3600; 1197 i = remaining / 3600;
1229 if (i) 1198 if (i)
1230 snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), 1199 snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf),
1231 "%2d:", i); 1200 "%2d:", i);
1232 else 1201 else
1233 snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), 1202 snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf),
1234 " "); 1203 " ");
1235 i = remaining % 3600; 1204 i = remaining % 3600;
1236 snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), 1205 snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf),
1237 "%02d:%02d%s", i / 60, i % 60, 1206 "%02d:%02d%s", i / 60, i % 60,
1238 (flag != 1) ? " ETA" : " "); 1207 (flag != 1) ? " ETA" : " ");
1239 } 1208 }
1240 atomicio(write, fileno(stdout), buf, strlen(buf)); 1209 atomicio(write, fileno(stdout), buf, strlen(buf));
1241 1210
diff --git a/session.c b/session.c
index d65b06984..82096c3ab 100644
--- a/session.c
+++ b/session.c
@@ -8,7 +8,7 @@
8 */ 8 */
9 9
10#include "includes.h" 10#include "includes.h"
11RCSID("$OpenBSD: session.c,v 1.25 2000/08/17 20:06:34 markus Exp $"); 11RCSID("$OpenBSD: session.c,v 1.29 2000/08/21 16:23:31 millert Exp $");
12 12
13#include "xmalloc.h" 13#include "xmalloc.h"
14#include "ssh.h" 14#include "ssh.h"
@@ -52,6 +52,10 @@ RCSID("$OpenBSD: session.c,v 1.25 2000/08/17 20:06:34 markus Exp $");
52# define S_UNOFILE_HARD S_UNOFILE "_hard" 52# define S_UNOFILE_HARD S_UNOFILE "_hard"
53#endif 53#endif
54 54
55#ifdef HAVE_LOGIN_CAP
56#include <login_cap.h>
57#endif
58
55/* types */ 59/* types */
56 60
57#define TTYSZ 64 61#define TTYSZ 64
@@ -117,6 +121,10 @@ Session sessions[MAX_SESSIONS];
117char *aixloginmsg; 121char *aixloginmsg;
118#endif /* WITH_AIXAUTHENTICATE */ 122#endif /* WITH_AIXAUTHENTICATE */
119 123
124#ifdef HAVE_LOGIN_CAP
125static login_cap_t *lc;
126#endif
127
120/* 128/*
121 * Remove local Xauthority file. 129 * Remove local Xauthority file.
122 */ 130 */
@@ -200,6 +208,13 @@ do_authenticated(struct passwd * pw)
200 s = session_new(); 208 s = session_new();
201 s->pw = pw; 209 s->pw = pw;
202 210
211#ifdef HAVE_LOGIN_CAP
212 if ((lc = login_getclass(pw->pw_class)) == NULL) {
213 error("unable to get login class");
214 return;
215 }
216#endif
217
203 /* 218 /*
204 * We stay in this loop until the client requests to execute a shell 219 * We stay in this loop until the client requests to execute a shell
205 * or a command. 220 * or a command.
@@ -650,7 +665,11 @@ do_login(Session *s)
650 665
651 /* Done if .hushlogin exists. */ 666 /* Done if .hushlogin exists. */
652 snprintf(buf, sizeof(buf), "%.200s/.hushlogin", pw->pw_dir); 667 snprintf(buf, sizeof(buf), "%.200s/.hushlogin", pw->pw_dir);
668#ifdef HAVE_LOGIN_CAP
669 if (login_getcapbool(lc, "hushlogin", 0) || stat(buf, &st) >= 0)
670#else
653 if (stat(buf, &st) >= 0) 671 if (stat(buf, &st) >= 0)
672#endif
654 return; 673 return;
655 674
656#ifdef USE_PAM 675#ifdef USE_PAM
@@ -677,7 +696,12 @@ do_login(Session *s)
677 printf("Last login: %s from %s\r\n", time_string, buf); 696 printf("Last login: %s from %s\r\n", time_string, buf);
678 } 697 }
679 if (options.print_motd) { 698 if (options.print_motd) {
699#ifdef HAVE_LOGIN_CAP
700 f = fopen(login_getcapstr(lc, "welcome", "/etc/motd",
701 "/etc/motd"), "r");
702#else
680 f = fopen("/etc/motd", "r"); 703 f = fopen("/etc/motd", "r");
704#endif
681 if (f) { 705 if (f) {
682 while (fgets(buf, sizeof(buf), f)) 706 while (fgets(buf, sizeof(buf), f))
683 fputs(buf, stdout); 707 fputs(buf, stdout);
@@ -887,10 +911,10 @@ do_child(const char *command, struct passwd * pw, const char *term,
887 const char *display, const char *auth_proto, 911 const char *display, const char *auth_proto,
888 const char *auth_data, const char *ttyname) 912 const char *auth_data, const char *ttyname)
889{ 913{
890 const char *shell, *cp = NULL; 914 const char *shell, *hostname, *cp = NULL;
891 char buf[256]; 915 char buf[256];
892 char cmd[1024]; 916 char cmd[1024];
893 FILE *f; 917 FILE *f = NULL;
894 unsigned int envsize, i; 918 unsigned int envsize, i;
895 char **env; 919 char **env;
896 extern char **environ; 920 extern char **environ;
@@ -905,24 +929,26 @@ do_child(const char *command, struct passwd * pw, const char *term,
905 options.use_login = 0; 929 options.use_login = 0;
906 930
907#ifndef USE_PAM /* pam_nologin handles this */ 931#ifndef USE_PAM /* pam_nologin handles this */
908 f = fopen("/etc/nologin", "r"); 932 if (!options.use_login) {
909 if (f) { 933# ifdef HAVE_LOGIN_CAP
910 /* /etc/nologin exists. Print its contents and exit. */ 934 if (!login_getcapbool(lc, "ignorenologin", 0) && pw->pw_uid)
911 while (fgets(buf, sizeof(buf), f)) 935 f = fopen(login_getcapstr(lc, "nologin", _PATH_NOLOGIN,
912 fputs(buf, stderr); 936 _PATH_NOLOGIN), "r");
913 fclose(f); 937# else /* HAVE_LOGIN_CAP */
914 if (pw->pw_uid != 0) 938 if (pw->pw_uid)
939 f = fopen(_PATH_NOLOGIN, "r");
940# endif /* HAVE_LOGIN_CAP */
941 if (f) {
942 /* /etc/nologin exists. Print its contents and exit. */
943 while (fgets(buf, sizeof(buf), f))
944 fputs(buf, stderr);
945 fclose(f);
915 exit(254); 946 exit(254);
947 }
916 } 948 }
917#endif /* USE_PAM */ 949#endif /* USE_PAM */
918 950
919#ifndef HAVE_OSF_SIA 951 /* Set login name, uid, gid, and groups. */
920 /* Set login name in the kernel. */
921 if (setlogin(pw->pw_name) < 0)
922 error("setlogin failed: %s", strerror(errno));
923#endif
924
925 /* Set uid, gid, and groups. */
926 /* Login(1) does this as well, and it needs uid 0 for the "-h" 952 /* Login(1) does this as well, and it needs uid 0 for the "-h"
927 switch, so we let login(1) to this for us. */ 953 switch, so we let login(1) to this for us. */
928 if (!options.use_login) { 954 if (!options.use_login) {
@@ -943,10 +969,18 @@ do_child(const char *command, struct passwd * pw, const char *term,
943 } 969 }
944#else /* HAVE_OSF_SIA */ 970#else /* HAVE_OSF_SIA */
945 if (getuid() == 0 || geteuid() == 0) { 971 if (getuid() == 0 || geteuid() == 0) {
946#if defined(HAVE_GETUSERATTR) 972# ifdef HAVE_GETUSERATTR
947 set_limits_from_userattr(pw->pw_name); 973 set_limits_from_userattr(pw->pw_name);
948#endif /* defined(HAVE_GETUSERATTR) */ 974# endif /* HAVE_GETUSERATTR */
949 975# ifdef HAVE_LOGIN_CAP
976 if (setusercontext(lc, pw, pw->pw_uid,
977 (LOGIN_SETALL & ~LOGIN_SETPATH)) < 0) {
978 perror("unable to set user context");
979 exit(1);
980 }
981# else /* HAVE_LOGIN_CAP */
982 if (setlogin(pw->pw_name) < 0)
983 error("setlogin failed: %s", strerror(errno));
950 if (setgid(pw->pw_gid) < 0) { 984 if (setgid(pw->pw_gid) < 0) {
951 perror("setgid"); 985 perror("setgid");
952 exit(1); 986 exit(1);
@@ -957,38 +991,39 @@ do_child(const char *command, struct passwd * pw, const char *term,
957 exit(1); 991 exit(1);
958 } 992 }
959 endgrent(); 993 endgrent();
960 994# ifdef WITH_IRIX_ARRAY
961#ifdef WITH_IRIX_ARRAY
962 /* initialize array session */ 995 /* initialize array session */
963 if (newarraysess() != 0) 996 if (newarraysess() != 0)
964 fatal("Failed to set up new array session: %.100s", 997 fatal("Failed to set up new array session: %.100s",
965 strerror(errno)); 998 strerror(errno));
966#endif /* WITH_IRIX_ARRAY */ 999# endif /* WITH_IRIX_ARRAY */
967 1000# ifdef WITH_IRIX_PROJECT
968#ifdef WITH_IRIX_PROJECT
969 /* initialize irix project info */ 1001 /* initialize irix project info */
970 if ((projid = getdfltprojuser(pw->pw_name)) == -1) { 1002 if ((projid = getdfltprojuser(pw->pw_name)) == -1) {
971 debug("Failed to get project id, using projid 0"); 1003 debug("Failed to get project id, using projid 0");
972 projid = 0; 1004 projid = 0;
973 } 1005 }
974
975 if (setprid(projid)) 1006 if (setprid(projid))
976 fatal("Failed to initialize project %d for %s: %.100s", 1007 fatal("Failed to initialize project %d for %s: %.100s",
977 (int)projid, pw->pw_name, strerror(errno)); 1008 (int)projid, pw->pw_name, strerror(errno));
978#endif /* WITH_IRIX_PROJECT */ 1009# endif /* WITH_IRIX_PROJECT */
979
980 /* Permanently switch to the desired uid. */ 1010 /* Permanently switch to the desired uid. */
981 permanently_set_uid(pw->pw_uid); 1011 permanently_set_uid(pw->pw_uid);
1012# endif /* HAVE_LOGIN_CAP */
982 } 1013 }
1014#endif /* HAVE_OSF_SIA */
1015
983 if (getuid() != pw->pw_uid || geteuid() != pw->pw_uid) 1016 if (getuid() != pw->pw_uid || geteuid() != pw->pw_uid)
984 fatal("Failed to set uids to %d.", (int) pw->pw_uid); 1017 fatal("Failed to set uids to %d.", (int) pw->pw_uid);
985#endif /* HAVE_OSF_SIA */
986 } 1018 }
987 /* 1019 /*
988 * Get the shell from the password data. An empty shell field is 1020 * Get the shell from the password data. An empty shell field is
989 * legal, and means /bin/sh. 1021 * legal, and means /bin/sh.
990 */ 1022 */
991 shell = (pw->pw_shell[0] == '\0') ? _PATH_BSHELL : pw->pw_shell; 1023 shell = (pw->pw_shell[0] == '\0') ? _PATH_BSHELL : pw->pw_shell;
1024#ifdef HAVE_LOGIN_CAP
1025 shell = login_getcapstr(lc, "shell", (char *)shell, (char *)shell);
1026#endif
992 1027
993#ifdef AFS 1028#ifdef AFS
994 /* Try to get AFS tokens for the local cell. */ 1029 /* Try to get AFS tokens for the local cell. */
@@ -1012,7 +1047,12 @@ do_child(const char *command, struct passwd * pw, const char *term,
1012 child_set_env(&env, &envsize, "USER", pw->pw_name); 1047 child_set_env(&env, &envsize, "USER", pw->pw_name);
1013 child_set_env(&env, &envsize, "LOGNAME", pw->pw_name); 1048 child_set_env(&env, &envsize, "LOGNAME", pw->pw_name);
1014 child_set_env(&env, &envsize, "HOME", pw->pw_dir); 1049 child_set_env(&env, &envsize, "HOME", pw->pw_dir);
1050#ifdef HAVE_LOGIN_CAP
1051 (void) setusercontext(lc, pw, pw->pw_uid, LOGIN_SETPATH);
1052 child_set_env(&env, &envsize, "PATH", getenv("PATH"));
1053#else
1015 child_set_env(&env, &envsize, "PATH", _PATH_STDPATH); 1054 child_set_env(&env, &envsize, "PATH", _PATH_STDPATH);
1055#endif
1016 1056
1017 snprintf(buf, sizeof buf, "%.200s/%.50s", 1057 snprintf(buf, sizeof buf, "%.200s/%.50s",
1018 _PATH_MAILDIR, pw->pw_name); 1058 _PATH_MAILDIR, pw->pw_name);
@@ -1096,6 +1136,9 @@ do_child(const char *command, struct passwd * pw, const char *term,
1096 for (i = 0; env[i]; i++) 1136 for (i = 0; env[i]; i++)
1097 fprintf(stderr, " %.200s\n", env[i]); 1137 fprintf(stderr, " %.200s\n", env[i]);
1098 } 1138 }
1139 /* we have to stash the hostname before we close our socket. */
1140 if (options.use_login)
1141 hostname = get_remote_name_or_ip();
1099 /* 1142 /*
1100 * Close the connection descriptors; note that this is the child, and 1143 * Close the connection descriptors; note that this is the child, and
1101 * the server will still have the socket open, and it is important 1144 * the server will still have the socket open, and it is important
@@ -1132,9 +1175,14 @@ do_child(const char *command, struct passwd * pw, const char *term,
1132 close(i); 1175 close(i);
1133 1176
1134 /* Change current directory to the user\'s home directory. */ 1177 /* Change current directory to the user\'s home directory. */
1135 if (chdir(pw->pw_dir) < 0) 1178 if (chdir(pw->pw_dir) < 0) {
1136 fprintf(stderr, "Could not chdir to home directory %s: %s\n", 1179 fprintf(stderr, "Could not chdir to home directory %s: %s\n",
1137 pw->pw_dir, strerror(errno)); 1180 pw->pw_dir, strerror(errno));
1181#ifdef HAVE_LOGIN_CAP
1182 if (login_getcapbool(lc, "requirehome", 0))
1183 exit(1);
1184#endif
1185 }
1138 1186
1139 /* 1187 /*
1140 * Must take new environment into use so that .ssh/rc, /etc/sshrc and 1188 * Must take new environment into use so that .ssh/rc, /etc/sshrc and
@@ -1252,8 +1300,7 @@ do_child(const char *command, struct passwd * pw, const char *term,
1252 } else { 1300 } else {
1253 /* Launch login(1). */ 1301 /* Launch login(1). */
1254 1302
1255 execl(LOGIN_PROGRAM, "login", 1303 execl(LOGIN_PROGRAM, "login", "-h", hostname,
1256 "-h", get_remote_name_or_ip(),
1257 "-p", "-f", "--", pw->pw_name, NULL); 1304 "-p", "-f", "--", pw->pw_name, NULL);
1258 1305
1259 /* Login couldn't be executed, die. */ 1306 /* Login couldn't be executed, die. */
@@ -1790,6 +1837,8 @@ session_proctitle(Session *s)
1790void 1837void
1791do_authenticated2(void) 1838do_authenticated2(void)
1792{ 1839{
1840 struct passwd *pw;
1841
1793 /* 1842 /*
1794 * Cancel the alarm we set to limit the time taken for 1843 * Cancel the alarm we set to limit the time taken for
1795 * authentication. 1844 * authentication.
@@ -1799,6 +1848,13 @@ do_authenticated2(void)
1799 close(startup_pipe); 1848 close(startup_pipe);
1800 startup_pipe = -1; 1849 startup_pipe = -1;
1801 } 1850 }
1851#ifdef HAVE_LOGIN_CAP
1852 pw = auth_get_user();
1853 if ((lc = login_getclass(pw->pw_class)) == NULL) {
1854 error("unable to get login class");
1855 return;
1856 }
1857#endif
1802 server_loop2(); 1858 server_loop2();
1803 if (xauthfile) 1859 if (xauthfile)
1804 xauthfile_cleanup_proc(NULL); 1860 xauthfile_cleanup_proc(NULL);
diff --git a/ssh-add.1 b/ssh-add.1
index 5d2f2497a..d2d0c205a 100644
--- a/ssh-add.1
+++ b/ssh-add.1
@@ -9,21 +9,21 @@
9.\" 9.\"
10.\" Created: Sat Apr 22 23:55:14 1995 ylo 10.\" Created: Sat Apr 22 23:55:14 1995 ylo
11.\" 11.\"
12.\" $Id: ssh-add.1,v 1.13 2000/05/07 02:03:18 damien Exp $ 12.\" $Id: ssh-add.1,v 1.14 2000/08/23 00:46:24 djm Exp $
13.\" 13.\"
14.Dd September 25, 1999 14.Dd September 25, 1999
15.Dt SSH-ADD 1 15.Dt SSH-ADD 1
16.Os 16.Os
17.Sh NAME 17.Sh NAME
18.Nm ssh-add 18.Nm ssh-add
19.Nd adds RSA identities for the authentication agent 19.Nd adds RSA or DSA identities for the authentication agent
20.Sh SYNOPSIS 20.Sh SYNOPSIS
21.Nm ssh-add 21.Nm ssh-add
22.Op Fl lLdD 22.Op Fl lLdD
23.Op Ar 23.Op Ar
24.Sh DESCRIPTION 24.Sh DESCRIPTION
25.Nm 25.Nm
26adds RSA identities to the authentication agent, 26adds RSA or DSA identities to the authentication agent,
27.Xr ssh-agent 1 . 27.Xr ssh-agent 1 .
28When run without arguments, it adds the file 28When run without arguments, it adds the file
29.Pa $HOME/.ssh/identity . 29.Pa $HOME/.ssh/identity .
@@ -63,6 +63,8 @@ used to encrypt the private part of this file.
63This is the default file added by 63This is the default file added by
64.Nm 64.Nm
65when no other files have been specified. 65when no other files have been specified.
66.It Pa $HOME/.ssh/id_dsa
67Contains the DSA authentication identity of the user.
66.Pp 68.Pp
67.Sh ENVIRONMENT 69.Sh ENVIRONMENT
68.Bl -tag -width Ds 70.Bl -tag -width Ds
diff --git a/ssh-add.c b/ssh-add.c
index 482229c22..a51f477a5 100644
--- a/ssh-add.c
+++ b/ssh-add.c
@@ -4,18 +4,21 @@
4 * All rights reserved 4 * All rights reserved
5 * Created: Thu Apr 6 00:52:24 1995 ylo 5 * Created: Thu Apr 6 00:52:24 1995 ylo
6 * Adds an identity to the authentication server, or removes an identity. 6 * Adds an identity to the authentication server, or removes an identity.
7 *
8 * SSH2 implementation,
9 * Copyright (c) 2000 Markus Friedl. All rights reserved.
7 */ 10 */
8 11
9#include "includes.h" 12#include "includes.h"
10RCSID("$OpenBSD: ssh-add.c,v 1.18 2000/07/16 08:27:21 markus Exp $"); 13RCSID("$OpenBSD: ssh-add.c,v 1.19 2000/08/19 21:34:43 markus Exp $");
11 14
15#include <openssl/evp.h>
12#include <openssl/rsa.h> 16#include <openssl/rsa.h>
13#include <openssl/dsa.h> 17#include <openssl/dsa.h>
14 18
15#include "rsa.h" 19#include "rsa.h"
16#include "ssh.h" 20#include "ssh.h"
17#include "xmalloc.h" 21#include "xmalloc.h"
18#include "fingerprint.h"
19#include "key.h" 22#include "key.h"
20#include "authfd.h" 23#include "authfd.h"
21#include "authfile.h" 24#include "authfile.h"
@@ -37,7 +40,7 @@ delete_file(AuthenticationConnection *ac, const char *filename)
37 printf("Bad key file %s: %s\n", filename, strerror(errno)); 40 printf("Bad key file %s: %s\n", filename, strerror(errno));
38 return; 41 return;
39 } 42 }
40 if (ssh_remove_identity(ac, public->rsa)) 43 if (ssh_remove_identity(ac, public))
41 fprintf(stderr, "Identity removed: %s (%s)\n", filename, comment); 44 fprintf(stderr, "Identity removed: %s (%s)\n", filename, comment);
42 else 45 else
43 fprintf(stderr, "Could not remove identity: %s\n", filename); 46 fprintf(stderr, "Could not remove identity: %s\n", filename);
@@ -45,11 +48,18 @@ delete_file(AuthenticationConnection *ac, const char *filename)
45 xfree(comment); 48 xfree(comment);
46} 49}
47 50
51/* Send a request to remove all identities. */
48void 52void
49delete_all(AuthenticationConnection *ac) 53delete_all(AuthenticationConnection *ac)
50{ 54{
51 /* Send a request to remove all identities. */ 55 int success = 1;
52 if (ssh_remove_all_identities(ac)) 56
57 if (!ssh_remove_all_identities(ac, 1))
58 success = 0;
59 /* ignore error-code for ssh2 */
60 ssh_remove_all_identities(ac, 2);
61
62 if (success)
53 fprintf(stderr, "All identities removed.\n"); 63 fprintf(stderr, "All identities removed.\n");
54 else 64 else
55 fprintf(stderr, "Failed to remove all identitities.\n"); 65 fprintf(stderr, "Failed to remove all identitities.\n");
@@ -96,6 +106,7 @@ ssh_askpass(char *askpass, char *msg)
96void 106void
97add_file(AuthenticationConnection *ac, const char *filename) 107add_file(AuthenticationConnection *ac, const char *filename)
98{ 108{
109 struct stat st;
99 Key *public; 110 Key *public;
100 Key *private; 111 Key *private;
101 char *saved_comment, *comment, *askpass = NULL; 112 char *saved_comment, *comment, *askpass = NULL;
@@ -104,6 +115,10 @@ add_file(AuthenticationConnection *ac, const char *filename)
104 int interactive = isatty(STDIN_FILENO); 115 int interactive = isatty(STDIN_FILENO);
105 int type = KEY_RSA; 116 int type = KEY_RSA;
106 117
118 if (stat(filename, &st) < 0) {
119 perror(filename);
120 exit(1);
121 }
107 /* 122 /*
108 * try to load the public key. right now this only works for RSA, 123 * try to load the public key. right now this only works for RSA,
109 * since DSA keys are fully encrypted 124 * since DSA keys are fully encrypted
@@ -154,54 +169,40 @@ add_file(AuthenticationConnection *ac, const char *filename)
154 strlcpy(msg, "Bad passphrase, try again", sizeof msg); 169 strlcpy(msg, "Bad passphrase, try again", sizeof msg);
155 } 170 }
156 } 171 }
157 xfree(saved_comment); 172 xfree(comment);
158 173 if (ssh_add_identity(ac, private, saved_comment))
159 if (ssh_add_identity(ac, private, comment)) 174 fprintf(stderr, "Identity added: %s (%s)\n", filename, saved_comment);
160 fprintf(stderr, "Identity added: %s (%s)\n", filename, comment);
161 else 175 else
162 fprintf(stderr, "Could not add identity: %s\n", filename); 176 fprintf(stderr, "Could not add identity: %s\n", filename);
163 key_free(private); 177 key_free(private);
164 xfree(comment); 178 xfree(saved_comment);
165} 179}
166 180
167void 181void
168list_identities(AuthenticationConnection *ac, int fp) 182list_identities(AuthenticationConnection *ac, int fp)
169{ 183{
170 BIGNUM *e, *n; 184 Key *key;
171 int status;
172 char *comment; 185 char *comment;
173 int had_identities; 186 int had_identities = 0;
187 int version;
174 188
175 e = BN_new(); 189 for (version = 1; version <= 2; version++) {
176 n = BN_new(); 190 for (key = ssh_get_first_identity(ac, &comment, version);
177 had_identities = 0; 191 key != NULL;
178 for (status = ssh_get_first_identity(ac, e, n, &comment); 192 key = ssh_get_next_identity(ac, &comment, version)) {
179 status; 193 had_identities = 1;
180 status = ssh_get_next_identity(ac, e, n, &comment)) { 194 if (fp) {
181 unsigned int bits = BN_num_bits(n); 195 printf("%d %s %s\n",
182 had_identities = 1; 196 key_size(key), key_fingerprint(key), comment);
183 if (fp) {
184 printf("%d %s %s\n", bits, fingerprint(e, n), comment);
185 } else {
186 char *ebuf, *nbuf;
187 ebuf = BN_bn2dec(e);
188 if (ebuf == NULL) {
189 error("list_identities: BN_bn2dec(e) failed.");
190 } else { 197 } else {
191 nbuf = BN_bn2dec(n); 198 if (!key_write(key, stdout))
192 if (nbuf == NULL) { 199 fprintf(stderr, "key_write failed");
193 error("list_identities: BN_bn2dec(n) failed."); 200 fprintf(stdout, " %s\n", comment);
194 } else {
195 printf("%d %s %s %s\n", bits, ebuf, nbuf, comment);
196 free(nbuf);
197 }
198 free(ebuf);
199 } 201 }
202 key_free(key);
203 xfree(comment);
200 } 204 }
201 xfree(comment);
202 } 205 }
203 BN_clear_free(e);
204 BN_clear_free(n);
205 if (!had_identities) 206 if (!had_identities)
206 printf("The agent has no identities.\n"); 207 printf("The agent has no identities.\n");
207} 208}
@@ -225,6 +226,8 @@ main(int argc, char **argv)
225 __progname); 226 __progname);
226 exit(1); 227 exit(1);
227 } 228 }
229 SSLeay_add_all_algorithms();
230
228 /* At first, get a connection to the authentication agent. */ 231 /* At first, get a connection to the authentication agent. */
229 ac = ssh_get_authentication_connection(); 232 ac = ssh_get_authentication_connection();
230 if (ac == NULL) { 233 if (ac == NULL) {
diff --git a/ssh-agent.1 b/ssh-agent.1
index 47b1e5cc5..0aa1ecf49 100644
--- a/ssh-agent.1
+++ b/ssh-agent.1
@@ -1,4 +1,4 @@
1.\" $OpenBSD: ssh-agent.1,v 1.13 2000/07/06 04:06:56 aaron Exp $ 1.\" $OpenBSD: ssh-agent.1,v 1.14 2000/08/19 21:34:43 markus Exp $
2.\" 2.\"
3.\" -*- nroff -*- 3.\" -*- nroff -*-
4.\" 4.\"
@@ -27,14 +27,15 @@
27.Oc 27.Oc
28.Sh DESCRIPTION 28.Sh DESCRIPTION
29.Nm 29.Nm
30is a program to hold private keys used for RSA authentication. 30is a program to hold private keys used for public key authentication
31(RSA, DSA).
31The idea is that 32The idea is that
32.Nm 33.Nm
33is started in the beginning of an X-session or a login session, and 34is started in the beginning of an X-session or a login session, and
34all other windows or programs are started as clients to the ssh-agent 35all other windows or programs are started as clients to the ssh-agent
35program. 36program.
36Through use of environment variables the agent can be located 37Through use of environment variables the agent can be located
37and automatically used for RSA authentication when logging in to other 38and automatically used for authentication when logging in to other
38machines using 39machines using
39.Xr ssh 1 . 40.Xr ssh 1 .
40.Pp 41.Pp
@@ -128,7 +129,9 @@ This file is not used by
128but is normally added to the agent using 129but is normally added to the agent using
129.Xr ssh-add 1 130.Xr ssh-add 1
130at login time. 131at login time.
131.It Pa /tmp/ssh-XXXX/agent.<pid> , 132.It Pa $HOME/.ssh/id_dsa
133Contains the DSA authentication identity of the user.
134.Pq Pa /tmp/ssh-XXXXXXXX/agent.<pid> ,
132Unix-domain sockets used to contain the connection to the 135Unix-domain sockets used to contain the connection to the
133authentication agent. 136authentication agent.
134These sockets should only be readable by the owner. 137These sockets should only be readable by the owner.
diff --git a/ssh-agent.c b/ssh-agent.c
index e8383b5df..56b81a78d 100644
--- a/ssh-agent.c
+++ b/ssh-agent.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: ssh-agent.c,v 1.32 2000/07/16 08:27:21 markus Exp $ */ 1/* $OpenBSD: ssh-agent.c,v 1.33 2000/08/19 21:34:43 markus Exp $ */
2 2
3/* 3/*
4 * Author: Tatu Ylonen <ylo@cs.hut.fi> 4 * Author: Tatu Ylonen <ylo@cs.hut.fi>
@@ -6,10 +6,13 @@
6 * All rights reserved 6 * All rights reserved
7 * Created: Wed Mar 29 03:46:59 1995 ylo 7 * Created: Wed Mar 29 03:46:59 1995 ylo
8 * The authentication agent program. 8 * The authentication agent program.
9 *
10 * SSH2 implementation,
11 * Copyright (c) 2000 Markus Friedl. All rights reserved.
9 */ 12 */
10 13
11#include "includes.h" 14#include "includes.h"
12RCSID("$OpenBSD: ssh-agent.c,v 1.32 2000/07/16 08:27:21 markus Exp $"); 15RCSID("$OpenBSD: ssh-agent.c,v 1.33 2000/08/19 21:34:43 markus Exp $");
13 16
14#include "ssh.h" 17#include "ssh.h"
15#include "rsa.h" 18#include "rsa.h"
@@ -20,11 +23,14 @@ RCSID("$OpenBSD: ssh-agent.c,v 1.32 2000/07/16 08:27:21 markus Exp $");
20#include "getput.h" 23#include "getput.h"
21#include "mpaux.h" 24#include "mpaux.h"
22 25
26#include <openssl/evp.h>
23#include <openssl/md5.h> 27#include <openssl/md5.h>
24#include <openssl/dsa.h> 28#include <openssl/dsa.h>
25#include <openssl/rsa.h> 29#include <openssl/rsa.h>
26#include "key.h" 30#include "key.h"
27#include "authfd.h" 31#include "authfd.h"
32#include "dsa.h"
33#include "kex.h"
28 34
29typedef struct { 35typedef struct {
30 int fd; 36 int fd;
@@ -39,12 +45,17 @@ unsigned int sockets_alloc = 0;
39SocketEntry *sockets = NULL; 45SocketEntry *sockets = NULL;
40 46
41typedef struct { 47typedef struct {
42 RSA *key; 48 Key *key;
43 char *comment; 49 char *comment;
44} Identity; 50} Identity;
45 51
46unsigned int num_identities = 0; 52typedef struct {
47Identity *identities = NULL; 53 int nentries;
54 Identity *identities;
55} Idtab;
56
57/* private key table, one per protocol version */
58Idtab idtable[3];
48 59
49int max_fd = 0; 60int max_fd = 0;
50 61
@@ -62,175 +73,243 @@ static const char *__progname = "ssh-agent";
62#endif /* HAVE___PROGNAME */ 73#endif /* HAVE___PROGNAME */
63 74
64void 75void
65process_request_identity(SocketEntry *e) 76idtab_init(void)
77{
78 int i;
79 for (i = 0; i <=2; i++){
80 idtable[i].identities = NULL;
81 idtable[i].nentries = 0;
82 }
83}
84
85/* return private key table for requested protocol version */
86Idtab *
87idtab_lookup(int version)
88{
89 if (version < 1 || version > 2)
90 fatal("internal error, bad protocol version %d", version);
91 return &idtable[version];
92}
93
94/* return matching private key for given public key */
95Key *
96lookup_private_key(Key *key, int *idx, int version)
97{
98 int i;
99 Idtab *tab = idtab_lookup(version);
100 for (i = 0; i < tab->nentries; i++) {
101 if (key_equal(key, tab->identities[i].key)) {
102 if (idx != NULL)
103 *idx = i;
104 return tab->identities[i].key;
105 }
106 }
107 return NULL;
108}
109
110/* send list of supported public keys to 'client' */
111void
112process_request_identities(SocketEntry *e, int version)
66{ 113{
114 Idtab *tab = idtab_lookup(version);
67 Buffer msg; 115 Buffer msg;
68 int i; 116 int i;
69 117
70 buffer_init(&msg); 118 buffer_init(&msg);
71 buffer_put_char(&msg, SSH_AGENT_RSA_IDENTITIES_ANSWER); 119 buffer_put_char(&msg, (version == 1) ?
72 buffer_put_int(&msg, num_identities); 120 SSH_AGENT_RSA_IDENTITIES_ANSWER : SSH2_AGENT_IDENTITIES_ANSWER);
73 for (i = 0; i < num_identities; i++) { 121 buffer_put_int(&msg, tab->nentries);
74 buffer_put_int(&msg, BN_num_bits(identities[i].key->n)); 122 for (i = 0; i < tab->nentries; i++) {
75 buffer_put_bignum(&msg, identities[i].key->e); 123 Identity *id = &tab->identities[i];
76 buffer_put_bignum(&msg, identities[i].key->n); 124 if (id->key->type == KEY_RSA) {
77 buffer_put_string(&msg, identities[i].comment, 125 buffer_put_int(&msg, BN_num_bits(id->key->rsa->n));
78 strlen(identities[i].comment)); 126 buffer_put_bignum(&msg, id->key->rsa->e);
127 buffer_put_bignum(&msg, id->key->rsa->n);
128 } else {
129 unsigned char *blob;
130 unsigned int blen;
131 dsa_make_key_blob(id->key, &blob, &blen);
132 buffer_put_string(&msg, blob, blen);
133 xfree(blob);
134 }
135 buffer_put_cstring(&msg, id->comment);
79 } 136 }
80 buffer_put_int(&e->output, buffer_len(&msg)); 137 buffer_put_int(&e->output, buffer_len(&msg));
81 buffer_append(&e->output, buffer_ptr(&msg), buffer_len(&msg)); 138 buffer_append(&e->output, buffer_ptr(&msg), buffer_len(&msg));
82 buffer_free(&msg); 139 buffer_free(&msg);
83} 140}
84 141
142/* ssh1 only */
85void 143void
86process_authentication_challenge(SocketEntry *e) 144process_authentication_challenge1(SocketEntry *e)
87{ 145{
88 int i, pub_bits, len; 146 Key *key, *private;
89 BIGNUM *pub_e, *pub_n, *challenge; 147 BIGNUM *challenge;
148 int i, len;
90 Buffer msg; 149 Buffer msg;
91 MD5_CTX md; 150 MD5_CTX md;
92 unsigned char buf[32], mdbuf[16], session_id[16]; 151 unsigned char buf[32], mdbuf[16], session_id[16];
93 unsigned int response_type; 152 unsigned int response_type;
94 153
95 buffer_init(&msg); 154 buffer_init(&msg);
96 pub_e = BN_new(); 155 key = key_new(KEY_RSA);
97 pub_n = BN_new();
98 challenge = BN_new(); 156 challenge = BN_new();
99 pub_bits = buffer_get_int(&e->input);
100 buffer_get_bignum(&e->input, pub_e);
101 buffer_get_bignum(&e->input, pub_n);
102 buffer_get_bignum(&e->input, challenge);
103 if (buffer_len(&e->input) == 0) {
104 /* Compatibility code for old servers. */
105 memset(session_id, 0, 16);
106 response_type = 0;
107 } else {
108 /* New code. */
109 buffer_get(&e->input, (char *) session_id, 16);
110 response_type = buffer_get_int(&e->input);
111 }
112 for (i = 0; i < num_identities; i++)
113 if (pub_bits == BN_num_bits(identities[i].key->n) &&
114 BN_cmp(pub_e, identities[i].key->e) == 0 &&
115 BN_cmp(pub_n, identities[i].key->n) == 0) {
116 /* Decrypt the challenge using the private key. */
117 rsa_private_decrypt(challenge, challenge, identities[i].key);
118
119 /* Compute the desired response. */
120 switch (response_type) {
121 case 0:/* As of protocol 1.0 */
122 /* This response type is no longer supported. */
123 log("Compatibility with ssh protocol 1.0 no longer supported.");
124 buffer_put_char(&msg, SSH_AGENT_FAILURE);
125 goto send;
126
127 case 1:/* As of protocol 1.1 */
128 /* The response is MD5 of decrypted challenge plus session id. */
129 len = BN_num_bytes(challenge);
130
131 if (len <= 0 || len > 32) {
132 fatal("process_authentication_challenge: "
133 "bad challenge length %d", len);
134 }
135 memset(buf, 0, 32);
136 BN_bn2bin(challenge, buf + 32 - len);
137 MD5_Init(&md);
138 MD5_Update(&md, buf, 32);
139 MD5_Update(&md, session_id, 16);
140 MD5_Final(mdbuf, &md);
141 break;
142
143 default:
144 fatal("process_authentication_challenge: bad response_type %d",
145 response_type);
146 break;
147 }
148 157
149 /* Send the response. */ 158 buffer_get_int(&e->input); /* ignored */
150 buffer_put_char(&msg, SSH_AGENT_RSA_RESPONSE); 159 buffer_get_bignum(&e->input, key->rsa->e);
151 for (i = 0; i < 16; i++) 160 buffer_get_bignum(&e->input, key->rsa->n);
152 buffer_put_char(&msg, mdbuf[i]); 161 buffer_get_bignum(&e->input, challenge);
153 162
154 goto send; 163 /* Only protocol 1.1 is supported */
164 if (buffer_len(&e->input) == 0)
165 goto failure;
166 buffer_get(&e->input, (char *) session_id, 16);
167 response_type = buffer_get_int(&e->input);
168 if (response_type != 1)
169 goto failure;
170
171 private = lookup_private_key(key, NULL, 1);
172 if (private != NULL) {
173 /* Decrypt the challenge using the private key. */
174 rsa_private_decrypt(challenge, challenge, private->rsa);
175
176 /* The response is MD5 of decrypted challenge plus session id. */
177 len = BN_num_bytes(challenge);
178 if (len <= 0 || len > 32) {
179 log("process_authentication_challenge: bad challenge length %d", len);
180 goto failure;
155 } 181 }
156 /* Unknown identity. Send failure. */ 182 memset(buf, 0, 32);
183 BN_bn2bin(challenge, buf + 32 - len);
184 MD5_Init(&md);
185 MD5_Update(&md, buf, 32);
186 MD5_Update(&md, session_id, 16);
187 MD5_Final(mdbuf, &md);
188
189 /* Send the response. */
190 buffer_put_char(&msg, SSH_AGENT_RSA_RESPONSE);
191 for (i = 0; i < 16; i++)
192 buffer_put_char(&msg, mdbuf[i]);
193 goto send;
194 }
195
196failure:
197 /* Unknown identity or protocol error. Send failure. */
157 buffer_put_char(&msg, SSH_AGENT_FAILURE); 198 buffer_put_char(&msg, SSH_AGENT_FAILURE);
158send: 199send:
159 buffer_put_int(&e->output, buffer_len(&msg)); 200 buffer_put_int(&e->output, buffer_len(&msg));
201 buffer_append(&e->output, buffer_ptr(&msg), buffer_len(&msg));
202 key_free(key);
203 BN_clear_free(challenge);
204 buffer_free(&msg);
205}
206
207/* ssh2 only */
208void
209process_sign_request2(SocketEntry *e)
210{
211 extern int datafellows;
212 Key *key, *private;
213 unsigned char *blob, *data, *signature = NULL;
214 unsigned int blen, dlen, slen = 0;
215 Buffer msg;
216 int ok = -1;
217
218 datafellows = 0;
219
220 blob = buffer_get_string(&e->input, &blen);
221 data = buffer_get_string(&e->input, &dlen);
222
223 key = dsa_key_from_blob(blob, blen);
224 if (key != NULL) {
225 private = lookup_private_key(key, NULL, 2);
226 if (private != NULL)
227 ok = dsa_sign(private, &signature, &slen, data, dlen);
228 }
229 key_free(key);
230 buffer_init(&msg);
231 if (ok == 0) {
232 buffer_put_char(&msg, SSH2_AGENT_SIGN_RESPONSE);
233 buffer_put_string(&msg, signature, slen);
234 } else {
235 buffer_put_char(&msg, SSH_AGENT_FAILURE);
236 }
237 buffer_put_int(&e->output, buffer_len(&msg));
160 buffer_append(&e->output, buffer_ptr(&msg), 238 buffer_append(&e->output, buffer_ptr(&msg),
161 buffer_len(&msg)); 239 buffer_len(&msg));
162 buffer_free(&msg); 240 buffer_free(&msg);
163 BN_clear_free(pub_e); 241 xfree(data);
164 BN_clear_free(pub_n); 242 xfree(blob);
165 BN_clear_free(challenge); 243 if (signature != NULL)
244 xfree(signature);
166} 245}
167 246
247/* shared */
168void 248void
169process_remove_identity(SocketEntry *e) 249process_remove_identity(SocketEntry *e, int version)
170{ 250{
251 Key *key = NULL, *private;
252 unsigned char *blob;
253 unsigned int blen;
171 unsigned int bits; 254 unsigned int bits;
172 unsigned int i; 255 int success = 0;
173 BIGNUM *dummy, *n; 256
174 257 switch(version){
175 dummy = BN_new(); 258 case 1:
176 n = BN_new(); 259 key = key_new(KEY_RSA);
177 260 bits = buffer_get_int(&e->input);
178 /* Get the key from the packet. */ 261 buffer_get_bignum(&e->input, key->rsa->e);
179 bits = buffer_get_int(&e->input); 262 buffer_get_bignum(&e->input, key->rsa->n);
180 buffer_get_bignum(&e->input, dummy); 263
181 buffer_get_bignum(&e->input, n); 264 if (bits != key_size(key))
182 265 log("Warning: identity keysize mismatch: actual %d, announced %d",
183 if (bits != BN_num_bits(n)) 266 key_size(key), bits);
184 log("Warning: identity keysize mismatch: actual %d, announced %d", 267 break;
185 BN_num_bits(n), bits); 268 case 2:
186 269 blob = buffer_get_string(&e->input, &blen);
187 /* Check if we have the key. */ 270 key = dsa_key_from_blob(blob, blen);
188 for (i = 0; i < num_identities; i++) 271 xfree(blob);
189 if (BN_cmp(identities[i].key->n, n) == 0) { 272 break;
273 }
274 if (key != NULL) {
275 int idx;
276 private = lookup_private_key(key, &idx, version);
277 if (private != NULL) {
190 /* 278 /*
191 * We have this key. Free the old key. Since we 279 * We have this key. Free the old key. Since we
192 * don\'t want to leave empty slots in the middle of 280 * don\'t want to leave empty slots in the middle of
193 * the array, we actually free the key there and copy 281 * the array, we actually free the key there and copy
194 * data from the last entry. 282 * data from the last entry.
195 */ 283 */
196 RSA_free(identities[i].key); 284 Idtab *tab = idtab_lookup(version);
197 xfree(identities[i].comment); 285 key_free(tab->identities[idx].key);
198 if (i < num_identities - 1) 286 xfree(tab->identities[idx].comment);
199 identities[i] = identities[num_identities - 1]; 287 if (idx != tab->nentries)
200 num_identities--; 288 tab->identities[idx] = tab->identities[tab->nentries];
201 BN_clear_free(dummy); 289 tab->nentries--;
202 BN_clear_free(n); 290 success = 1;
203
204 /* Send success. */
205 buffer_put_int(&e->output, 1);
206 buffer_put_char(&e->output, SSH_AGENT_SUCCESS);
207 return;
208 } 291 }
209 /* We did not have the key. */ 292 key_free(key);
210 BN_clear(dummy); 293 }
211 BN_clear(n);
212
213 /* Send failure. */
214 buffer_put_int(&e->output, 1); 294 buffer_put_int(&e->output, 1);
215 buffer_put_char(&e->output, SSH_AGENT_FAILURE); 295 buffer_put_char(&e->output,
296 success ? SSH_AGENT_SUCCESS : SSH_AGENT_FAILURE);
216} 297}
217 298
218/*
219 * Removes all identities from the agent.
220 */
221void 299void
222process_remove_all_identities(SocketEntry *e) 300process_remove_all_identities(SocketEntry *e, int version)
223{ 301{
224 unsigned int i; 302 unsigned int i;
303 Idtab *tab = idtab_lookup(version);
225 304
226 /* Loop over all identities and clear the keys. */ 305 /* Loop over all identities and clear the keys. */
227 for (i = 0; i < num_identities; i++) { 306 for (i = 0; i < tab->nentries; i++) {
228 RSA_free(identities[i].key); 307 key_free(tab->identities[i].key);
229 xfree(identities[i].comment); 308 xfree(tab->identities[i].comment);
230 } 309 }
231 310
232 /* Mark that there are no identities. */ 311 /* Mark that there are no identities. */
233 num_identities = 0; 312 tab->nentries = 0;
234 313
235 /* Send success. */ 314 /* Send success. */
236 buffer_put_int(&e->output, 1); 315 buffer_put_int(&e->output, 1);
@@ -238,79 +317,108 @@ process_remove_all_identities(SocketEntry *e)
238 return; 317 return;
239} 318}
240 319
241/*
242 * Adds an identity to the agent.
243 */
244void 320void
245process_add_identity(SocketEntry *e) 321process_add_identity(SocketEntry *e, int version)
246{ 322{
247 RSA *k; 323 Key *k = NULL;
248 int i; 324 RSA *rsa;
249 BIGNUM *aux; 325 BIGNUM *aux;
250 BN_CTX *ctx; 326 BN_CTX *ctx;
327 char *type;
328 char *comment;
329 int success = 0;
330 Idtab *tab = idtab_lookup(version);
251 331
252 if (num_identities == 0) 332 switch (version) {
253 identities = xmalloc(sizeof(Identity)); 333 case 1:
254 else 334 k = key_new(KEY_RSA);
255 identities = xrealloc(identities, (num_identities + 1) * sizeof(Identity)); 335 rsa = k->rsa;
256
257 identities[num_identities].key = RSA_new();
258 k = identities[num_identities].key;
259 buffer_get_int(&e->input); /* bits */
260 k->n = BN_new();
261 buffer_get_bignum(&e->input, k->n);
262 k->e = BN_new();
263 buffer_get_bignum(&e->input, k->e);
264 k->d = BN_new();
265 buffer_get_bignum(&e->input, k->d);
266 k->iqmp = BN_new();
267 buffer_get_bignum(&e->input, k->iqmp);
268 /* SSH and SSL have p and q swapped */
269 k->q = BN_new();
270 buffer_get_bignum(&e->input, k->q); /* p */
271 k->p = BN_new();
272 buffer_get_bignum(&e->input, k->p); /* q */
273
274 /* Generate additional parameters */
275 aux = BN_new();
276 ctx = BN_CTX_new();
277
278 BN_sub(aux, k->q, BN_value_one());
279 k->dmq1 = BN_new();
280 BN_mod(k->dmq1, k->d, aux, ctx);
281
282 BN_sub(aux, k->p, BN_value_one());
283 k->dmp1 = BN_new();
284 BN_mod(k->dmp1, k->d, aux, ctx);
285
286 BN_clear_free(aux);
287 BN_CTX_free(ctx);
288
289 identities[num_identities].comment = buffer_get_string(&e->input, NULL);
290
291 /* Check if we already have the key. */
292 for (i = 0; i < num_identities; i++)
293 if (BN_cmp(identities[i].key->n, k->n) == 0) {
294 /*
295 * We already have this key. Clear and free the new
296 * data and return success.
297 */
298 RSA_free(k);
299 xfree(identities[num_identities].comment);
300 336
301 /* Send success. */ 337 /* allocate mem for private key */
302 buffer_put_int(&e->output, 1); 338 /* XXX rsa->n and rsa->e are already allocated */
303 buffer_put_char(&e->output, SSH_AGENT_SUCCESS); 339 rsa->d = BN_new();
304 return; 340 rsa->iqmp = BN_new();
341 rsa->q = BN_new();
342 rsa->p = BN_new();
343 rsa->dmq1 = BN_new();
344 rsa->dmp1 = BN_new();
345
346 buffer_get_int(&e->input); /* ignored */
347
348 buffer_get_bignum(&e->input, rsa->n);
349 buffer_get_bignum(&e->input, rsa->e);
350 buffer_get_bignum(&e->input, rsa->d);
351 buffer_get_bignum(&e->input, rsa->iqmp);
352
353 /* SSH and SSL have p and q swapped */
354 buffer_get_bignum(&e->input, rsa->q); /* p */
355 buffer_get_bignum(&e->input, rsa->p); /* q */
356
357 /* Generate additional parameters */
358 aux = BN_new();
359 ctx = BN_CTX_new();
360
361 BN_sub(aux, rsa->q, BN_value_one());
362 BN_mod(rsa->dmq1, rsa->d, aux, ctx);
363
364 BN_sub(aux, rsa->p, BN_value_one());
365 BN_mod(rsa->dmp1, rsa->d, aux, ctx);
366
367 BN_clear_free(aux);
368 BN_CTX_free(ctx);
369
370 break;
371 case 2:
372 type = buffer_get_string(&e->input, NULL);
373 if (strcmp(type, KEX_DSS)) {
374 buffer_clear(&e->input);
375 xfree(type);
376 goto send;
305 } 377 }
306 /* Increment the number of identities. */ 378 xfree(type);
307 num_identities++;
308 379
309 /* Send a success message. */ 380 k = key_new(KEY_DSA);
381
382 /* allocate mem for private key */
383 k->dsa->priv_key = BN_new();
384
385 buffer_get_bignum2(&e->input, k->dsa->p);
386 buffer_get_bignum2(&e->input, k->dsa->q);
387 buffer_get_bignum2(&e->input, k->dsa->g);
388 buffer_get_bignum2(&e->input, k->dsa->pub_key);
389 buffer_get_bignum2(&e->input, k->dsa->priv_key);
390
391 break;
392 }
393
394 comment = buffer_get_string(&e->input, NULL);
395 if (k == NULL) {
396 xfree(comment);
397 goto send;
398 }
399 success = 1;
400 if (lookup_private_key(k, NULL, version) == NULL) {
401 if (tab->nentries == 0)
402 tab->identities = xmalloc(sizeof(Identity));
403 else
404 tab->identities = xrealloc(tab->identities,
405 (tab->nentries + 1) * sizeof(Identity));
406 tab->identities[tab->nentries].key = k;
407 tab->identities[tab->nentries].comment = comment;
408 /* Increment the number of identities. */
409 tab->nentries++;
410 } else {
411 key_free(k);
412 xfree(comment);
413 }
414send:
310 buffer_put_int(&e->output, 1); 415 buffer_put_int(&e->output, 1);
311 buffer_put_char(&e->output, SSH_AGENT_SUCCESS); 416 buffer_put_char(&e->output,
417 success ? SSH_AGENT_SUCCESS : SSH_AGENT_FAILURE);
312} 418}
313 419
420/* dispatch incoming messages */
421
314void 422void
315process_message(SocketEntry *e) 423process_message(SocketEntry *e)
316{ 424{
@@ -333,20 +441,37 @@ process_message(SocketEntry *e)
333 type = buffer_get_char(&e->input); 441 type = buffer_get_char(&e->input);
334 442
335 switch (type) { 443 switch (type) {
336 case SSH_AGENTC_REQUEST_RSA_IDENTITIES: 444 /* ssh1 */
337 process_request_identity(e);
338 break;
339 case SSH_AGENTC_RSA_CHALLENGE: 445 case SSH_AGENTC_RSA_CHALLENGE:
340 process_authentication_challenge(e); 446 process_authentication_challenge1(e);
447 break;
448 case SSH_AGENTC_REQUEST_RSA_IDENTITIES:
449 process_request_identities(e, 1);
341 break; 450 break;
342 case SSH_AGENTC_ADD_RSA_IDENTITY: 451 case SSH_AGENTC_ADD_RSA_IDENTITY:
343 process_add_identity(e); 452 process_add_identity(e, 1);
344 break; 453 break;
345 case SSH_AGENTC_REMOVE_RSA_IDENTITY: 454 case SSH_AGENTC_REMOVE_RSA_IDENTITY:
346 process_remove_identity(e); 455 process_remove_identity(e, 1);
347 break; 456 break;
348 case SSH_AGENTC_REMOVE_ALL_RSA_IDENTITIES: 457 case SSH_AGENTC_REMOVE_ALL_RSA_IDENTITIES:
349 process_remove_all_identities(e); 458 process_remove_all_identities(e, 1);
459 break;
460 /* ssh2 */
461 case SSH2_AGENTC_SIGN_REQUEST:
462 process_sign_request2(e);
463 break;
464 case SSH2_AGENTC_REQUEST_IDENTITIES:
465 process_request_identities(e, 2);
466 break;
467 case SSH2_AGENTC_ADD_IDENTITY:
468 process_add_identity(e, 2);
469 break;
470 case SSH2_AGENTC_REMOVE_IDENTITY:
471 process_remove_identity(e, 2);
472 break;
473 case SSH2_AGENTC_REMOVE_ALL_IDENTITIES:
474 process_remove_all_identities(e, 2);
350 break; 475 break;
351 default: 476 default:
352 /* Unknown message. Respond with failure. */ 477 /* Unknown message. Respond with failure. */
@@ -511,9 +636,9 @@ main(int ac, char **av)
511 pid_t pid; 636 pid_t pid;
512 char *shell, *format, *pidstr, pidstrbuf[1 + 3 * sizeof pid]; 637 char *shell, *format, *pidstr, pidstrbuf[1 + 3 * sizeof pid];
513 extern int optind; 638 extern int optind;
514 639
515 init_rng(); 640 init_rng();
516 641
517 /* check if RSA support exists */ 642 /* check if RSA support exists */
518 if (rsa_alive() == 0) { 643 if (rsa_alive() == 0) {
519 fprintf(stderr, 644 fprintf(stderr,
@@ -654,6 +779,7 @@ main(int ac, char **av)
654 signal(SIGALRM, check_parent_exists); 779 signal(SIGALRM, check_parent_exists);
655 alarm(10); 780 alarm(10);
656 } 781 }
782 idtab_init();
657 signal(SIGINT, SIG_IGN); 783 signal(SIGINT, SIG_IGN);
658 signal(SIGPIPE, SIG_IGN); 784 signal(SIGPIPE, SIG_IGN);
659 signal(SIGHUP, cleanup_exit); 785 signal(SIGHUP, cleanup_exit);
diff --git a/ssh-keygen.c b/ssh-keygen.c
index 8a03f0d8d..83450fe84 100644
--- a/ssh-keygen.c
+++ b/ssh-keygen.c
@@ -7,7 +7,7 @@
7 */ 7 */
8 8
9#include "includes.h" 9#include "includes.h"
10RCSID("$OpenBSD: ssh-keygen.c,v 1.29 2000/07/15 04:01:37 djm Exp $"); 10RCSID("$OpenBSD: ssh-keygen.c,v 1.30 2000/08/19 21:34:43 markus Exp $");
11 11
12#include <openssl/evp.h> 12#include <openssl/evp.h>
13#include <openssl/pem.h> 13#include <openssl/pem.h>
@@ -16,7 +16,6 @@ RCSID("$OpenBSD: ssh-keygen.c,v 1.29 2000/07/15 04:01:37 djm Exp $");
16 16
17#include "ssh.h" 17#include "ssh.h"
18#include "xmalloc.h" 18#include "xmalloc.h"
19#include "fingerprint.h"
20#include "key.h" 19#include "key.h"
21#include "rsa.h" 20#include "rsa.h"
22#include "dsa.h" 21#include "dsa.h"
@@ -228,8 +227,9 @@ do_print_public(struct passwd *pw)
228void 227void
229do_fingerprint(struct passwd *pw) 228do_fingerprint(struct passwd *pw)
230{ 229{
230 /* XXX RSA1 only */
231
231 FILE *f; 232 FILE *f;
232 BIGNUM *e, *n;
233 Key *public; 233 Key *public;
234 char *comment = NULL, *cp, *ep, line[16*1024]; 234 char *comment = NULL, *cp, *ep, line[16*1024];
235 int i, skip = 0, num = 1, invalid = 1; 235 int i, skip = 0, num = 1, invalid = 1;
@@ -249,13 +249,9 @@ do_fingerprint(struct passwd *pw)
249 key_free(public); 249 key_free(public);
250 exit(0); 250 exit(0);
251 } 251 }
252 key_free(public);
253 252
254 /* XXX */
255 f = fopen(identity_file, "r"); 253 f = fopen(identity_file, "r");
256 if (f != NULL) { 254 if (f != NULL) {
257 n = BN_new();
258 e = BN_new();
259 while (fgets(line, sizeof(line), f)) { 255 while (fgets(line, sizeof(line), f)) {
260 i = strlen(line) - 1; 256 i = strlen(line) - 1;
261 if (line[i] != '\n') { 257 if (line[i] != '\n') {
@@ -290,18 +286,17 @@ do_fingerprint(struct passwd *pw)
290 *cp++ = '\0'; 286 *cp++ = '\0';
291 } 287 }
292 ep = cp; 288 ep = cp;
293 if (auth_rsa_read_key(&cp, &ignore, e, n)) { 289 if (auth_rsa_read_key(&cp, &ignore, public->rsa->e, public->rsa->n)) {
294 invalid = 0; 290 invalid = 0;
295 comment = *cp ? cp : comment; 291 comment = *cp ? cp : comment;
296 printf("%d %s %s\n", BN_num_bits(n), 292 printf("%d %s %s\n", key_size(public),
297 fingerprint(e, n), 293 key_fingerprint(public),
298 comment ? comment : "no comment"); 294 comment ? comment : "no comment");
299 } 295 }
300 } 296 }
301 BN_free(e);
302 BN_free(n);
303 fclose(f); 297 fclose(f);
304 } 298 }
299 key_free(public);
305 if (invalid) { 300 if (invalid) {
306 printf("%s is not a valid key file.\n", identity_file); 301 printf("%s is not a valid key file.\n", identity_file);
307 exit(1); 302 exit(1);
diff --git a/ssh.c b/ssh.c
index 58e4d7bd9..39512c5f1 100644
--- a/ssh.c
+++ b/ssh.c
@@ -11,7 +11,7 @@
11 */ 11 */
12 12
13#include "includes.h" 13#include "includes.h"
14RCSID("$OpenBSD: ssh.c,v 1.58 2000/07/16 08:27:22 markus Exp $"); 14RCSID("$OpenBSD: ssh.c,v 1.61 2000/08/20 18:42:40 millert Exp $");
15 15
16#include <openssl/evp.h> 16#include <openssl/evp.h>
17#include <openssl/dsa.h> 17#include <openssl/dsa.h>
@@ -253,8 +253,8 @@ main(int ac, char **av)
253 cp = strrchr(av0, '/') + 1; 253 cp = strrchr(av0, '/') + 1;
254 else 254 else
255 cp = av0; 255 cp = av0;
256 if (strcmp(cp, "rsh") != 0 && strcmp(cp, "ssh") != 0 && 256 if (strcmp(cp, "rsh") && strcmp(cp, "ssh") && strcmp(cp, "rlogin") &&
257 strcmp(cp, "rlogin") != 0 && strcmp(cp, "slogin") != 0) 257 strcmp(cp, "slogin") && strcmp(cp, "remsh"))
258 host = cp; 258 host = cp;
259 259
260 for (optind = 1; optind < ac; optind++) { 260 for (optind = 1; optind < ac; optind++) {
@@ -490,6 +490,9 @@ main(int ac, char **av)
490 pwcopy.pw_passwd = xstrdup(pw->pw_passwd); 490 pwcopy.pw_passwd = xstrdup(pw->pw_passwd);
491 pwcopy.pw_uid = pw->pw_uid; 491 pwcopy.pw_uid = pw->pw_uid;
492 pwcopy.pw_gid = pw->pw_gid; 492 pwcopy.pw_gid = pw->pw_gid;
493#ifdef HAVE_PW_CLASS_IN_PASSWD
494 pwcopy.pw_class = xstrdup(pw->pw_class);
495#endif
493 pwcopy.pw_dir = xstrdup(pw->pw_dir); 496 pwcopy.pw_dir = xstrdup(pw->pw_dir);
494 pwcopy.pw_shell = xstrdup(pw->pw_shell); 497 pwcopy.pw_shell = xstrdup(pw->pw_shell);
495 pw = &pwcopy; 498 pw = &pwcopy;
@@ -871,7 +874,7 @@ ssh_session(void)
871 } 874 }
872 875
873 /* Enter the interactive session. */ 876 /* Enter the interactive session. */
874 return client_loop(have_tty, tty_flag ? options.escape_char : -1); 877 return client_loop(have_tty, tty_flag ? options.escape_char : -1, 0);
875} 878}
876 879
877void 880void
@@ -954,9 +957,16 @@ int
954ssh_session2(void) 957ssh_session2(void)
955{ 958{
956 int window, packetmax, id; 959 int window, packetmax, id;
957 int in = dup(STDIN_FILENO); 960 int in, out, err;
958 int out = dup(STDOUT_FILENO); 961
959 int err = dup(STDERR_FILENO); 962 /* If requested, let ssh continue in the background. */
963 if (fork_after_authentication_flag)
964 if (daemon(1, 1) < 0)
965 fatal("daemon() failed: %.200s", strerror(errno));
966
967 in = dup(STDIN_FILENO);
968 out = dup(STDOUT_FILENO);
969 err = dup(STDERR_FILENO);
960 970
961 if (in < 0 || out < 0 || err < 0) 971 if (in < 0 || out < 0 || err < 0)
962 fatal("dump in/out/err failed"); 972 fatal("dump in/out/err failed");
@@ -972,13 +982,13 @@ ssh_session2(void)
972 packetmax = window/2; 982 packetmax = window/2;
973 } 983 }
974 984
985/*XXX MAXPACK */
975 id = channel_new( 986 id = channel_new(
976 "session", SSH_CHANNEL_OPENING, in, out, err, 987 "session", SSH_CHANNEL_OPENING, in, out, err,
977 window, packetmax, CHAN_EXTENDED_WRITE, xstrdup("client-session")); 988 window, packetmax, CHAN_EXTENDED_WRITE, xstrdup("client-session"));
978 989
979
980 channel_open(id); 990 channel_open(id);
981 channel_register_callback(id, SSH2_MSG_CHANNEL_OPEN_CONFIRMATION, client_init, (void *)0); 991 channel_register_callback(id, SSH2_MSG_CHANNEL_OPEN_CONFIRMATION, client_init, (void *)0);
982 992
983 return client_loop(tty_flag, tty_flag ? options.escape_char : -1); 993 return client_loop(tty_flag, tty_flag ? options.escape_char : -1, id);
984} 994}
diff --git a/ssh.h b/ssh.h
index f3f049fcc..f21dee494 100644
--- a/ssh.h
+++ b/ssh.h
@@ -13,7 +13,7 @@
13 * 13 *
14 */ 14 */
15 15
16/* RCSID("$OpenBSD: ssh.h,v 1.48 2000/07/13 22:53:21 provos Exp $"); */ 16/* RCSID("$OpenBSD: ssh.h,v 1.49 2000/08/19 18:48:11 markus Exp $"); */
17 17
18#ifndef SSH_H 18#ifndef SSH_H
19#define SSH_H 19#define SSH_H
@@ -105,7 +105,11 @@
105#endif /* SSH_PROGRAM */ 105#endif /* SSH_PROGRAM */
106 106
107#ifndef LOGIN_PROGRAM 107#ifndef LOGIN_PROGRAM
108#define LOGIN_PROGRAM "/usr/bin/login" 108# ifdef LOGIN_PROGRAM_FALLBACK
109# define LOGIN_PROGRAM LOGIN_PROGRAM_FALLBACK
110# else
111# define LOGIN_PROGRAM "/usr/bin/login"
112# endif
109#endif /* LOGIN_PROGRAM */ 113#endif /* LOGIN_PROGRAM */
110 114
111#ifndef ASKPASS_PROGRAM 115#ifndef ASKPASS_PROGRAM
@@ -506,7 +510,7 @@ void server_loop(pid_t pid, int fdin, int fdout, int fderr);
506void server_loop2(void); 510void server_loop2(void);
507 511
508/* Client side main loop for the interactive session. */ 512/* Client side main loop for the interactive session. */
509int client_loop(int have_pty, int escape_char); 513int client_loop(int have_pty, int escape_char, int id);
510 514
511/* Linked list of custom environment strings (see auth-rsa.c). */ 515/* Linked list of custom environment strings (see auth-rsa.c). */
512struct envstring { 516struct envstring {
diff --git a/sshconnect1.c b/sshconnect1.c
index aaebf17ff..7b60d6276 100644
--- a/sshconnect1.c
+++ b/sshconnect1.c
@@ -9,7 +9,7 @@
9 */ 9 */
10 10
11#include "includes.h" 11#include "includes.h"
12RCSID("$OpenBSD: sshconnect1.c,v 1.4 2000/07/16 08:27:22 markus Exp $"); 12RCSID("$OpenBSD: sshconnect1.c,v 1.5 2000/08/19 21:34:44 markus Exp $");
13 13
14#include <openssl/bn.h> 14#include <openssl/bn.h>
15#include <openssl/dsa.h> 15#include <openssl/dsa.h>
@@ -44,27 +44,27 @@ extern char *__progname;
44int 44int
45try_agent_authentication() 45try_agent_authentication()
46{ 46{
47 int status, type; 47 int type;
48 char *comment; 48 char *comment;
49 AuthenticationConnection *auth; 49 AuthenticationConnection *auth;
50 unsigned char response[16]; 50 unsigned char response[16];
51 unsigned int i; 51 unsigned int i;
52 BIGNUM *e, *n, *challenge; 52 int plen, clen;
53 Key *key;
54 BIGNUM *challenge;
53 55
54 /* Get connection to the agent. */ 56 /* Get connection to the agent. */
55 auth = ssh_get_authentication_connection(); 57 auth = ssh_get_authentication_connection();
56 if (!auth) 58 if (!auth)
57 return 0; 59 return 0;
58 60
59 e = BN_new();
60 n = BN_new();
61 challenge = BN_new(); 61 challenge = BN_new();
62 key = key_new(KEY_RSA);
62 63
63 /* Loop through identities served by the agent. */ 64 /* Loop through identities served by the agent. */
64 for (status = ssh_get_first_identity(auth, e, n, &comment); 65 for (key = ssh_get_first_identity(auth, &comment, 1);
65 status; 66 key != NULL;
66 status = ssh_get_next_identity(auth, e, n, &comment)) { 67 key = ssh_get_next_identity(auth, &comment, 1)) {
67 int plen, clen;
68 68
69 /* Try this identity. */ 69 /* Try this identity. */
70 debug("Trying RSA authentication via agent with '%.100s'", comment); 70 debug("Trying RSA authentication via agent with '%.100s'", comment);
@@ -72,7 +72,7 @@ try_agent_authentication()
72 72
73 /* Tell the server that we are willing to authenticate using this key. */ 73 /* Tell the server that we are willing to authenticate using this key. */
74 packet_start(SSH_CMSG_AUTH_RSA); 74 packet_start(SSH_CMSG_AUTH_RSA);
75 packet_put_bignum(n); 75 packet_put_bignum(key->rsa->n);
76 packet_send(); 76 packet_send();
77 packet_write_wait(); 77 packet_write_wait();
78 78
@@ -83,6 +83,7 @@ try_agent_authentication()
83 does not support RSA authentication. */ 83 does not support RSA authentication. */
84 if (type == SSH_SMSG_FAILURE) { 84 if (type == SSH_SMSG_FAILURE) {
85 debug("Server refused our key."); 85 debug("Server refused our key.");
86 key_free(key);
86 continue; 87 continue;
87 } 88 }
88 /* Otherwise it should have sent a challenge. */ 89 /* Otherwise it should have sent a challenge. */
@@ -97,13 +98,16 @@ try_agent_authentication()
97 debug("Received RSA challenge from server."); 98 debug("Received RSA challenge from server.");
98 99
99 /* Ask the agent to decrypt the challenge. */ 100 /* Ask the agent to decrypt the challenge. */
100 if (!ssh_decrypt_challenge(auth, e, n, challenge, 101 if (!ssh_decrypt_challenge(auth, key, challenge, session_id, 1, response)) {
101 session_id, 1, response)) { 102 /*
102 /* The agent failed to authenticate this identifier although it 103 * The agent failed to authenticate this identifier
103 advertised it supports this. Just return a wrong value. */ 104 * although it advertised it supports this. Just
105 * return a wrong value.
106 */
104 log("Authentication agent failed to decrypt challenge."); 107 log("Authentication agent failed to decrypt challenge.");
105 memset(response, 0, sizeof(response)); 108 memset(response, 0, sizeof(response));
106 } 109 }
110 key_free(key);
107 debug("Sending response to RSA challenge."); 111 debug("Sending response to RSA challenge.");
108 112
109 /* Send the decrypted challenge back to the server. */ 113 /* Send the decrypted challenge back to the server. */
@@ -118,10 +122,8 @@ try_agent_authentication()
118 122
119 /* The server returns success if it accepted the authentication. */ 123 /* The server returns success if it accepted the authentication. */
120 if (type == SSH_SMSG_SUCCESS) { 124 if (type == SSH_SMSG_SUCCESS) {
121 debug("RSA authentication accepted by server.");
122 BN_clear_free(e);
123 BN_clear_free(n);
124 BN_clear_free(challenge); 125 BN_clear_free(challenge);
126 debug("RSA authentication accepted by server.");
125 return 1; 127 return 1;
126 } 128 }
127 /* Otherwise it should return failure. */ 129 /* Otherwise it should return failure. */
@@ -129,11 +131,7 @@ try_agent_authentication()
129 packet_disconnect("Protocol error waiting RSA auth response: %d", 131 packet_disconnect("Protocol error waiting RSA auth response: %d",
130 type); 132 type);
131 } 133 }
132
133 BN_clear_free(e);
134 BN_clear_free(n);
135 BN_clear_free(challenge); 134 BN_clear_free(challenge);
136
137 debug("RSA authentication using agent refused."); 135 debug("RSA authentication using agent refused.");
138 return 0; 136 return 0;
139} 137}
diff --git a/sshconnect2.c b/sshconnect2.c
index 22ad39e7f..1f49067ad 100644
--- a/sshconnect2.c
+++ b/sshconnect2.c
@@ -28,7 +28,7 @@
28 */ 28 */
29 29
30#include "includes.h" 30#include "includes.h"
31RCSID("$OpenBSD: sshconnect2.c,v 1.16 2000/07/16 08:27:22 markus Exp $"); 31RCSID("$OpenBSD: sshconnect2.c,v 1.17 2000/08/19 21:34:44 markus Exp $");
32 32
33#include <openssl/bn.h> 33#include <openssl/bn.h>
34#include <openssl/rsa.h> 34#include <openssl/rsa.h>
@@ -54,6 +54,7 @@ RCSID("$OpenBSD: sshconnect2.c,v 1.16 2000/07/16 08:27:22 markus Exp $");
54#include "dsa.h" 54#include "dsa.h"
55#include "sshconnect.h" 55#include "sshconnect.h"
56#include "authfile.h" 56#include "authfile.h"
57#include "authfd.h"
57 58
58/* import */ 59/* import */
59extern char *client_version_string; 60extern char *client_version_string;
@@ -291,7 +292,7 @@ typedef int sign_fn(
291 unsigned char **sigp, int *lenp, 292 unsigned char **sigp, int *lenp,
292 unsigned char *data, int datalen); 293 unsigned char *data, int datalen);
293 294
294void 295int
295ssh2_sign_and_send_pubkey(Key *k, sign_fn *do_sign, 296ssh2_sign_and_send_pubkey(Key *k, sign_fn *do_sign,
296 const char *server_user, const char *host, const char *service) 297 const char *server_user, const char *host, const char *service)
297{ 298{
@@ -299,6 +300,7 @@ ssh2_sign_and_send_pubkey(Key *k, sign_fn *do_sign,
299 unsigned char *blob, *signature; 300 unsigned char *blob, *signature;
300 int bloblen, slen; 301 int bloblen, slen;
301 int skip = 0; 302 int skip = 0;
303 int ret = -1;
302 304
303 dsa_make_key_blob(k, &blob, &bloblen); 305 dsa_make_key_blob(k, &blob, &bloblen);
304 306
@@ -323,8 +325,12 @@ ssh2_sign_and_send_pubkey(Key *k, sign_fn *do_sign,
323 buffer_put_string(&b, blob, bloblen); 325 buffer_put_string(&b, blob, bloblen);
324 326
325 /* generate signature */ 327 /* generate signature */
326 do_sign(k, &signature, &slen, buffer_ptr(&b), buffer_len(&b)); 328 ret = do_sign(k, &signature, &slen, buffer_ptr(&b), buffer_len(&b));
327 key_free(k); /* XXX */ 329 if (ret == -1) {
330 xfree(blob);
331 buffer_free(&b);
332 return 0;
333 }
328#ifdef DEBUG_DSS 334#ifdef DEBUG_DSS
329 buffer_dump(&b); 335 buffer_dump(&b);
330#endif 336#endif
@@ -357,6 +363,8 @@ ssh2_sign_and_send_pubkey(Key *k, sign_fn *do_sign,
357 /* send */ 363 /* send */
358 packet_send(); 364 packet_send();
359 packet_write_wait(); 365 packet_write_wait();
366
367 return 1;
360} 368}
361 369
362int 370int
@@ -364,6 +372,7 @@ ssh2_try_pubkey(char *filename,
364 const char *server_user, const char *host, const char *service) 372 const char *server_user, const char *host, const char *service)
365{ 373{
366 Key *k; 374 Key *k;
375 int ret = 0;
367 struct stat st; 376 struct stat st;
368 377
369 if (stat(filename, &st) != 0) { 378 if (stat(filename, &st) != 0) {
@@ -389,13 +398,53 @@ ssh2_try_pubkey(char *filename,
389 return 0; 398 return 0;
390 } 399 }
391 } 400 }
392 ssh2_sign_and_send_pubkey(k, dsa_sign, server_user, host, service); 401 ret = ssh2_sign_and_send_pubkey(k, dsa_sign, server_user, host, service);
393 return 1; 402 key_free(k);
403 return ret;
404}
405
406int agent_sign(
407 Key *key,
408 unsigned char **sigp, int *lenp,
409 unsigned char *data, int datalen)
410{
411 int ret = -1;
412 AuthenticationConnection *ac = ssh_get_authentication_connection();
413 if (ac != NULL) {
414 ret = ssh_agent_sign(ac, key, sigp, lenp, data, datalen);
415 ssh_close_authentication_connection(ac);
416 }
417 return ret;
418}
419
420int
421ssh2_try_agent(AuthenticationConnection *ac,
422 const char *server_user, const char *host, const char *service)
423{
424 static int called = 0;
425 char *comment;
426 Key *k;
427 int ret;
428
429 if (called == 0) {
430 k = ssh_get_first_identity(ac, &comment, 2);
431 called ++;
432 } else {
433 k = ssh_get_next_identity(ac, &comment, 2);
434 }
435 if (k == NULL)
436 return 0;
437 debug("trying DSA agent key %s", comment);
438 xfree(comment);
439 ret = ssh2_sign_and_send_pubkey(k, agent_sign, server_user, host, service);
440 key_free(k);
441 return ret;
394} 442}
395 443
396void 444void
397ssh_userauth2(const char *server_user, char *host) 445ssh_userauth2(const char *server_user, char *host)
398{ 446{
447 AuthenticationConnection *ac = ssh_get_authentication_connection();
399 int type; 448 int type;
400 int plen; 449 int plen;
401 int sent; 450 int sent;
@@ -450,12 +499,17 @@ ssh_userauth2(const char *server_user, char *host)
450 debug("partial success"); 499 debug("partial success");
451 if (options.dsa_authentication && 500 if (options.dsa_authentication &&
452 strstr(auths, "publickey") != NULL) { 501 strstr(auths, "publickey") != NULL) {
453 while (i < options.num_identity_files2) { 502 if (ac != NULL)
454 sent = ssh2_try_pubkey( 503 sent = ssh2_try_agent(ac,
455 options.identity_files2[i++],
456 server_user, host, service); 504 server_user, host, service);
457 if (sent) 505 if (!sent) {
458 break; 506 while (i < options.num_identity_files2) {
507 sent = ssh2_try_pubkey(
508 options.identity_files2[i++],
509 server_user, host, service);
510 if (sent)
511 break;
512 }
459 } 513 }
460 } 514 }
461 if (!sent) { 515 if (!sent) {
@@ -469,6 +523,8 @@ ssh_userauth2(const char *server_user, char *host)
469 fatal("Permission denied (%s).", auths); 523 fatal("Permission denied (%s).", auths);
470 xfree(auths); 524 xfree(auths);
471 } 525 }
526 if (ac != NULL)
527 ssh_close_authentication_connection(ac);
472 packet_done(); 528 packet_done();
473 debug("ssh-userauth2 successfull"); 529 debug("ssh-userauth2 successfull");
474} 530}