]> andersk Git - openssh.git/commitdiff
- (djm) Pick up LOGIN_PROGRAM from environment or PATH if not set by headers
authordjm <djm>
Wed, 23 Aug 2000 00:46:23 +0000 (00:46 +0000)
committerdjm <djm>
Wed, 23 Aug 2000 00:46:23 +0000 (00:46 +0000)
 - (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.

33 files changed:
ChangeLog
Makefile.in
TODO
acconfig.h
auth1.c
auth2.c
authfd.c
authfd.h
channels.c
channels.h
clientloop.c
configure.in
crc32.c
crc32.h
deattack.c
defines.h
fingerprint.c [deleted file]
fingerprint.h [deleted file]
key.c
log-client.c
packet.c
scp.1
scp.c
session.c
ssh-add.1
ssh-add.c
ssh-agent.1
ssh-agent.c
ssh-keygen.c
ssh.c
ssh.h
sshconnect1.c
sshconnect2.c

index 4463cf2bbb1272efcbb81244d9d651ea7756c187..9d3dd02e2eff6abdd7971cd0ae01e28ba28d055e 100644 (file)
--- 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:
index ff34c49323d40287d9b10d45966b63e7893993f5..4ceef7043fa5a6fdd636551e0813f78241553b99 100644 (file)
@@ -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 1d46ae1c3a24ecb9323b085a3ad7e0d8c6a2b2da..ecfd21e330b3cde7102d4c2977f3761ac46b7f1d 100644 (file)
--- a/TODO
+++ b/TODO
@@ -14,3 +14,5 @@
   underlying shell.
 
 - utmp/wtmp logging does not work on NeXT
+
+- Complete Tru64 SIA support
index 601dc16f75e0981affe93fa52f6536a075d84e3c..eeee4eaf1faf61a5cd30df4a29b36eebc8c4fac7 100644 (file)
@@ -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 d8f2652e36d0db01c039379c013bdb61666db324..b043e8a953d08cae1a11d3eba866300364fabd7b 100644 (file)
--- 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 4926ff8a0b88f02514fd0640d5e2c1d4a3cca022..7769046fbcac75d508253a283fb63fe2ef8ae77c 100644 (file)
--- 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;
index a34e111ac140bf9bc5226b90767fca65b5f481f2..d9427d3776acce1e1d36d8729124bf76c1ed0f43 100644 (file)
--- a/authfd.c
+++ b/authfd.c
  *
  * 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);
 }
 
index 14b9bee94d6089c39568a600bd47a8d2aeefb2df..5819b9139eac7935caa9706cd735111cc85760be 100644 (file)
--- 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
 #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 */
index ea395293a6b68f83ee23a9d7f83919c77d062515..c77f6b96a4a96534251074e6c8aec25ef9cf6654 100644 (file)
@@ -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)
index 9629124b968ef56d2d73d129c28ff891962fef34..9acdf5810e16e2cd52721fb73adc5b51af1fdd22 100644 (file)
@@ -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
  * 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);
 
index 67fa36d911af79820b610f16a868d61d7b8d813b..d339e1274b474ec1f21a60a8c4ca47143437afa5 100644 (file)
@@ -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"));
index f048b000d8dc4c764d3d3f22703cedbef73f8359..02287b802c494397bd59093aaa1618fe5b080970 100644 (file)
@@ -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 05a1af7b35afc33a5c667034151dbb8f7d27db4e..eb9b2dcd44eef2fccb5ea54eb456615d5cc2ce71 100644 (file)
--- 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 45495b4223c4a8bcc4d8972bad7ff462b1067e69..2c84a80173dbb94fb1a3ad52457416220fe9e19f 100644 (file)
--- 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 */
index 7f95eca31999ec29154039493422e3e16c1ca67b..72e7f1e0611e70d898c31ef8ab056ede1364e561 100644 (file)
@@ -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 */
index cd322f9b8ba1ee110f516e154829403d6e797b4d..1fe74a92b84799fd1ec346b85d8f33f1271d125f 100644 (file)
--- 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 (file)
index 801f6a6..0000000
+++ /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 (file)
index 3d7bcb3..0000000
+++ /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 764f1f227fbba1c818348ba009632354dfa73b23..f2ce75e7f1f2fcecbd24e59cb16c563e44f74266 100644 (file)
--- 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;
+}
index 7e9fd61e78cc676a66d44ca860a75e612f6d85eb..7615a94f007fa3c25b16555f0abbc99539afebbf 100644 (file)
@@ -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);
 }
index 56080cbb118c4feb40aa12b917cc28b625bcdbe4..8f9311074332a0a3a0939d89843e3e145de72459 100644 (file)
--- 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 60466cff93d9a10c77791ffae88851a329fd4f47..54ca0f4bf375517a49c561e6a104bfbf51030c4f 100644 (file)
--- a/scp.1
+++ b/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 02feba9c1fdfd5a2f2b4c8d9740c62c91f513d42..d2e4224bbee4d1b43cd4c6811688d906642a1db5 100644 (file)
--- 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));
 
index d65b06984a1e01ff5f8f834e9b2851c7b793eab5..82096c3abc4a1b8ebf57169b7caef0ba19b229d4 100644 (file)
--- 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);
index 5fe73a9c994465da4a81d13e83b35415feb58ce7..b5dae10de62671a5494f3658c908aee91ec38ee2 100644 (file)
--- a/ssh-add.1
+++ b/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
index 482229c22caf27469a5f997f96648c4f6cc6882c..a51f477a53aeb9149d06504ede8849d644ee64cc 100644 (file)
--- 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) {
index 47b1e5cc5112eec6a920f294bf67a6e14d1b02dd..0aa1ecf49dae4424e1e9cb98ffb469d3cf149d78 100644 (file)
@@ -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 -*-
 .\"
 .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.
index e8383b5dfbab669be7dca507c0172affeefde9bc..56b81a78db8e22b37915299890a8336b372d2d8d 100644 (file)
@@ -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);
index 8a03f0d8d37ae96d3195e3e3c079de6a637bafbc..83450fe840bf90e0d8ca0989c5c7026477dcf398 100644 (file)
@@ -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 58e4d7bd9b066dcabdde930e61b2ed2058533d9b..39512c5f14bab26f252663b31a9d70805124be01 100644 (file)
--- 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 f3f049fccfaeaf2606a1e8a8cd1410ac52e5b109..f21dee4943813b98b44ed38d64295184faa28bdd 100644 (file)
--- 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
 #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 {
index aaebf17ffa1ee4b18f3571e8812d89bddb4a62ab..7b60d6276ef116516b981428b54b97ad7e969889 100644 (file)
@@ -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;
 }
index 22ad39e7f3860825686248b0b89f982b1ffaedc9..1f49067adf0bd77ba2fc576402d8aeb76c114d52 100644 (file)
@@ -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");
 }
This page took 2.348523 seconds and 5 git commands to generate.