- (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.
This commit is contained in:
Damien Miller 2000-08-23 10:46:23 +10:00
parent b078567bf5
commit ad833b3e65
33 changed files with 1168 additions and 801 deletions

View File

@ -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:

View 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

2
TODO
View File

@ -14,3 +14,5 @@
underlying shell.
- utmp/wtmp logging does not work on NeXT
- Complete Tru64 SIA support

View 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

View File

@ -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;

View File

@ -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;

231
authfd.c
View File

@ -11,10 +11,13 @@
*
* Functions for connecting the local authentication agent.
*
* SSH2 implementation,
* Copyright (c) 2000 Markus Friedl. All rights reserved.
*
*/
#include "includes.h"
RCSID("$OpenBSD: authfd.c,v 1.24 2000/08/15 19:20:46 markus Exp $");
RCSID("$OpenBSD: authfd.c,v 1.25 2000/08/19 21:34:42 markus Exp $");
#include "ssh.h"
#include "rsa.h"
@ -29,6 +32,7 @@ RCSID("$OpenBSD: authfd.c,v 1.24 2000/08/15 19:20:46 markus Exp $");
#include "key.h"
#include "authfd.h"
#include "kex.h"
#include "dsa.h"
/* helper */
int decode_reply(int type);
@ -71,8 +75,7 @@ ssh_get_authentication_socket()
}
int
ssh_request_reply(AuthenticationConnection *auth,
Buffer *request, Buffer *reply)
ssh_request_reply(AuthenticationConnection *auth, Buffer *request, Buffer *reply)
{
int l, len;
char buf[1024];
@ -162,7 +165,6 @@ ssh_get_authentication_connection()
auth = xmalloc(sizeof(*auth));
auth->fd = sock;
buffer_init(&auth->packet);
buffer_init(&auth->identities);
auth->howmany = 0;
@ -175,46 +177,57 @@ ssh_get_authentication_connection()
*/
void
ssh_close_authentication_connection(AuthenticationConnection *ac)
ssh_close_authentication_connection(AuthenticationConnection *auth)
{
buffer_free(&ac->packet);
buffer_free(&ac->identities);
close(ac->fd);
xfree(ac);
buffer_free(&auth->identities);
close(auth->fd);
xfree(auth);
}
/*
* Returns the first authentication identity held by the agent.
* Returns true if an identity is available, 0 otherwise.
* The caller must initialize the integers before the call, and free the
* comment after a successful call (before calling ssh_get_next_identity).
*/
int
ssh_get_first_identity(AuthenticationConnection *auth,
BIGNUM *e, BIGNUM *n, char **comment)
Key *
ssh_get_first_identity(AuthenticationConnection *auth, char **comment, int version)
{
int type, code1 = 0, code2 = 0;
Buffer request;
int type;
switch(version){
case 1:
code1 = SSH_AGENTC_REQUEST_RSA_IDENTITIES;
code2 = SSH_AGENT_RSA_IDENTITIES_ANSWER;
break;
case 2:
code1 = SSH2_AGENTC_REQUEST_IDENTITIES;
code2 = SSH2_AGENT_IDENTITIES_ANSWER;
break;
default:
return NULL;
}
/*
* Send a message to the agent requesting for a list of the
* identities it can represent.
*/
buffer_init(&request);
buffer_put_char(&request, SSH_AGENTC_REQUEST_RSA_IDENTITIES);
buffer_put_char(&request, code1);
buffer_clear(&auth->identities);
if (ssh_request_reply(auth, &request, &auth->identities) == 0) {
buffer_free(&request);
return 0;
return NULL;
}
buffer_free(&request);
/* Get message type, and verify that we got a proper answer. */
type = buffer_get_char(&auth->identities);
if (type != SSH_AGENT_RSA_IDENTITIES_ANSWER)
if (type == SSH_AGENT_FAILURE) {
return NULL;
} else if (type != code2) {
fatal("Bad authentication reply message type: %d", type);
}
/* Get the number of entries in the response and check it for sanity. */
auth->howmany = buffer_get_int(&auth->identities);
@ -223,43 +236,49 @@ ssh_get_first_identity(AuthenticationConnection *auth,
auth->howmany);
/* Return the first entry (if any). */
return ssh_get_next_identity(auth, e, n, comment);
return ssh_get_next_identity(auth, comment, version);
}
/*
* Returns the next authentication identity for the agent. Other functions
* can be called between this and ssh_get_first_identity or two calls of this
* function. This returns 0 if there are no more identities. The caller
* must free comment after a successful return.
*/
int
ssh_get_next_identity(AuthenticationConnection *auth,
BIGNUM *e, BIGNUM *n, char **comment)
Key *
ssh_get_next_identity(AuthenticationConnection *auth, char **comment, int version)
{
unsigned int bits;
unsigned char *blob;
unsigned int blen;
Key *key = NULL;
/* Return failure if no more entries. */
if (auth->howmany <= 0)
return 0;
return NULL;
/*
* Get the next entry from the packet. These will abort with a fatal
* error if the packet is too short or contains corrupt data.
*/
bits = buffer_get_int(&auth->identities);
buffer_get_bignum(&auth->identities, e);
buffer_get_bignum(&auth->identities, n);
*comment = buffer_get_string(&auth->identities, NULL);
if (bits != BN_num_bits(n))
log("Warning: identity keysize mismatch: actual %d, announced %u",
BN_num_bits(n), bits);
switch(version){
case 1:
key = key_new(KEY_RSA);
bits = buffer_get_int(&auth->identities);
buffer_get_bignum(&auth->identities, key->rsa->e);
buffer_get_bignum(&auth->identities, key->rsa->n);
*comment = buffer_get_string(&auth->identities, NULL);
if (bits != BN_num_bits(key->rsa->n))
log("Warning: identity keysize mismatch: actual %d, announced %u",
BN_num_bits(key->rsa->n), bits);
break;
case 2:
blob = buffer_get_string(&auth->identities, &blen);
*comment = buffer_get_string(&auth->identities, NULL);
key = dsa_key_from_blob(blob, blen);
xfree(blob);
break;
default:
return NULL;
break;
}
/* Decrement the number of remaining entries. */
auth->howmany--;
return 1;
return key;
}
/*
@ -272,7 +291,7 @@ ssh_get_next_identity(AuthenticationConnection *auth,
int
ssh_decrypt_challenge(AuthenticationConnection *auth,
BIGNUM* e, BIGNUM *n, BIGNUM *challenge,
Key* key, BIGNUM *challenge,
unsigned char session_id[16],
unsigned int response_type,
unsigned char response[16])
@ -282,15 +301,17 @@ ssh_decrypt_challenge(AuthenticationConnection *auth,
int i;
int type;
if (response_type == 0)
fatal("Compatibility with ssh protocol version "
"1.0 no longer supported.");
if (key->type != KEY_RSA)
return 0;
if (response_type == 0) {
log("Compatibility with ssh protocol version 1.0 no longer supported.");
return 0;
}
buffer_init(&buffer);
buffer_put_char(&buffer, SSH_AGENTC_RSA_CHALLENGE);
buffer_put_int(&buffer, BN_num_bits(n));
buffer_put_bignum(&buffer, e);
buffer_put_bignum(&buffer, n);
buffer_put_int(&buffer, BN_num_bits(key->rsa->n));
buffer_put_bignum(&buffer, key->rsa->e);
buffer_put_bignum(&buffer, key->rsa->n);
buffer_put_bignum(&buffer, challenge);
buffer_append(&buffer, (char *) session_id, 16);
buffer_put_int(&buffer, response_type);
@ -318,6 +339,45 @@ ssh_decrypt_challenge(AuthenticationConnection *auth,
return success;
}
/* ask agent to sign data, returns -1 on error, 0 on success */
int
ssh_agent_sign(AuthenticationConnection *auth,
Key *key,
unsigned char **sigp, int *lenp,
unsigned char *data, int datalen)
{
Buffer msg;
unsigned char *blob;
unsigned int blen;
int type;
int ret = -1;
if (dsa_make_key_blob(key, &blob, &blen) == 0)
return -1;
buffer_init(&msg);
buffer_put_char(&msg, SSH2_AGENTC_SIGN_REQUEST);
buffer_put_string(&msg, blob, blen);
buffer_put_string(&msg, data, datalen);
xfree(blob);
if (ssh_request_reply(auth, &msg, &msg) == 0) {
buffer_free(&msg);
return -1;
}
type = buffer_get_char(&msg);
if (type == SSH_AGENT_FAILURE) {
log("Agent admitted failure to sign using the key.");
} else if (type != SSH2_AGENT_SIGN_RESPONSE) {
fatal("Bad authentication response: %d", type);
} else {
ret = 0;
*sigp = buffer_get_string(&msg, lenp);
}
buffer_free(&msg);
return ret;
}
/* Encode key for a message to the agent. */
void
@ -358,29 +418,29 @@ ssh_encode_identity_dsa(Buffer *b, DSA *key, const char *comment)
int
ssh_add_identity(AuthenticationConnection *auth, Key *key, const char *comment)
{
Buffer buffer;
Buffer msg;
int type;
buffer_init(&buffer);
buffer_init(&msg);
switch (key->type) {
case KEY_RSA:
ssh_encode_identity_rsa(&buffer, key->rsa, comment);
ssh_encode_identity_rsa(&msg, key->rsa, comment);
break;
case KEY_DSA:
ssh_encode_identity_dsa(&buffer, key->dsa, comment);
ssh_encode_identity_dsa(&msg, key->dsa, comment);
break;
default:
buffer_free(&buffer);
buffer_free(&msg);
return 0;
break;
}
if (ssh_request_reply(auth, &buffer, &buffer) == 0) {
buffer_free(&buffer);
if (ssh_request_reply(auth, &msg, &msg) == 0) {
buffer_free(&msg);
return 0;
}
type = buffer_get_char(&buffer);
buffer_free(&buffer);
type = buffer_get_char(&msg);
buffer_free(&msg);
return decode_reply(type);
}
@ -390,23 +450,35 @@ ssh_add_identity(AuthenticationConnection *auth, Key *key, const char *comment)
*/
int
ssh_remove_identity(AuthenticationConnection *auth, RSA *key)
ssh_remove_identity(AuthenticationConnection *auth, Key *key)
{
Buffer buffer;
Buffer msg;
int type;
unsigned char *blob;
unsigned int blen;
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);
buffer_init(&msg);
if (ssh_request_reply(auth, &buffer, &buffer) == 0) {
buffer_free(&buffer);
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);
}

View File

@ -13,7 +13,7 @@
*
*/
/* RCSID("$OpenBSD: authfd.h,v 1.9 2000/07/16 08:27:21 markus Exp $"); */
/* RCSID("$OpenBSD: authfd.h,v 1.10 2000/08/19 21:34:43 markus Exp $"); */
#ifndef AUTHFD_H
#define AUTHFD_H
@ -35,18 +35,16 @@
#define SSH2_AGENT_IDENTITIES_ANSWER 12
#define SSH2_AGENTC_SIGN_REQUEST 13
#define SSH2_AGENT_SIGN_RESPONSE 14
#define SSH2_AGENT_FAILURE SSH_AGENT_FAILURE
#define SSH2_AGENT_SUCCESS SSH_AGENT_SUCCESS
#define SSH2_AGENTC_ADD_IDENTITY 17
#define SSH2_AGENTC_REMOVE_IDENTITY 18
#define SSH2_AGENTC_REMOVE_ALL_IDENTITIES 19
typedef struct {
int fd;
Buffer packet;
Buffer identities;
int howmany;
} AuthenticationConnection;
/* Returns the number of the authentication fd, or -1 if there is none. */
int ssh_get_authentication_socket();
@ -69,44 +67,48 @@ AuthenticationConnection *ssh_get_authentication_connection();
* Closes the connection to the authentication agent and frees any associated
* memory.
*/
void ssh_close_authentication_connection(AuthenticationConnection * ac);
void ssh_close_authentication_connection(AuthenticationConnection *auth);
/*
* Returns the first authentication identity held by the agent. Returns true
* if an identity is available, 0 otherwise. The caller must initialize the
* integers before the call, and free the comment after a successful call
* (before calling ssh_get_next_identity).
* Returns the first authentication identity held by the agent or NULL if
* no identies are available. Caller must free comment and key.
* Note that you cannot mix calls with different versions.
*/
int
ssh_get_first_identity(AuthenticationConnection * connection,
BIGNUM * e, BIGNUM * n, char **comment);
Key *ssh_get_first_identity(AuthenticationConnection *auth, char **comment, int version);
/*
* Returns the next authentication identity for the agent. Other functions
* can be called between this and ssh_get_first_identity or two calls of this
* function. This returns 0 if there are no more identities. The caller
* must free comment after a successful return.
* function. This returns NULL if there are no more identities. The caller
* must free key and comment after a successful return.
*/
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.
*/
int
ssh_get_next_identity(AuthenticationConnection * connection,
BIGNUM * e, BIGNUM * n, char **comment);
/* 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 */

View 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)

View 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
@ -21,9 +21,13 @@
* Data structure for channel data. This is iniailized in channel_allocate
* and cleared in channel_free.
*/
typedef void channel_callback_fn(int id, void *arg);
struct Channel;
typedef struct Channel Channel;
typedef struct Channel {
typedef void channel_callback_fn(int id, void *arg);
typedef int channel_filter_fn(struct Channel *c, char *buf, int len);
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);

View 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"));

View 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([],

View File

@ -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;

View File

@ -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 */

View 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 */

View File

@ -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))

View File

@ -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;
}

View File

@ -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

14
key.c
View File

@ -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;
}

View 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);
}

View File

@ -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. */

12
scp.1
View File

@ -9,7 +9,7 @@
.\"
.\" Created: Sun May 7 00:14:37 1995 ylo
.\"
.\" $Id: scp.1,v 1.8 2000/07/11 07:31:38 djm Exp $
.\" $Id: scp.1,v 1.9 2000/08/23 00:46:24 djm Exp $
.\"
.Dd September 25, 1999
.Dt SCP 1
@ -68,6 +68,11 @@ This option is directly passed to
.It Fl p
Preserves modification times, access times, and modes from the
original file.
.It Fl S
Name of program to use for the encrypted connection.
The program must understand
.Xr ssh 1
options.
.It Fl r
Recursively copy entire directories.
.It Fl v
@ -98,6 +103,11 @@ because
.Fl p
is already reserved for preserving the times and modes of the file in
.Xr rcp 1 .
.It Fl S
Name of program to use for the encrypted connection. The program must
understand
.Xr ssh 1
options.
.It Fl 4
Forces
.Nm

137
scp.c
View File

@ -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));

120
session.c
View File

@ -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);

View File

@ -9,21 +9,21 @@
.\"
.\" Created: Sat Apr 22 23:55:14 1995 ylo
.\"
.\" $Id: ssh-add.1,v 1.13 2000/05/07 02:03:18 damien Exp $
.\" $Id: ssh-add.1,v 1.14 2000/08/23 00:46:24 djm Exp $
.\"
.Dd September 25, 1999
.Dt SSH-ADD 1
.Os
.Sh NAME
.Nm ssh-add
.Nd adds RSA identities for the authentication agent
.Nd adds RSA or DSA identities for the authentication agent
.Sh SYNOPSIS
.Nm ssh-add
.Op Fl lLdD
.Op Ar
.Sh DESCRIPTION
.Nm
adds RSA identities to the authentication agent,
adds RSA or DSA identities to the authentication agent,
.Xr ssh-agent 1 .
When run without arguments, it adds the file
.Pa $HOME/.ssh/identity .
@ -63,6 +63,8 @@ used to encrypt the private part of this file.
This is the default file added by
.Nm
when no other files have been specified.
.It Pa $HOME/.ssh/id_dsa
Contains the DSA authentication identity of the user.
.Pp
.Sh ENVIRONMENT
.Bl -tag -width Ds

View File

@ -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) {

View 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 -*-
.\"
@ -27,14 +27,15 @@
.Oc
.Sh DESCRIPTION
.Nm
is a program to hold private keys used for RSA authentication.
is a program to hold private keys used for public key authentication
(RSA, DSA).
The idea is that
.Nm
is started in the beginning of an X-session or a login session, and
all other windows or programs are started as clients to the ssh-agent
program.
Through use of environment variables the agent can be located
and automatically used for RSA authentication when logging in to other
and automatically used for authentication when logging in to other
machines using
.Xr ssh 1 .
.Pp
@ -128,7 +129,9 @@ This file is not used by
but is normally added to the agent using
.Xr ssh-add 1
at login time.
.It Pa /tmp/ssh-XXXX/agent.<pid> ,
.It Pa $HOME/.ssh/id_dsa
Contains the DSA authentication identity of the user.
.Pq Pa /tmp/ssh-XXXXXXXX/agent.<pid> ,
Unix-domain sockets used to contain the connection to the
authentication agent.
These sockets should only be readable by the owner.

View 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_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);
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;
/* 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;
case 1:/* As of protocol 1.1 */
/* The response is MD5 of decrypted challenge plus session id. */
len = BN_num_bytes(challenge);
private = lookup_private_key(key, NULL, 1);
if (private != NULL) {
/* Decrypt the challenge using the private key. */
rsa_private_decrypt(challenge, challenge, private->rsa);
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]);
goto send;
/* 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));
buffer_free(&msg);
BN_clear_free(pub_e);
BN_clear_free(pub_n);
buffer_append(&e->output, buffer_ptr(&msg), buffer_len(&msg));
key_free(key);
BN_clear_free(challenge);
buffer_free(&msg);
}
/* ssh2 only */
void
process_remove_identity(SocketEntry *e)
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_free(&msg);
xfree(data);
xfree(blob);
if (signature != NULL)
xfree(signature);
}
/* shared */
void
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;
int success = 0;
dummy = BN_new();
n = BN_new();
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);
/* 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) {
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));
switch (version) {
case 1:
k = key_new(KEY_RSA);
rsa = k->rsa;
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 */
/* 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();
/* Generate additional parameters */
aux = BN_new();
ctx = BN_CTX_new();
buffer_get_int(&e->input); /* ignored */
BN_sub(aux, k->q, BN_value_one());
k->dmq1 = BN_new();
BN_mod(k->dmq1, k->d, aux, ctx);
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);
BN_sub(aux, k->p, BN_value_one());
k->dmp1 = BN_new();
BN_mod(k->dmp1, k->d, aux, ctx);
/* SSH and SSL have p and q swapped */
buffer_get_bignum(&e->input, rsa->q); /* p */
buffer_get_bignum(&e->input, rsa->p); /* q */
BN_clear_free(aux);
BN_CTX_free(ctx);
/* Generate additional parameters */
aux = BN_new();
ctx = BN_CTX_new();
identities[num_identities].comment = buffer_get_string(&e->input, NULL);
BN_sub(aux, rsa->q, BN_value_one());
BN_mod(rsa->dmq1, rsa->d, aux, ctx);
/* 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);
BN_sub(aux, rsa->p, BN_value_one());
BN_mod(rsa->dmp1, rsa->d, aux, ctx);
/* Send success. */
buffer_put_int(&e->output, 1);
buffer_put_char(&e->output, SSH_AGENT_SUCCESS);
return;
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);

View 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);

28
ssh.c
View File

@ -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);
}

10
ssh.h
View File

@ -13,7 +13,7 @@
*
*/
/* RCSID("$OpenBSD: ssh.h,v 1.48 2000/07/13 22:53:21 provos Exp $"); */
/* RCSID("$OpenBSD: ssh.h,v 1.49 2000/08/19 18:48:11 markus Exp $"); */
#ifndef SSH_H
#define SSH_H
@ -105,7 +105,11 @@
#endif /* SSH_PROGRAM */
#ifndef LOGIN_PROGRAM
#define LOGIN_PROGRAM "/usr/bin/login"
# ifdef LOGIN_PROGRAM_FALLBACK
# define LOGIN_PROGRAM LOGIN_PROGRAM_FALLBACK
# else
# define LOGIN_PROGRAM "/usr/bin/login"
# endif
#endif /* LOGIN_PROGRAM */
#ifndef ASKPASS_PROGRAM
@ -506,7 +510,7 @@ void server_loop(pid_t pid, int fdin, int fdout, int fderr);
void server_loop2(void);
/* Client side main loop for the interactive session. */
int client_loop(int have_pty, int escape_char);
int client_loop(int have_pty, int escape_char, int id);
/* Linked list of custom environment strings (see auth-rsa.c). */
struct envstring {

View 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;
}

View 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");
}