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 4463cf2b..9d3dd02e 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -3,6 +3,61 @@
Avoids "scp never exits" problem. Reports from Lutz Jaenicke
<Lutz.Jaenicke@aet.TU-Cottbus.DE> and Tamito KAJIYAMA
<kajiyama@grad.sccs.chukyo-u.ac.jp>
+ - (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.
20000818
- (djm) OpenBSD CVS changes:
diff --git a/Makefile.in b/Makefile.in
index ff34c493..4ceef704 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -34,7 +34,7 @@ INSTALL_SSH_PRNG_CMDS=@INSTALL_SSH_PRNG_CMDS@
TARGETS=ssh sshd ssh-add ssh-keygen ssh-agent scp $(EXTRA_TARGETS)
-LIBSSH_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
+LIBSSH_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
LIBOPENBSD_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
diff --git a/TODO b/TODO
index 1d46ae1c..ecfd21e3 100644
--- a/TODO
+++ b/TODO
@@ -14,3 +14,5 @@
underlying shell.
- utmp/wtmp logging does not work on NeXT
+
+- Complete Tru64 SIA support
diff --git a/acconfig.h b/acconfig.h
index 601dc16f..eeee4eaf 100644
--- a/acconfig.h
+++ b/acconfig.h
@@ -6,6 +6,13 @@
@TOP@
+/* If your header files don't define LOGIN_PROGRAM, then use this (detected) */
+/* from environment and PATH */
+#undef LOGIN_PROGRAM_FALLBACK
+
+/* Define if your password has a pw_class field */
+#undef HAVE_PW_CLASS_IN_PASSWD
+
/* Define if your socketpair() has bugs */
#undef USE_PIPES
diff --git a/auth1.c b/auth1.c
index d8f2652e..b043e8a9 100644
--- a/auth1.c
+++ b/auth1.c
@@ -4,7 +4,7 @@
*/
#include "includes.h"
-RCSID("$OpenBSD: auth1.c,v 1.2 2000/04/29 18:11:52 markus Exp $");
+RCSID("$OpenBSD: auth1.c,v 1.3 2000/08/20 18:42:40 millert Exp $");
#include "xmalloc.h"
#include "rsa.h"
@@ -480,6 +480,9 @@ do_authentication()
pwcopy.pw_passwd = xstrdup(pw->pw_passwd);
pwcopy.pw_uid = pw->pw_uid;
pwcopy.pw_gid = pw->pw_gid;
+#ifdef HAVE_PW_CLASS_IN_PASSWD
+ pwcopy.pw_class = xstrdup(pw->pw_class);
+#endif
pwcopy.pw_dir = xstrdup(pw->pw_dir);
pwcopy.pw_shell = xstrdup(pw->pw_shell);
pw = &pwcopy;
diff --git a/auth2.c b/auth2.c
index 4926ff8a..7769046f 100644
--- a/auth2.c
+++ b/auth2.c
@@ -27,7 +27,7 @@
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "includes.h"
-RCSID("$OpenBSD: auth2.c,v 1.12 2000/07/07 03:55:03 todd Exp $");
+RCSID("$OpenBSD: auth2.c,v 1.13 2000/08/20 18:42:40 millert Exp $");
#include <openssl/dsa.h>
#include <openssl/rsa.h>
@@ -411,6 +411,9 @@ auth_set_user(char *u, char *s)
copy->pw_passwd = xstrdup(pw->pw_passwd);
copy->pw_uid = pw->pw_uid;
copy->pw_gid = pw->pw_gid;
+#ifdef HAVE_PW_CLASS_IN_PASSWD
+ copy->pw_class = xstrdup(pw->pw_class);
+#endif
copy->pw_dir = xstrdup(pw->pw_dir);
copy->pw_shell = xstrdup(pw->pw_shell);
authctxt->valid = 1;
diff --git a/authfd.c b/authfd.c
index a34e111a..d9427d37 100644
--- a/authfd.c
+++ b/authfd.c
@@ -11,10 +11,13 @@
*
* Functions for connecting the local authentication agent.
*
+ * SSH2 implementation,
+ * Copyright (c) 2000 Markus Friedl. All rights reserved.
+ *
*/
#include "includes.h"
-RCSID("$OpenBSD: authfd.c,v 1.24 2000/08/15 19:20:46 markus Exp $");
+RCSID("$OpenBSD: authfd.c,v 1.25 2000/08/19 21:34:42 markus Exp $");
#include "ssh.h"
#include "rsa.h"
@@ -29,6 +32,7 @@ RCSID("$OpenBSD: authfd.c,v 1.24 2000/08/15 19:20:46 markus Exp $");
#include "key.h"
#include "authfd.h"
#include "kex.h"
+#include "dsa.h"
/* helper */
int decode_reply(int type);
@@ -71,8 +75,7 @@ ssh_get_authentication_socket()
}
int
-ssh_request_reply(AuthenticationConnection *auth,
- Buffer *request, Buffer *reply)
+ssh_request_reply(AuthenticationConnection *auth, Buffer *request, Buffer *reply)
{
int l, len;
char buf[1024];
@@ -162,7 +165,6 @@ ssh_get_authentication_connection()
auth = xmalloc(sizeof(*auth));
auth->fd = sock;
- buffer_init(&auth->packet);
buffer_init(&auth->identities);
auth->howmany = 0;
@@ -175,46 +177,57 @@ ssh_get_authentication_connection()
*/
void
-ssh_close_authentication_connection(AuthenticationConnection *ac)
+ssh_close_authentication_connection(AuthenticationConnection *auth)
{
- buffer_free(&ac->packet);
- buffer_free(&ac->identities);
- close(ac->fd);
- xfree(ac);
+ buffer_free(&auth->identities);
+ close(auth->fd);
+ xfree(auth);
}
/*
* Returns the first authentication identity held by the agent.
- * Returns true if an identity is available, 0 otherwise.
- * The caller must initialize the integers before the call, and free the
- * comment after a successful call (before calling ssh_get_next_identity).
*/
-int
-ssh_get_first_identity(AuthenticationConnection *auth,
- BIGNUM *e, BIGNUM *n, char **comment)
+Key *
+ssh_get_first_identity(AuthenticationConnection *auth, char **comment, int version)
{
+ int type, code1 = 0, code2 = 0;
Buffer request;
- int type;
+
+ switch(version){
+ case 1:
+ code1 = SSH_AGENTC_REQUEST_RSA_IDENTITIES;
+ code2 = SSH_AGENT_RSA_IDENTITIES_ANSWER;
+ break;
+ case 2:
+ code1 = SSH2_AGENTC_REQUEST_IDENTITIES;
+ code2 = SSH2_AGENT_IDENTITIES_ANSWER;
+ break;
+ default:
+ return NULL;
+ }
/*
* Send a message to the agent requesting for a list of the
* identities it can represent.
*/
buffer_init(&request);
- buffer_put_char(&request, SSH_AGENTC_REQUEST_RSA_IDENTITIES);
+ buffer_put_char(&request, code1);
buffer_clear(&auth->identities);
if (ssh_request_reply(auth, &request, &auth->identities) == 0) {
buffer_free(&request);
- return 0;
+ return NULL;
}
buffer_free(&request);
/* Get message type, and verify that we got a proper answer. */
type = buffer_get_char(&auth->identities);
- if (type != SSH_AGENT_RSA_IDENTITIES_ANSWER)
+ if (type == SSH_AGENT_FAILURE) {
+ return NULL;
+ } else if (type != code2) {
fatal("Bad authentication reply message type: %d", type);
+ }
/* Get the number of entries in the response and check it for sanity. */
auth->howmany = buffer_get_int(&auth->identities);
@@ -223,43 +236,49 @@ ssh_get_first_identity(AuthenticationConnection *auth,
auth->howmany);
/* Return the first entry (if any). */
- return ssh_get_next_identity(auth, e, n, comment);
+ return ssh_get_next_identity(auth, comment, version);
}
-/*
- * Returns the next authentication identity for the agent. Other functions
- * can be called between this and ssh_get_first_identity or two calls of this
- * function. This returns 0 if there are no more identities. The caller
- * must free comment after a successful return.
- */
-
-int
-ssh_get_next_identity(AuthenticationConnection *auth,
- BIGNUM *e, BIGNUM *n, char **comment)
+Key *
+ssh_get_next_identity(AuthenticationConnection *auth, char **comment, int version)
{
unsigned int bits;
+ unsigned char *blob;
+ unsigned int blen;
+ Key *key = NULL;
/* Return failure if no more entries. */
if (auth->howmany <= 0)
- return 0;
+ return NULL;
/*
* Get the next entry from the packet. These will abort with a fatal
* error if the packet is too short or contains corrupt data.
*/
- bits = buffer_get_int(&auth->identities);
- buffer_get_bignum(&auth->identities, e);
- buffer_get_bignum(&auth->identities, n);
- *comment = buffer_get_string(&auth->identities, NULL);
-
- if (bits != BN_num_bits(n))
- log("Warning: identity keysize mismatch: actual %d, announced %u",
- BN_num_bits(n), bits);
-
+ switch(version){
+ case 1:
+ key = key_new(KEY_RSA);
+ bits = buffer_get_int(&auth->identities);
+ buffer_get_bignum(&auth->identities, key->rsa->e);
+ buffer_get_bignum(&auth->identities, key->rsa->n);
+ *comment = buffer_get_string(&auth->identities, NULL);
+ if (bits != BN_num_bits(key->rsa->n))
+ log("Warning: identity keysize mismatch: actual %d, announced %u",
+ BN_num_bits(key->rsa->n), bits);
+ break;
+ case 2:
+ blob = buffer_get_string(&auth->identities, &blen);
+ *comment = buffer_get_string(&auth->identities, NULL);
+ key = dsa_key_from_blob(blob, blen);
+ xfree(blob);
+ break;
+ default:
+ return NULL;
+ break;
+ }
/* Decrement the number of remaining entries. */
auth->howmany--;
-
- return 1;
+ return key;
}
/*
@@ -272,7 +291,7 @@ ssh_get_next_identity(AuthenticationConnection *auth,
int
ssh_decrypt_challenge(AuthenticationConnection *auth,
- BIGNUM* e, BIGNUM *n, BIGNUM *challenge,
+ Key* key, BIGNUM *challenge,
unsigned char session_id[16],
unsigned int response_type,
unsigned char response[16])
@@ -282,15 +301,17 @@ ssh_decrypt_challenge(AuthenticationConnection *auth,
int i;
int type;
- if (response_type == 0)
- fatal("Compatibility with ssh protocol version "
- "1.0 no longer supported.");
-
+ if (key->type != KEY_RSA)
+ return 0;
+ if (response_type == 0) {
+ log("Compatibility with ssh protocol version 1.0 no longer supported.");
+ return 0;
+ }
buffer_init(&buffer);
buffer_put_char(&buffer, SSH_AGENTC_RSA_CHALLENGE);
- buffer_put_int(&buffer, BN_num_bits(n));
- buffer_put_bignum(&buffer, e);
- buffer_put_bignum(&buffer, n);
+ buffer_put_int(&buffer, BN_num_bits(key->rsa->n));
+ buffer_put_bignum(&buffer, key->rsa->e);
+ buffer_put_bignum(&buffer, key->rsa->n);
buffer_put_bignum(&buffer, challenge);
buffer_append(&buffer, (char *) session_id, 16);
buffer_put_int(&buffer, response_type);
@@ -318,6 +339,45 @@ ssh_decrypt_challenge(AuthenticationConnection *auth,
return success;
}
+/* ask agent to sign data, returns -1 on error, 0 on success */
+int
+ssh_agent_sign(AuthenticationConnection *auth,
+ Key *key,
+ unsigned char **sigp, int *lenp,
+ unsigned char *data, int datalen)
+{
+ Buffer msg;
+ unsigned char *blob;
+ unsigned int blen;
+ int type;
+ int ret = -1;
+
+ if (dsa_make_key_blob(key, &blob, &blen) == 0)
+ return -1;
+
+ buffer_init(&msg);
+ buffer_put_char(&msg, SSH2_AGENTC_SIGN_REQUEST);
+ buffer_put_string(&msg, blob, blen);
+ buffer_put_string(&msg, data, datalen);
+ xfree(blob);
+
+ if (ssh_request_reply(auth, &msg, &msg) == 0) {
+ buffer_free(&msg);
+ return -1;
+ }
+ type = buffer_get_char(&msg);
+ if (type == SSH_AGENT_FAILURE) {
+ log("Agent admitted failure to sign using the key.");
+ } else if (type != SSH2_AGENT_SIGN_RESPONSE) {
+ fatal("Bad authentication response: %d", type);
+ } else {
+ ret = 0;
+ *sigp = buffer_get_string(&msg, lenp);
+ }
+ buffer_free(&msg);
+ return ret;
+}
+
/* Encode key for a message to the agent. */
void
@@ -358,29 +418,29 @@ ssh_encode_identity_dsa(Buffer *b, DSA *key, const char *comment)
int
ssh_add_identity(AuthenticationConnection *auth, Key *key, const char *comment)
{
- Buffer buffer;
+ Buffer msg;
int type;
- buffer_init(&buffer);
+ buffer_init(&msg);
switch (key->type) {
case KEY_RSA:
- ssh_encode_identity_rsa(&buffer, key->rsa, comment);
+ ssh_encode_identity_rsa(&msg, key->rsa, comment);
break;
case KEY_DSA:
- ssh_encode_identity_dsa(&buffer, key->dsa, comment);
+ ssh_encode_identity_dsa(&msg, key->dsa, comment);
break;
default:
- buffer_free(&buffer);
+ buffer_free(&msg);
return 0;
break;
}
- if (ssh_request_reply(auth, &buffer, &buffer) == 0) {
- buffer_free(&buffer);
+ if (ssh_request_reply(auth, &msg, &msg) == 0) {
+ buffer_free(&msg);
return 0;
}
- type = buffer_get_char(&buffer);
- buffer_free(&buffer);
+ type = buffer_get_char(&msg);
+ buffer_free(&msg);
return decode_reply(type);
}
@@ -390,23 +450,35 @@ ssh_add_identity(AuthenticationConnection *auth, Key *key, const char *comment)
*/
int
-ssh_remove_identity(AuthenticationConnection *auth, RSA *key)
+ssh_remove_identity(AuthenticationConnection *auth, Key *key)
{
- Buffer buffer;
+ Buffer msg;
int type;
-
- buffer_init(&buffer);
- buffer_put_char(&buffer, SSH_AGENTC_REMOVE_RSA_IDENTITY);
- buffer_put_int(&buffer, BN_num_bits(key->n));
- buffer_put_bignum(&buffer, key->e);
- buffer_put_bignum(&buffer, key->n);
-
- if (ssh_request_reply(auth, &buffer, &buffer) == 0) {
- buffer_free(&buffer);
+ unsigned char *blob;
+ unsigned int blen;
+
+ buffer_init(&msg);
+
+ if (key->type == KEY_RSA) {
+ buffer_put_char(&msg, SSH_AGENTC_REMOVE_RSA_IDENTITY);
+ buffer_put_int(&msg, BN_num_bits(key->rsa->n));
+ buffer_put_bignum(&msg, key->rsa->e);
+ buffer_put_bignum(&msg, key->rsa->n);
+ } else if (key->type == KEY_DSA) {
+ dsa_make_key_blob(key, &blob, &blen);
+ buffer_put_char(&msg, SSH2_AGENTC_REMOVE_IDENTITY);
+ buffer_put_string(&msg, blob, blen);
+ xfree(blob);
+ } else {
+ buffer_free(&msg);
return 0;
}
- type = buffer_get_char(&buffer);
- buffer_free(&buffer);
+ if (ssh_request_reply(auth, &msg, &msg) == 0) {
+ buffer_free(&msg);
+ return 0;
+ }
+ type = buffer_get_char(&msg);
+ buffer_free(&msg);
return decode_reply(type);
}
@@ -416,20 +488,23 @@ ssh_remove_identity(AuthenticationConnection *auth, RSA *key)
*/
int
-ssh_remove_all_identities(AuthenticationConnection *auth)
+ssh_remove_all_identities(AuthenticationConnection *auth, int version)
{
- Buffer buffer;
+ Buffer msg;
int type;
+ int code = (version==1) ?
+ SSH_AGENTC_REMOVE_ALL_RSA_IDENTITIES :
+ SSH2_AGENTC_REMOVE_ALL_IDENTITIES;
- buffer_init(&buffer);
- buffer_put_char(&buffer, SSH_AGENTC_REMOVE_ALL_RSA_IDENTITIES);
+ buffer_init(&msg);
+ buffer_put_char(&msg, code);
- if (ssh_request_reply(auth, &buffer, &buffer) == 0) {
- buffer_free(&buffer);
+ if (ssh_request_reply(auth, &msg, &msg) == 0) {
+ buffer_free(&msg);
return 0;
}
- type = buffer_get_char(&buffer);
- buffer_free(&buffer);
+ type = buffer_get_char(&msg);
+ buffer_free(&msg);
return decode_reply(type);
}
diff --git a/authfd.h b/authfd.h
index 14b9bee9..5819b913 100644
--- a/authfd.h
+++ b/authfd.h
@@ -13,7 +13,7 @@
*
*/
-/* RCSID("$OpenBSD: authfd.h,v 1.9 2000/07/16 08:27:21 markus Exp $"); */
+/* RCSID("$OpenBSD: authfd.h,v 1.10 2000/08/19 21:34:43 markus Exp $"); */
#ifndef AUTHFD_H
#define AUTHFD_H
@@ -35,18 +35,16 @@
#define SSH2_AGENT_IDENTITIES_ANSWER 12
#define SSH2_AGENTC_SIGN_REQUEST 13
#define SSH2_AGENT_SIGN_RESPONSE 14
-#define SSH2_AGENT_FAILURE SSH_AGENT_FAILURE
-#define SSH2_AGENT_SUCCESS SSH_AGENT_SUCCESS
#define SSH2_AGENTC_ADD_IDENTITY 17
#define SSH2_AGENTC_REMOVE_IDENTITY 18
#define SSH2_AGENTC_REMOVE_ALL_IDENTITIES 19
typedef struct {
int fd;
- Buffer packet;
Buffer identities;
int howmany;
} AuthenticationConnection;
+
/* Returns the number of the authentication fd, or -1 if there is none. */
int ssh_get_authentication_socket();
@@ -69,44 +67,48 @@ AuthenticationConnection *ssh_get_authentication_connection();
* Closes the connection to the authentication agent and frees any associated
* memory.
*/
-void ssh_close_authentication_connection(AuthenticationConnection * ac);
+void ssh_close_authentication_connection(AuthenticationConnection *auth);
/*
- * Returns the first authentication identity held by the agent. Returns true
- * if an identity is available, 0 otherwise. The caller must initialize the
- * integers before the call, and free the comment after a successful call
- * (before calling ssh_get_next_identity).
+ * Returns the first authentication identity held by the agent or NULL if
+ * no identies are available. Caller must free comment and key.
+ * Note that you cannot mix calls with different versions.
*/
-int
-ssh_get_first_identity(AuthenticationConnection * connection,
- BIGNUM * e, BIGNUM * n, char **comment);
+Key *ssh_get_first_identity(AuthenticationConnection *auth, char **comment, int version);
/*
* Returns the next authentication identity for the agent. Other functions
* can be called between this and ssh_get_first_identity or two calls of this
- * function. This returns 0 if there are no more identities. The caller
- * must free comment after a successful return.
+ * function. This returns NULL if there are no more identities. The caller
+ * must free key and comment after a successful return.
*/
-int
-ssh_get_next_identity(AuthenticationConnection * connection,
- BIGNUM * e, BIGNUM * n, char **comment);
+Key *ssh_get_next_identity(AuthenticationConnection *auth, char **comment, int version);
-/* Requests the agent to decrypt the given challenge. Returns true if
- the agent claims it was able to decrypt it. */
+/*
+ * Requests the agent to decrypt the given challenge. Returns true if the
+ * agent claims it was able to decrypt it.
+ */
int
-ssh_decrypt_challenge(AuthenticationConnection * auth,
- BIGNUM * e, BIGNUM * n, BIGNUM * challenge,
+ssh_decrypt_challenge(AuthenticationConnection *auth,
+ Key *key, BIGNUM * challenge,
unsigned char session_id[16],
unsigned int response_type,
unsigned char response[16]);
+/* Requests the agent to sign data using key */
+int
+ssh_agent_sign(AuthenticationConnection *auth,
+ Key *key,
+ unsigned char **sigp, int *lenp,
+ unsigned char *data, int datalen);
+
/*
* Adds an identity to the authentication server. This call is not meant to
* be used by normal applications. This returns true if the identity was
* successfully added.
*/
int
-ssh_add_identity(AuthenticationConnection * connection, Key *key,
+ssh_add_identity(AuthenticationConnection *auth, Key *key,
const char *comment);
/*
@@ -114,16 +116,13 @@ ssh_add_identity(AuthenticationConnection * connection, Key *key,
* meant to be used by normal applications. This returns true if the
* identity was successfully added.
*/
-int ssh_remove_identity(AuthenticationConnection * connection, RSA * key);
+int ssh_remove_identity(AuthenticationConnection *auth, Key *key);
/*
* Removes all identities from the authentication agent. This call is not
* meant to be used by normal applications. This returns true if the
* operation was successful.
*/
-int ssh_remove_all_identities(AuthenticationConnection * connection);
-
-/* Closes the connection to the authentication agent. */
-void ssh_close_authentication(AuthenticationConnection * connection);
+int ssh_remove_all_identities(AuthenticationConnection *auth, int version);
#endif /* AUTHFD_H */
diff --git a/channels.c b/channels.c
index ea395293..c77f6b96 100644
--- a/channels.c
+++ b/channels.c
@@ -17,7 +17,7 @@
*/
#include "includes.h"
-RCSID("$OpenBSD: channels.c,v 1.64 2000/07/16 08:27:21 markus Exp $");
+RCSID("$OpenBSD: channels.c,v 1.66 2000/08/19 21:55:51 markus Exp $");
#include "ssh.h"
#include "packet.h"
@@ -244,6 +244,7 @@ channel_new(char *ctype, int type, int rfd, int wfd, int efd,
c->cb_arg = NULL;
c->cb_event = 0;
c->dettach_user = NULL;
+ c->input_filter = NULL;
debug("channel %d: new [%s]", found, remote_name);
return found;
}
@@ -665,7 +666,14 @@ channel_handle_rfd(Channel *c, fd_set * readset, fd_set * writeset)
}
return -1;
}
- buffer_append(&c->input, buf, len);
+ if(c->input_filter != NULL) {
+ if (c->input_filter(c, buf, len) == -1) {
+ debug("filter stops channel %d", c->self);
+ chan_read_failed(c);
+ }
+ } else {
+ buffer_append(&c->input, buf, len);
+ }
}
return 1;
}
@@ -2309,6 +2317,16 @@ channel_cancel_cleanup(int id)
}
c->dettach_user = NULL;
}
+void
+channel_register_filter(int id, channel_filter_fn *fn)
+{
+ Channel *c = channel_lookup(id);
+ if (c == NULL) {
+ log("channel_register_filter: %d: bad id", id);
+ return;
+ }
+ c->input_filter = fn;
+}
void
channel_set_fds(int id, int rfd, int wfd, int efd, int extusage)
diff --git a/channels.h b/channels.h
index 9629124b..9acdf581 100644
--- a/channels.h
+++ b/channels.h
@@ -1,4 +1,4 @@
-/* RCSID("$OpenBSD: channels.h,v 1.14 2000/06/20 01:39:40 markus Exp $"); */
+/* RCSID("$OpenBSD: channels.h,v 1.16 2000/08/19 21:55:51 markus Exp $"); */
#ifndef CHANNELS_H
#define CHANNELS_H
@@ -21,9 +21,13 @@
* Data structure for channel data. This is iniailized in channel_allocate
* and cleared in channel_free.
*/
+struct Channel;
+typedef struct Channel Channel;
+
typedef void channel_callback_fn(int id, void *arg);
+typedef int channel_filter_fn(struct Channel *c, char *buf, int len);
-typedef struct Channel {
+struct Channel {
int type; /* channel type/state */
int self; /* my own channel identifier */
int remote_id; /* channel identifier for remote peer */
@@ -61,7 +65,10 @@ typedef struct Channel {
void *cb_arg;
int cb_event;
channel_callback_fn *dettach_user;
-} Channel;
+
+ /* filter */
+ channel_filter_fn *input_filter;
+};
#define CHAN_EXTENDED_IGNORE 0
#define CHAN_EXTENDED_READ 1
@@ -73,6 +80,7 @@ void channel_request(int id, char *service, int wantconfirm);
void channel_request_start(int id, char *service, int wantconfirm);
void channel_register_callback(int id, int mtype, channel_callback_fn *fn, void *arg);
void channel_register_cleanup(int id, channel_callback_fn *fn);
+void channel_register_filter(int id, channel_filter_fn *fn);
void channel_cancel_cleanup(int id);
Channel *channel_lookup(int id);
diff --git a/clientloop.c b/clientloop.c
index 67fa36d9..d339e127 100644
--- a/clientloop.c
+++ b/clientloop.c
@@ -16,7 +16,7 @@
*/
#include "includes.h"
-RCSID("$OpenBSD: clientloop.c,v 1.29 2000/07/16 08:27:21 markus Exp $");
+RCSID("$OpenBSD: clientloop.c,v 1.32 2000/08/19 22:21:19 markus Exp $");
#include "xmalloc.h"
#include "ssh.h"
@@ -29,6 +29,9 @@ RCSID("$OpenBSD: clientloop.c,v 1.29 2000/07/16 08:27:21 markus Exp $");
#include "channels.h"
#include "dispatch.h"
+#include "buffer.h"
+#include "bufaux.h"
+
/* Flag indicating that stdin should be redirected from /dev/null. */
extern int stdin_null_flag;
@@ -60,6 +63,8 @@ static int in_raw_mode = 0;
static int in_non_blocking_mode = 0;
/* Common data for the client loop code. */
+static int quit_pending; /* Set to non-zero to quit the client loop. */
+static int escape_char; /* Escape character. */
static int escape_pending; /* Last character was the escape character */
static int last_was_cr; /* Last character was a newline. */
static 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. */
static Buffer stdin_buffer; /* Buffer for stdin data. */
static Buffer stdout_buffer; /* Buffer for stdout data. */
static Buffer stderr_buffer; /* Buffer for stderr data. */
+static unsigned long stdin_bytes, stdout_bytes, stderr_bytes;
static unsigned int buffer_high;/* Soft max buffer size. */
static int max_fd; /* Maximum file descriptor number in select(). */
static int connection_in; /* Connection to server (input). */
static int connection_out; /* Connection to server (output). */
-static unsigned long stdin_bytes, stdout_bytes, stderr_bytes;
-static int quit_pending; /* Set to non-zero to quit the client loop. */
-static int escape_char; /* Escape character. */
void client_init_dispatch(void);
@@ -379,17 +382,15 @@ client_wait_until_can_do_something(fd_set * readset, fd_set * writeset)
}
void
-client_suspend_self()
+client_suspend_self(Buffer *bin, Buffer *bout, Buffer *berr)
{
struct winsize oldws, newws;
/* Flush stdout and stderr buffers. */
- if (buffer_len(&stdout_buffer) > 0)
- atomicio(write, fileno(stdout), buffer_ptr(&stdout_buffer),
- buffer_len(&stdout_buffer));
- if (buffer_len(&stderr_buffer) > 0)
- atomicio(write, fileno(stderr), buffer_ptr(&stderr_buffer),
- buffer_len(&stderr_buffer));
+ if (buffer_len(bout) > 0)
+ atomicio(write, fileno(stdout), buffer_ptr(bout), buffer_len(bout));
+ if (buffer_len(berr) > 0)
+ atomicio(write, fileno(stderr), buffer_ptr(berr), buffer_len(berr));
leave_raw_mode();
@@ -397,9 +398,9 @@ client_suspend_self()
* Free (and clear) the buffer to reduce the amount of data that gets
* written to swap.
*/
- buffer_free(&stdin_buffer);
- buffer_free(&stdout_buffer);
- buffer_free(&stderr_buffer);
+ buffer_free(bin);
+ buffer_free(bout);
+ buffer_free(berr);
/* Save old window size. */
ioctl(fileno(stdin), TIOCGWINSZ, &oldws);
@@ -416,9 +417,9 @@ client_suspend_self()
received_window_change_signal = 1;
/* OK, we have been continued by the user. Reinitialize buffers. */
- buffer_init(&stdin_buffer);
- buffer_init(&stdout_buffer);
- buffer_init(&stderr_buffer);
+ buffer_init(bin);
+ buffer_init(bout);
+ buffer_init(berr);
enter_raw_mode();
}
@@ -466,12 +467,155 @@ client_process_net_input(fd_set * readset)
}
}
+/* process the characters one by one */
+int
+process_escapes(Buffer *bin, Buffer *bout, Buffer *berr, char *buf, int len)
+{
+ char string[1024];
+ pid_t pid;
+ int bytes = 0;
+ unsigned int i;
+ unsigned char ch;
+ char *s;
+
+ for (i = 0; i < len; i++) {
+ /* Get one character at a time. */
+ ch = buf[i];
+
+ if (escape_pending) {
+ /* We have previously seen an escape character. */
+ /* Clear the flag now. */
+ escape_pending = 0;
+
+ /* Process the escaped character. */
+ switch (ch) {
+ case '.':
+ /* Terminate the connection. */
+ snprintf(string, sizeof string, "%c.\r\n", escape_char);
+ buffer_append(berr, string, strlen(string));
+ /*stderr_bytes += strlen(string); XXX*/
+
+ quit_pending = 1;
+ return -1;
+
+ case 'Z' - 64:
+ /* Suspend the program. */
+ /* Print a message to that effect to the user. */
+ snprintf(string, sizeof string, "%c^Z [suspend ssh]\r\n", escape_char);
+ buffer_append(berr, string, strlen(string));
+ /*stderr_bytes += strlen(string); XXX*/
+
+ /* Restore terminal modes and suspend. */
+ client_suspend_self(bin, bout, berr);
+
+ /* We have been continued. */
+ continue;
+
+ case '&':
+ /* XXX does not work yet with proto 2 */
+ if (compat20)
+ continue;
+ /*
+ * Detach the program (continue to serve connections,
+ * but put in background and no more new connections).
+ */
+ if (!stdin_eof) {
+ /*
+ * Sending SSH_CMSG_EOF alone does not always appear
+ * to be enough. So we try to send an EOF character
+ * first.
+ */
+ packet_start(SSH_CMSG_STDIN_DATA);
+ packet_put_string("\004", 1);
+ packet_send();
+ /* Close stdin. */
+ stdin_eof = 1;
+ if (buffer_len(bin) == 0) {
+ packet_start(SSH_CMSG_EOF);
+ packet_send();
+ }
+ }
+ /* Restore tty modes. */
+ leave_raw_mode();
+
+ /* Stop listening for new connections. */
+ channel_stop_listening();
+
+ printf("%c& [backgrounded]\n", escape_char);
+
+ /* Fork into background. */
+ pid = fork();
+ if (pid < 0) {
+ error("fork: %.100s", strerror(errno));
+ continue;
+ }
+ if (pid != 0) { /* This is the parent. */
+ /* The parent just exits. */
+ exit(0);
+ }
+ /* The child continues serving connections. */
+ continue; /*XXX ? */
+
+ case '?':
+ snprintf(string, sizeof string,
+"%c?\r\n\
+Supported escape sequences:\r\n\
+~. - terminate connection\r\n\
+~^Z - suspend ssh\r\n\
+~# - list forwarded connections\r\n\
+~& - background ssh (when waiting for connections to terminate)\r\n\
+~? - this message\r\n\
+~~ - send the escape character by typing it twice\r\n\
+(Note that escapes are only recognized immediately after newline.)\r\n",
+ escape_char);
+ buffer_append(berr, string, strlen(string));
+ continue;
+
+ case '#':
+ snprintf(string, sizeof string, "%c#\r\n", escape_char);
+ buffer_append(berr, string, strlen(string));
+ s = channel_open_message();
+ buffer_append(berr, s, strlen(s));
+ xfree(s);
+ continue;
+
+ default:
+ if (ch != escape_char) {
+ buffer_put_char(bin, escape_char);
+ bytes++;
+ }
+ /* Escaped characters fall through here */
+ break;
+ }
+ } else {
+ /*
+ * The previous character was not an escape char. Check if this
+ * is an escape.
+ */
+ if (last_was_cr && ch == escape_char) {
+ /* It is. Set the flag and continue to next character. */
+ escape_pending = 1;
+ continue;
+ }
+ }
+
+ /*
+ * Normal character. Record whether it was a newline,
+ * and append it to the buffer.
+ */
+ last_was_cr = (ch == '\r' || ch == '\n');
+ buffer_put_char(bin, ch);
+ bytes++;
+ }
+ return bytes;
+}
+
void
client_process_input(fd_set * readset)
{
+ int ret;
int len;
- pid_t pid;
- char buf[8192], *s;
+ char buf[8192];
/* Read input from stdin. */
if (FD_ISSET(fileno(stdin), readset)) {
@@ -513,145 +657,10 @@ client_process_input(fd_set * readset)
* Normal, successful read. But we have an escape character
* and have to process the characters one by one.
*/
- unsigned int i;
- for (i = 0; i < len; i++) {
- unsigned char ch;
- /* Get one character at a time. */
- ch = buf[i];
-
- if (escape_pending) {
- /* We have previously seen an escape character. */
- /* Clear the flag now. */
- escape_pending = 0;
- /* Process the escaped character. */
- switch (ch) {
- case '.':
- /* Terminate the connection. */
- snprintf(buf, sizeof buf, "%c.\r\n", escape_char);
- buffer_append(&stderr_buffer, buf, strlen(buf));
- stderr_bytes += strlen(buf);
- quit_pending = 1;
- return;
-
- case 'Z' - 64:
- /* Suspend the program. */
- /* Print a message to that effect to the user. */
- snprintf(buf, sizeof buf, "%c^Z\r\n", escape_char);
- buffer_append(&stderr_buffer, buf, strlen(buf));
- stderr_bytes += strlen(buf);
-
- /* Restore terminal modes and suspend. */
- client_suspend_self();
-
- /* We have been continued. */
- continue;
-
- case '&':
- /*
- * Detach the program (continue to serve connections,
- * but put in background and no more new connections).
- */
- if (!stdin_eof) {
- /*
- * Sending SSH_CMSG_EOF alone does not always appear
- * to be enough. So we try to send an EOF character
- * first.
- */
- packet_start(SSH_CMSG_STDIN_DATA);
- packet_put_string("\004", 1);
- packet_send();
- /* Close stdin. */
- stdin_eof = 1;
- if (buffer_len(&stdin_buffer) == 0) {
- packet_start(SSH_CMSG_EOF);
- packet_send();
- }
- }
- /* Restore tty modes. */
- leave_raw_mode();
-
- /* Stop listening for new connections. */
- channel_stop_listening();
-
- printf("%c& [backgrounded]\n", escape_char);
-
- /* Fork into background. */
- pid = fork();
- if (pid < 0) {
- error("fork: %.100s", strerror(errno));
- continue;
- }
- if (pid != 0) { /* This is the parent. */
- /* The parent just exits. */
- exit(0);
- }
- /* The child continues serving connections. */
- continue;
-
- case '?':
- snprintf(buf, sizeof buf,
-"%c?\r\n\
-Supported escape sequences:\r\n\
-~. - terminate connection\r\n\
-~^Z - suspend ssh\r\n\
-~# - list forwarded connections\r\n\
-~& - background ssh (when waiting for connections to terminate)\r\n\
-~? - this message\r\n\
-~~ - send the escape character by typing it twice\r\n\
-(Note that escapes are only recognized immediately after newline.)\r\n",
- escape_char);
- buffer_append(&stderr_buffer, buf, strlen(buf));
- continue;
-
- case '#':
- snprintf(buf, sizeof buf, "%c#\r\n", escape_char);
- buffer_append(&stderr_buffer, buf, strlen(buf));
- s = channel_open_message();
- buffer_append(&stderr_buffer, s, strlen(s));
- xfree(s);
- continue;
-
- default:
- if (ch != escape_char) {
- /*
- * Escape character followed by non-special character.
- * Append both to the input buffer.
- */
- buf[0] = escape_char;
- buf[1] = ch;
- buffer_append(&stdin_buffer, buf, 2);
- stdin_bytes += 2;
- continue;
- }
- /*
- * Note that escape character typed twice
- * falls through here; the latter gets processed
- * as a normal character below.
- */
- break;
- }
- } else {
- /*
- * The previous character was not an escape char. Check if this
- * is an escape.
- */
- if (last_was_cr && ch == escape_char) {
- /* It is. Set the flag and continue to next character. */
- escape_pending = 1;
- continue;
- }
- }
-
- /*
- * Normal character. Record whether it was a newline,
- * and append it to the buffer.
- */
- last_was_cr = (ch == '\r' || ch == '\n');
- buf[0] = ch;
- buffer_append(&stdin_buffer, buf, 1);
- stdin_bytes += 1;
- continue;
- }
+ ret = process_escapes(&stdin_buffer, &stdout_buffer, &stderr_buffer, buf, len);
+ if (ret == -1)
+ return;
+ stdout_bytes += ret;
}
}
}
@@ -722,6 +731,15 @@ client_process_buffered_input_packets()
dispatch_run(DISPATCH_NONBLOCK, &quit_pending);
}
+/* scan buf[] for '~' before sending data to the peer */
+
+int
+simple_escape_filter(Channel *c, char *buf, int len)
+{
+ /* XXX we assume c->extended is writeable */
+ return process_escapes(&c->input, &c->output, &c->extended, buf, len);
+}
+
/*
* Implements the interactive session with the server. This is called after
* the user has been authenticated, and a command has been started on the
@@ -730,7 +748,7 @@ client_process_buffered_input_packets()
*/
int
-client_loop(int have_pty, int escape_char_arg)
+client_loop(int have_pty, int escape_char_arg, int ssh2_chan_id)
{
extern Options options;
double start_time, total_time;
@@ -780,6 +798,9 @@ client_loop(int have_pty, int escape_char_arg)
if (!compat20)
client_check_initial_eof_on_stdin();
+ if (compat20 && escape_char != -1)
+ channel_register_filter(ssh2_chan_id, simple_escape_filter);
+
/* Main loop of the client for the interactive session mode. */
while (!quit_pending) {
fd_set readset, writeset;
@@ -989,6 +1010,7 @@ client_input_channel_open(int type, int plen)
/* XXX move to channels.c */
sock = x11_connect_display();
if (sock >= 0) {
+/*XXX MAXPACK */
id = channel_new("x11", SSH_CHANNEL_X11_OPEN,
sock, sock, -1, 4*1024, 32*1024, 0,
xstrdup("x11"));
diff --git a/configure.in b/configure.in
index f048b000..02287b80 100644
--- a/configure.in
+++ b/configure.in
@@ -14,6 +14,17 @@ AC_SUBST(PERL)
AC_PATH_PROG(ENT, ent)
AC_SUBST(ENT)
+# Use LOGIN_PROGRAM from environment if possible
+if test ! -z "$LOGIN_PROGRAM" ; then
+ AC_DEFINE_UNQUOTED(LOGIN_PROGRAM_FALLBACK, "$LOGIN_PROGRAM")
+else
+ # Search for login
+ AC_PATH_PROG(LOGIN_PROGRAM_FALLBACK, login)
+ if test ! -z "$LOGIN_PROGRAM_FALLBACK" ; then
+ AC_DEFINE_UNQUOTED(LOGIN_PROGRAM_FALLBACK, "$LOGIN_PROGRAM_FALLBACK")
+ fi
+fi
+
if test -z "$LD" ; then
LD=$CC
fi
@@ -225,18 +236,18 @@ if test -z "$no_libnsl" ; then
fi
# Checks for header files.
-AC_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)
+AC_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)
-# Checks for library functions.
-AC_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)
-dnl checks for time functions
+dnl Checks for library functions.
+AC_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)
+dnl Checks for time functions
AC_CHECK_FUNCS(gettimeofday time)
-dnl checks for libutil functions
+dnl Checks for libutil functions
AC_CHECK_FUNCS(login logout updwtmp logwtmp)
-dnl checks for utmp functions
+dnl Checks for utmp functions
AC_CHECK_FUNCS(entutent getutent getutid getutline pututline setutent)
AC_CHECK_FUNCS(utmpname)
-dnl checks for utmpx functions
+dnl Checks for utmpx functions
AC_CHECK_FUNCS(entutxent getutxent getutxid getutxline pututxline )
AC_CHECK_FUNCS(setutxent utmpxname)
@@ -736,6 +747,22 @@ if test "x$ac_cv_have___ss_family_in_struct_ss" = "xyes" ; then
AC_DEFINE(HAVE___SS_FAMILY_IN_SS)
fi
+AC_CACHE_CHECK([for pw_class field in struct passwd],
+ ac_cv_have_pw_class_in_struct_passwd, [
+ AC_TRY_COMPILE(
+ [
+#include <sys/types.h>
+#include <pwd.h>
+ ],
+ [ struct passwd p s; p.pw_class = NULL; ],
+ [ ac_cv_have_pw_class_in_struct_passwd="yes" ],
+ [ ac_cv_have_pw_class_in_struct_passwd="no" ]
+ )
+])
+if test "x$ac_cv_have_pw_class_in_struct_passwd" = "xyes" ; then
+ AC_DEFINE(HAVE_PW_CLASS_IN_PASSWD)
+fi
+
AC_CACHE_CHECK([if libc defines __progname], ac_cv_libc_defines___progname, [
AC_TRY_LINK([],
diff --git a/crc32.c b/crc32.c
index 05a1af7b..eb9b2dcd 100644
--- a/crc32.c
+++ b/crc32.c
@@ -6,7 +6,7 @@
*/
#include "includes.h"
-RCSID("$OpenBSD: crc32.c,v 1.5 2000/06/20 01:39:40 markus Exp $");
+RCSID("$OpenBSD: crc32.c,v 1.6 2000/08/19 02:17:12 deraadt Exp $");
#include "crc32.h"
@@ -108,7 +108,7 @@ static unsigned int crc32_tab[] = {
/* Return a 32-bit CRC of the contents of the buffer. */
unsigned int
-crc32(const unsigned char *s, unsigned int len)
+ssh_crc32(const unsigned char *s, unsigned int len)
{
unsigned int i;
unsigned int crc32val;
diff --git a/crc32.h b/crc32.h
index 45495b42..2c84a801 100644
--- a/crc32.h
+++ b/crc32.h
@@ -13,7 +13,7 @@
*
*/
-/* RCSID("$OpenBSD: crc32.h,v 1.6 2000/06/20 01:39:40 markus Exp $"); */
+/* RCSID("$OpenBSD: crc32.h,v 1.7 2000/08/19 21:29:40 deraadt Exp $"); */
#ifndef CRC32_H
#define CRC32_H
@@ -22,6 +22,6 @@
* This computes a 32 bit CRC of the data in the buffer, and returns the CRC.
* The polynomial used is 0xedb88320.
*/
-unsigned int crc32(const unsigned char *buf, unsigned int len);
+unsigned int ssh_crc32(const unsigned char *buf, unsigned int len);
#endif /* CRC32_H */
diff --git a/deattack.c b/deattack.c
index 7f95eca3..72e7f1e0 100644
--- a/deattack.c
+++ b/deattack.c
@@ -1,5 +1,5 @@
/*
- * $OpenBSD: deattack.c,v 1.7 2000/06/20 01:39:41 markus Exp $
+ * $OpenBSD: deattack.c,v 1.8 2000/08/19 02:17:12 deraadt Exp $
* Cryptographic attack detector for ssh - source code
*
* Copyright (c) 1998 CORE SDI S.A., Buenos Aires, Argentina.
@@ -50,7 +50,7 @@ void
crc_update(u_int32_t *a, u_int32_t b)
{
b ^= *a;
- *a = crc32((unsigned char *) &b, sizeof(b));
+ *a = ssh_crc32((unsigned char *) &b, sizeof(b));
}
/* detect if a block is used in a particular pattern */
diff --git a/defines.h b/defines.h
index cd322f9b..1fe74a92 100644
--- a/defines.h
+++ b/defines.h
@@ -246,8 +246,16 @@ typedef int mode_t;
# endif /* RSH_PATH */
#endif /* _PATH_RSH */
+#ifndef _PATH_NOLOGIN
+# define _PATH_NOLOGIN "/etc/nologin"
+#endif
+
/* Macros */
+#if defined(HAVE_LOGIN_GETCAPBOOL) && defined(HAVE_LOGIN_CAP_H)
+# define HAVE_LOGIN_CAP
+#endif
+
#ifndef MAX
# define MAX(a,b) (((a)>(b))?(a):(b))
# define MIN(a,b) (((a)<(b))?(a):(b))
diff --git a/fingerprint.c b/fingerprint.c
deleted file mode 100644
index 801f6a6e..00000000
--- a/fingerprint.c
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * Copyright (c) 1999 Markus Friedl. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by Markus Friedl.
- * 4. The name of the author may not be used to endorse or promote products
- * derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "includes.h"
-RCSID("$OpenBSD: fingerprint.c,v 1.7 2000/06/20 01:39:41 markus Exp $");
-
-#include "ssh.h"
-#include "xmalloc.h"
-#include <openssl/md5.h>
-
-#define FPRINT "%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x"
-
-/*
- * Generate key fingerprint in ascii format.
- * Based on ideas and code from Bjoern Groenvall <bg@sics.se>
- */
-char *
-fingerprint(BIGNUM *e, BIGNUM *n)
-{
- static char retval[80];
- MD5_CTX md;
- unsigned char d[16];
- unsigned char *buf;
- int nlen, elen;
-
- nlen = BN_num_bytes(n);
- elen = BN_num_bytes(e);
-
- buf = xmalloc(nlen + elen);
-
- BN_bn2bin(n, buf);
- BN_bn2bin(e, buf + nlen);
-
- MD5_Init(&md);
- MD5_Update(&md, buf, nlen + elen);
- MD5_Final(d, &md);
- snprintf(retval, sizeof(retval), FPRINT,
- d[0], d[1], d[2], d[3], d[4], d[5], d[6], d[7],
- d[8], d[9], d[10], d[11], d[12], d[13], d[14], d[15]);
- memset(buf, 0, nlen + elen);
- xfree(buf);
- return retval;
-}
diff --git a/fingerprint.h b/fingerprint.h
deleted file mode 100644
index 3d7bcb32..00000000
--- a/fingerprint.h
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * Copyright (c) 1999 Markus Friedl. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by Markus Friedl.
- * 4. The name of the author may not be used to endorse or promote products
- * derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-/* RCSID("$OpenBSD: fingerprint.h,v 1.4 2000/06/20 01:39:41 markus Exp $"); */
-
-#ifndef FINGERPRINT_H
-#define FINGERPRINT_H
-char *fingerprint(BIGNUM * e, BIGNUM * n);
-#endif
diff --git a/key.c b/key.c
index 764f1f22..f2ce75e7 100644
--- a/key.c
+++ b/key.c
@@ -41,7 +41,7 @@
#include "dsa.h"
#include "uuencode.h"
-RCSID("$OpenBSD: key.c,v 1.9 2000/06/22 23:55:00 djm Exp $");
+RCSID("$OpenBSD: key.c,v 1.10 2000/08/19 21:34:43 markus Exp $");
#define SSH_DSS "ssh-dss"
@@ -335,3 +335,15 @@ key_type(Key *k)
}
return "unknown";
}
+unsigned int
+key_size(Key *k){
+ switch (k->type) {
+ case KEY_RSA:
+ return BN_num_bits(k->rsa->n);
+ break;
+ case KEY_DSA:
+ return BN_num_bits(k->dsa->p);
+ break;
+ }
+ return 0;
+}
diff --git a/log-client.c b/log-client.c
index 7e9fd61e..7615a94f 100644
--- a/log-client.c
+++ b/log-client.c
@@ -15,7 +15,7 @@
*/
#include "includes.h"
-RCSID("$OpenBSD: log-client.c,v 1.9 2000/06/20 01:39:42 markus Exp $");
+RCSID("$OpenBSD: log-client.c,v 1.10 2000/08/19 02:57:33 deraadt Exp $");
#include "xmalloc.h"
#include "ssh.h"
@@ -57,6 +57,5 @@ do_log(LogLevel level, const char *fmt, va_list args)
if (level == SYSLOG_LEVEL_DEBUG)
fprintf(stderr, "debug: ");
vsnprintf(msgbuf, sizeof(msgbuf), fmt, args);
- fprintf(stderr, "%s", msgbuf);
- fprintf(stderr, "\r\n");
+ fprintf(stderr, "%s\r\n", msgbuf);
}
diff --git a/packet.c b/packet.c
index 56080cbb..8f931107 100644
--- a/packet.c
+++ b/packet.c
@@ -17,7 +17,7 @@
*/
#include "includes.h"
-RCSID("$OpenBSD: packet.c,v 1.33 2000/06/20 01:39:43 markus Exp $");
+RCSID("$OpenBSD: packet.c,v 1.34 2000/08/19 02:17:12 deraadt Exp $");
#include "xmalloc.h"
#include "buffer.h"
@@ -479,8 +479,8 @@ packet_send1()
buffer_consume(&outgoing_packet, 8 - padding);
/* Add check bytes. */
- checksum = crc32((unsigned char *) buffer_ptr(&outgoing_packet),
- buffer_len(&outgoing_packet));
+ checksum = ssh_crc32((unsigned char *) buffer_ptr(&outgoing_packet),
+ buffer_len(&outgoing_packet));
PUT_32BIT(buf, checksum);
buffer_append(&outgoing_packet, buf, 4);
@@ -764,7 +764,7 @@ packet_read_poll1(int *payload_len_ptr)
#endif
/* Compute packet checksum. */
- checksum = crc32((unsigned char *) buffer_ptr(&incoming_packet),
+ checksum = ssh_crc32((unsigned char *) buffer_ptr(&incoming_packet),
buffer_len(&incoming_packet) - 4);
/* Skip padding. */
diff --git a/scp.1 b/scp.1
index d2fa546a..b7b24762 100644
--- a/scp.1
+++ b/scp.1
@@ -9,7 +9,7 @@
.\"
.\" Created: Sun May 7 00:14:37 1995 ylo
.\"
-.\" $Id: scp.1,v 1.8 2000/07/11 07:31:38 djm Exp $
+.\" $Id: scp.1,v 1.9 2000/08/23 00:46:24 djm Exp $
.\"
.Dd September 25, 1999
.Dt SCP 1
@@ -68,6 +68,11 @@ This option is directly passed to
.It Fl p
Preserves modification times, access times, and modes from the
original file.
+.It Fl S
+Name of program to use for the encrypted connection.
+The program must understand
+.Xr ssh 1
+options.
.It Fl r
Recursively copy entire directories.
.It Fl v
@@ -98,6 +103,11 @@ because
.Fl p
is already reserved for preserving the times and modes of the file in
.Xr rcp 1 .
+.It Fl S
+Name of program to use for the encrypted connection. The program must
+understand
+.Xr ssh 1
+options.
.It Fl 4
Forces
.Nm
diff --git a/scp.c b/scp.c
index 02feba9c..d2e4224b 100644
--- a/scp.c
+++ b/scp.c
@@ -11,6 +11,8 @@
*/
/*
+ * Parts from:
+ *
* Copyright (c) 1983, 1990, 1992, 1993, 1995
* The Regents of the University of California. All rights reserved.
*
@@ -45,7 +47,7 @@
*/
#include "includes.h"
-RCSID("$OpenBSD: scp.c,v 1.33 2000/07/13 23:19:31 provos Exp $");
+RCSID("$OpenBSD: scp.c,v 1.35 2000/08/19 02:50:07 deraadt Exp $");
#include "ssh.h"
#include "xmalloc.h"
@@ -69,6 +71,7 @@ void progressmeter(int);
/* Returns width of the terminal (for progress meter calculations). */
int getttywidth(void);
+int do_cmd(char *host, char *remuser, char *cmd, int *fdin, int *fdout, int argc);
/* Time a transfer started. */
static struct timeval start;
@@ -111,6 +114,9 @@ char *identity = NULL;
/* This is the port to use in contacting the remote site (is non-NULL). */
char *port = NULL;
+/* This is the program to execute for the secured connection. ("ssh" or -S) */
+char *ssh_program = SSH_PROGRAM;
+
/*
* This function executes the given command as the specified user on the
* given host. This returns < 0 if execution fails, and >= 0 otherwise. This
@@ -118,13 +124,13 @@ char *port = NULL;
*/
int
-do_cmd(char *host, char *remuser, char *cmd, int *fdin, int *fdout)
+do_cmd(char *host, char *remuser, char *cmd, int *fdin, int *fdout, int argc)
{
int pin[2], pout[2], reserved[2];
if (verbose_mode)
fprintf(stderr, "Executing: host %s, user %s, command %s\n",
- host, remuser ? remuser : "(unspecified)", cmd);
+ host, remuser ? remuser : "(unspecified)", cmd);
/*
* 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)
/* For a child to execute the command on the remote host using ssh. */
if (fork() == 0) {
- char *args[100];
+ char *args[100]; /* XXX careful */
unsigned int i;
/* Child. */
@@ -156,7 +162,7 @@ do_cmd(char *host, char *remuser, char *cmd, int *fdin, int *fdout)
close(pout[1]);
i = 0;
- args[i++] = SSH_PROGRAM;
+ args[i++] = ssh_program;
args[i++] = "-x";
args[i++] = "-oFallBackToRsh no";
if (IPv4)
@@ -189,8 +195,8 @@ do_cmd(char *host, char *remuser, char *cmd, int *fdin, int *fdout)
args[i++] = cmd;
args[i++] = NULL;
- execvp(SSH_PROGRAM, args);
- perror(SSH_PROGRAM);
+ execvp(ssh_program, args);
+ perror(ssh_program);
exit(1);
}
/* Parent. Close the other side, and return the local side. */
@@ -214,8 +220,6 @@ fatal(const char *fmt,...)
exit(255);
}
-/* This stuff used to be in BSD rcp extern.h. */
-
typedef struct {
int cnt;
char *buf;
@@ -231,8 +235,6 @@ int okname(char *);
void run_err(const char *,...);
void verifydir(char *);
-/* Stuff from BSD rcp.c continues. */
-
struct passwd *pwd;
uid_t userid;
int errs, remin, remout;
@@ -260,7 +262,7 @@ main(argc, argv)
extern int optind;
fflag = tflag = 0;
- while ((ch = getopt(argc, argv, "dfprtvBCc:i:P:q46")) != EOF)
+ while ((ch = getopt(argc, argv, "dfprtvBCc:i:P:q46S")) != EOF)
switch (ch) {
/* User-visible flags. */
case '4':
@@ -278,6 +280,10 @@ main(argc, argv)
case 'r':
iamrecursive = 1;
break;
+ case 'S':
+ ssh_program = optarg;
+ break;
+
/* Server options. */
case 'd':
targetshouldbedirectory = 1;
@@ -343,8 +349,8 @@ main(argc, argv)
remin = remout = -1;
/* Command to be executed on remote system using "ssh". */
(void) sprintf(cmd, "scp%s%s%s%s", verbose_mode ? " -v" : "",
- iamrecursive ? " -r" : "", pflag ? " -p" : "",
- targetshouldbedirectory ? " -d" : "");
+ iamrecursive ? " -r" : "", pflag ? " -p" : "",
+ targetshouldbedirectory ? " -d" : "");
(void) signal(SIGPIPE, lostconn);
@@ -401,9 +407,9 @@ toremote(targ, argc, argv)
if (*src == 0)
src = ".";
host = strchr(argv[i], '@');
- len = strlen(SSH_PROGRAM) + strlen(argv[i]) +
- strlen(src) + (tuser ? strlen(tuser) : 0) +
- strlen(thost) + strlen(targ) + CMDNEEDS + 32;
+ len = strlen(ssh_program) + strlen(argv[i]) +
+ strlen(src) + (tuser ? strlen(tuser) : 0) +
+ strlen(thost) + strlen(targ) + CMDNEEDS + 32;
bp = xmalloc(len);
if (host) {
*host++ = 0;
@@ -414,19 +420,19 @@ toremote(targ, argc, argv)
else if (!okname(suser))
continue;
(void) sprintf(bp,
- "%s%s -x -o'FallBackToRsh no' -n -l %s %s %s %s '%s%s%s:%s'",
- SSH_PROGRAM, verbose_mode ? " -v" : "",
- suser, host, cmd, src,
- tuser ? tuser : "", tuser ? "@" : "",
- thost, targ);
+ "%s%s -x -o'FallBackToRsh no' -n -l %s %s %s %s '%s%s%s:%s'",
+ ssh_program, verbose_mode ? " -v" : "",
+ suser, host, cmd, src,
+ tuser ? tuser : "", tuser ? "@" : "",
+ thost, targ);
} else {
host = cleanhostname(argv[i]);
(void) sprintf(bp,
- "exec %s%s -x -o'FallBackToRsh no' -n %s %s %s '%s%s%s:%s'",
- SSH_PROGRAM, verbose_mode ? " -v" : "",
- host, cmd, src,
- tuser ? tuser : "", tuser ? "@" : "",
- thost, targ);
+ "exec %s%s -x -o'FallBackToRsh no' -n %s %s %s '%s%s%s:%s'",
+ ssh_program, verbose_mode ? " -v" : "",
+ host, cmd, src,
+ tuser ? tuser : "", tuser ? "@" : "",
+ thost, targ);
}
if (verbose_mode)
fprintf(stderr, "Executing: %s\n", bp);
@@ -438,8 +444,8 @@ toremote(targ, argc, argv)
bp = xmalloc(len);
(void) sprintf(bp, "%s -t %s", cmd, targ);
host = cleanhostname(thost);
- if (do_cmd(host, tuser,
- bp, &remin, &remout) < 0)
+ if (do_cmd(host, tuser, bp, &remin,
+ &remout, argc) < 0)
exit(1);
if (response() < 0)
exit(1);
@@ -461,11 +467,11 @@ tolocal(argc, argv)
for (i = 0; i < argc - 1; i++) {
if (!(src = colon(argv[i]))) { /* Local to local. */
len = strlen(_PATH_CP) + strlen(argv[i]) +
- strlen(argv[argc - 1]) + 20;
+ strlen(argv[argc - 1]) + 20;
bp = xmalloc(len);
(void) sprintf(bp, "exec %s%s%s %s %s", _PATH_CP,
- iamrecursive ? " -r" : "", pflag ? " -p" : "",
- argv[i], argv[argc - 1]);
+ iamrecursive ? " -r" : "", pflag ? " -p" : "",
+ argv[i], argv[argc - 1]);
if (verbose_mode)
fprintf(stderr, "Executing: %s\n", bp);
if (system(bp))
@@ -491,7 +497,7 @@ tolocal(argc, argv)
len = strlen(src) + CMDNEEDS + 20;
bp = xmalloc(len);
(void) sprintf(bp, "%s -f %s", cmd, src);
- if (do_cmd(host, suser, bp, &remin, &remout) < 0) {
+ if (do_cmd(host, suser, bp, &remin, &remout, argc) < 0) {
(void) xfree(bp);
++errs;
continue;
@@ -548,8 +554,8 @@ syserr: run_err("%s: %s", name, strerror(errno));
* versions expecting microseconds.
*/
(void) sprintf(buf, "T%lu 0 %lu 0\n",
- (unsigned long) stb.st_mtime,
- (unsigned long) stb.st_atime);
+ (unsigned long) stb.st_mtime,
+ (unsigned long) stb.st_atime);
(void) atomicio(write, remout, buf, strlen(buf));
if (response() < 0)
goto next;
@@ -626,8 +632,8 @@ rsource(name, statp)
last++;
if (pflag) {
(void) sprintf(path, "T%lu 0 %lu 0\n",
- (unsigned long) statp->st_mtime,
- (unsigned long) statp->st_atime);
+ (unsigned long) statp->st_mtime,
+ (unsigned long) statp->st_atime);
(void) atomicio(write, remout, path, strlen(path));
if (response() < 0) {
closedir(dirp);
@@ -635,8 +641,7 @@ rsource(name, statp)
}
}
(void) sprintf(path, "D%04o %d %.1024s\n",
- (unsigned int) (statp->st_mode & FILEMODEMASK),
- 0, last);
+ (unsigned int) (statp->st_mode & FILEMODEMASK), 0, last);
if (verbose_mode)
fprintf(stderr, "Entering directory: %s", path);
(void) atomicio(write, remout, path, strlen(path));
@@ -783,7 +788,7 @@ sink(argc, argv)
if (need > cursize)
namebuf = xmalloc(need);
(void) sprintf(namebuf, "%s%s%s", targ,
- *targ ? "/" : "", cp);
+ *targ ? "/" : "", cp);
np = namebuf;
} else
np = targ;
@@ -954,8 +959,9 @@ response()
void
usage()
{
- (void) fprintf(stderr,
- "usage: scp [-pqrvC46] [-P port] [-c cipher] [-i identity] f1 f2; or:\n scp [options] f1 ... fn directory\n");
+ (void) fprintf(stderr, "usage: scp "
+ "[-pqrvC46] [-S ssh] [-P port] [-c cipher] [-i identity] f1 f2; or:\n"
+ " scp [options] f1 ... fn directory\n");
exit(1);
}
@@ -984,43 +990,6 @@ run_err(const char *fmt,...)
}
}
-/* Stuff below is from BSD rcp util.c. */
-
-/*-
- * Copyright (c) 1992, 1993
- * The Regents of the University of California. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * $OpenBSD: scp.c,v 1.33 2000/07/13 23:19:31 provos Exp $
- */
-
char *
colon(cp)
char *cp;
@@ -1097,7 +1066,7 @@ allocbuf(bp, fd, blksize)
size = blksize;
else
size = blksize + (stb.st_blksize - blksize % stb.st_blksize) %
- stb.st_blksize;
+ stb.st_blksize;
if (bp->cnt >= size)
return (bp);
if (bp->buf == NULL)
@@ -1228,14 +1197,14 @@ progressmeter(int flag)
i = remaining / 3600;
if (i)
snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf),
- "%2d:", i);
+ "%2d:", i);
else
snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf),
- " ");
+ " ");
i = remaining % 3600;
snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf),
- "%02d:%02d%s", i / 60, i % 60,
- (flag != 1) ? " ETA" : " ");
+ "%02d:%02d%s", i / 60, i % 60,
+ (flag != 1) ? " ETA" : " ");
}
atomicio(write, fileno(stdout), buf, strlen(buf));
diff --git a/session.c b/session.c
index d65b0698..82096c3a 100644
--- a/session.c
+++ b/session.c
@@ -8,7 +8,7 @@
*/
#include "includes.h"
-RCSID("$OpenBSD: session.c,v 1.25 2000/08/17 20:06:34 markus Exp $");
+RCSID("$OpenBSD: session.c,v 1.29 2000/08/21 16:23:31 millert Exp $");
#include "xmalloc.h"
#include "ssh.h"
@@ -52,6 +52,10 @@ RCSID("$OpenBSD: session.c,v 1.25 2000/08/17 20:06:34 markus Exp $");
# define S_UNOFILE_HARD S_UNOFILE "_hard"
#endif
+#ifdef HAVE_LOGIN_CAP
+#include <login_cap.h>
+#endif
+
/* types */
#define TTYSZ 64
@@ -117,6 +121,10 @@ Session sessions[MAX_SESSIONS];
char *aixloginmsg;
#endif /* WITH_AIXAUTHENTICATE */
+#ifdef HAVE_LOGIN_CAP
+static login_cap_t *lc;
+#endif
+
/*
* Remove local Xauthority file.
*/
@@ -200,6 +208,13 @@ do_authenticated(struct passwd * pw)
s = session_new();
s->pw = pw;
+#ifdef HAVE_LOGIN_CAP
+ if ((lc = login_getclass(pw->pw_class)) == NULL) {
+ error("unable to get login class");
+ return;
+ }
+#endif
+
/*
* We stay in this loop until the client requests to execute a shell
* or a command.
@@ -650,7 +665,11 @@ do_login(Session *s)
/* Done if .hushlogin exists. */
snprintf(buf, sizeof(buf), "%.200s/.hushlogin", pw->pw_dir);
+#ifdef HAVE_LOGIN_CAP
+ if (login_getcapbool(lc, "hushlogin", 0) || stat(buf, &st) >= 0)
+#else
if (stat(buf, &st) >= 0)
+#endif
return;
#ifdef USE_PAM
@@ -677,7 +696,12 @@ do_login(Session *s)
printf("Last login: %s from %s\r\n", time_string, buf);
}
if (options.print_motd) {
+#ifdef HAVE_LOGIN_CAP
+ f = fopen(login_getcapstr(lc, "welcome", "/etc/motd",
+ "/etc/motd"), "r");
+#else
f = fopen("/etc/motd", "r");
+#endif
if (f) {
while (fgets(buf, sizeof(buf), f))
fputs(buf, stdout);
@@ -887,10 +911,10 @@ do_child(const char *command, struct passwd * pw, const char *term,
const char *display, const char *auth_proto,
const char *auth_data, const char *ttyname)
{
- const char *shell, *cp = NULL;
+ const char *shell, *hostname, *cp = NULL;
char buf[256];
char cmd[1024];
- FILE *f;
+ FILE *f = NULL;
unsigned int envsize, i;
char **env;
extern char **environ;
@@ -905,24 +929,26 @@ do_child(const char *command, struct passwd * pw, const char *term,
options.use_login = 0;
#ifndef USE_PAM /* pam_nologin handles this */
- f = fopen("/etc/nologin", "r");
- if (f) {
- /* /etc/nologin exists. Print its contents and exit. */
- while (fgets(buf, sizeof(buf), f))
- fputs(buf, stderr);
- fclose(f);
- if (pw->pw_uid != 0)
+ if (!options.use_login) {
+# ifdef HAVE_LOGIN_CAP
+ if (!login_getcapbool(lc, "ignorenologin", 0) && pw->pw_uid)
+ f = fopen(login_getcapstr(lc, "nologin", _PATH_NOLOGIN,
+ _PATH_NOLOGIN), "r");
+# else /* HAVE_LOGIN_CAP */
+ if (pw->pw_uid)
+ f = fopen(_PATH_NOLOGIN, "r");
+# endif /* HAVE_LOGIN_CAP */
+ if (f) {
+ /* /etc/nologin exists. Print its contents and exit. */
+ while (fgets(buf, sizeof(buf), f))
+ fputs(buf, stderr);
+ fclose(f);
exit(254);
+ }
}
#endif /* USE_PAM */
-#ifndef HAVE_OSF_SIA
- /* Set login name in the kernel. */
- if (setlogin(pw->pw_name) < 0)
- error("setlogin failed: %s", strerror(errno));
-#endif
-
- /* Set uid, gid, and groups. */
+ /* Set login name, uid, gid, and groups. */
/* Login(1) does this as well, and it needs uid 0 for the "-h"
switch, so we let login(1) to this for us. */
if (!options.use_login) {
@@ -943,10 +969,18 @@ do_child(const char *command, struct passwd * pw, const char *term,
}
#else /* HAVE_OSF_SIA */
if (getuid() == 0 || geteuid() == 0) {
-#if defined(HAVE_GETUSERATTR)
+# ifdef HAVE_GETUSERATTR
set_limits_from_userattr(pw->pw_name);
-#endif /* defined(HAVE_GETUSERATTR) */
-
+# endif /* HAVE_GETUSERATTR */
+# ifdef HAVE_LOGIN_CAP
+ if (setusercontext(lc, pw, pw->pw_uid,
+ (LOGIN_SETALL & ~LOGIN_SETPATH)) < 0) {
+ perror("unable to set user context");
+ exit(1);
+ }
+# else /* HAVE_LOGIN_CAP */
+ if (setlogin(pw->pw_name) < 0)
+ error("setlogin failed: %s", strerror(errno));
if (setgid(pw->pw_gid) < 0) {
perror("setgid");
exit(1);
@@ -957,38 +991,39 @@ do_child(const char *command, struct passwd * pw, const char *term,
exit(1);
}
endgrent();
-
-#ifdef WITH_IRIX_ARRAY
+# ifdef WITH_IRIX_ARRAY
/* initialize array session */
if (newarraysess() != 0)
fatal("Failed to set up new array session: %.100s",
strerror(errno));
-#endif /* WITH_IRIX_ARRAY */
-
-#ifdef WITH_IRIX_PROJECT
+# endif /* WITH_IRIX_ARRAY */
+# ifdef WITH_IRIX_PROJECT
/* initialize irix project info */
if ((projid = getdfltprojuser(pw->pw_name)) == -1) {
debug("Failed to get project id, using projid 0");
projid = 0;
}
-
if (setprid(projid))
fatal("Failed to initialize project %d for %s: %.100s",
(int)projid, pw->pw_name, strerror(errno));
-#endif /* WITH_IRIX_PROJECT */
-
+# endif /* WITH_IRIX_PROJECT */
/* Permanently switch to the desired uid. */
permanently_set_uid(pw->pw_uid);
+# endif /* HAVE_LOGIN_CAP */
}
+#endif /* HAVE_OSF_SIA */
+
if (getuid() != pw->pw_uid || geteuid() != pw->pw_uid)
fatal("Failed to set uids to %d.", (int) pw->pw_uid);
-#endif /* HAVE_OSF_SIA */
}
/*
* Get the shell from the password data. An empty shell field is
* legal, and means /bin/sh.
*/
shell = (pw->pw_shell[0] == '\0') ? _PATH_BSHELL : pw->pw_shell;
+#ifdef HAVE_LOGIN_CAP
+ shell = login_getcapstr(lc, "shell", (char *)shell, (char *)shell);
+#endif
#ifdef AFS
/* Try to get AFS tokens for the local cell. */
@@ -1012,7 +1047,12 @@ do_child(const char *command, struct passwd * pw, const char *term,
child_set_env(&env, &envsize, "USER", pw->pw_name);
child_set_env(&env, &envsize, "LOGNAME", pw->pw_name);
child_set_env(&env, &envsize, "HOME", pw->pw_dir);
+#ifdef HAVE_LOGIN_CAP
+ (void) setusercontext(lc, pw, pw->pw_uid, LOGIN_SETPATH);
+ child_set_env(&env, &envsize, "PATH", getenv("PATH"));
+#else
child_set_env(&env, &envsize, "PATH", _PATH_STDPATH);
+#endif
snprintf(buf, sizeof buf, "%.200s/%.50s",
_PATH_MAILDIR, pw->pw_name);
@@ -1096,6 +1136,9 @@ do_child(const char *command, struct passwd * pw, const char *term,
for (i = 0; env[i]; i++)
fprintf(stderr, " %.200s\n", env[i]);
}
+ /* we have to stash the hostname before we close our socket. */
+ if (options.use_login)
+ hostname = get_remote_name_or_ip();
/*
* Close the connection descriptors; note that this is the child, and
* 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,
close(i);
/* Change current directory to the user\'s home directory. */
- if (chdir(pw->pw_dir) < 0)
+ if (chdir(pw->pw_dir) < 0) {
fprintf(stderr, "Could not chdir to home directory %s: %s\n",
pw->pw_dir, strerror(errno));
+#ifdef HAVE_LOGIN_CAP
+ if (login_getcapbool(lc, "requirehome", 0))
+ exit(1);
+#endif
+ }
/*
* 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,
} else {
/* Launch login(1). */
- execl(LOGIN_PROGRAM, "login",
- "-h", get_remote_name_or_ip(),
+ execl(LOGIN_PROGRAM, "login", "-h", hostname,
"-p", "-f", "--", pw->pw_name, NULL);
/* Login couldn't be executed, die. */
@@ -1790,6 +1837,8 @@ session_proctitle(Session *s)
void
do_authenticated2(void)
{
+ struct passwd *pw;
+
/*
* Cancel the alarm we set to limit the time taken for
* authentication.
@@ -1799,6 +1848,13 @@ do_authenticated2(void)
close(startup_pipe);
startup_pipe = -1;
}
+#ifdef HAVE_LOGIN_CAP
+ pw = auth_get_user();
+ if ((lc = login_getclass(pw->pw_class)) == NULL) {
+ error("unable to get login class");
+ return;
+ }
+#endif
server_loop2();
if (xauthfile)
xauthfile_cleanup_proc(NULL);
diff --git a/ssh-add.1 b/ssh-add.1
index 5d2f2497..d2d0c205 100644
--- a/ssh-add.1
+++ b/ssh-add.1
@@ -9,21 +9,21 @@
.\"
.\" Created: Sat Apr 22 23:55:14 1995 ylo
.\"
-.\" $Id: ssh-add.1,v 1.13 2000/05/07 02:03:18 damien Exp $
+.\" $Id: ssh-add.1,v 1.14 2000/08/23 00:46:24 djm Exp $
.\"
.Dd September 25, 1999
.Dt SSH-ADD 1
.Os
.Sh NAME
.Nm ssh-add
-.Nd adds RSA identities for the authentication agent
+.Nd adds RSA or DSA identities for the authentication agent
.Sh SYNOPSIS
.Nm ssh-add
.Op Fl lLdD
.Op Ar
.Sh DESCRIPTION
.Nm
-adds RSA identities to the authentication agent,
+adds RSA or DSA identities to the authentication agent,
.Xr ssh-agent 1 .
When run without arguments, it adds the file
.Pa $HOME/.ssh/identity .
@@ -63,6 +63,8 @@ used to encrypt the private part of this file.
This is the default file added by
.Nm
when no other files have been specified.
+.It Pa $HOME/.ssh/id_dsa
+Contains the DSA authentication identity of the user.
.Pp
.Sh ENVIRONMENT
.Bl -tag -width Ds
diff --git a/ssh-add.c b/ssh-add.c
index 482229c2..a51f477a 100644
--- a/ssh-add.c
+++ b/ssh-add.c
@@ -4,18 +4,21 @@
* All rights reserved
* Created: Thu Apr 6 00:52:24 1995 ylo
* Adds an identity to the authentication server, or removes an identity.
+ *
+ * SSH2 implementation,
+ * Copyright (c) 2000 Markus Friedl. All rights reserved.
*/
#include "includes.h"
-RCSID("$OpenBSD: ssh-add.c,v 1.18 2000/07/16 08:27:21 markus Exp $");
+RCSID("$OpenBSD: ssh-add.c,v 1.19 2000/08/19 21:34:43 markus Exp $");
+#include <openssl/evp.h>
#include <openssl/rsa.h>
#include <openssl/dsa.h>
#include "rsa.h"
#include "ssh.h"
#include "xmalloc.h"
-#include "fingerprint.h"
#include "key.h"
#include "authfd.h"
#include "authfile.h"
@@ -37,7 +40,7 @@ delete_file(AuthenticationConnection *ac, const char *filename)
printf("Bad key file %s: %s\n", filename, strerror(errno));
return;
}
- if (ssh_remove_identity(ac, public->rsa))
+ if (ssh_remove_identity(ac, public))
fprintf(stderr, "Identity removed: %s (%s)\n", filename, comment);
else
fprintf(stderr, "Could not remove identity: %s\n", filename);
@@ -45,11 +48,18 @@ delete_file(AuthenticationConnection *ac, const char *filename)
xfree(comment);
}
+/* Send a request to remove all identities. */
void
delete_all(AuthenticationConnection *ac)
{
- /* Send a request to remove all identities. */
- if (ssh_remove_all_identities(ac))
+ int success = 1;
+
+ if (!ssh_remove_all_identities(ac, 1))
+ success = 0;
+ /* ignore error-code for ssh2 */
+ ssh_remove_all_identities(ac, 2);
+
+ if (success)
fprintf(stderr, "All identities removed.\n");
else
fprintf(stderr, "Failed to remove all identitities.\n");
@@ -96,6 +106,7 @@ ssh_askpass(char *askpass, char *msg)
void
add_file(AuthenticationConnection *ac, const char *filename)
{
+ struct stat st;
Key *public;
Key *private;
char *saved_comment, *comment, *askpass = NULL;
@@ -104,6 +115,10 @@ add_file(AuthenticationConnection *ac, const char *filename)
int interactive = isatty(STDIN_FILENO);
int type = KEY_RSA;
+ if (stat(filename, &st) < 0) {
+ perror(filename);
+ exit(1);
+ }
/*
* try to load the public key. right now this only works for RSA,
* since DSA keys are fully encrypted
@@ -154,54 +169,40 @@ add_file(AuthenticationConnection *ac, const char *filename)
strlcpy(msg, "Bad passphrase, try again", sizeof msg);
}
}
- xfree(saved_comment);
-
- if (ssh_add_identity(ac, private, comment))
- fprintf(stderr, "Identity added: %s (%s)\n", filename, comment);
+ xfree(comment);
+ if (ssh_add_identity(ac, private, saved_comment))
+ fprintf(stderr, "Identity added: %s (%s)\n", filename, saved_comment);
else
fprintf(stderr, "Could not add identity: %s\n", filename);
key_free(private);
- xfree(comment);
+ xfree(saved_comment);
}
void
list_identities(AuthenticationConnection *ac, int fp)
{
- BIGNUM *e, *n;
- int status;
+ Key *key;
char *comment;
- int had_identities;
+ int had_identities = 0;
+ int version;
- e = BN_new();
- n = BN_new();
- had_identities = 0;
- for (status = ssh_get_first_identity(ac, e, n, &comment);
- status;
- status = ssh_get_next_identity(ac, e, n, &comment)) {
- unsigned int bits = BN_num_bits(n);
- had_identities = 1;
- if (fp) {
- printf("%d %s %s\n", bits, fingerprint(e, n), comment);
- } else {
- char *ebuf, *nbuf;
- ebuf = BN_bn2dec(e);
- if (ebuf == NULL) {
- error("list_identities: BN_bn2dec(e) failed.");
+ for (version = 1; version <= 2; version++) {
+ for (key = ssh_get_first_identity(ac, &comment, version);
+ key != NULL;
+ key = ssh_get_next_identity(ac, &comment, version)) {
+ had_identities = 1;
+ if (fp) {
+ printf("%d %s %s\n",
+ key_size(key), key_fingerprint(key), comment);
} else {
- nbuf = BN_bn2dec(n);
- if (nbuf == NULL) {
- error("list_identities: BN_bn2dec(n) failed.");
- } else {
- printf("%d %s %s %s\n", bits, ebuf, nbuf, comment);
- free(nbuf);
- }
- free(ebuf);
+ if (!key_write(key, stdout))
+ fprintf(stderr, "key_write failed");
+ fprintf(stdout, " %s\n", comment);
}
+ key_free(key);
+ xfree(comment);
}
- xfree(comment);
}
- BN_clear_free(e);
- BN_clear_free(n);
if (!had_identities)
printf("The agent has no identities.\n");
}
@@ -225,6 +226,8 @@ main(int argc, char **argv)
__progname);
exit(1);
}
+ SSLeay_add_all_algorithms();
+
/* At first, get a connection to the authentication agent. */
ac = ssh_get_authentication_connection();
if (ac == NULL) {
diff --git a/ssh-agent.1 b/ssh-agent.1
index 47b1e5cc..0aa1ecf4 100644
--- a/ssh-agent.1
+++ b/ssh-agent.1
@@ -1,4 +1,4 @@
-.\" $OpenBSD: ssh-agent.1,v 1.13 2000/07/06 04:06:56 aaron Exp $
+.\" $OpenBSD: ssh-agent.1,v 1.14 2000/08/19 21:34:43 markus Exp $
.\"
.\" -*- nroff -*-
.\"
@@ -27,14 +27,15 @@
.Oc
.Sh DESCRIPTION
.Nm
-is a program to hold private keys used for RSA authentication.
+is a program to hold private keys used for public key authentication
+(RSA, DSA).
The idea is that
.Nm
is started in the beginning of an X-session or a login session, and
all other windows or programs are started as clients to the ssh-agent
program.
Through use of environment variables the agent can be located
-and automatically used for RSA authentication when logging in to other
+and automatically used for authentication when logging in to other
machines using
.Xr ssh 1 .
.Pp
@@ -128,7 +129,9 @@ This file is not used by
but is normally added to the agent using
.Xr ssh-add 1
at login time.
-.It Pa /tmp/ssh-XXXX/agent.<pid> ,
+.It Pa $HOME/.ssh/id_dsa
+Contains the DSA authentication identity of the user.
+.Pq Pa /tmp/ssh-XXXXXXXX/agent.<pid> ,
Unix-domain sockets used to contain the connection to the
authentication agent.
These sockets should only be readable by the owner.
diff --git a/ssh-agent.c b/ssh-agent.c
index e8383b5d..56b81a78 100644
--- a/ssh-agent.c
+++ b/ssh-agent.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ssh-agent.c,v 1.32 2000/07/16 08:27:21 markus Exp $ */
+/* $OpenBSD: ssh-agent.c,v 1.33 2000/08/19 21:34:43 markus Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
@@ -6,10 +6,13 @@
* All rights reserved
* Created: Wed Mar 29 03:46:59 1995 ylo
* The authentication agent program.
+ *
+ * SSH2 implementation,
+ * Copyright (c) 2000 Markus Friedl. All rights reserved.
*/
#include "includes.h"
-RCSID("$OpenBSD: ssh-agent.c,v 1.32 2000/07/16 08:27:21 markus Exp $");
+RCSID("$OpenBSD: ssh-agent.c,v 1.33 2000/08/19 21:34:43 markus Exp $");
#include "ssh.h"
#include "rsa.h"
@@ -20,11 +23,14 @@ RCSID("$OpenBSD: ssh-agent.c,v 1.32 2000/07/16 08:27:21 markus Exp $");
#include "getput.h"
#include "mpaux.h"
+#include <openssl/evp.h>
#include <openssl/md5.h>
#include <openssl/dsa.h>
#include <openssl/rsa.h>
#include "key.h"
#include "authfd.h"
+#include "dsa.h"
+#include "kex.h"
typedef struct {
int fd;
@@ -39,12 +45,17 @@ unsigned int sockets_alloc = 0;
SocketEntry *sockets = NULL;
typedef struct {
- RSA *key;
+ Key *key;
char *comment;
} Identity;
-unsigned int num_identities = 0;
-Identity *identities = NULL;
+typedef struct {
+ int nentries;
+ Identity *identities;
+} Idtab;
+
+/* private key table, one per protocol version */
+Idtab idtable[3];
int max_fd = 0;
@@ -62,175 +73,243 @@ static const char *__progname = "ssh-agent";
#endif /* HAVE___PROGNAME */
void
-process_request_identity(SocketEntry *e)
+idtab_init(void)
+{
+ int i;
+ for (i = 0; i <=2; i++){
+ idtable[i].identities = NULL;
+ idtable[i].nentries = 0;
+ }
+}
+
+/* return private key table for requested protocol version */
+Idtab *
+idtab_lookup(int version)
+{
+ if (version < 1 || version > 2)
+ fatal("internal error, bad protocol version %d", version);
+ return &idtable[version];
+}
+
+/* return matching private key for given public key */
+Key *
+lookup_private_key(Key *key, int *idx, int version)
+{
+ int i;
+ Idtab *tab = idtab_lookup(version);
+ for (i = 0; i < tab->nentries; i++) {
+ if (key_equal(key, tab->identities[i].key)) {
+ if (idx != NULL)
+ *idx = i;
+ return tab->identities[i].key;
+ }
+ }
+ return NULL;
+}
+
+/* send list of supported public keys to 'client' */
+void
+process_request_identities(SocketEntry *e, int version)
{
+ Idtab *tab = idtab_lookup(version);
Buffer msg;
int i;
buffer_init(&msg);
- buffer_put_char(&msg, SSH_AGENT_RSA_IDENTITIES_ANSWER);
- buffer_put_int(&msg, num_identities);
- for (i = 0; i < num_identities; i++) {
- buffer_put_int(&msg, BN_num_bits(identities[i].key->n));
- buffer_put_bignum(&msg, identities[i].key->e);
- buffer_put_bignum(&msg, identities[i].key->n);
- buffer_put_string(&msg, identities[i].comment,
- strlen(identities[i].comment));
+ buffer_put_char(&msg, (version == 1) ?
+ SSH_AGENT_RSA_IDENTITIES_ANSWER : SSH2_AGENT_IDENTITIES_ANSWER);
+ buffer_put_int(&msg, tab->nentries);
+ for (i = 0; i < tab->nentries; i++) {
+ Identity *id = &tab->identities[i];
+ if (id->key->type == KEY_RSA) {
+ buffer_put_int(&msg, BN_num_bits(id->key->rsa->n));
+ buffer_put_bignum(&msg, id->key->rsa->e);
+ buffer_put_bignum(&msg, id->key->rsa->n);
+ } else {
+ unsigned char *blob;
+ unsigned int blen;
+ dsa_make_key_blob(id->key, &blob, &blen);
+ buffer_put_string(&msg, blob, blen);
+ xfree(blob);
+ }
+ buffer_put_cstring(&msg, id->comment);
}
buffer_put_int(&e->output, buffer_len(&msg));
buffer_append(&e->output, buffer_ptr(&msg), buffer_len(&msg));
buffer_free(&msg);
}
+/* ssh1 only */
void
-process_authentication_challenge(SocketEntry *e)
+process_authentication_challenge1(SocketEntry *e)
{
- int i, pub_bits, len;
- BIGNUM *pub_e, *pub_n, *challenge;
+ Key *key, *private;
+ BIGNUM *challenge;
+ int i, len;
Buffer msg;
MD5_CTX md;
unsigned char buf[32], mdbuf[16], session_id[16];
unsigned int response_type;
buffer_init(&msg);
- pub_e = BN_new();
- pub_n = BN_new();
+ key = key_new(KEY_RSA);
challenge = BN_new();
- pub_bits = buffer_get_int(&e->input);
- buffer_get_bignum(&e->input, pub_e);
- buffer_get_bignum(&e->input, pub_n);
- buffer_get_bignum(&e->input, challenge);
- if (buffer_len(&e->input) == 0) {
- /* Compatibility code for old servers. */
- memset(session_id, 0, 16);
- response_type = 0;
- } else {
- /* New code. */
- buffer_get(&e->input, (char *) session_id, 16);
- response_type = buffer_get_int(&e->input);
- }
- for (i = 0; i < num_identities; i++)
- if (pub_bits == BN_num_bits(identities[i].key->n) &&
- BN_cmp(pub_e, identities[i].key->e) == 0 &&
- BN_cmp(pub_n, identities[i].key->n) == 0) {
- /* Decrypt the challenge using the private key. */
- rsa_private_decrypt(challenge, challenge, identities[i].key);
-
- /* Compute the desired response. */
- switch (response_type) {
- case 0:/* As of protocol 1.0 */
- /* This response type is no longer supported. */
- log("Compatibility with ssh protocol 1.0 no longer supported.");
- buffer_put_char(&msg, SSH_AGENT_FAILURE);
- goto send;
-
- case 1:/* As of protocol 1.1 */
- /* The response is MD5 of decrypted challenge plus session id. */
- len = BN_num_bytes(challenge);
-
- if (len <= 0 || len > 32) {
- fatal("process_authentication_challenge: "
- "bad challenge length %d", len);
- }
- memset(buf, 0, 32);
- BN_bn2bin(challenge, buf + 32 - len);
- MD5_Init(&md);
- MD5_Update(&md, buf, 32);
- MD5_Update(&md, session_id, 16);
- MD5_Final(mdbuf, &md);
- break;
-
- default:
- fatal("process_authentication_challenge: bad response_type %d",
- response_type);
- break;
- }
- /* Send the response. */
- buffer_put_char(&msg, SSH_AGENT_RSA_RESPONSE);
- for (i = 0; i < 16; i++)
- buffer_put_char(&msg, mdbuf[i]);
+ buffer_get_int(&e->input); /* ignored */
+ buffer_get_bignum(&e->input, key->rsa->e);
+ buffer_get_bignum(&e->input, key->rsa->n);
+ buffer_get_bignum(&e->input, challenge);
- goto send;
+ /* Only protocol 1.1 is supported */
+ if (buffer_len(&e->input) == 0)
+ goto failure;
+ buffer_get(&e->input, (char *) session_id, 16);
+ response_type = buffer_get_int(&e->input);
+ if (response_type != 1)
+ goto failure;
+
+ private = lookup_private_key(key, NULL, 1);
+ if (private != NULL) {
+ /* Decrypt the challenge using the private key. */
+ rsa_private_decrypt(challenge, challenge, private->rsa);
+
+ /* The response is MD5 of decrypted challenge plus session id. */
+ len = BN_num_bytes(challenge);
+ if (len <= 0 || len > 32) {
+ log("process_authentication_challenge: bad challenge length %d", len);
+ goto failure;
}
- /* Unknown identity. Send failure. */
+ memset(buf, 0, 32);
+ BN_bn2bin(challenge, buf + 32 - len);
+ MD5_Init(&md);
+ MD5_Update(&md, buf, 32);
+ MD5_Update(&md, session_id, 16);
+ MD5_Final(mdbuf, &md);
+
+ /* Send the response. */
+ buffer_put_char(&msg, SSH_AGENT_RSA_RESPONSE);
+ for (i = 0; i < 16; i++)
+ buffer_put_char(&msg, mdbuf[i]);
+ goto send;
+ }
+
+failure:
+ /* Unknown identity or protocol error. Send failure. */
buffer_put_char(&msg, SSH_AGENT_FAILURE);
send:
buffer_put_int(&e->output, buffer_len(&msg));
+ buffer_append(&e->output, buffer_ptr(&msg), buffer_len(&msg));
+ key_free(key);
+ BN_clear_free(challenge);
+ buffer_free(&msg);
+}
+
+/* ssh2 only */
+void
+process_sign_request2(SocketEntry *e)
+{
+ extern int datafellows;
+ Key *key, *private;
+ unsigned char *blob, *data, *signature = NULL;
+ unsigned int blen, dlen, slen = 0;
+ Buffer msg;
+ int ok = -1;
+
+ datafellows = 0;
+
+ blob = buffer_get_string(&e->input, &blen);
+ data = buffer_get_string(&e->input, &dlen);
+
+ key = dsa_key_from_blob(blob, blen);
+ if (key != NULL) {
+ private = lookup_private_key(key, NULL, 2);
+ if (private != NULL)
+ ok = dsa_sign(private, &signature, &slen, data, dlen);
+ }
+ key_free(key);
+ buffer_init(&msg);
+ if (ok == 0) {
+ buffer_put_char(&msg, SSH2_AGENT_SIGN_RESPONSE);
+ buffer_put_string(&msg, signature, slen);
+ } else {
+ buffer_put_char(&msg, SSH_AGENT_FAILURE);
+ }
+ buffer_put_int(&e->output, buffer_len(&msg));
buffer_append(&e->output, buffer_ptr(&msg),
- buffer_len(&msg));
+ buffer_len(&msg));
buffer_free(&msg);
- BN_clear_free(pub_e);
- BN_clear_free(pub_n);
- BN_clear_free(challenge);
+ xfree(data);
+ xfree(blob);
+ if (signature != NULL)
+ xfree(signature);
}
+/* shared */
void
-process_remove_identity(SocketEntry *e)
+process_remove_identity(SocketEntry *e, int version)
{
+ Key *key = NULL, *private;
+ unsigned char *blob;
+ unsigned int blen;
unsigned int bits;
- unsigned int i;
- BIGNUM *dummy, *n;
-
- dummy = BN_new();
- n = BN_new();
-
- /* Get the key from the packet. */
- bits = buffer_get_int(&e->input);
- buffer_get_bignum(&e->input, dummy);
- buffer_get_bignum(&e->input, n);
-
- if (bits != BN_num_bits(n))
- log("Warning: identity keysize mismatch: actual %d, announced %d",
- BN_num_bits(n), bits);
-
- /* Check if we have the key. */
- for (i = 0; i < num_identities; i++)
- if (BN_cmp(identities[i].key->n, n) == 0) {
+ int success = 0;
+
+ switch(version){
+ case 1:
+ key = key_new(KEY_RSA);
+ bits = buffer_get_int(&e->input);
+ buffer_get_bignum(&e->input, key->rsa->e);
+ buffer_get_bignum(&e->input, key->rsa->n);
+
+ if (bits != key_size(key))
+ log("Warning: identity keysize mismatch: actual %d, announced %d",
+ key_size(key), bits);
+ break;
+ case 2:
+ blob = buffer_get_string(&e->input, &blen);
+ key = dsa_key_from_blob(blob, blen);
+ xfree(blob);
+ break;
+ }
+ if (key != NULL) {
+ int idx;
+ private = lookup_private_key(key, &idx, version);
+ if (private != NULL) {
/*
* We have this key. Free the old key. Since we
* don\'t want to leave empty slots in the middle of
* the array, we actually free the key there and copy
* data from the last entry.
*/
- RSA_free(identities[i].key);
- xfree(identities[i].comment);
- if (i < num_identities - 1)
- identities[i] = identities[num_identities - 1];
- num_identities--;
- BN_clear_free(dummy);
- BN_clear_free(n);
-
- /* Send success. */
- buffer_put_int(&e->output, 1);
- buffer_put_char(&e->output, SSH_AGENT_SUCCESS);
- return;
+ Idtab *tab = idtab_lookup(version);
+ key_free(tab->identities[idx].key);
+ xfree(tab->identities[idx].comment);
+ if (idx != tab->nentries)
+ tab->identities[idx] = tab->identities[tab->nentries];
+ tab->nentries--;
+ success = 1;
}
- /* We did not have the key. */
- BN_clear(dummy);
- BN_clear(n);
-
- /* Send failure. */
+ key_free(key);
+ }
buffer_put_int(&e->output, 1);
- buffer_put_char(&e->output, SSH_AGENT_FAILURE);
+ buffer_put_char(&e->output,
+ success ? SSH_AGENT_SUCCESS : SSH_AGENT_FAILURE);
}
-/*
- * Removes all identities from the agent.
- */
void
-process_remove_all_identities(SocketEntry *e)
+process_remove_all_identities(SocketEntry *e, int version)
{
unsigned int i;
+ Idtab *tab = idtab_lookup(version);
/* Loop over all identities and clear the keys. */
- for (i = 0; i < num_identities; i++) {
- RSA_free(identities[i].key);
- xfree(identities[i].comment);
+ for (i = 0; i < tab->nentries; i++) {
+ key_free(tab->identities[i].key);
+ xfree(tab->identities[i].comment);
}
/* Mark that there are no identities. */
- num_identities = 0;
+ tab->nentries = 0;
/* Send success. */
buffer_put_int(&e->output, 1);
@@ -238,79 +317,108 @@ process_remove_all_identities(SocketEntry *e)
return;
}
-/*
- * Adds an identity to the agent.
- */
void
-process_add_identity(SocketEntry *e)
+process_add_identity(SocketEntry *e, int version)
{
- RSA *k;
- int i;
+ Key *k = NULL;
+ RSA *rsa;
BIGNUM *aux;
BN_CTX *ctx;
+ char *type;
+ char *comment;
+ int success = 0;
+ Idtab *tab = idtab_lookup(version);
- if (num_identities == 0)
- identities = xmalloc(sizeof(Identity));
- else
- identities = xrealloc(identities, (num_identities + 1) * sizeof(Identity));
-
- identities[num_identities].key = RSA_new();
- k = identities[num_identities].key;
- buffer_get_int(&e->input); /* bits */
- k->n = BN_new();
- buffer_get_bignum(&e->input, k->n);
- k->e = BN_new();
- buffer_get_bignum(&e->input, k->e);
- k->d = BN_new();
- buffer_get_bignum(&e->input, k->d);
- k->iqmp = BN_new();
- buffer_get_bignum(&e->input, k->iqmp);
- /* SSH and SSL have p and q swapped */
- k->q = BN_new();
- buffer_get_bignum(&e->input, k->q); /* p */
- k->p = BN_new();
- buffer_get_bignum(&e->input, k->p); /* q */
-
- /* Generate additional parameters */
- aux = BN_new();
- ctx = BN_CTX_new();
-
- BN_sub(aux, k->q, BN_value_one());
- k->dmq1 = BN_new();
- BN_mod(k->dmq1, k->d, aux, ctx);
-
- BN_sub(aux, k->p, BN_value_one());
- k->dmp1 = BN_new();
- BN_mod(k->dmp1, k->d, aux, ctx);
-
- BN_clear_free(aux);
- BN_CTX_free(ctx);
-
- identities[num_identities].comment = buffer_get_string(&e->input, NULL);
-
- /* Check if we already have the key. */
- for (i = 0; i < num_identities; i++)
- if (BN_cmp(identities[i].key->n, k->n) == 0) {
- /*
- * We already have this key. Clear and free the new
- * data and return success.
- */
- RSA_free(k);
- xfree(identities[num_identities].comment);
+ switch (version) {
+ case 1:
+ k = key_new(KEY_RSA);
+ rsa = k->rsa;
- /* Send success. */
- buffer_put_int(&e->output, 1);
- buffer_put_char(&e->output, SSH_AGENT_SUCCESS);
- return;
+ /* allocate mem for private key */
+ /* XXX rsa->n and rsa->e are already allocated */
+ rsa->d = BN_new();
+ rsa->iqmp = BN_new();
+ rsa->q = BN_new();
+ rsa->p = BN_new();
+ rsa->dmq1 = BN_new();
+ rsa->dmp1 = BN_new();
+
+ buffer_get_int(&e->input); /* ignored */
+
+ buffer_get_bignum(&e->input, rsa->n);
+ buffer_get_bignum(&e->input, rsa->e);
+ buffer_get_bignum(&e->input, rsa->d);
+ buffer_get_bignum(&e->input, rsa->iqmp);
+
+ /* SSH and SSL have p and q swapped */
+ buffer_get_bignum(&e->input, rsa->q); /* p */
+ buffer_get_bignum(&e->input, rsa->p); /* q */
+
+ /* Generate additional parameters */
+ aux = BN_new();
+ ctx = BN_CTX_new();
+
+ BN_sub(aux, rsa->q, BN_value_one());
+ BN_mod(rsa->dmq1, rsa->d, aux, ctx);
+
+ BN_sub(aux, rsa->p, BN_value_one());
+ BN_mod(rsa->dmp1, rsa->d, aux, ctx);
+
+ BN_clear_free(aux);
+ BN_CTX_free(ctx);
+
+ break;
+ case 2:
+ type = buffer_get_string(&e->input, NULL);
+ if (strcmp(type, KEX_DSS)) {
+ buffer_clear(&e->input);
+ xfree(type);
+ goto send;
}
- /* Increment the number of identities. */
- num_identities++;
+ xfree(type);
- /* Send a success message. */
+ k = key_new(KEY_DSA);
+
+ /* allocate mem for private key */
+ k->dsa->priv_key = BN_new();
+
+ buffer_get_bignum2(&e->input, k->dsa->p);
+ buffer_get_bignum2(&e->input, k->dsa->q);
+ buffer_get_bignum2(&e->input, k->dsa->g);
+ buffer_get_bignum2(&e->input, k->dsa->pub_key);
+ buffer_get_bignum2(&e->input, k->dsa->priv_key);
+
+ break;
+ }
+
+ comment = buffer_get_string(&e->input, NULL);
+ if (k == NULL) {
+ xfree(comment);
+ goto send;
+ }
+ success = 1;
+ if (lookup_private_key(k, NULL, version) == NULL) {
+ if (tab->nentries == 0)
+ tab->identities = xmalloc(sizeof(Identity));
+ else
+ tab->identities = xrealloc(tab->identities,
+ (tab->nentries + 1) * sizeof(Identity));
+ tab->identities[tab->nentries].key = k;
+ tab->identities[tab->nentries].comment = comment;
+ /* Increment the number of identities. */
+ tab->nentries++;
+ } else {
+ key_free(k);
+ xfree(comment);
+ }
+send:
buffer_put_int(&e->output, 1);
- buffer_put_char(&e->output, SSH_AGENT_SUCCESS);
+ buffer_put_char(&e->output,
+ success ? SSH_AGENT_SUCCESS : SSH_AGENT_FAILURE);
}
+/* dispatch incoming messages */
+
void
process_message(SocketEntry *e)
{
@@ -333,20 +441,37 @@ process_message(SocketEntry *e)
type = buffer_get_char(&e->input);
switch (type) {
- case SSH_AGENTC_REQUEST_RSA_IDENTITIES:
- process_request_identity(e);
- break;
+ /* ssh1 */
case SSH_AGENTC_RSA_CHALLENGE:
- process_authentication_challenge(e);
+ process_authentication_challenge1(e);
+ break;
+ case SSH_AGENTC_REQUEST_RSA_IDENTITIES:
+ process_request_identities(e, 1);
break;
case SSH_AGENTC_ADD_RSA_IDENTITY:
- process_add_identity(e);
+ process_add_identity(e, 1);
break;
case SSH_AGENTC_REMOVE_RSA_IDENTITY:
- process_remove_identity(e);
+ process_remove_identity(e, 1);
break;
case SSH_AGENTC_REMOVE_ALL_RSA_IDENTITIES:
- process_remove_all_identities(e);
+ process_remove_all_identities(e, 1);
+ break;
+ /* ssh2 */
+ case SSH2_AGENTC_SIGN_REQUEST:
+ process_sign_request2(e);
+ break;
+ case SSH2_AGENTC_REQUEST_IDENTITIES:
+ process_request_identities(e, 2);
+ break;
+ case SSH2_AGENTC_ADD_IDENTITY:
+ process_add_identity(e, 2);
+ break;
+ case SSH2_AGENTC_REMOVE_IDENTITY:
+ process_remove_identity(e, 2);
+ break;
+ case SSH2_AGENTC_REMOVE_ALL_IDENTITIES:
+ process_remove_all_identities(e, 2);
break;
default:
/* Unknown message. Respond with failure. */
@@ -511,9 +636,9 @@ main(int ac, char **av)
pid_t pid;
char *shell, *format, *pidstr, pidstrbuf[1 + 3 * sizeof pid];
extern int optind;
-
+
init_rng();
-
+
/* check if RSA support exists */
if (rsa_alive() == 0) {
fprintf(stderr,
@@ -654,6 +779,7 @@ main(int ac, char **av)
signal(SIGALRM, check_parent_exists);
alarm(10);
}
+ idtab_init();
signal(SIGINT, SIG_IGN);
signal(SIGPIPE, SIG_IGN);
signal(SIGHUP, cleanup_exit);
diff --git a/ssh-keygen.c b/ssh-keygen.c
index 8a03f0d8..83450fe8 100644
--- a/ssh-keygen.c
+++ b/ssh-keygen.c
@@ -7,7 +7,7 @@
*/
#include "includes.h"
-RCSID("$OpenBSD: ssh-keygen.c,v 1.29 2000/07/15 04:01:37 djm Exp $");
+RCSID("$OpenBSD: ssh-keygen.c,v 1.30 2000/08/19 21:34:43 markus Exp $");
#include <openssl/evp.h>
#include <openssl/pem.h>
@@ -16,7 +16,6 @@ RCSID("$OpenBSD: ssh-keygen.c,v 1.29 2000/07/15 04:01:37 djm Exp $");
#include "ssh.h"
#include "xmalloc.h"
-#include "fingerprint.h"
#include "key.h"
#include "rsa.h"
#include "dsa.h"
@@ -228,8 +227,9 @@ do_print_public(struct passwd *pw)
void
do_fingerprint(struct passwd *pw)
{
+ /* XXX RSA1 only */
+
FILE *f;
- BIGNUM *e, *n;
Key *public;
char *comment = NULL, *cp, *ep, line[16*1024];
int i, skip = 0, num = 1, invalid = 1;
@@ -249,13 +249,9 @@ do_fingerprint(struct passwd *pw)
key_free(public);
exit(0);
}
- key_free(public);
- /* XXX */
f = fopen(identity_file, "r");
if (f != NULL) {
- n = BN_new();
- e = BN_new();
while (fgets(line, sizeof(line), f)) {
i = strlen(line) - 1;
if (line[i] != '\n') {
@@ -290,18 +286,17 @@ do_fingerprint(struct passwd *pw)
*cp++ = '\0';
}
ep = cp;
- if (auth_rsa_read_key(&cp, &ignore, e, n)) {
+ if (auth_rsa_read_key(&cp, &ignore, public->rsa->e, public->rsa->n)) {
invalid = 0;
comment = *cp ? cp : comment;
- printf("%d %s %s\n", BN_num_bits(n),
- fingerprint(e, n),
+ printf("%d %s %s\n", key_size(public),
+ key_fingerprint(public),
comment ? comment : "no comment");
}
}
- BN_free(e);
- BN_free(n);
fclose(f);
}
+ key_free(public);
if (invalid) {
printf("%s is not a valid key file.\n", identity_file);
exit(1);
diff --git a/ssh.c b/ssh.c
index 58e4d7bd..39512c5f 100644
--- a/ssh.c
+++ b/ssh.c
@@ -11,7 +11,7 @@
*/
#include "includes.h"
-RCSID("$OpenBSD: ssh.c,v 1.58 2000/07/16 08:27:22 markus Exp $");
+RCSID("$OpenBSD: ssh.c,v 1.61 2000/08/20 18:42:40 millert Exp $");
#include <openssl/evp.h>
#include <openssl/dsa.h>
@@ -253,8 +253,8 @@ main(int ac, char **av)
cp = strrchr(av0, '/') + 1;
else
cp = av0;
- if (strcmp(cp, "rsh") != 0 && strcmp(cp, "ssh") != 0 &&
- strcmp(cp, "rlogin") != 0 && strcmp(cp, "slogin") != 0)
+ if (strcmp(cp, "rsh") && strcmp(cp, "ssh") && strcmp(cp, "rlogin") &&
+ strcmp(cp, "slogin") && strcmp(cp, "remsh"))
host = cp;
for (optind = 1; optind < ac; optind++) {
@@ -490,6 +490,9 @@ main(int ac, char **av)
pwcopy.pw_passwd = xstrdup(pw->pw_passwd);
pwcopy.pw_uid = pw->pw_uid;
pwcopy.pw_gid = pw->pw_gid;
+#ifdef HAVE_PW_CLASS_IN_PASSWD
+ pwcopy.pw_class = xstrdup(pw->pw_class);
+#endif
pwcopy.pw_dir = xstrdup(pw->pw_dir);
pwcopy.pw_shell = xstrdup(pw->pw_shell);
pw = &pwcopy;
@@ -871,7 +874,7 @@ ssh_session(void)
}
/* Enter the interactive session. */
- return client_loop(have_tty, tty_flag ? options.escape_char : -1);
+ return client_loop(have_tty, tty_flag ? options.escape_char : -1, 0);
}
void
@@ -954,9 +957,16 @@ int
ssh_session2(void)
{
int window, packetmax, id;
- int in = dup(STDIN_FILENO);
- int out = dup(STDOUT_FILENO);
- int err = dup(STDERR_FILENO);
+ int in, out, err;
+
+ /* If requested, let ssh continue in the background. */
+ if (fork_after_authentication_flag)
+ if (daemon(1, 1) < 0)
+ fatal("daemon() failed: %.200s", strerror(errno));
+
+ in = dup(STDIN_FILENO);
+ out = dup(STDOUT_FILENO);
+ err = dup(STDERR_FILENO);
if (in < 0 || out < 0 || err < 0)
fatal("dump in/out/err failed");
@@ -972,13 +982,13 @@ ssh_session2(void)
packetmax = window/2;
}
+/*XXX MAXPACK */
id = channel_new(
"session", SSH_CHANNEL_OPENING, in, out, err,
window, packetmax, CHAN_EXTENDED_WRITE, xstrdup("client-session"));
-
channel_open(id);
channel_register_callback(id, SSH2_MSG_CHANNEL_OPEN_CONFIRMATION, client_init, (void *)0);
- return client_loop(tty_flag, tty_flag ? options.escape_char : -1);
+ return client_loop(tty_flag, tty_flag ? options.escape_char : -1, id);
}
diff --git a/ssh.h b/ssh.h
index f3f049fc..f21dee49 100644
--- a/ssh.h
+++ b/ssh.h
@@ -13,7 +13,7 @@
*
*/
-/* RCSID("$OpenBSD: ssh.h,v 1.48 2000/07/13 22:53:21 provos Exp $"); */
+/* RCSID("$OpenBSD: ssh.h,v 1.49 2000/08/19 18:48:11 markus Exp $"); */
#ifndef SSH_H
#define SSH_H
@@ -105,7 +105,11 @@
#endif /* SSH_PROGRAM */
#ifndef LOGIN_PROGRAM
-#define LOGIN_PROGRAM "/usr/bin/login"
+# ifdef LOGIN_PROGRAM_FALLBACK
+# define LOGIN_PROGRAM LOGIN_PROGRAM_FALLBACK
+# else
+# define LOGIN_PROGRAM "/usr/bin/login"
+# endif
#endif /* LOGIN_PROGRAM */
#ifndef ASKPASS_PROGRAM
@@ -506,7 +510,7 @@ void server_loop(pid_t pid, int fdin, int fdout, int fderr);
void server_loop2(void);
/* Client side main loop for the interactive session. */
-int client_loop(int have_pty, int escape_char);
+int client_loop(int have_pty, int escape_char, int id);
/* Linked list of custom environment strings (see auth-rsa.c). */
struct envstring {
diff --git a/sshconnect1.c b/sshconnect1.c
index aaebf17f..7b60d627 100644
--- a/sshconnect1.c
+++ b/sshconnect1.c
@@ -9,7 +9,7 @@
*/
#include "includes.h"
-RCSID("$OpenBSD: sshconnect1.c,v 1.4 2000/07/16 08:27:22 markus Exp $");
+RCSID("$OpenBSD: sshconnect1.c,v 1.5 2000/08/19 21:34:44 markus Exp $");
#include <openssl/bn.h>
#include <openssl/dsa.h>
@@ -44,27 +44,27 @@ extern char *__progname;
int
try_agent_authentication()
{
- int status, type;
+ int type;
char *comment;
AuthenticationConnection *auth;
unsigned char response[16];
unsigned int i;
- BIGNUM *e, *n, *challenge;
+ int plen, clen;
+ Key *key;
+ BIGNUM *challenge;
/* Get connection to the agent. */
auth = ssh_get_authentication_connection();
if (!auth)
return 0;
- e = BN_new();
- n = BN_new();
challenge = BN_new();
+ key = key_new(KEY_RSA);
/* Loop through identities served by the agent. */
- for (status = ssh_get_first_identity(auth, e, n, &comment);
- status;
- status = ssh_get_next_identity(auth, e, n, &comment)) {
- int plen, clen;
+ for (key = ssh_get_first_identity(auth, &comment, 1);
+ key != NULL;
+ key = ssh_get_next_identity(auth, &comment, 1)) {
/* Try this identity. */
debug("Trying RSA authentication via agent with '%.100s'", comment);
@@ -72,7 +72,7 @@ try_agent_authentication()
/* Tell the server that we are willing to authenticate using this key. */
packet_start(SSH_CMSG_AUTH_RSA);
- packet_put_bignum(n);
+ packet_put_bignum(key->rsa->n);
packet_send();
packet_write_wait();
@@ -83,6 +83,7 @@ try_agent_authentication()
does not support RSA authentication. */
if (type == SSH_SMSG_FAILURE) {
debug("Server refused our key.");
+ key_free(key);
continue;
}
/* Otherwise it should have sent a challenge. */
@@ -97,13 +98,16 @@ try_agent_authentication()
debug("Received RSA challenge from server.");
/* Ask the agent to decrypt the challenge. */
- if (!ssh_decrypt_challenge(auth, e, n, challenge,
- session_id, 1, response)) {
- /* The agent failed to authenticate this identifier although it
- advertised it supports this. Just return a wrong value. */
+ if (!ssh_decrypt_challenge(auth, key, challenge, session_id, 1, response)) {
+ /*
+ * The agent failed to authenticate this identifier
+ * although it advertised it supports this. Just
+ * return a wrong value.
+ */
log("Authentication agent failed to decrypt challenge.");
memset(response, 0, sizeof(response));
}
+ key_free(key);
debug("Sending response to RSA challenge.");
/* Send the decrypted challenge back to the server. */
@@ -118,10 +122,8 @@ try_agent_authentication()
/* The server returns success if it accepted the authentication. */
if (type == SSH_SMSG_SUCCESS) {
- debug("RSA authentication accepted by server.");
- BN_clear_free(e);
- BN_clear_free(n);
BN_clear_free(challenge);
+ debug("RSA authentication accepted by server.");
return 1;
}
/* Otherwise it should return failure. */
@@ -129,11 +131,7 @@ try_agent_authentication()
packet_disconnect("Protocol error waiting RSA auth response: %d",
type);
}
-
- BN_clear_free(e);
- BN_clear_free(n);
BN_clear_free(challenge);
-
debug("RSA authentication using agent refused.");
return 0;
}
diff --git a/sshconnect2.c b/sshconnect2.c
index 22ad39e7..1f49067a 100644
--- a/sshconnect2.c
+++ b/sshconnect2.c
@@ -28,7 +28,7 @@
*/
#include "includes.h"
-RCSID("$OpenBSD: sshconnect2.c,v 1.16 2000/07/16 08:27:22 markus Exp $");
+RCSID("$OpenBSD: sshconnect2.c,v 1.17 2000/08/19 21:34:44 markus Exp $");
#include <openssl/bn.h>
#include <openssl/rsa.h>
@@ -54,6 +54,7 @@ RCSID("$OpenBSD: sshconnect2.c,v 1.16 2000/07/16 08:27:22 markus Exp $");
#include "dsa.h"
#include "sshconnect.h"
#include "authfile.h"
+#include "authfd.h"
/* import */
extern char *client_version_string;
@@ -291,7 +292,7 @@ typedef int sign_fn(
unsigned char **sigp, int *lenp,
unsigned char *data, int datalen);
-void
+int
ssh2_sign_and_send_pubkey(Key *k, sign_fn *do_sign,
const char *server_user, const char *host, const char *service)
{
@@ -299,6 +300,7 @@ ssh2_sign_and_send_pubkey(Key *k, sign_fn *do_sign,
unsigned char *blob, *signature;
int bloblen, slen;
int skip = 0;
+ int ret = -1;
dsa_make_key_blob(k, &blob, &bloblen);
@@ -323,8 +325,12 @@ ssh2_sign_and_send_pubkey(Key *k, sign_fn *do_sign,
buffer_put_string(&b, blob, bloblen);
/* generate signature */
- do_sign(k, &signature, &slen, buffer_ptr(&b), buffer_len(&b));
- key_free(k); /* XXX */
+ ret = do_sign(k, &signature, &slen, buffer_ptr(&b), buffer_len(&b));
+ if (ret == -1) {
+ xfree(blob);
+ buffer_free(&b);
+ return 0;
+ }
#ifdef DEBUG_DSS
buffer_dump(&b);
#endif
@@ -357,6 +363,8 @@ ssh2_sign_and_send_pubkey(Key *k, sign_fn *do_sign,
/* send */
packet_send();
packet_write_wait();
+
+ return 1;
}
int
@@ -364,6 +372,7 @@ ssh2_try_pubkey(char *filename,
const char *server_user, const char *host, const char *service)
{
Key *k;
+ int ret = 0;
struct stat st;
if (stat(filename, &st) != 0) {
@@ -389,13 +398,53 @@ ssh2_try_pubkey(char *filename,
return 0;
}
}
- ssh2_sign_and_send_pubkey(k, dsa_sign, server_user, host, service);
- return 1;
+ ret = ssh2_sign_and_send_pubkey(k, dsa_sign, server_user, host, service);
+ key_free(k);
+ return ret;
+}
+
+int agent_sign(
+ Key *key,
+ unsigned char **sigp, int *lenp,
+ unsigned char *data, int datalen)
+{
+ int ret = -1;
+ AuthenticationConnection *ac = ssh_get_authentication_connection();
+ if (ac != NULL) {
+ ret = ssh_agent_sign(ac, key, sigp, lenp, data, datalen);
+ ssh_close_authentication_connection(ac);
+ }
+ return ret;
+}
+
+int
+ssh2_try_agent(AuthenticationConnection *ac,
+ const char *server_user, const char *host, const char *service)
+{
+ static int called = 0;
+ char *comment;
+ Key *k;
+ int ret;
+
+ if (called == 0) {
+ k = ssh_get_first_identity(ac, &comment, 2);
+ called ++;
+ } else {
+ k = ssh_get_next_identity(ac, &comment, 2);
+ }
+ if (k == NULL)
+ return 0;
+ debug("trying DSA agent key %s", comment);
+ xfree(comment);
+ ret = ssh2_sign_and_send_pubkey(k, agent_sign, server_user, host, service);
+ key_free(k);
+ return ret;
}
void
ssh_userauth2(const char *server_user, char *host)
{
+ AuthenticationConnection *ac = ssh_get_authentication_connection();
int type;
int plen;
int sent;
@@ -450,12 +499,17 @@ ssh_userauth2(const char *server_user, char *host)
debug("partial success");
if (options.dsa_authentication &&
strstr(auths, "publickey") != NULL) {
- while (i < options.num_identity_files2) {
- sent = ssh2_try_pubkey(
- options.identity_files2[i++],
+ if (ac != NULL)
+ sent = ssh2_try_agent(ac,
server_user, host, service);
- if (sent)
- break;
+ if (!sent) {
+ while (i < options.num_identity_files2) {
+ sent = ssh2_try_pubkey(
+ options.identity_files2[i++],
+ server_user, host, service);
+ if (sent)
+ break;
+ }
}
}
if (!sent) {
@@ -469,6 +523,8 @@ ssh_userauth2(const char *server_user, char *host)
fatal("Permission denied (%s).", auths);
xfree(auths);
}
+ if (ac != NULL)
+ ssh_close_authentication_connection(ac);
packet_done();
debug("ssh-userauth2 successfull");
}