- (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:
parent
b078567bf5
commit
ad833b3e65
55
ChangeLog
55
ChangeLog
|
@ -3,6 +3,61 @@
|
||||||
Avoids "scp never exits" problem. Reports from Lutz Jaenicke
|
Avoids "scp never exits" problem. Reports from Lutz Jaenicke
|
||||||
<Lutz.Jaenicke@aet.TU-Cottbus.DE> and Tamito KAJIYAMA
|
<Lutz.Jaenicke@aet.TU-Cottbus.DE> and Tamito KAJIYAMA
|
||||||
<kajiyama@grad.sccs.chukyo-u.ac.jp>
|
<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
|
20000818
|
||||||
- (djm) OpenBSD CVS changes:
|
- (djm) OpenBSD CVS changes:
|
||||||
|
|
|
@ -34,7 +34,7 @@ INSTALL_SSH_PRNG_CMDS=@INSTALL_SSH_PRNG_CMDS@
|
||||||
|
|
||||||
TARGETS=ssh sshd ssh-add ssh-keygen ssh-agent scp $(EXTRA_TARGETS)
|
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
|
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
2
TODO
|
@ -14,3 +14,5 @@
|
||||||
underlying shell.
|
underlying shell.
|
||||||
|
|
||||||
- utmp/wtmp logging does not work on NeXT
|
- utmp/wtmp logging does not work on NeXT
|
||||||
|
|
||||||
|
- Complete Tru64 SIA support
|
||||||
|
|
|
@ -6,6 +6,13 @@
|
||||||
|
|
||||||
@TOP@
|
@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 */
|
/* Define if your socketpair() has bugs */
|
||||||
#undef USE_PIPES
|
#undef USE_PIPES
|
||||||
|
|
||||||
|
|
5
auth1.c
5
auth1.c
|
@ -4,7 +4,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "includes.h"
|
#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 "xmalloc.h"
|
||||||
#include "rsa.h"
|
#include "rsa.h"
|
||||||
|
@ -480,6 +480,9 @@ do_authentication()
|
||||||
pwcopy.pw_passwd = xstrdup(pw->pw_passwd);
|
pwcopy.pw_passwd = xstrdup(pw->pw_passwd);
|
||||||
pwcopy.pw_uid = pw->pw_uid;
|
pwcopy.pw_uid = pw->pw_uid;
|
||||||
pwcopy.pw_gid = pw->pw_gid;
|
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_dir = xstrdup(pw->pw_dir);
|
||||||
pwcopy.pw_shell = xstrdup(pw->pw_shell);
|
pwcopy.pw_shell = xstrdup(pw->pw_shell);
|
||||||
pw = &pwcopy;
|
pw = &pwcopy;
|
||||||
|
|
5
auth2.c
5
auth2.c
|
@ -27,7 +27,7 @@
|
||||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
*/
|
*/
|
||||||
#include "includes.h"
|
#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/dsa.h>
|
||||||
#include <openssl/rsa.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_passwd = xstrdup(pw->pw_passwd);
|
||||||
copy->pw_uid = pw->pw_uid;
|
copy->pw_uid = pw->pw_uid;
|
||||||
copy->pw_gid = pw->pw_gid;
|
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_dir = xstrdup(pw->pw_dir);
|
||||||
copy->pw_shell = xstrdup(pw->pw_shell);
|
copy->pw_shell = xstrdup(pw->pw_shell);
|
||||||
authctxt->valid = 1;
|
authctxt->valid = 1;
|
||||||
|
|
231
authfd.c
231
authfd.c
|
@ -11,10 +11,13 @@
|
||||||
*
|
*
|
||||||
* Functions for connecting the local authentication agent.
|
* Functions for connecting the local authentication agent.
|
||||||
*
|
*
|
||||||
|
* SSH2 implementation,
|
||||||
|
* Copyright (c) 2000 Markus Friedl. All rights reserved.
|
||||||
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "includes.h"
|
#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 "ssh.h"
|
||||||
#include "rsa.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 "key.h"
|
||||||
#include "authfd.h"
|
#include "authfd.h"
|
||||||
#include "kex.h"
|
#include "kex.h"
|
||||||
|
#include "dsa.h"
|
||||||
|
|
||||||
/* helper */
|
/* helper */
|
||||||
int decode_reply(int type);
|
int decode_reply(int type);
|
||||||
|
@ -71,8 +75,7 @@ ssh_get_authentication_socket()
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
ssh_request_reply(AuthenticationConnection *auth,
|
ssh_request_reply(AuthenticationConnection *auth, Buffer *request, Buffer *reply)
|
||||||
Buffer *request, Buffer *reply)
|
|
||||||
{
|
{
|
||||||
int l, len;
|
int l, len;
|
||||||
char buf[1024];
|
char buf[1024];
|
||||||
|
@ -162,7 +165,6 @@ ssh_get_authentication_connection()
|
||||||
|
|
||||||
auth = xmalloc(sizeof(*auth));
|
auth = xmalloc(sizeof(*auth));
|
||||||
auth->fd = sock;
|
auth->fd = sock;
|
||||||
buffer_init(&auth->packet);
|
|
||||||
buffer_init(&auth->identities);
|
buffer_init(&auth->identities);
|
||||||
auth->howmany = 0;
|
auth->howmany = 0;
|
||||||
|
|
||||||
|
@ -175,46 +177,57 @@ ssh_get_authentication_connection()
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void
|
void
|
||||||
ssh_close_authentication_connection(AuthenticationConnection *ac)
|
ssh_close_authentication_connection(AuthenticationConnection *auth)
|
||||||
{
|
{
|
||||||
buffer_free(&ac->packet);
|
buffer_free(&auth->identities);
|
||||||
buffer_free(&ac->identities);
|
close(auth->fd);
|
||||||
close(ac->fd);
|
xfree(auth);
|
||||||
xfree(ac);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Returns the first authentication identity held by the agent.
|
* 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
|
Key *
|
||||||
ssh_get_first_identity(AuthenticationConnection *auth,
|
ssh_get_first_identity(AuthenticationConnection *auth, char **comment, int version)
|
||||||
BIGNUM *e, BIGNUM *n, char **comment)
|
|
||||||
{
|
{
|
||||||
|
int type, code1 = 0, code2 = 0;
|
||||||
Buffer request;
|
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
|
* Send a message to the agent requesting for a list of the
|
||||||
* identities it can represent.
|
* identities it can represent.
|
||||||
*/
|
*/
|
||||||
buffer_init(&request);
|
buffer_init(&request);
|
||||||
buffer_put_char(&request, SSH_AGENTC_REQUEST_RSA_IDENTITIES);
|
buffer_put_char(&request, code1);
|
||||||
|
|
||||||
buffer_clear(&auth->identities);
|
buffer_clear(&auth->identities);
|
||||||
if (ssh_request_reply(auth, &request, &auth->identities) == 0) {
|
if (ssh_request_reply(auth, &request, &auth->identities) == 0) {
|
||||||
buffer_free(&request);
|
buffer_free(&request);
|
||||||
return 0;
|
return NULL;
|
||||||
}
|
}
|
||||||
buffer_free(&request);
|
buffer_free(&request);
|
||||||
|
|
||||||
/* Get message type, and verify that we got a proper answer. */
|
/* Get message type, and verify that we got a proper answer. */
|
||||||
type = buffer_get_char(&auth->identities);
|
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);
|
fatal("Bad authentication reply message type: %d", type);
|
||||||
|
}
|
||||||
|
|
||||||
/* Get the number of entries in the response and check it for sanity. */
|
/* Get the number of entries in the response and check it for sanity. */
|
||||||
auth->howmany = buffer_get_int(&auth->identities);
|
auth->howmany = buffer_get_int(&auth->identities);
|
||||||
|
@ -223,43 +236,49 @@ ssh_get_first_identity(AuthenticationConnection *auth,
|
||||||
auth->howmany);
|
auth->howmany);
|
||||||
|
|
||||||
/* Return the first entry (if any). */
|
/* Return the first entry (if any). */
|
||||||
return ssh_get_next_identity(auth, e, n, comment);
|
return ssh_get_next_identity(auth, comment, version);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
Key *
|
||||||
* Returns the next authentication identity for the agent. Other functions
|
ssh_get_next_identity(AuthenticationConnection *auth, char **comment, int version)
|
||||||
* 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)
|
|
||||||
{
|
{
|
||||||
unsigned int bits;
|
unsigned int bits;
|
||||||
|
unsigned char *blob;
|
||||||
|
unsigned int blen;
|
||||||
|
Key *key = NULL;
|
||||||
|
|
||||||
/* Return failure if no more entries. */
|
/* Return failure if no more entries. */
|
||||||
if (auth->howmany <= 0)
|
if (auth->howmany <= 0)
|
||||||
return 0;
|
return NULL;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Get the next entry from the packet. These will abort with a fatal
|
* Get the next entry from the packet. These will abort with a fatal
|
||||||
* error if the packet is too short or contains corrupt data.
|
* error if the packet is too short or contains corrupt data.
|
||||||
*/
|
*/
|
||||||
bits = buffer_get_int(&auth->identities);
|
switch(version){
|
||||||
buffer_get_bignum(&auth->identities, e);
|
case 1:
|
||||||
buffer_get_bignum(&auth->identities, n);
|
key = key_new(KEY_RSA);
|
||||||
*comment = buffer_get_string(&auth->identities, NULL);
|
bits = buffer_get_int(&auth->identities);
|
||||||
|
buffer_get_bignum(&auth->identities, key->rsa->e);
|
||||||
if (bits != BN_num_bits(n))
|
buffer_get_bignum(&auth->identities, key->rsa->n);
|
||||||
log("Warning: identity keysize mismatch: actual %d, announced %u",
|
*comment = buffer_get_string(&auth->identities, NULL);
|
||||||
BN_num_bits(n), bits);
|
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. */
|
/* Decrement the number of remaining entries. */
|
||||||
auth->howmany--;
|
auth->howmany--;
|
||||||
|
return key;
|
||||||
return 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -272,7 +291,7 @@ ssh_get_next_identity(AuthenticationConnection *auth,
|
||||||
|
|
||||||
int
|
int
|
||||||
ssh_decrypt_challenge(AuthenticationConnection *auth,
|
ssh_decrypt_challenge(AuthenticationConnection *auth,
|
||||||
BIGNUM* e, BIGNUM *n, BIGNUM *challenge,
|
Key* key, BIGNUM *challenge,
|
||||||
unsigned char session_id[16],
|
unsigned char session_id[16],
|
||||||
unsigned int response_type,
|
unsigned int response_type,
|
||||||
unsigned char response[16])
|
unsigned char response[16])
|
||||||
|
@ -282,15 +301,17 @@ ssh_decrypt_challenge(AuthenticationConnection *auth,
|
||||||
int i;
|
int i;
|
||||||
int type;
|
int type;
|
||||||
|
|
||||||
if (response_type == 0)
|
if (key->type != KEY_RSA)
|
||||||
fatal("Compatibility with ssh protocol version "
|
return 0;
|
||||||
"1.0 no longer supported.");
|
if (response_type == 0) {
|
||||||
|
log("Compatibility with ssh protocol version 1.0 no longer supported.");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
buffer_init(&buffer);
|
buffer_init(&buffer);
|
||||||
buffer_put_char(&buffer, SSH_AGENTC_RSA_CHALLENGE);
|
buffer_put_char(&buffer, SSH_AGENTC_RSA_CHALLENGE);
|
||||||
buffer_put_int(&buffer, BN_num_bits(n));
|
buffer_put_int(&buffer, BN_num_bits(key->rsa->n));
|
||||||
buffer_put_bignum(&buffer, e);
|
buffer_put_bignum(&buffer, key->rsa->e);
|
||||||
buffer_put_bignum(&buffer, n);
|
buffer_put_bignum(&buffer, key->rsa->n);
|
||||||
buffer_put_bignum(&buffer, challenge);
|
buffer_put_bignum(&buffer, challenge);
|
||||||
buffer_append(&buffer, (char *) session_id, 16);
|
buffer_append(&buffer, (char *) session_id, 16);
|
||||||
buffer_put_int(&buffer, response_type);
|
buffer_put_int(&buffer, response_type);
|
||||||
|
@ -318,6 +339,45 @@ ssh_decrypt_challenge(AuthenticationConnection *auth,
|
||||||
return success;
|
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. */
|
/* Encode key for a message to the agent. */
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -358,29 +418,29 @@ ssh_encode_identity_dsa(Buffer *b, DSA *key, const char *comment)
|
||||||
int
|
int
|
||||||
ssh_add_identity(AuthenticationConnection *auth, Key *key, const char *comment)
|
ssh_add_identity(AuthenticationConnection *auth, Key *key, const char *comment)
|
||||||
{
|
{
|
||||||
Buffer buffer;
|
Buffer msg;
|
||||||
int type;
|
int type;
|
||||||
|
|
||||||
buffer_init(&buffer);
|
buffer_init(&msg);
|
||||||
|
|
||||||
switch (key->type) {
|
switch (key->type) {
|
||||||
case KEY_RSA:
|
case KEY_RSA:
|
||||||
ssh_encode_identity_rsa(&buffer, key->rsa, comment);
|
ssh_encode_identity_rsa(&msg, key->rsa, comment);
|
||||||
break;
|
break;
|
||||||
case KEY_DSA:
|
case KEY_DSA:
|
||||||
ssh_encode_identity_dsa(&buffer, key->dsa, comment);
|
ssh_encode_identity_dsa(&msg, key->dsa, comment);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
buffer_free(&buffer);
|
buffer_free(&msg);
|
||||||
return 0;
|
return 0;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (ssh_request_reply(auth, &buffer, &buffer) == 0) {
|
if (ssh_request_reply(auth, &msg, &msg) == 0) {
|
||||||
buffer_free(&buffer);
|
buffer_free(&msg);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
type = buffer_get_char(&buffer);
|
type = buffer_get_char(&msg);
|
||||||
buffer_free(&buffer);
|
buffer_free(&msg);
|
||||||
return decode_reply(type);
|
return decode_reply(type);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -390,23 +450,35 @@ ssh_add_identity(AuthenticationConnection *auth, Key *key, const char *comment)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int
|
int
|
||||||
ssh_remove_identity(AuthenticationConnection *auth, RSA *key)
|
ssh_remove_identity(AuthenticationConnection *auth, Key *key)
|
||||||
{
|
{
|
||||||
Buffer buffer;
|
Buffer msg;
|
||||||
int type;
|
int type;
|
||||||
|
unsigned char *blob;
|
||||||
|
unsigned int blen;
|
||||||
|
|
||||||
buffer_init(&buffer);
|
buffer_init(&msg);
|
||||||
buffer_put_char(&buffer, SSH_AGENTC_REMOVE_RSA_IDENTITY);
|
|
||||||
buffer_put_int(&buffer, BN_num_bits(key->n));
|
|
||||||
buffer_put_bignum(&buffer, key->e);
|
|
||||||
buffer_put_bignum(&buffer, key->n);
|
|
||||||
|
|
||||||
if (ssh_request_reply(auth, &buffer, &buffer) == 0) {
|
if (key->type == KEY_RSA) {
|
||||||
buffer_free(&buffer);
|
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;
|
return 0;
|
||||||
}
|
}
|
||||||
type = buffer_get_char(&buffer);
|
if (ssh_request_reply(auth, &msg, &msg) == 0) {
|
||||||
buffer_free(&buffer);
|
buffer_free(&msg);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
type = buffer_get_char(&msg);
|
||||||
|
buffer_free(&msg);
|
||||||
return decode_reply(type);
|
return decode_reply(type);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -416,20 +488,23 @@ ssh_remove_identity(AuthenticationConnection *auth, RSA *key)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int
|
int
|
||||||
ssh_remove_all_identities(AuthenticationConnection *auth)
|
ssh_remove_all_identities(AuthenticationConnection *auth, int version)
|
||||||
{
|
{
|
||||||
Buffer buffer;
|
Buffer msg;
|
||||||
int type;
|
int type;
|
||||||
|
int code = (version==1) ?
|
||||||
|
SSH_AGENTC_REMOVE_ALL_RSA_IDENTITIES :
|
||||||
|
SSH2_AGENTC_REMOVE_ALL_IDENTITIES;
|
||||||
|
|
||||||
buffer_init(&buffer);
|
buffer_init(&msg);
|
||||||
buffer_put_char(&buffer, SSH_AGENTC_REMOVE_ALL_RSA_IDENTITIES);
|
buffer_put_char(&msg, code);
|
||||||
|
|
||||||
if (ssh_request_reply(auth, &buffer, &buffer) == 0) {
|
if (ssh_request_reply(auth, &msg, &msg) == 0) {
|
||||||
buffer_free(&buffer);
|
buffer_free(&msg);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
type = buffer_get_char(&buffer);
|
type = buffer_get_char(&msg);
|
||||||
buffer_free(&buffer);
|
buffer_free(&msg);
|
||||||
return decode_reply(type);
|
return decode_reply(type);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
55
authfd.h
55
authfd.h
|
@ -13,7 +13,7 @@
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* RCSID("$OpenBSD: authfd.h,v 1.9 2000/07/16 08:27:21 markus Exp $"); */
|
/* RCSID("$OpenBSD: authfd.h,v 1.10 2000/08/19 21:34:43 markus Exp $"); */
|
||||||
|
|
||||||
#ifndef AUTHFD_H
|
#ifndef AUTHFD_H
|
||||||
#define AUTHFD_H
|
#define AUTHFD_H
|
||||||
|
@ -35,18 +35,16 @@
|
||||||
#define SSH2_AGENT_IDENTITIES_ANSWER 12
|
#define SSH2_AGENT_IDENTITIES_ANSWER 12
|
||||||
#define SSH2_AGENTC_SIGN_REQUEST 13
|
#define SSH2_AGENTC_SIGN_REQUEST 13
|
||||||
#define SSH2_AGENT_SIGN_RESPONSE 14
|
#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_ADD_IDENTITY 17
|
||||||
#define SSH2_AGENTC_REMOVE_IDENTITY 18
|
#define SSH2_AGENTC_REMOVE_IDENTITY 18
|
||||||
#define SSH2_AGENTC_REMOVE_ALL_IDENTITIES 19
|
#define SSH2_AGENTC_REMOVE_ALL_IDENTITIES 19
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
int fd;
|
int fd;
|
||||||
Buffer packet;
|
|
||||||
Buffer identities;
|
Buffer identities;
|
||||||
int howmany;
|
int howmany;
|
||||||
} AuthenticationConnection;
|
} AuthenticationConnection;
|
||||||
|
|
||||||
/* Returns the number of the authentication fd, or -1 if there is none. */
|
/* Returns the number of the authentication fd, or -1 if there is none. */
|
||||||
int ssh_get_authentication_socket();
|
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
|
* Closes the connection to the authentication agent and frees any associated
|
||||||
* memory.
|
* 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
|
* Returns the first authentication identity held by the agent or NULL if
|
||||||
* if an identity is available, 0 otherwise. The caller must initialize the
|
* no identies are available. Caller must free comment and key.
|
||||||
* integers before the call, and free the comment after a successful call
|
* Note that you cannot mix calls with different versions.
|
||||||
* (before calling ssh_get_next_identity).
|
|
||||||
*/
|
*/
|
||||||
int
|
Key *ssh_get_first_identity(AuthenticationConnection *auth, char **comment, int version);
|
||||||
ssh_get_first_identity(AuthenticationConnection * connection,
|
|
||||||
BIGNUM * e, BIGNUM * n, char **comment);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Returns the next authentication identity for the agent. Other functions
|
* 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
|
* 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
|
* function. This returns NULL if there are no more identities. The caller
|
||||||
* must free comment after a successful return.
|
* 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
|
int
|
||||||
ssh_get_next_identity(AuthenticationConnection * connection,
|
ssh_decrypt_challenge(AuthenticationConnection *auth,
|
||||||
BIGNUM * e, BIGNUM * n, char **comment);
|
Key *key, BIGNUM * challenge,
|
||||||
|
|
||||||
/* 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,
|
|
||||||
unsigned char session_id[16],
|
unsigned char session_id[16],
|
||||||
unsigned int response_type,
|
unsigned int response_type,
|
||||||
unsigned char response[16]);
|
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
|
* 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
|
* be used by normal applications. This returns true if the identity was
|
||||||
* successfully added.
|
* successfully added.
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
ssh_add_identity(AuthenticationConnection * connection, Key *key,
|
ssh_add_identity(AuthenticationConnection *auth, Key *key,
|
||||||
const char *comment);
|
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
|
* meant to be used by normal applications. This returns true if the
|
||||||
* identity was successfully added.
|
* 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
|
* Removes all identities from the authentication agent. This call is not
|
||||||
* meant to be used by normal applications. This returns true if the
|
* meant to be used by normal applications. This returns true if the
|
||||||
* operation was successful.
|
* operation was successful.
|
||||||
*/
|
*/
|
||||||
int ssh_remove_all_identities(AuthenticationConnection * connection);
|
int ssh_remove_all_identities(AuthenticationConnection *auth, int version);
|
||||||
|
|
||||||
/* Closes the connection to the authentication agent. */
|
|
||||||
void ssh_close_authentication(AuthenticationConnection * connection);
|
|
||||||
|
|
||||||
#endif /* AUTHFD_H */
|
#endif /* AUTHFD_H */
|
||||||
|
|
22
channels.c
22
channels.c
|
@ -17,7 +17,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "includes.h"
|
#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 "ssh.h"
|
||||||
#include "packet.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_arg = NULL;
|
||||||
c->cb_event = 0;
|
c->cb_event = 0;
|
||||||
c->dettach_user = NULL;
|
c->dettach_user = NULL;
|
||||||
|
c->input_filter = NULL;
|
||||||
debug("channel %d: new [%s]", found, remote_name);
|
debug("channel %d: new [%s]", found, remote_name);
|
||||||
return found;
|
return found;
|
||||||
}
|
}
|
||||||
|
@ -665,7 +666,14 @@ channel_handle_rfd(Channel *c, fd_set * readset, fd_set * writeset)
|
||||||
}
|
}
|
||||||
return -1;
|
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;
|
return 1;
|
||||||
}
|
}
|
||||||
|
@ -2309,6 +2317,16 @@ channel_cancel_cleanup(int id)
|
||||||
}
|
}
|
||||||
c->dettach_user = NULL;
|
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
|
void
|
||||||
channel_set_fds(int id, int rfd, int wfd, int efd, int extusage)
|
channel_set_fds(int id, int rfd, int wfd, int efd, int extusage)
|
||||||
|
|
16
channels.h
16
channels.h
|
@ -1,4 +1,4 @@
|
||||||
/* RCSID("$OpenBSD: channels.h,v 1.14 2000/06/20 01:39:40 markus Exp $"); */
|
/* RCSID("$OpenBSD: channels.h,v 1.16 2000/08/19 21:55:51 markus Exp $"); */
|
||||||
|
|
||||||
#ifndef CHANNELS_H
|
#ifndef CHANNELS_H
|
||||||
#define CHANNELS_H
|
#define CHANNELS_H
|
||||||
|
@ -21,9 +21,13 @@
|
||||||
* Data structure for channel data. This is iniailized in channel_allocate
|
* Data structure for channel data. This is iniailized in channel_allocate
|
||||||
* and cleared in channel_free.
|
* 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 type; /* channel type/state */
|
||||||
int self; /* my own channel identifier */
|
int self; /* my own channel identifier */
|
||||||
int remote_id; /* channel identifier for remote peer */
|
int remote_id; /* channel identifier for remote peer */
|
||||||
|
@ -61,7 +65,10 @@ typedef struct Channel {
|
||||||
void *cb_arg;
|
void *cb_arg;
|
||||||
int cb_event;
|
int cb_event;
|
||||||
channel_callback_fn *dettach_user;
|
channel_callback_fn *dettach_user;
|
||||||
} Channel;
|
|
||||||
|
/* filter */
|
||||||
|
channel_filter_fn *input_filter;
|
||||||
|
};
|
||||||
|
|
||||||
#define CHAN_EXTENDED_IGNORE 0
|
#define CHAN_EXTENDED_IGNORE 0
|
||||||
#define CHAN_EXTENDED_READ 1
|
#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_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_callback(int id, int mtype, channel_callback_fn *fn, void *arg);
|
||||||
void channel_register_cleanup(int id, channel_callback_fn *fn);
|
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);
|
void channel_cancel_cleanup(int id);
|
||||||
Channel *channel_lookup(int id);
|
Channel *channel_lookup(int id);
|
||||||
|
|
||||||
|
|
340
clientloop.c
340
clientloop.c
|
@ -16,7 +16,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "includes.h"
|
#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 "xmalloc.h"
|
||||||
#include "ssh.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 "channels.h"
|
||||||
#include "dispatch.h"
|
#include "dispatch.h"
|
||||||
|
|
||||||
|
#include "buffer.h"
|
||||||
|
#include "bufaux.h"
|
||||||
|
|
||||||
/* Flag indicating that stdin should be redirected from /dev/null. */
|
/* Flag indicating that stdin should be redirected from /dev/null. */
|
||||||
extern int stdin_null_flag;
|
extern int stdin_null_flag;
|
||||||
|
|
||||||
|
@ -60,6 +63,8 @@ static int in_raw_mode = 0;
|
||||||
static int in_non_blocking_mode = 0;
|
static int in_non_blocking_mode = 0;
|
||||||
|
|
||||||
/* Common data for the client loop code. */
|
/* 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 escape_pending; /* Last character was the escape character */
|
||||||
static int last_was_cr; /* Last character was a newline. */
|
static int last_was_cr; /* Last character was a newline. */
|
||||||
static int exit_status; /* Used to store the exit status of the command. */
|
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 stdin_buffer; /* Buffer for stdin data. */
|
||||||
static Buffer stdout_buffer; /* Buffer for stdout data. */
|
static Buffer stdout_buffer; /* Buffer for stdout data. */
|
||||||
static Buffer stderr_buffer; /* Buffer for stderr 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 unsigned int buffer_high;/* Soft max buffer size. */
|
||||||
static int max_fd; /* Maximum file descriptor number in select(). */
|
static int max_fd; /* Maximum file descriptor number in select(). */
|
||||||
static int connection_in; /* Connection to server (input). */
|
static int connection_in; /* Connection to server (input). */
|
||||||
static int connection_out; /* Connection to server (output). */
|
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);
|
void client_init_dispatch(void);
|
||||||
|
@ -379,17 +382,15 @@ client_wait_until_can_do_something(fd_set * readset, fd_set * writeset)
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
client_suspend_self()
|
client_suspend_self(Buffer *bin, Buffer *bout, Buffer *berr)
|
||||||
{
|
{
|
||||||
struct winsize oldws, newws;
|
struct winsize oldws, newws;
|
||||||
|
|
||||||
/* Flush stdout and stderr buffers. */
|
/* Flush stdout and stderr buffers. */
|
||||||
if (buffer_len(&stdout_buffer) > 0)
|
if (buffer_len(bout) > 0)
|
||||||
atomicio(write, fileno(stdout), buffer_ptr(&stdout_buffer),
|
atomicio(write, fileno(stdout), buffer_ptr(bout), buffer_len(bout));
|
||||||
buffer_len(&stdout_buffer));
|
if (buffer_len(berr) > 0)
|
||||||
if (buffer_len(&stderr_buffer) > 0)
|
atomicio(write, fileno(stderr), buffer_ptr(berr), buffer_len(berr));
|
||||||
atomicio(write, fileno(stderr), buffer_ptr(&stderr_buffer),
|
|
||||||
buffer_len(&stderr_buffer));
|
|
||||||
|
|
||||||
leave_raw_mode();
|
leave_raw_mode();
|
||||||
|
|
||||||
|
@ -397,9 +398,9 @@ client_suspend_self()
|
||||||
* Free (and clear) the buffer to reduce the amount of data that gets
|
* Free (and clear) the buffer to reduce the amount of data that gets
|
||||||
* written to swap.
|
* written to swap.
|
||||||
*/
|
*/
|
||||||
buffer_free(&stdin_buffer);
|
buffer_free(bin);
|
||||||
buffer_free(&stdout_buffer);
|
buffer_free(bout);
|
||||||
buffer_free(&stderr_buffer);
|
buffer_free(berr);
|
||||||
|
|
||||||
/* Save old window size. */
|
/* Save old window size. */
|
||||||
ioctl(fileno(stdin), TIOCGWINSZ, &oldws);
|
ioctl(fileno(stdin), TIOCGWINSZ, &oldws);
|
||||||
|
@ -416,9 +417,9 @@ client_suspend_self()
|
||||||
received_window_change_signal = 1;
|
received_window_change_signal = 1;
|
||||||
|
|
||||||
/* OK, we have been continued by the user. Reinitialize buffers. */
|
/* OK, we have been continued by the user. Reinitialize buffers. */
|
||||||
buffer_init(&stdin_buffer);
|
buffer_init(bin);
|
||||||
buffer_init(&stdout_buffer);
|
buffer_init(bout);
|
||||||
buffer_init(&stderr_buffer);
|
buffer_init(berr);
|
||||||
|
|
||||||
enter_raw_mode();
|
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
|
void
|
||||||
client_process_input(fd_set * readset)
|
client_process_input(fd_set * readset)
|
||||||
{
|
{
|
||||||
|
int ret;
|
||||||
int len;
|
int len;
|
||||||
pid_t pid;
|
char buf[8192];
|
||||||
char buf[8192], *s;
|
|
||||||
|
|
||||||
/* Read input from stdin. */
|
/* Read input from stdin. */
|
||||||
if (FD_ISSET(fileno(stdin), readset)) {
|
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
|
* Normal, successful read. But we have an escape character
|
||||||
* and have to process the characters one by one.
|
* and have to process the characters one by one.
|
||||||
*/
|
*/
|
||||||
unsigned int i;
|
ret = process_escapes(&stdin_buffer, &stdout_buffer, &stderr_buffer, buf, len);
|
||||||
for (i = 0; i < len; i++) {
|
if (ret == -1)
|
||||||
unsigned char ch;
|
return;
|
||||||
/* Get one character at a time. */
|
stdout_bytes += ret;
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -722,6 +731,15 @@ client_process_buffered_input_packets()
|
||||||
dispatch_run(DISPATCH_NONBLOCK, &quit_pending);
|
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
|
* Implements the interactive session with the server. This is called after
|
||||||
* the user has been authenticated, and a command has been started on the
|
* the user has been authenticated, and a command has been started on the
|
||||||
|
@ -730,7 +748,7 @@ client_process_buffered_input_packets()
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int
|
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;
|
extern Options options;
|
||||||
double start_time, total_time;
|
double start_time, total_time;
|
||||||
|
@ -780,6 +798,9 @@ client_loop(int have_pty, int escape_char_arg)
|
||||||
if (!compat20)
|
if (!compat20)
|
||||||
client_check_initial_eof_on_stdin();
|
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. */
|
/* Main loop of the client for the interactive session mode. */
|
||||||
while (!quit_pending) {
|
while (!quit_pending) {
|
||||||
fd_set readset, writeset;
|
fd_set readset, writeset;
|
||||||
|
@ -989,6 +1010,7 @@ client_input_channel_open(int type, int plen)
|
||||||
/* XXX move to channels.c */
|
/* XXX move to channels.c */
|
||||||
sock = x11_connect_display();
|
sock = x11_connect_display();
|
||||||
if (sock >= 0) {
|
if (sock >= 0) {
|
||||||
|
/*XXX MAXPACK */
|
||||||
id = channel_new("x11", SSH_CHANNEL_X11_OPEN,
|
id = channel_new("x11", SSH_CHANNEL_X11_OPEN,
|
||||||
sock, sock, -1, 4*1024, 32*1024, 0,
|
sock, sock, -1, 4*1024, 32*1024, 0,
|
||||||
xstrdup("x11"));
|
xstrdup("x11"));
|
||||||
|
|
41
configure.in
41
configure.in
|
@ -14,6 +14,17 @@ AC_SUBST(PERL)
|
||||||
AC_PATH_PROG(ENT, ent)
|
AC_PATH_PROG(ENT, ent)
|
||||||
AC_SUBST(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
|
if test -z "$LD" ; then
|
||||||
LD=$CC
|
LD=$CC
|
||||||
fi
|
fi
|
||||||
|
@ -225,18 +236,18 @@ if test -z "$no_libnsl" ; then
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Checks for header files.
|
# 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.
|
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 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)
|
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
|
dnl Checks for time functions
|
||||||
AC_CHECK_FUNCS(gettimeofday time)
|
AC_CHECK_FUNCS(gettimeofday time)
|
||||||
dnl checks for libutil functions
|
dnl Checks for libutil functions
|
||||||
AC_CHECK_FUNCS(login logout updwtmp logwtmp)
|
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(entutent getutent getutid getutline pututline setutent)
|
||||||
AC_CHECK_FUNCS(utmpname)
|
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(entutxent getutxent getutxid getutxline pututxline )
|
||||||
AC_CHECK_FUNCS(setutxent utmpxname)
|
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)
|
AC_DEFINE(HAVE___SS_FAMILY_IN_SS)
|
||||||
fi
|
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_CACHE_CHECK([if libc defines __progname], ac_cv_libc_defines___progname, [
|
||||||
AC_TRY_LINK([],
|
AC_TRY_LINK([],
|
||||||
|
|
4
crc32.c
4
crc32.c
|
@ -6,7 +6,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "includes.h"
|
#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"
|
#include "crc32.h"
|
||||||
|
|
||||||
|
@ -108,7 +108,7 @@ static unsigned int crc32_tab[] = {
|
||||||
/* Return a 32-bit CRC of the contents of the buffer. */
|
/* Return a 32-bit CRC of the contents of the buffer. */
|
||||||
|
|
||||||
unsigned int
|
unsigned int
|
||||||
crc32(const unsigned char *s, unsigned int len)
|
ssh_crc32(const unsigned char *s, unsigned int len)
|
||||||
{
|
{
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
unsigned int crc32val;
|
unsigned int crc32val;
|
||||||
|
|
4
crc32.h
4
crc32.h
|
@ -13,7 +13,7 @@
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* RCSID("$OpenBSD: crc32.h,v 1.6 2000/06/20 01:39:40 markus Exp $"); */
|
/* RCSID("$OpenBSD: crc32.h,v 1.7 2000/08/19 21:29:40 deraadt Exp $"); */
|
||||||
|
|
||||||
#ifndef CRC32_H
|
#ifndef CRC32_H
|
||||||
#define 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.
|
* This computes a 32 bit CRC of the data in the buffer, and returns the CRC.
|
||||||
* The polynomial used is 0xedb88320.
|
* 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 */
|
#endif /* CRC32_H */
|
||||||
|
|
|
@ -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
|
* Cryptographic attack detector for ssh - source code
|
||||||
*
|
*
|
||||||
* Copyright (c) 1998 CORE SDI S.A., Buenos Aires, Argentina.
|
* 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)
|
crc_update(u_int32_t *a, u_int32_t b)
|
||||||
{
|
{
|
||||||
b ^= *a;
|
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 */
|
/* detect if a block is used in a particular pattern */
|
||||||
|
|
|
@ -246,8 +246,16 @@ typedef int mode_t;
|
||||||
# endif /* RSH_PATH */
|
# endif /* RSH_PATH */
|
||||||
#endif /* _PATH_RSH */
|
#endif /* _PATH_RSH */
|
||||||
|
|
||||||
|
#ifndef _PATH_NOLOGIN
|
||||||
|
# define _PATH_NOLOGIN "/etc/nologin"
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Macros */
|
/* Macros */
|
||||||
|
|
||||||
|
#if defined(HAVE_LOGIN_GETCAPBOOL) && defined(HAVE_LOGIN_CAP_H)
|
||||||
|
# define HAVE_LOGIN_CAP
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifndef MAX
|
#ifndef MAX
|
||||||
# define MAX(a,b) (((a)>(b))?(a):(b))
|
# define MAX(a,b) (((a)>(b))?(a):(b))
|
||||||
# define MIN(a,b) (((a)<(b))?(a):(b))
|
# define MIN(a,b) (((a)<(b))?(a):(b))
|
||||||
|
|
|
@ -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;
|
|
||||||
}
|
|
|
@ -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
14
key.c
|
@ -41,7 +41,7 @@
|
||||||
#include "dsa.h"
|
#include "dsa.h"
|
||||||
#include "uuencode.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"
|
#define SSH_DSS "ssh-dss"
|
||||||
|
|
||||||
|
@ -335,3 +335,15 @@ key_type(Key *k)
|
||||||
}
|
}
|
||||||
return "unknown";
|
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;
|
||||||
|
}
|
||||||
|
|
|
@ -15,7 +15,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "includes.h"
|
#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 "xmalloc.h"
|
||||||
#include "ssh.h"
|
#include "ssh.h"
|
||||||
|
@ -57,6 +57,5 @@ do_log(LogLevel level, const char *fmt, va_list args)
|
||||||
if (level == SYSLOG_LEVEL_DEBUG)
|
if (level == SYSLOG_LEVEL_DEBUG)
|
||||||
fprintf(stderr, "debug: ");
|
fprintf(stderr, "debug: ");
|
||||||
vsnprintf(msgbuf, sizeof(msgbuf), fmt, args);
|
vsnprintf(msgbuf, sizeof(msgbuf), fmt, args);
|
||||||
fprintf(stderr, "%s", msgbuf);
|
fprintf(stderr, "%s\r\n", msgbuf);
|
||||||
fprintf(stderr, "\r\n");
|
|
||||||
}
|
}
|
||||||
|
|
8
packet.c
8
packet.c
|
@ -17,7 +17,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "includes.h"
|
#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 "xmalloc.h"
|
||||||
#include "buffer.h"
|
#include "buffer.h"
|
||||||
|
@ -479,8 +479,8 @@ packet_send1()
|
||||||
buffer_consume(&outgoing_packet, 8 - padding);
|
buffer_consume(&outgoing_packet, 8 - padding);
|
||||||
|
|
||||||
/* Add check bytes. */
|
/* Add check bytes. */
|
||||||
checksum = crc32((unsigned char *) buffer_ptr(&outgoing_packet),
|
checksum = ssh_crc32((unsigned char *) buffer_ptr(&outgoing_packet),
|
||||||
buffer_len(&outgoing_packet));
|
buffer_len(&outgoing_packet));
|
||||||
PUT_32BIT(buf, checksum);
|
PUT_32BIT(buf, checksum);
|
||||||
buffer_append(&outgoing_packet, buf, 4);
|
buffer_append(&outgoing_packet, buf, 4);
|
||||||
|
|
||||||
|
@ -764,7 +764,7 @@ packet_read_poll1(int *payload_len_ptr)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Compute packet checksum. */
|
/* 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);
|
buffer_len(&incoming_packet) - 4);
|
||||||
|
|
||||||
/* Skip padding. */
|
/* Skip padding. */
|
||||||
|
|
12
scp.1
12
scp.1
|
@ -9,7 +9,7 @@
|
||||||
.\"
|
.\"
|
||||||
.\" Created: Sun May 7 00:14:37 1995 ylo
|
.\" 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
|
.Dd September 25, 1999
|
||||||
.Dt SCP 1
|
.Dt SCP 1
|
||||||
|
@ -68,6 +68,11 @@ This option is directly passed to
|
||||||
.It Fl p
|
.It Fl p
|
||||||
Preserves modification times, access times, and modes from the
|
Preserves modification times, access times, and modes from the
|
||||||
original file.
|
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
|
.It Fl r
|
||||||
Recursively copy entire directories.
|
Recursively copy entire directories.
|
||||||
.It Fl v
|
.It Fl v
|
||||||
|
@ -98,6 +103,11 @@ because
|
||||||
.Fl p
|
.Fl p
|
||||||
is already reserved for preserving the times and modes of the file in
|
is already reserved for preserving the times and modes of the file in
|
||||||
.Xr rcp 1 .
|
.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
|
.It Fl 4
|
||||||
Forces
|
Forces
|
||||||
.Nm
|
.Nm
|
||||||
|
|
137
scp.c
137
scp.c
|
@ -11,6 +11,8 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
* Parts from:
|
||||||
|
*
|
||||||
* Copyright (c) 1983, 1990, 1992, 1993, 1995
|
* Copyright (c) 1983, 1990, 1992, 1993, 1995
|
||||||
* The Regents of the University of California. All rights reserved.
|
* The Regents of the University of California. All rights reserved.
|
||||||
*
|
*
|
||||||
|
@ -45,7 +47,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "includes.h"
|
#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 "ssh.h"
|
||||||
#include "xmalloc.h"
|
#include "xmalloc.h"
|
||||||
|
@ -69,6 +71,7 @@ void progressmeter(int);
|
||||||
|
|
||||||
/* Returns width of the terminal (for progress meter calculations). */
|
/* Returns width of the terminal (for progress meter calculations). */
|
||||||
int getttywidth(void);
|
int getttywidth(void);
|
||||||
|
int do_cmd(char *host, char *remuser, char *cmd, int *fdin, int *fdout, int argc);
|
||||||
|
|
||||||
/* Time a transfer started. */
|
/* Time a transfer started. */
|
||||||
static struct timeval start;
|
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). */
|
/* This is the port to use in contacting the remote site (is non-NULL). */
|
||||||
char *port = 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
|
* This function executes the given command as the specified user on the
|
||||||
* given host. This returns < 0 if execution fails, and >= 0 otherwise. This
|
* given host. This returns < 0 if execution fails, and >= 0 otherwise. This
|
||||||
|
@ -118,13 +124,13 @@ char *port = NULL;
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int
|
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];
|
int pin[2], pout[2], reserved[2];
|
||||||
|
|
||||||
if (verbose_mode)
|
if (verbose_mode)
|
||||||
fprintf(stderr, "Executing: host %s, user %s, command %s\n",
|
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
|
* 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. */
|
/* For a child to execute the command on the remote host using ssh. */
|
||||||
if (fork() == 0) {
|
if (fork() == 0) {
|
||||||
char *args[100];
|
char *args[100]; /* XXX careful */
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
|
|
||||||
/* Child. */
|
/* Child. */
|
||||||
|
@ -156,7 +162,7 @@ do_cmd(char *host, char *remuser, char *cmd, int *fdin, int *fdout)
|
||||||
close(pout[1]);
|
close(pout[1]);
|
||||||
|
|
||||||
i = 0;
|
i = 0;
|
||||||
args[i++] = SSH_PROGRAM;
|
args[i++] = ssh_program;
|
||||||
args[i++] = "-x";
|
args[i++] = "-x";
|
||||||
args[i++] = "-oFallBackToRsh no";
|
args[i++] = "-oFallBackToRsh no";
|
||||||
if (IPv4)
|
if (IPv4)
|
||||||
|
@ -189,8 +195,8 @@ do_cmd(char *host, char *remuser, char *cmd, int *fdin, int *fdout)
|
||||||
args[i++] = cmd;
|
args[i++] = cmd;
|
||||||
args[i++] = NULL;
|
args[i++] = NULL;
|
||||||
|
|
||||||
execvp(SSH_PROGRAM, args);
|
execvp(ssh_program, args);
|
||||||
perror(SSH_PROGRAM);
|
perror(ssh_program);
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
/* Parent. Close the other side, and return the local side. */
|
/* Parent. Close the other side, and return the local side. */
|
||||||
|
@ -214,8 +220,6 @@ fatal(const char *fmt,...)
|
||||||
exit(255);
|
exit(255);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* This stuff used to be in BSD rcp extern.h. */
|
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
int cnt;
|
int cnt;
|
||||||
char *buf;
|
char *buf;
|
||||||
|
@ -231,8 +235,6 @@ int okname(char *);
|
||||||
void run_err(const char *,...);
|
void run_err(const char *,...);
|
||||||
void verifydir(char *);
|
void verifydir(char *);
|
||||||
|
|
||||||
/* Stuff from BSD rcp.c continues. */
|
|
||||||
|
|
||||||
struct passwd *pwd;
|
struct passwd *pwd;
|
||||||
uid_t userid;
|
uid_t userid;
|
||||||
int errs, remin, remout;
|
int errs, remin, remout;
|
||||||
|
@ -260,7 +262,7 @@ main(argc, argv)
|
||||||
extern int optind;
|
extern int optind;
|
||||||
|
|
||||||
fflag = tflag = 0;
|
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) {
|
switch (ch) {
|
||||||
/* User-visible flags. */
|
/* User-visible flags. */
|
||||||
case '4':
|
case '4':
|
||||||
|
@ -278,6 +280,10 @@ main(argc, argv)
|
||||||
case 'r':
|
case 'r':
|
||||||
iamrecursive = 1;
|
iamrecursive = 1;
|
||||||
break;
|
break;
|
||||||
|
case 'S':
|
||||||
|
ssh_program = optarg;
|
||||||
|
break;
|
||||||
|
|
||||||
/* Server options. */
|
/* Server options. */
|
||||||
case 'd':
|
case 'd':
|
||||||
targetshouldbedirectory = 1;
|
targetshouldbedirectory = 1;
|
||||||
|
@ -343,8 +349,8 @@ main(argc, argv)
|
||||||
remin = remout = -1;
|
remin = remout = -1;
|
||||||
/* Command to be executed on remote system using "ssh". */
|
/* Command to be executed on remote system using "ssh". */
|
||||||
(void) sprintf(cmd, "scp%s%s%s%s", verbose_mode ? " -v" : "",
|
(void) sprintf(cmd, "scp%s%s%s%s", verbose_mode ? " -v" : "",
|
||||||
iamrecursive ? " -r" : "", pflag ? " -p" : "",
|
iamrecursive ? " -r" : "", pflag ? " -p" : "",
|
||||||
targetshouldbedirectory ? " -d" : "");
|
targetshouldbedirectory ? " -d" : "");
|
||||||
|
|
||||||
(void) signal(SIGPIPE, lostconn);
|
(void) signal(SIGPIPE, lostconn);
|
||||||
|
|
||||||
|
@ -401,9 +407,9 @@ toremote(targ, argc, argv)
|
||||||
if (*src == 0)
|
if (*src == 0)
|
||||||
src = ".";
|
src = ".";
|
||||||
host = strchr(argv[i], '@');
|
host = strchr(argv[i], '@');
|
||||||
len = strlen(SSH_PROGRAM) + strlen(argv[i]) +
|
len = strlen(ssh_program) + strlen(argv[i]) +
|
||||||
strlen(src) + (tuser ? strlen(tuser) : 0) +
|
strlen(src) + (tuser ? strlen(tuser) : 0) +
|
||||||
strlen(thost) + strlen(targ) + CMDNEEDS + 32;
|
strlen(thost) + strlen(targ) + CMDNEEDS + 32;
|
||||||
bp = xmalloc(len);
|
bp = xmalloc(len);
|
||||||
if (host) {
|
if (host) {
|
||||||
*host++ = 0;
|
*host++ = 0;
|
||||||
|
@ -414,19 +420,19 @@ toremote(targ, argc, argv)
|
||||||
else if (!okname(suser))
|
else if (!okname(suser))
|
||||||
continue;
|
continue;
|
||||||
(void) sprintf(bp,
|
(void) sprintf(bp,
|
||||||
"%s%s -x -o'FallBackToRsh no' -n -l %s %s %s %s '%s%s%s:%s'",
|
"%s%s -x -o'FallBackToRsh no' -n -l %s %s %s %s '%s%s%s:%s'",
|
||||||
SSH_PROGRAM, verbose_mode ? " -v" : "",
|
ssh_program, verbose_mode ? " -v" : "",
|
||||||
suser, host, cmd, src,
|
suser, host, cmd, src,
|
||||||
tuser ? tuser : "", tuser ? "@" : "",
|
tuser ? tuser : "", tuser ? "@" : "",
|
||||||
thost, targ);
|
thost, targ);
|
||||||
} else {
|
} else {
|
||||||
host = cleanhostname(argv[i]);
|
host = cleanhostname(argv[i]);
|
||||||
(void) sprintf(bp,
|
(void) sprintf(bp,
|
||||||
"exec %s%s -x -o'FallBackToRsh no' -n %s %s %s '%s%s%s:%s'",
|
"exec %s%s -x -o'FallBackToRsh no' -n %s %s %s '%s%s%s:%s'",
|
||||||
SSH_PROGRAM, verbose_mode ? " -v" : "",
|
ssh_program, verbose_mode ? " -v" : "",
|
||||||
host, cmd, src,
|
host, cmd, src,
|
||||||
tuser ? tuser : "", tuser ? "@" : "",
|
tuser ? tuser : "", tuser ? "@" : "",
|
||||||
thost, targ);
|
thost, targ);
|
||||||
}
|
}
|
||||||
if (verbose_mode)
|
if (verbose_mode)
|
||||||
fprintf(stderr, "Executing: %s\n", bp);
|
fprintf(stderr, "Executing: %s\n", bp);
|
||||||
|
@ -438,8 +444,8 @@ toremote(targ, argc, argv)
|
||||||
bp = xmalloc(len);
|
bp = xmalloc(len);
|
||||||
(void) sprintf(bp, "%s -t %s", cmd, targ);
|
(void) sprintf(bp, "%s -t %s", cmd, targ);
|
||||||
host = cleanhostname(thost);
|
host = cleanhostname(thost);
|
||||||
if (do_cmd(host, tuser,
|
if (do_cmd(host, tuser, bp, &remin,
|
||||||
bp, &remin, &remout) < 0)
|
&remout, argc) < 0)
|
||||||
exit(1);
|
exit(1);
|
||||||
if (response() < 0)
|
if (response() < 0)
|
||||||
exit(1);
|
exit(1);
|
||||||
|
@ -461,11 +467,11 @@ tolocal(argc, argv)
|
||||||
for (i = 0; i < argc - 1; i++) {
|
for (i = 0; i < argc - 1; i++) {
|
||||||
if (!(src = colon(argv[i]))) { /* Local to local. */
|
if (!(src = colon(argv[i]))) { /* Local to local. */
|
||||||
len = strlen(_PATH_CP) + strlen(argv[i]) +
|
len = strlen(_PATH_CP) + strlen(argv[i]) +
|
||||||
strlen(argv[argc - 1]) + 20;
|
strlen(argv[argc - 1]) + 20;
|
||||||
bp = xmalloc(len);
|
bp = xmalloc(len);
|
||||||
(void) sprintf(bp, "exec %s%s%s %s %s", _PATH_CP,
|
(void) sprintf(bp, "exec %s%s%s %s %s", _PATH_CP,
|
||||||
iamrecursive ? " -r" : "", pflag ? " -p" : "",
|
iamrecursive ? " -r" : "", pflag ? " -p" : "",
|
||||||
argv[i], argv[argc - 1]);
|
argv[i], argv[argc - 1]);
|
||||||
if (verbose_mode)
|
if (verbose_mode)
|
||||||
fprintf(stderr, "Executing: %s\n", bp);
|
fprintf(stderr, "Executing: %s\n", bp);
|
||||||
if (system(bp))
|
if (system(bp))
|
||||||
|
@ -491,7 +497,7 @@ tolocal(argc, argv)
|
||||||
len = strlen(src) + CMDNEEDS + 20;
|
len = strlen(src) + CMDNEEDS + 20;
|
||||||
bp = xmalloc(len);
|
bp = xmalloc(len);
|
||||||
(void) sprintf(bp, "%s -f %s", cmd, src);
|
(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);
|
(void) xfree(bp);
|
||||||
++errs;
|
++errs;
|
||||||
continue;
|
continue;
|
||||||
|
@ -548,8 +554,8 @@ syserr: run_err("%s: %s", name, strerror(errno));
|
||||||
* versions expecting microseconds.
|
* versions expecting microseconds.
|
||||||
*/
|
*/
|
||||||
(void) sprintf(buf, "T%lu 0 %lu 0\n",
|
(void) sprintf(buf, "T%lu 0 %lu 0\n",
|
||||||
(unsigned long) stb.st_mtime,
|
(unsigned long) stb.st_mtime,
|
||||||
(unsigned long) stb.st_atime);
|
(unsigned long) stb.st_atime);
|
||||||
(void) atomicio(write, remout, buf, strlen(buf));
|
(void) atomicio(write, remout, buf, strlen(buf));
|
||||||
if (response() < 0)
|
if (response() < 0)
|
||||||
goto next;
|
goto next;
|
||||||
|
@ -626,8 +632,8 @@ rsource(name, statp)
|
||||||
last++;
|
last++;
|
||||||
if (pflag) {
|
if (pflag) {
|
||||||
(void) sprintf(path, "T%lu 0 %lu 0\n",
|
(void) sprintf(path, "T%lu 0 %lu 0\n",
|
||||||
(unsigned long) statp->st_mtime,
|
(unsigned long) statp->st_mtime,
|
||||||
(unsigned long) statp->st_atime);
|
(unsigned long) statp->st_atime);
|
||||||
(void) atomicio(write, remout, path, strlen(path));
|
(void) atomicio(write, remout, path, strlen(path));
|
||||||
if (response() < 0) {
|
if (response() < 0) {
|
||||||
closedir(dirp);
|
closedir(dirp);
|
||||||
|
@ -635,8 +641,7 @@ rsource(name, statp)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
(void) sprintf(path, "D%04o %d %.1024s\n",
|
(void) sprintf(path, "D%04o %d %.1024s\n",
|
||||||
(unsigned int) (statp->st_mode & FILEMODEMASK),
|
(unsigned int) (statp->st_mode & FILEMODEMASK), 0, last);
|
||||||
0, last);
|
|
||||||
if (verbose_mode)
|
if (verbose_mode)
|
||||||
fprintf(stderr, "Entering directory: %s", path);
|
fprintf(stderr, "Entering directory: %s", path);
|
||||||
(void) atomicio(write, remout, path, strlen(path));
|
(void) atomicio(write, remout, path, strlen(path));
|
||||||
|
@ -783,7 +788,7 @@ sink(argc, argv)
|
||||||
if (need > cursize)
|
if (need > cursize)
|
||||||
namebuf = xmalloc(need);
|
namebuf = xmalloc(need);
|
||||||
(void) sprintf(namebuf, "%s%s%s", targ,
|
(void) sprintf(namebuf, "%s%s%s", targ,
|
||||||
*targ ? "/" : "", cp);
|
*targ ? "/" : "", cp);
|
||||||
np = namebuf;
|
np = namebuf;
|
||||||
} else
|
} else
|
||||||
np = targ;
|
np = targ;
|
||||||
|
@ -954,8 +959,9 @@ response()
|
||||||
void
|
void
|
||||||
usage()
|
usage()
|
||||||
{
|
{
|
||||||
(void) fprintf(stderr,
|
(void) fprintf(stderr, "usage: scp "
|
||||||
"usage: scp [-pqrvC46] [-P port] [-c cipher] [-i identity] f1 f2; or:\n scp [options] f1 ... fn directory\n");
|
"[-pqrvC46] [-S ssh] [-P port] [-c cipher] [-i identity] f1 f2; or:\n"
|
||||||
|
" scp [options] f1 ... fn directory\n");
|
||||||
exit(1);
|
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 *
|
char *
|
||||||
colon(cp)
|
colon(cp)
|
||||||
char *cp;
|
char *cp;
|
||||||
|
@ -1097,7 +1066,7 @@ allocbuf(bp, fd, blksize)
|
||||||
size = blksize;
|
size = blksize;
|
||||||
else
|
else
|
||||||
size = blksize + (stb.st_blksize - blksize % stb.st_blksize) %
|
size = blksize + (stb.st_blksize - blksize % stb.st_blksize) %
|
||||||
stb.st_blksize;
|
stb.st_blksize;
|
||||||
if (bp->cnt >= size)
|
if (bp->cnt >= size)
|
||||||
return (bp);
|
return (bp);
|
||||||
if (bp->buf == NULL)
|
if (bp->buf == NULL)
|
||||||
|
@ -1228,14 +1197,14 @@ progressmeter(int flag)
|
||||||
i = remaining / 3600;
|
i = remaining / 3600;
|
||||||
if (i)
|
if (i)
|
||||||
snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf),
|
snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf),
|
||||||
"%2d:", i);
|
"%2d:", i);
|
||||||
else
|
else
|
||||||
snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf),
|
snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf),
|
||||||
" ");
|
" ");
|
||||||
i = remaining % 3600;
|
i = remaining % 3600;
|
||||||
snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf),
|
snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf),
|
||||||
"%02d:%02d%s", i / 60, i % 60,
|
"%02d:%02d%s", i / 60, i % 60,
|
||||||
(flag != 1) ? " ETA" : " ");
|
(flag != 1) ? " ETA" : " ");
|
||||||
}
|
}
|
||||||
atomicio(write, fileno(stdout), buf, strlen(buf));
|
atomicio(write, fileno(stdout), buf, strlen(buf));
|
||||||
|
|
||||||
|
|
120
session.c
120
session.c
|
@ -8,7 +8,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "includes.h"
|
#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 "xmalloc.h"
|
||||||
#include "ssh.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"
|
# define S_UNOFILE_HARD S_UNOFILE "_hard"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef HAVE_LOGIN_CAP
|
||||||
|
#include <login_cap.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
/* types */
|
/* types */
|
||||||
|
|
||||||
#define TTYSZ 64
|
#define TTYSZ 64
|
||||||
|
@ -117,6 +121,10 @@ Session sessions[MAX_SESSIONS];
|
||||||
char *aixloginmsg;
|
char *aixloginmsg;
|
||||||
#endif /* WITH_AIXAUTHENTICATE */
|
#endif /* WITH_AIXAUTHENTICATE */
|
||||||
|
|
||||||
|
#ifdef HAVE_LOGIN_CAP
|
||||||
|
static login_cap_t *lc;
|
||||||
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Remove local Xauthority file.
|
* Remove local Xauthority file.
|
||||||
*/
|
*/
|
||||||
|
@ -200,6 +208,13 @@ do_authenticated(struct passwd * pw)
|
||||||
s = session_new();
|
s = session_new();
|
||||||
s->pw = pw;
|
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
|
* We stay in this loop until the client requests to execute a shell
|
||||||
* or a command.
|
* or a command.
|
||||||
|
@ -650,7 +665,11 @@ do_login(Session *s)
|
||||||
|
|
||||||
/* Done if .hushlogin exists. */
|
/* Done if .hushlogin exists. */
|
||||||
snprintf(buf, sizeof(buf), "%.200s/.hushlogin", pw->pw_dir);
|
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)
|
if (stat(buf, &st) >= 0)
|
||||||
|
#endif
|
||||||
return;
|
return;
|
||||||
|
|
||||||
#ifdef USE_PAM
|
#ifdef USE_PAM
|
||||||
|
@ -677,7 +696,12 @@ do_login(Session *s)
|
||||||
printf("Last login: %s from %s\r\n", time_string, buf);
|
printf("Last login: %s from %s\r\n", time_string, buf);
|
||||||
}
|
}
|
||||||
if (options.print_motd) {
|
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");
|
f = fopen("/etc/motd", "r");
|
||||||
|
#endif
|
||||||
if (f) {
|
if (f) {
|
||||||
while (fgets(buf, sizeof(buf), f))
|
while (fgets(buf, sizeof(buf), f))
|
||||||
fputs(buf, stdout);
|
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 *display, const char *auth_proto,
|
||||||
const char *auth_data, const char *ttyname)
|
const char *auth_data, const char *ttyname)
|
||||||
{
|
{
|
||||||
const char *shell, *cp = NULL;
|
const char *shell, *hostname, *cp = NULL;
|
||||||
char buf[256];
|
char buf[256];
|
||||||
char cmd[1024];
|
char cmd[1024];
|
||||||
FILE *f;
|
FILE *f = NULL;
|
||||||
unsigned int envsize, i;
|
unsigned int envsize, i;
|
||||||
char **env;
|
char **env;
|
||||||
extern char **environ;
|
extern char **environ;
|
||||||
|
@ -905,24 +929,26 @@ do_child(const char *command, struct passwd * pw, const char *term,
|
||||||
options.use_login = 0;
|
options.use_login = 0;
|
||||||
|
|
||||||
#ifndef USE_PAM /* pam_nologin handles this */
|
#ifndef USE_PAM /* pam_nologin handles this */
|
||||||
f = fopen("/etc/nologin", "r");
|
if (!options.use_login) {
|
||||||
if (f) {
|
# ifdef HAVE_LOGIN_CAP
|
||||||
/* /etc/nologin exists. Print its contents and exit. */
|
if (!login_getcapbool(lc, "ignorenologin", 0) && pw->pw_uid)
|
||||||
while (fgets(buf, sizeof(buf), f))
|
f = fopen(login_getcapstr(lc, "nologin", _PATH_NOLOGIN,
|
||||||
fputs(buf, stderr);
|
_PATH_NOLOGIN), "r");
|
||||||
fclose(f);
|
# else /* HAVE_LOGIN_CAP */
|
||||||
if (pw->pw_uid != 0)
|
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);
|
exit(254);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#endif /* USE_PAM */
|
#endif /* USE_PAM */
|
||||||
|
|
||||||
#ifndef HAVE_OSF_SIA
|
/* Set login name, uid, gid, and groups. */
|
||||||
/* Set login name in the kernel. */
|
|
||||||
if (setlogin(pw->pw_name) < 0)
|
|
||||||
error("setlogin failed: %s", strerror(errno));
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Set uid, gid, and groups. */
|
|
||||||
/* Login(1) does this as well, and it needs uid 0 for the "-h"
|
/* Login(1) does this as well, and it needs uid 0 for the "-h"
|
||||||
switch, so we let login(1) to this for us. */
|
switch, so we let login(1) to this for us. */
|
||||||
if (!options.use_login) {
|
if (!options.use_login) {
|
||||||
|
@ -943,10 +969,18 @@ do_child(const char *command, struct passwd * pw, const char *term,
|
||||||
}
|
}
|
||||||
#else /* HAVE_OSF_SIA */
|
#else /* HAVE_OSF_SIA */
|
||||||
if (getuid() == 0 || geteuid() == 0) {
|
if (getuid() == 0 || geteuid() == 0) {
|
||||||
#if defined(HAVE_GETUSERATTR)
|
# ifdef HAVE_GETUSERATTR
|
||||||
set_limits_from_userattr(pw->pw_name);
|
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) {
|
if (setgid(pw->pw_gid) < 0) {
|
||||||
perror("setgid");
|
perror("setgid");
|
||||||
exit(1);
|
exit(1);
|
||||||
|
@ -957,38 +991,39 @@ do_child(const char *command, struct passwd * pw, const char *term,
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
endgrent();
|
endgrent();
|
||||||
|
# ifdef WITH_IRIX_ARRAY
|
||||||
#ifdef WITH_IRIX_ARRAY
|
|
||||||
/* initialize array session */
|
/* initialize array session */
|
||||||
if (newarraysess() != 0)
|
if (newarraysess() != 0)
|
||||||
fatal("Failed to set up new array session: %.100s",
|
fatal("Failed to set up new array session: %.100s",
|
||||||
strerror(errno));
|
strerror(errno));
|
||||||
#endif /* WITH_IRIX_ARRAY */
|
# endif /* WITH_IRIX_ARRAY */
|
||||||
|
# ifdef WITH_IRIX_PROJECT
|
||||||
#ifdef WITH_IRIX_PROJECT
|
|
||||||
/* initialize irix project info */
|
/* initialize irix project info */
|
||||||
if ((projid = getdfltprojuser(pw->pw_name)) == -1) {
|
if ((projid = getdfltprojuser(pw->pw_name)) == -1) {
|
||||||
debug("Failed to get project id, using projid 0");
|
debug("Failed to get project id, using projid 0");
|
||||||
projid = 0;
|
projid = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (setprid(projid))
|
if (setprid(projid))
|
||||||
fatal("Failed to initialize project %d for %s: %.100s",
|
fatal("Failed to initialize project %d for %s: %.100s",
|
||||||
(int)projid, pw->pw_name, strerror(errno));
|
(int)projid, pw->pw_name, strerror(errno));
|
||||||
#endif /* WITH_IRIX_PROJECT */
|
# endif /* WITH_IRIX_PROJECT */
|
||||||
|
|
||||||
/* Permanently switch to the desired uid. */
|
/* Permanently switch to the desired uid. */
|
||||||
permanently_set_uid(pw->pw_uid);
|
permanently_set_uid(pw->pw_uid);
|
||||||
|
# endif /* HAVE_LOGIN_CAP */
|
||||||
}
|
}
|
||||||
|
#endif /* HAVE_OSF_SIA */
|
||||||
|
|
||||||
if (getuid() != pw->pw_uid || geteuid() != pw->pw_uid)
|
if (getuid() != pw->pw_uid || geteuid() != pw->pw_uid)
|
||||||
fatal("Failed to set uids to %d.", (int) 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
|
* Get the shell from the password data. An empty shell field is
|
||||||
* legal, and means /bin/sh.
|
* legal, and means /bin/sh.
|
||||||
*/
|
*/
|
||||||
shell = (pw->pw_shell[0] == '\0') ? _PATH_BSHELL : pw->pw_shell;
|
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
|
#ifdef AFS
|
||||||
/* Try to get AFS tokens for the local cell. */
|
/* 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, "USER", pw->pw_name);
|
||||||
child_set_env(&env, &envsize, "LOGNAME", pw->pw_name);
|
child_set_env(&env, &envsize, "LOGNAME", pw->pw_name);
|
||||||
child_set_env(&env, &envsize, "HOME", pw->pw_dir);
|
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);
|
child_set_env(&env, &envsize, "PATH", _PATH_STDPATH);
|
||||||
|
#endif
|
||||||
|
|
||||||
snprintf(buf, sizeof buf, "%.200s/%.50s",
|
snprintf(buf, sizeof buf, "%.200s/%.50s",
|
||||||
_PATH_MAILDIR, pw->pw_name);
|
_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++)
|
for (i = 0; env[i]; i++)
|
||||||
fprintf(stderr, " %.200s\n", env[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
|
* Close the connection descriptors; note that this is the child, and
|
||||||
* the server will still have the socket open, and it is important
|
* 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);
|
close(i);
|
||||||
|
|
||||||
/* Change current directory to the user\'s home directory. */
|
/* 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",
|
fprintf(stderr, "Could not chdir to home directory %s: %s\n",
|
||||||
pw->pw_dir, strerror(errno));
|
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
|
* 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 {
|
} else {
|
||||||
/* Launch login(1). */
|
/* Launch login(1). */
|
||||||
|
|
||||||
execl(LOGIN_PROGRAM, "login",
|
execl(LOGIN_PROGRAM, "login", "-h", hostname,
|
||||||
"-h", get_remote_name_or_ip(),
|
|
||||||
"-p", "-f", "--", pw->pw_name, NULL);
|
"-p", "-f", "--", pw->pw_name, NULL);
|
||||||
|
|
||||||
/* Login couldn't be executed, die. */
|
/* Login couldn't be executed, die. */
|
||||||
|
@ -1790,6 +1837,8 @@ session_proctitle(Session *s)
|
||||||
void
|
void
|
||||||
do_authenticated2(void)
|
do_authenticated2(void)
|
||||||
{
|
{
|
||||||
|
struct passwd *pw;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Cancel the alarm we set to limit the time taken for
|
* Cancel the alarm we set to limit the time taken for
|
||||||
* authentication.
|
* authentication.
|
||||||
|
@ -1799,6 +1848,13 @@ do_authenticated2(void)
|
||||||
close(startup_pipe);
|
close(startup_pipe);
|
||||||
startup_pipe = -1;
|
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();
|
server_loop2();
|
||||||
if (xauthfile)
|
if (xauthfile)
|
||||||
xauthfile_cleanup_proc(NULL);
|
xauthfile_cleanup_proc(NULL);
|
||||||
|
|
|
@ -9,21 +9,21 @@
|
||||||
.\"
|
.\"
|
||||||
.\" Created: Sat Apr 22 23:55:14 1995 ylo
|
.\" 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
|
.Dd September 25, 1999
|
||||||
.Dt SSH-ADD 1
|
.Dt SSH-ADD 1
|
||||||
.Os
|
.Os
|
||||||
.Sh NAME
|
.Sh NAME
|
||||||
.Nm ssh-add
|
.Nm ssh-add
|
||||||
.Nd adds RSA identities for the authentication agent
|
.Nd adds RSA or DSA identities for the authentication agent
|
||||||
.Sh SYNOPSIS
|
.Sh SYNOPSIS
|
||||||
.Nm ssh-add
|
.Nm ssh-add
|
||||||
.Op Fl lLdD
|
.Op Fl lLdD
|
||||||
.Op Ar
|
.Op Ar
|
||||||
.Sh DESCRIPTION
|
.Sh DESCRIPTION
|
||||||
.Nm
|
.Nm
|
||||||
adds RSA identities to the authentication agent,
|
adds RSA or DSA identities to the authentication agent,
|
||||||
.Xr ssh-agent 1 .
|
.Xr ssh-agent 1 .
|
||||||
When run without arguments, it adds the file
|
When run without arguments, it adds the file
|
||||||
.Pa $HOME/.ssh/identity .
|
.Pa $HOME/.ssh/identity .
|
||||||
|
@ -63,6 +63,8 @@ used to encrypt the private part of this file.
|
||||||
This is the default file added by
|
This is the default file added by
|
||||||
.Nm
|
.Nm
|
||||||
when no other files have been specified.
|
when no other files have been specified.
|
||||||
|
.It Pa $HOME/.ssh/id_dsa
|
||||||
|
Contains the DSA authentication identity of the user.
|
||||||
.Pp
|
.Pp
|
||||||
.Sh ENVIRONMENT
|
.Sh ENVIRONMENT
|
||||||
.Bl -tag -width Ds
|
.Bl -tag -width Ds
|
||||||
|
|
81
ssh-add.c
81
ssh-add.c
|
@ -4,18 +4,21 @@
|
||||||
* All rights reserved
|
* All rights reserved
|
||||||
* Created: Thu Apr 6 00:52:24 1995 ylo
|
* Created: Thu Apr 6 00:52:24 1995 ylo
|
||||||
* Adds an identity to the authentication server, or removes an identity.
|
* Adds an identity to the authentication server, or removes an identity.
|
||||||
|
*
|
||||||
|
* SSH2 implementation,
|
||||||
|
* Copyright (c) 2000 Markus Friedl. All rights reserved.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "includes.h"
|
#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/rsa.h>
|
||||||
#include <openssl/dsa.h>
|
#include <openssl/dsa.h>
|
||||||
|
|
||||||
#include "rsa.h"
|
#include "rsa.h"
|
||||||
#include "ssh.h"
|
#include "ssh.h"
|
||||||
#include "xmalloc.h"
|
#include "xmalloc.h"
|
||||||
#include "fingerprint.h"
|
|
||||||
#include "key.h"
|
#include "key.h"
|
||||||
#include "authfd.h"
|
#include "authfd.h"
|
||||||
#include "authfile.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));
|
printf("Bad key file %s: %s\n", filename, strerror(errno));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (ssh_remove_identity(ac, public->rsa))
|
if (ssh_remove_identity(ac, public))
|
||||||
fprintf(stderr, "Identity removed: %s (%s)\n", filename, comment);
|
fprintf(stderr, "Identity removed: %s (%s)\n", filename, comment);
|
||||||
else
|
else
|
||||||
fprintf(stderr, "Could not remove identity: %s\n", filename);
|
fprintf(stderr, "Could not remove identity: %s\n", filename);
|
||||||
|
@ -45,11 +48,18 @@ delete_file(AuthenticationConnection *ac, const char *filename)
|
||||||
xfree(comment);
|
xfree(comment);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Send a request to remove all identities. */
|
||||||
void
|
void
|
||||||
delete_all(AuthenticationConnection *ac)
|
delete_all(AuthenticationConnection *ac)
|
||||||
{
|
{
|
||||||
/* Send a request to remove all identities. */
|
int success = 1;
|
||||||
if (ssh_remove_all_identities(ac))
|
|
||||||
|
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");
|
fprintf(stderr, "All identities removed.\n");
|
||||||
else
|
else
|
||||||
fprintf(stderr, "Failed to remove all identitities.\n");
|
fprintf(stderr, "Failed to remove all identitities.\n");
|
||||||
|
@ -96,6 +106,7 @@ ssh_askpass(char *askpass, char *msg)
|
||||||
void
|
void
|
||||||
add_file(AuthenticationConnection *ac, const char *filename)
|
add_file(AuthenticationConnection *ac, const char *filename)
|
||||||
{
|
{
|
||||||
|
struct stat st;
|
||||||
Key *public;
|
Key *public;
|
||||||
Key *private;
|
Key *private;
|
||||||
char *saved_comment, *comment, *askpass = NULL;
|
char *saved_comment, *comment, *askpass = NULL;
|
||||||
|
@ -104,6 +115,10 @@ add_file(AuthenticationConnection *ac, const char *filename)
|
||||||
int interactive = isatty(STDIN_FILENO);
|
int interactive = isatty(STDIN_FILENO);
|
||||||
int type = KEY_RSA;
|
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,
|
* try to load the public key. right now this only works for RSA,
|
||||||
* since DSA keys are fully encrypted
|
* 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);
|
strlcpy(msg, "Bad passphrase, try again", sizeof msg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
xfree(saved_comment);
|
xfree(comment);
|
||||||
|
if (ssh_add_identity(ac, private, saved_comment))
|
||||||
if (ssh_add_identity(ac, private, comment))
|
fprintf(stderr, "Identity added: %s (%s)\n", filename, saved_comment);
|
||||||
fprintf(stderr, "Identity added: %s (%s)\n", filename, comment);
|
|
||||||
else
|
else
|
||||||
fprintf(stderr, "Could not add identity: %s\n", filename);
|
fprintf(stderr, "Could not add identity: %s\n", filename);
|
||||||
key_free(private);
|
key_free(private);
|
||||||
xfree(comment);
|
xfree(saved_comment);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
list_identities(AuthenticationConnection *ac, int fp)
|
list_identities(AuthenticationConnection *ac, int fp)
|
||||||
{
|
{
|
||||||
BIGNUM *e, *n;
|
Key *key;
|
||||||
int status;
|
|
||||||
char *comment;
|
char *comment;
|
||||||
int had_identities;
|
int had_identities = 0;
|
||||||
|
int version;
|
||||||
|
|
||||||
e = BN_new();
|
for (version = 1; version <= 2; version++) {
|
||||||
n = BN_new();
|
for (key = ssh_get_first_identity(ac, &comment, version);
|
||||||
had_identities = 0;
|
key != NULL;
|
||||||
for (status = ssh_get_first_identity(ac, e, n, &comment);
|
key = ssh_get_next_identity(ac, &comment, version)) {
|
||||||
status;
|
had_identities = 1;
|
||||||
status = ssh_get_next_identity(ac, e, n, &comment)) {
|
if (fp) {
|
||||||
unsigned int bits = BN_num_bits(n);
|
printf("%d %s %s\n",
|
||||||
had_identities = 1;
|
key_size(key), key_fingerprint(key), comment);
|
||||||
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.");
|
|
||||||
} else {
|
} else {
|
||||||
nbuf = BN_bn2dec(n);
|
if (!key_write(key, stdout))
|
||||||
if (nbuf == NULL) {
|
fprintf(stderr, "key_write failed");
|
||||||
error("list_identities: BN_bn2dec(n) failed.");
|
fprintf(stdout, " %s\n", comment);
|
||||||
} else {
|
|
||||||
printf("%d %s %s %s\n", bits, ebuf, nbuf, comment);
|
|
||||||
free(nbuf);
|
|
||||||
}
|
|
||||||
free(ebuf);
|
|
||||||
}
|
}
|
||||||
|
key_free(key);
|
||||||
|
xfree(comment);
|
||||||
}
|
}
|
||||||
xfree(comment);
|
|
||||||
}
|
}
|
||||||
BN_clear_free(e);
|
|
||||||
BN_clear_free(n);
|
|
||||||
if (!had_identities)
|
if (!had_identities)
|
||||||
printf("The agent has no identities.\n");
|
printf("The agent has no identities.\n");
|
||||||
}
|
}
|
||||||
|
@ -225,6 +226,8 @@ main(int argc, char **argv)
|
||||||
__progname);
|
__progname);
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
SSLeay_add_all_algorithms();
|
||||||
|
|
||||||
/* At first, get a connection to the authentication agent. */
|
/* At first, get a connection to the authentication agent. */
|
||||||
ac = ssh_get_authentication_connection();
|
ac = ssh_get_authentication_connection();
|
||||||
if (ac == NULL) {
|
if (ac == NULL) {
|
||||||
|
|
11
ssh-agent.1
11
ssh-agent.1
|
@ -1,4 +1,4 @@
|
||||||
.\" $OpenBSD: ssh-agent.1,v 1.13 2000/07/06 04:06:56 aaron Exp $
|
.\" $OpenBSD: ssh-agent.1,v 1.14 2000/08/19 21:34:43 markus Exp $
|
||||||
.\"
|
.\"
|
||||||
.\" -*- nroff -*-
|
.\" -*- nroff -*-
|
||||||
.\"
|
.\"
|
||||||
|
@ -27,14 +27,15 @@
|
||||||
.Oc
|
.Oc
|
||||||
.Sh DESCRIPTION
|
.Sh DESCRIPTION
|
||||||
.Nm
|
.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
|
The idea is that
|
||||||
.Nm
|
.Nm
|
||||||
is started in the beginning of an X-session or a login session, and
|
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
|
all other windows or programs are started as clients to the ssh-agent
|
||||||
program.
|
program.
|
||||||
Through use of environment variables the agent can be located
|
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
|
machines using
|
||||||
.Xr ssh 1 .
|
.Xr ssh 1 .
|
||||||
.Pp
|
.Pp
|
||||||
|
@ -128,7 +129,9 @@ This file is not used by
|
||||||
but is normally added to the agent using
|
but is normally added to the agent using
|
||||||
.Xr ssh-add 1
|
.Xr ssh-add 1
|
||||||
at login time.
|
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
|
Unix-domain sockets used to contain the connection to the
|
||||||
authentication agent.
|
authentication agent.
|
||||||
These sockets should only be readable by the owner.
|
These sockets should only be readable by the owner.
|
||||||
|
|
494
ssh-agent.c
494
ssh-agent.c
|
@ -1,4 +1,4 @@
|
||||||
/* $OpenBSD: ssh-agent.c,v 1.32 2000/07/16 08:27:21 markus Exp $ */
|
/* $OpenBSD: ssh-agent.c,v 1.33 2000/08/19 21:34:43 markus Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
||||||
|
@ -6,10 +6,13 @@
|
||||||
* All rights reserved
|
* All rights reserved
|
||||||
* Created: Wed Mar 29 03:46:59 1995 ylo
|
* Created: Wed Mar 29 03:46:59 1995 ylo
|
||||||
* The authentication agent program.
|
* The authentication agent program.
|
||||||
|
*
|
||||||
|
* SSH2 implementation,
|
||||||
|
* Copyright (c) 2000 Markus Friedl. All rights reserved.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "includes.h"
|
#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 "ssh.h"
|
||||||
#include "rsa.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 "getput.h"
|
||||||
#include "mpaux.h"
|
#include "mpaux.h"
|
||||||
|
|
||||||
|
#include <openssl/evp.h>
|
||||||
#include <openssl/md5.h>
|
#include <openssl/md5.h>
|
||||||
#include <openssl/dsa.h>
|
#include <openssl/dsa.h>
|
||||||
#include <openssl/rsa.h>
|
#include <openssl/rsa.h>
|
||||||
#include "key.h"
|
#include "key.h"
|
||||||
#include "authfd.h"
|
#include "authfd.h"
|
||||||
|
#include "dsa.h"
|
||||||
|
#include "kex.h"
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
int fd;
|
int fd;
|
||||||
|
@ -39,12 +45,17 @@ unsigned int sockets_alloc = 0;
|
||||||
SocketEntry *sockets = NULL;
|
SocketEntry *sockets = NULL;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
RSA *key;
|
Key *key;
|
||||||
char *comment;
|
char *comment;
|
||||||
} Identity;
|
} Identity;
|
||||||
|
|
||||||
unsigned int num_identities = 0;
|
typedef struct {
|
||||||
Identity *identities = NULL;
|
int nentries;
|
||||||
|
Identity *identities;
|
||||||
|
} Idtab;
|
||||||
|
|
||||||
|
/* private key table, one per protocol version */
|
||||||
|
Idtab idtable[3];
|
||||||
|
|
||||||
int max_fd = 0;
|
int max_fd = 0;
|
||||||
|
|
||||||
|
@ -62,175 +73,243 @@ static const char *__progname = "ssh-agent";
|
||||||
#endif /* HAVE___PROGNAME */
|
#endif /* HAVE___PROGNAME */
|
||||||
|
|
||||||
void
|
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;
|
Buffer msg;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
buffer_init(&msg);
|
buffer_init(&msg);
|
||||||
buffer_put_char(&msg, SSH_AGENT_RSA_IDENTITIES_ANSWER);
|
buffer_put_char(&msg, (version == 1) ?
|
||||||
buffer_put_int(&msg, num_identities);
|
SSH_AGENT_RSA_IDENTITIES_ANSWER : SSH2_AGENT_IDENTITIES_ANSWER);
|
||||||
for (i = 0; i < num_identities; i++) {
|
buffer_put_int(&msg, tab->nentries);
|
||||||
buffer_put_int(&msg, BN_num_bits(identities[i].key->n));
|
for (i = 0; i < tab->nentries; i++) {
|
||||||
buffer_put_bignum(&msg, identities[i].key->e);
|
Identity *id = &tab->identities[i];
|
||||||
buffer_put_bignum(&msg, identities[i].key->n);
|
if (id->key->type == KEY_RSA) {
|
||||||
buffer_put_string(&msg, identities[i].comment,
|
buffer_put_int(&msg, BN_num_bits(id->key->rsa->n));
|
||||||
strlen(identities[i].comment));
|
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_put_int(&e->output, buffer_len(&msg));
|
||||||
buffer_append(&e->output, buffer_ptr(&msg), buffer_len(&msg));
|
buffer_append(&e->output, buffer_ptr(&msg), buffer_len(&msg));
|
||||||
buffer_free(&msg);
|
buffer_free(&msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* ssh1 only */
|
||||||
void
|
void
|
||||||
process_authentication_challenge(SocketEntry *e)
|
process_authentication_challenge1(SocketEntry *e)
|
||||||
{
|
{
|
||||||
int i, pub_bits, len;
|
Key *key, *private;
|
||||||
BIGNUM *pub_e, *pub_n, *challenge;
|
BIGNUM *challenge;
|
||||||
|
int i, len;
|
||||||
Buffer msg;
|
Buffer msg;
|
||||||
MD5_CTX md;
|
MD5_CTX md;
|
||||||
unsigned char buf[32], mdbuf[16], session_id[16];
|
unsigned char buf[32], mdbuf[16], session_id[16];
|
||||||
unsigned int response_type;
|
unsigned int response_type;
|
||||||
|
|
||||||
buffer_init(&msg);
|
buffer_init(&msg);
|
||||||
pub_e = BN_new();
|
key = key_new(KEY_RSA);
|
||||||
pub_n = BN_new();
|
|
||||||
challenge = BN_new();
|
challenge = BN_new();
|
||||||
pub_bits = buffer_get_int(&e->input);
|
|
||||||
buffer_get_bignum(&e->input, pub_e);
|
buffer_get_int(&e->input); /* ignored */
|
||||||
buffer_get_bignum(&e->input, pub_n);
|
buffer_get_bignum(&e->input, key->rsa->e);
|
||||||
|
buffer_get_bignum(&e->input, key->rsa->n);
|
||||||
buffer_get_bignum(&e->input, challenge);
|
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. */
|
/* Only protocol 1.1 is supported */
|
||||||
switch (response_type) {
|
if (buffer_len(&e->input) == 0)
|
||||||
case 0:/* As of protocol 1.0 */
|
goto failure;
|
||||||
/* This response type is no longer supported. */
|
buffer_get(&e->input, (char *) session_id, 16);
|
||||||
log("Compatibility with ssh protocol 1.0 no longer supported.");
|
response_type = buffer_get_int(&e->input);
|
||||||
buffer_put_char(&msg, SSH_AGENT_FAILURE);
|
if (response_type != 1)
|
||||||
goto send;
|
goto failure;
|
||||||
|
|
||||||
case 1:/* As of protocol 1.1 */
|
private = lookup_private_key(key, NULL, 1);
|
||||||
/* The response is MD5 of decrypted challenge plus session id. */
|
if (private != NULL) {
|
||||||
len = BN_num_bytes(challenge);
|
/* Decrypt the challenge using the private key. */
|
||||||
|
rsa_private_decrypt(challenge, challenge, private->rsa);
|
||||||
|
|
||||||
if (len <= 0 || len > 32) {
|
/* The response is MD5 of decrypted challenge plus session id. */
|
||||||
fatal("process_authentication_challenge: "
|
len = BN_num_bytes(challenge);
|
||||||
"bad challenge length %d", len);
|
if (len <= 0 || len > 32) {
|
||||||
}
|
log("process_authentication_challenge: bad challenge length %d", len);
|
||||||
memset(buf, 0, 32);
|
goto failure;
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
/* 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);
|
buffer_put_char(&msg, SSH_AGENT_FAILURE);
|
||||||
send:
|
send:
|
||||||
buffer_put_int(&e->output, buffer_len(&msg));
|
buffer_put_int(&e->output, buffer_len(&msg));
|
||||||
buffer_append(&e->output, buffer_ptr(&msg),
|
buffer_append(&e->output, buffer_ptr(&msg), buffer_len(&msg));
|
||||||
buffer_len(&msg));
|
key_free(key);
|
||||||
buffer_free(&msg);
|
|
||||||
BN_clear_free(pub_e);
|
|
||||||
BN_clear_free(pub_n);
|
|
||||||
BN_clear_free(challenge);
|
BN_clear_free(challenge);
|
||||||
|
buffer_free(&msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* ssh2 only */
|
||||||
void
|
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 bits;
|
||||||
unsigned int i;
|
int success = 0;
|
||||||
BIGNUM *dummy, *n;
|
|
||||||
|
|
||||||
dummy = BN_new();
|
switch(version){
|
||||||
n = BN_new();
|
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. */
|
if (bits != key_size(key))
|
||||||
bits = buffer_get_int(&e->input);
|
log("Warning: identity keysize mismatch: actual %d, announced %d",
|
||||||
buffer_get_bignum(&e->input, dummy);
|
key_size(key), bits);
|
||||||
buffer_get_bignum(&e->input, n);
|
break;
|
||||||
|
case 2:
|
||||||
if (bits != BN_num_bits(n))
|
blob = buffer_get_string(&e->input, &blen);
|
||||||
log("Warning: identity keysize mismatch: actual %d, announced %d",
|
key = dsa_key_from_blob(blob, blen);
|
||||||
BN_num_bits(n), bits);
|
xfree(blob);
|
||||||
|
break;
|
||||||
/* Check if we have the key. */
|
}
|
||||||
for (i = 0; i < num_identities; i++)
|
if (key != NULL) {
|
||||||
if (BN_cmp(identities[i].key->n, n) == 0) {
|
int idx;
|
||||||
|
private = lookup_private_key(key, &idx, version);
|
||||||
|
if (private != NULL) {
|
||||||
/*
|
/*
|
||||||
* We have this key. Free the old key. Since we
|
* We have this key. Free the old key. Since we
|
||||||
* don\'t want to leave empty slots in the middle of
|
* don\'t want to leave empty slots in the middle of
|
||||||
* the array, we actually free the key there and copy
|
* the array, we actually free the key there and copy
|
||||||
* data from the last entry.
|
* data from the last entry.
|
||||||
*/
|
*/
|
||||||
RSA_free(identities[i].key);
|
Idtab *tab = idtab_lookup(version);
|
||||||
xfree(identities[i].comment);
|
key_free(tab->identities[idx].key);
|
||||||
if (i < num_identities - 1)
|
xfree(tab->identities[idx].comment);
|
||||||
identities[i] = identities[num_identities - 1];
|
if (idx != tab->nentries)
|
||||||
num_identities--;
|
tab->identities[idx] = tab->identities[tab->nentries];
|
||||||
BN_clear_free(dummy);
|
tab->nentries--;
|
||||||
BN_clear_free(n);
|
success = 1;
|
||||||
|
|
||||||
/* Send success. */
|
|
||||||
buffer_put_int(&e->output, 1);
|
|
||||||
buffer_put_char(&e->output, SSH_AGENT_SUCCESS);
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
/* We did not have the key. */
|
key_free(key);
|
||||||
BN_clear(dummy);
|
}
|
||||||
BN_clear(n);
|
|
||||||
|
|
||||||
/* Send failure. */
|
|
||||||
buffer_put_int(&e->output, 1);
|
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
|
void
|
||||||
process_remove_all_identities(SocketEntry *e)
|
process_remove_all_identities(SocketEntry *e, int version)
|
||||||
{
|
{
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
|
Idtab *tab = idtab_lookup(version);
|
||||||
|
|
||||||
/* Loop over all identities and clear the keys. */
|
/* Loop over all identities and clear the keys. */
|
||||||
for (i = 0; i < num_identities; i++) {
|
for (i = 0; i < tab->nentries; i++) {
|
||||||
RSA_free(identities[i].key);
|
key_free(tab->identities[i].key);
|
||||||
xfree(identities[i].comment);
|
xfree(tab->identities[i].comment);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Mark that there are no identities. */
|
/* Mark that there are no identities. */
|
||||||
num_identities = 0;
|
tab->nentries = 0;
|
||||||
|
|
||||||
/* Send success. */
|
/* Send success. */
|
||||||
buffer_put_int(&e->output, 1);
|
buffer_put_int(&e->output, 1);
|
||||||
|
@ -238,79 +317,108 @@ process_remove_all_identities(SocketEntry *e)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* Adds an identity to the agent.
|
|
||||||
*/
|
|
||||||
void
|
void
|
||||||
process_add_identity(SocketEntry *e)
|
process_add_identity(SocketEntry *e, int version)
|
||||||
{
|
{
|
||||||
RSA *k;
|
Key *k = NULL;
|
||||||
int i;
|
RSA *rsa;
|
||||||
BIGNUM *aux;
|
BIGNUM *aux;
|
||||||
BN_CTX *ctx;
|
BN_CTX *ctx;
|
||||||
|
char *type;
|
||||||
|
char *comment;
|
||||||
|
int success = 0;
|
||||||
|
Idtab *tab = idtab_lookup(version);
|
||||||
|
|
||||||
if (num_identities == 0)
|
switch (version) {
|
||||||
identities = xmalloc(sizeof(Identity));
|
case 1:
|
||||||
else
|
k = key_new(KEY_RSA);
|
||||||
identities = xrealloc(identities, (num_identities + 1) * sizeof(Identity));
|
rsa = k->rsa;
|
||||||
|
|
||||||
identities[num_identities].key = RSA_new();
|
/* allocate mem for private key */
|
||||||
k = identities[num_identities].key;
|
/* XXX rsa->n and rsa->e are already allocated */
|
||||||
buffer_get_int(&e->input); /* bits */
|
rsa->d = BN_new();
|
||||||
k->n = BN_new();
|
rsa->iqmp = BN_new();
|
||||||
buffer_get_bignum(&e->input, k->n);
|
rsa->q = BN_new();
|
||||||
k->e = BN_new();
|
rsa->p = BN_new();
|
||||||
buffer_get_bignum(&e->input, k->e);
|
rsa->dmq1 = BN_new();
|
||||||
k->d = BN_new();
|
rsa->dmp1 = BN_new();
|
||||||
buffer_get_bignum(&e->input, k->d);
|
|
||||||
k->iqmp = BN_new();
|
|
||||||
buffer_get_bignum(&e->input, k->iqmp);
|
|
||||||
/* SSH and SSL have p and q swapped */
|
|
||||||
k->q = BN_new();
|
|
||||||
buffer_get_bignum(&e->input, k->q); /* p */
|
|
||||||
k->p = BN_new();
|
|
||||||
buffer_get_bignum(&e->input, k->p); /* q */
|
|
||||||
|
|
||||||
/* Generate additional parameters */
|
buffer_get_int(&e->input); /* ignored */
|
||||||
aux = BN_new();
|
|
||||||
ctx = BN_CTX_new();
|
|
||||||
|
|
||||||
BN_sub(aux, k->q, BN_value_one());
|
buffer_get_bignum(&e->input, rsa->n);
|
||||||
k->dmq1 = BN_new();
|
buffer_get_bignum(&e->input, rsa->e);
|
||||||
BN_mod(k->dmq1, k->d, aux, ctx);
|
buffer_get_bignum(&e->input, rsa->d);
|
||||||
|
buffer_get_bignum(&e->input, rsa->iqmp);
|
||||||
|
|
||||||
BN_sub(aux, k->p, BN_value_one());
|
/* SSH and SSL have p and q swapped */
|
||||||
k->dmp1 = BN_new();
|
buffer_get_bignum(&e->input, rsa->q); /* p */
|
||||||
BN_mod(k->dmp1, k->d, aux, ctx);
|
buffer_get_bignum(&e->input, rsa->p); /* q */
|
||||||
|
|
||||||
BN_clear_free(aux);
|
/* Generate additional parameters */
|
||||||
BN_CTX_free(ctx);
|
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. */
|
BN_sub(aux, rsa->p, BN_value_one());
|
||||||
for (i = 0; i < num_identities; i++)
|
BN_mod(rsa->dmp1, rsa->d, aux, ctx);
|
||||||
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);
|
|
||||||
|
|
||||||
/* Send success. */
|
BN_clear_free(aux);
|
||||||
buffer_put_int(&e->output, 1);
|
BN_CTX_free(ctx);
|
||||||
buffer_put_char(&e->output, SSH_AGENT_SUCCESS);
|
|
||||||
return;
|
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. */
|
xfree(type);
|
||||||
num_identities++;
|
|
||||||
|
|
||||||
/* 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_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
|
void
|
||||||
process_message(SocketEntry *e)
|
process_message(SocketEntry *e)
|
||||||
{
|
{
|
||||||
|
@ -333,20 +441,37 @@ process_message(SocketEntry *e)
|
||||||
type = buffer_get_char(&e->input);
|
type = buffer_get_char(&e->input);
|
||||||
|
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case SSH_AGENTC_REQUEST_RSA_IDENTITIES:
|
/* ssh1 */
|
||||||
process_request_identity(e);
|
|
||||||
break;
|
|
||||||
case SSH_AGENTC_RSA_CHALLENGE:
|
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;
|
break;
|
||||||
case SSH_AGENTC_ADD_RSA_IDENTITY:
|
case SSH_AGENTC_ADD_RSA_IDENTITY:
|
||||||
process_add_identity(e);
|
process_add_identity(e, 1);
|
||||||
break;
|
break;
|
||||||
case SSH_AGENTC_REMOVE_RSA_IDENTITY:
|
case SSH_AGENTC_REMOVE_RSA_IDENTITY:
|
||||||
process_remove_identity(e);
|
process_remove_identity(e, 1);
|
||||||
break;
|
break;
|
||||||
case SSH_AGENTC_REMOVE_ALL_RSA_IDENTITIES:
|
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;
|
break;
|
||||||
default:
|
default:
|
||||||
/* Unknown message. Respond with failure. */
|
/* Unknown message. Respond with failure. */
|
||||||
|
@ -511,9 +636,9 @@ main(int ac, char **av)
|
||||||
pid_t pid;
|
pid_t pid;
|
||||||
char *shell, *format, *pidstr, pidstrbuf[1 + 3 * sizeof pid];
|
char *shell, *format, *pidstr, pidstrbuf[1 + 3 * sizeof pid];
|
||||||
extern int optind;
|
extern int optind;
|
||||||
|
|
||||||
init_rng();
|
init_rng();
|
||||||
|
|
||||||
/* check if RSA support exists */
|
/* check if RSA support exists */
|
||||||
if (rsa_alive() == 0) {
|
if (rsa_alive() == 0) {
|
||||||
fprintf(stderr,
|
fprintf(stderr,
|
||||||
|
@ -654,6 +779,7 @@ main(int ac, char **av)
|
||||||
signal(SIGALRM, check_parent_exists);
|
signal(SIGALRM, check_parent_exists);
|
||||||
alarm(10);
|
alarm(10);
|
||||||
}
|
}
|
||||||
|
idtab_init();
|
||||||
signal(SIGINT, SIG_IGN);
|
signal(SIGINT, SIG_IGN);
|
||||||
signal(SIGPIPE, SIG_IGN);
|
signal(SIGPIPE, SIG_IGN);
|
||||||
signal(SIGHUP, cleanup_exit);
|
signal(SIGHUP, cleanup_exit);
|
||||||
|
|
19
ssh-keygen.c
19
ssh-keygen.c
|
@ -7,7 +7,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "includes.h"
|
#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/evp.h>
|
||||||
#include <openssl/pem.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 "ssh.h"
|
||||||
#include "xmalloc.h"
|
#include "xmalloc.h"
|
||||||
#include "fingerprint.h"
|
|
||||||
#include "key.h"
|
#include "key.h"
|
||||||
#include "rsa.h"
|
#include "rsa.h"
|
||||||
#include "dsa.h"
|
#include "dsa.h"
|
||||||
|
@ -228,8 +227,9 @@ do_print_public(struct passwd *pw)
|
||||||
void
|
void
|
||||||
do_fingerprint(struct passwd *pw)
|
do_fingerprint(struct passwd *pw)
|
||||||
{
|
{
|
||||||
|
/* XXX RSA1 only */
|
||||||
|
|
||||||
FILE *f;
|
FILE *f;
|
||||||
BIGNUM *e, *n;
|
|
||||||
Key *public;
|
Key *public;
|
||||||
char *comment = NULL, *cp, *ep, line[16*1024];
|
char *comment = NULL, *cp, *ep, line[16*1024];
|
||||||
int i, skip = 0, num = 1, invalid = 1;
|
int i, skip = 0, num = 1, invalid = 1;
|
||||||
|
@ -249,13 +249,9 @@ do_fingerprint(struct passwd *pw)
|
||||||
key_free(public);
|
key_free(public);
|
||||||
exit(0);
|
exit(0);
|
||||||
}
|
}
|
||||||
key_free(public);
|
|
||||||
|
|
||||||
/* XXX */
|
|
||||||
f = fopen(identity_file, "r");
|
f = fopen(identity_file, "r");
|
||||||
if (f != NULL) {
|
if (f != NULL) {
|
||||||
n = BN_new();
|
|
||||||
e = BN_new();
|
|
||||||
while (fgets(line, sizeof(line), f)) {
|
while (fgets(line, sizeof(line), f)) {
|
||||||
i = strlen(line) - 1;
|
i = strlen(line) - 1;
|
||||||
if (line[i] != '\n') {
|
if (line[i] != '\n') {
|
||||||
|
@ -290,18 +286,17 @@ do_fingerprint(struct passwd *pw)
|
||||||
*cp++ = '\0';
|
*cp++ = '\0';
|
||||||
}
|
}
|
||||||
ep = cp;
|
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;
|
invalid = 0;
|
||||||
comment = *cp ? cp : comment;
|
comment = *cp ? cp : comment;
|
||||||
printf("%d %s %s\n", BN_num_bits(n),
|
printf("%d %s %s\n", key_size(public),
|
||||||
fingerprint(e, n),
|
key_fingerprint(public),
|
||||||
comment ? comment : "no comment");
|
comment ? comment : "no comment");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
BN_free(e);
|
|
||||||
BN_free(n);
|
|
||||||
fclose(f);
|
fclose(f);
|
||||||
}
|
}
|
||||||
|
key_free(public);
|
||||||
if (invalid) {
|
if (invalid) {
|
||||||
printf("%s is not a valid key file.\n", identity_file);
|
printf("%s is not a valid key file.\n", identity_file);
|
||||||
exit(1);
|
exit(1);
|
||||||
|
|
28
ssh.c
28
ssh.c
|
@ -11,7 +11,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "includes.h"
|
#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/evp.h>
|
||||||
#include <openssl/dsa.h>
|
#include <openssl/dsa.h>
|
||||||
|
@ -253,8 +253,8 @@ main(int ac, char **av)
|
||||||
cp = strrchr(av0, '/') + 1;
|
cp = strrchr(av0, '/') + 1;
|
||||||
else
|
else
|
||||||
cp = av0;
|
cp = av0;
|
||||||
if (strcmp(cp, "rsh") != 0 && strcmp(cp, "ssh") != 0 &&
|
if (strcmp(cp, "rsh") && strcmp(cp, "ssh") && strcmp(cp, "rlogin") &&
|
||||||
strcmp(cp, "rlogin") != 0 && strcmp(cp, "slogin") != 0)
|
strcmp(cp, "slogin") && strcmp(cp, "remsh"))
|
||||||
host = cp;
|
host = cp;
|
||||||
|
|
||||||
for (optind = 1; optind < ac; optind++) {
|
for (optind = 1; optind < ac; optind++) {
|
||||||
|
@ -490,6 +490,9 @@ main(int ac, char **av)
|
||||||
pwcopy.pw_passwd = xstrdup(pw->pw_passwd);
|
pwcopy.pw_passwd = xstrdup(pw->pw_passwd);
|
||||||
pwcopy.pw_uid = pw->pw_uid;
|
pwcopy.pw_uid = pw->pw_uid;
|
||||||
pwcopy.pw_gid = pw->pw_gid;
|
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_dir = xstrdup(pw->pw_dir);
|
||||||
pwcopy.pw_shell = xstrdup(pw->pw_shell);
|
pwcopy.pw_shell = xstrdup(pw->pw_shell);
|
||||||
pw = &pwcopy;
|
pw = &pwcopy;
|
||||||
|
@ -871,7 +874,7 @@ ssh_session(void)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Enter the interactive session. */
|
/* 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
|
void
|
||||||
|
@ -954,9 +957,16 @@ int
|
||||||
ssh_session2(void)
|
ssh_session2(void)
|
||||||
{
|
{
|
||||||
int window, packetmax, id;
|
int window, packetmax, id;
|
||||||
int in = dup(STDIN_FILENO);
|
int in, out, err;
|
||||||
int out = dup(STDOUT_FILENO);
|
|
||||||
int err = dup(STDERR_FILENO);
|
/* 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)
|
if (in < 0 || out < 0 || err < 0)
|
||||||
fatal("dump in/out/err failed");
|
fatal("dump in/out/err failed");
|
||||||
|
@ -972,13 +982,13 @@ ssh_session2(void)
|
||||||
packetmax = window/2;
|
packetmax = window/2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*XXX MAXPACK */
|
||||||
id = channel_new(
|
id = channel_new(
|
||||||
"session", SSH_CHANNEL_OPENING, in, out, err,
|
"session", SSH_CHANNEL_OPENING, in, out, err,
|
||||||
window, packetmax, CHAN_EXTENDED_WRITE, xstrdup("client-session"));
|
window, packetmax, CHAN_EXTENDED_WRITE, xstrdup("client-session"));
|
||||||
|
|
||||||
|
|
||||||
channel_open(id);
|
channel_open(id);
|
||||||
channel_register_callback(id, SSH2_MSG_CHANNEL_OPEN_CONFIRMATION, client_init, (void *)0);
|
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
10
ssh.h
|
@ -13,7 +13,7 @@
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* RCSID("$OpenBSD: ssh.h,v 1.48 2000/07/13 22:53:21 provos Exp $"); */
|
/* RCSID("$OpenBSD: ssh.h,v 1.49 2000/08/19 18:48:11 markus Exp $"); */
|
||||||
|
|
||||||
#ifndef SSH_H
|
#ifndef SSH_H
|
||||||
#define SSH_H
|
#define SSH_H
|
||||||
|
@ -105,7 +105,11 @@
|
||||||
#endif /* SSH_PROGRAM */
|
#endif /* SSH_PROGRAM */
|
||||||
|
|
||||||
#ifndef LOGIN_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 */
|
#endif /* LOGIN_PROGRAM */
|
||||||
|
|
||||||
#ifndef ASKPASS_PROGRAM
|
#ifndef ASKPASS_PROGRAM
|
||||||
|
@ -506,7 +510,7 @@ void server_loop(pid_t pid, int fdin, int fdout, int fderr);
|
||||||
void server_loop2(void);
|
void server_loop2(void);
|
||||||
|
|
||||||
/* Client side main loop for the interactive session. */
|
/* 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). */
|
/* Linked list of custom environment strings (see auth-rsa.c). */
|
||||||
struct envstring {
|
struct envstring {
|
||||||
|
|
|
@ -9,7 +9,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "includes.h"
|
#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/bn.h>
|
||||||
#include <openssl/dsa.h>
|
#include <openssl/dsa.h>
|
||||||
|
@ -44,27 +44,27 @@ extern char *__progname;
|
||||||
int
|
int
|
||||||
try_agent_authentication()
|
try_agent_authentication()
|
||||||
{
|
{
|
||||||
int status, type;
|
int type;
|
||||||
char *comment;
|
char *comment;
|
||||||
AuthenticationConnection *auth;
|
AuthenticationConnection *auth;
|
||||||
unsigned char response[16];
|
unsigned char response[16];
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
BIGNUM *e, *n, *challenge;
|
int plen, clen;
|
||||||
|
Key *key;
|
||||||
|
BIGNUM *challenge;
|
||||||
|
|
||||||
/* Get connection to the agent. */
|
/* Get connection to the agent. */
|
||||||
auth = ssh_get_authentication_connection();
|
auth = ssh_get_authentication_connection();
|
||||||
if (!auth)
|
if (!auth)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
e = BN_new();
|
|
||||||
n = BN_new();
|
|
||||||
challenge = BN_new();
|
challenge = BN_new();
|
||||||
|
key = key_new(KEY_RSA);
|
||||||
|
|
||||||
/* Loop through identities served by the agent. */
|
/* Loop through identities served by the agent. */
|
||||||
for (status = ssh_get_first_identity(auth, e, n, &comment);
|
for (key = ssh_get_first_identity(auth, &comment, 1);
|
||||||
status;
|
key != NULL;
|
||||||
status = ssh_get_next_identity(auth, e, n, &comment)) {
|
key = ssh_get_next_identity(auth, &comment, 1)) {
|
||||||
int plen, clen;
|
|
||||||
|
|
||||||
/* Try this identity. */
|
/* Try this identity. */
|
||||||
debug("Trying RSA authentication via agent with '%.100s'", comment);
|
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. */
|
/* Tell the server that we are willing to authenticate using this key. */
|
||||||
packet_start(SSH_CMSG_AUTH_RSA);
|
packet_start(SSH_CMSG_AUTH_RSA);
|
||||||
packet_put_bignum(n);
|
packet_put_bignum(key->rsa->n);
|
||||||
packet_send();
|
packet_send();
|
||||||
packet_write_wait();
|
packet_write_wait();
|
||||||
|
|
||||||
|
@ -83,6 +83,7 @@ try_agent_authentication()
|
||||||
does not support RSA authentication. */
|
does not support RSA authentication. */
|
||||||
if (type == SSH_SMSG_FAILURE) {
|
if (type == SSH_SMSG_FAILURE) {
|
||||||
debug("Server refused our key.");
|
debug("Server refused our key.");
|
||||||
|
key_free(key);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
/* Otherwise it should have sent a challenge. */
|
/* Otherwise it should have sent a challenge. */
|
||||||
|
@ -97,13 +98,16 @@ try_agent_authentication()
|
||||||
debug("Received RSA challenge from server.");
|
debug("Received RSA challenge from server.");
|
||||||
|
|
||||||
/* Ask the agent to decrypt the challenge. */
|
/* Ask the agent to decrypt the challenge. */
|
||||||
if (!ssh_decrypt_challenge(auth, e, n, challenge,
|
if (!ssh_decrypt_challenge(auth, key, challenge, session_id, 1, response)) {
|
||||||
session_id, 1, response)) {
|
/*
|
||||||
/* The agent failed to authenticate this identifier although it
|
* The agent failed to authenticate this identifier
|
||||||
advertised it supports this. Just return a wrong value. */
|
* although it advertised it supports this. Just
|
||||||
|
* return a wrong value.
|
||||||
|
*/
|
||||||
log("Authentication agent failed to decrypt challenge.");
|
log("Authentication agent failed to decrypt challenge.");
|
||||||
memset(response, 0, sizeof(response));
|
memset(response, 0, sizeof(response));
|
||||||
}
|
}
|
||||||
|
key_free(key);
|
||||||
debug("Sending response to RSA challenge.");
|
debug("Sending response to RSA challenge.");
|
||||||
|
|
||||||
/* Send the decrypted challenge back to the server. */
|
/* Send the decrypted challenge back to the server. */
|
||||||
|
@ -118,10 +122,8 @@ try_agent_authentication()
|
||||||
|
|
||||||
/* The server returns success if it accepted the authentication. */
|
/* The server returns success if it accepted the authentication. */
|
||||||
if (type == SSH_SMSG_SUCCESS) {
|
if (type == SSH_SMSG_SUCCESS) {
|
||||||
debug("RSA authentication accepted by server.");
|
|
||||||
BN_clear_free(e);
|
|
||||||
BN_clear_free(n);
|
|
||||||
BN_clear_free(challenge);
|
BN_clear_free(challenge);
|
||||||
|
debug("RSA authentication accepted by server.");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
/* Otherwise it should return failure. */
|
/* Otherwise it should return failure. */
|
||||||
|
@ -129,11 +131,7 @@ try_agent_authentication()
|
||||||
packet_disconnect("Protocol error waiting RSA auth response: %d",
|
packet_disconnect("Protocol error waiting RSA auth response: %d",
|
||||||
type);
|
type);
|
||||||
}
|
}
|
||||||
|
|
||||||
BN_clear_free(e);
|
|
||||||
BN_clear_free(n);
|
|
||||||
BN_clear_free(challenge);
|
BN_clear_free(challenge);
|
||||||
|
|
||||||
debug("RSA authentication using agent refused.");
|
debug("RSA authentication using agent refused.");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,7 +28,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "includes.h"
|
#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/bn.h>
|
||||||
#include <openssl/rsa.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 "dsa.h"
|
||||||
#include "sshconnect.h"
|
#include "sshconnect.h"
|
||||||
#include "authfile.h"
|
#include "authfile.h"
|
||||||
|
#include "authfd.h"
|
||||||
|
|
||||||
/* import */
|
/* import */
|
||||||
extern char *client_version_string;
|
extern char *client_version_string;
|
||||||
|
@ -291,7 +292,7 @@ typedef int sign_fn(
|
||||||
unsigned char **sigp, int *lenp,
|
unsigned char **sigp, int *lenp,
|
||||||
unsigned char *data, int datalen);
|
unsigned char *data, int datalen);
|
||||||
|
|
||||||
void
|
int
|
||||||
ssh2_sign_and_send_pubkey(Key *k, sign_fn *do_sign,
|
ssh2_sign_and_send_pubkey(Key *k, sign_fn *do_sign,
|
||||||
const char *server_user, const char *host, const char *service)
|
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;
|
unsigned char *blob, *signature;
|
||||||
int bloblen, slen;
|
int bloblen, slen;
|
||||||
int skip = 0;
|
int skip = 0;
|
||||||
|
int ret = -1;
|
||||||
|
|
||||||
dsa_make_key_blob(k, &blob, &bloblen);
|
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);
|
buffer_put_string(&b, blob, bloblen);
|
||||||
|
|
||||||
/* generate signature */
|
/* generate signature */
|
||||||
do_sign(k, &signature, &slen, buffer_ptr(&b), buffer_len(&b));
|
ret = do_sign(k, &signature, &slen, buffer_ptr(&b), buffer_len(&b));
|
||||||
key_free(k); /* XXX */
|
if (ret == -1) {
|
||||||
|
xfree(blob);
|
||||||
|
buffer_free(&b);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
#ifdef DEBUG_DSS
|
#ifdef DEBUG_DSS
|
||||||
buffer_dump(&b);
|
buffer_dump(&b);
|
||||||
#endif
|
#endif
|
||||||
|
@ -357,6 +363,8 @@ ssh2_sign_and_send_pubkey(Key *k, sign_fn *do_sign,
|
||||||
/* send */
|
/* send */
|
||||||
packet_send();
|
packet_send();
|
||||||
packet_write_wait();
|
packet_write_wait();
|
||||||
|
|
||||||
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
|
@ -364,6 +372,7 @@ ssh2_try_pubkey(char *filename,
|
||||||
const char *server_user, const char *host, const char *service)
|
const char *server_user, const char *host, const char *service)
|
||||||
{
|
{
|
||||||
Key *k;
|
Key *k;
|
||||||
|
int ret = 0;
|
||||||
struct stat st;
|
struct stat st;
|
||||||
|
|
||||||
if (stat(filename, &st) != 0) {
|
if (stat(filename, &st) != 0) {
|
||||||
|
@ -389,13 +398,53 @@ ssh2_try_pubkey(char *filename,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ssh2_sign_and_send_pubkey(k, dsa_sign, server_user, host, service);
|
ret = ssh2_sign_and_send_pubkey(k, dsa_sign, server_user, host, service);
|
||||||
return 1;
|
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
|
void
|
||||||
ssh_userauth2(const char *server_user, char *host)
|
ssh_userauth2(const char *server_user, char *host)
|
||||||
{
|
{
|
||||||
|
AuthenticationConnection *ac = ssh_get_authentication_connection();
|
||||||
int type;
|
int type;
|
||||||
int plen;
|
int plen;
|
||||||
int sent;
|
int sent;
|
||||||
|
@ -450,12 +499,17 @@ ssh_userauth2(const char *server_user, char *host)
|
||||||
debug("partial success");
|
debug("partial success");
|
||||||
if (options.dsa_authentication &&
|
if (options.dsa_authentication &&
|
||||||
strstr(auths, "publickey") != NULL) {
|
strstr(auths, "publickey") != NULL) {
|
||||||
while (i < options.num_identity_files2) {
|
if (ac != NULL)
|
||||||
sent = ssh2_try_pubkey(
|
sent = ssh2_try_agent(ac,
|
||||||
options.identity_files2[i++],
|
|
||||||
server_user, host, service);
|
server_user, host, service);
|
||||||
if (sent)
|
if (!sent) {
|
||||||
break;
|
while (i < options.num_identity_files2) {
|
||||||
|
sent = ssh2_try_pubkey(
|
||||||
|
options.identity_files2[i++],
|
||||||
|
server_user, host, service);
|
||||||
|
if (sent)
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!sent) {
|
if (!sent) {
|
||||||
|
@ -469,6 +523,8 @@ ssh_userauth2(const char *server_user, char *host)
|
||||||
fatal("Permission denied (%s).", auths);
|
fatal("Permission denied (%s).", auths);
|
||||||
xfree(auths);
|
xfree(auths);
|
||||||
}
|
}
|
||||||
|
if (ac != NULL)
|
||||||
|
ssh_close_authentication_connection(ac);
|
||||||
packet_done();
|
packet_done();
|
||||||
debug("ssh-userauth2 successfull");
|
debug("ssh-userauth2 successfull");
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue