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