- (djm) Merge OpenBSD changes:

- markus@cvs.openbsd.org  2000/11/06 16:04:56
     [channels.c channels.h clientloop.c nchan.c serverloop.c]
     [session.c ssh.c]
     agent forwarding and -R for ssh2, based on work from
     jhuuskon@messi.uku.fi
   - markus@cvs.openbsd.org  2000/11/06 16:13:27
     [ssh.c sshconnect.c sshd.c]
     do not disabled rhosts(rsa) if server port > 1024; from
     pekkas@netcore.fi
   - markus@cvs.openbsd.org  2000/11/06 16:16:35
     [sshconnect.c]
     downgrade client to 1.3 if server is 1.4; help from mdb@juniper.net
   - markus@cvs.openbsd.org  2000/11/09 18:04:40
     [auth1.c]
     typo; from mouring@pconline.com
   - markus@cvs.openbsd.org  2000/11/12 12:03:28
     [ssh-agent.c]
     off-by-one when removing a key from the agent
   - markus@cvs.openbsd.org  2000/11/12 12:50:39
     [auth-rh-rsa.c auth2.c authfd.c authfd.h]
     [authfile.c hostfile.c kex.c kex.h key.c key.h myproposal.h]
     [readconf.c readconf.h rsa.c rsa.h servconf.c servconf.h ssh-add.c]
     [ssh-agent.c ssh-keygen.1 ssh-keygen.c ssh.1 ssh.c ssh_config]
     [sshconnect1.c sshconnect2.c sshd.8 sshd.c sshd_config ssh-dss.c]
     [ssh-dss.h ssh-rsa.c ssh-rsa.h dsa.c dsa.h]
     add support for RSA to SSH2.  please test.
     there are now 3 types of keys: RSA1 is used by ssh-1 only,
     RSA and DSA are used by SSH2.
     you can use 'ssh-keygen -t rsa -f ssh2_rsa_file' to generate RSA
     keys for SSH2 and use the RSA keys for hostkeys or for user keys.
     SSH2 RSA or DSA keys are added to .ssh/authorised_keys2 as before.
 - (djm) Fix up Makefile and Redhat init script to create RSA host keys
 - (djm) Change to interim version
This commit is contained in:
Damien Miller 2000-11-13 22:57:25 +11:00
parent 559d383037
commit 0bc1bd814e
47 changed files with 1821 additions and 1001 deletions

View File

@ -1,6 +1,39 @@
20001113
- (djm) Add pointer to http://www.imasy.or.jp/~gotoh/connect.c to
contrib/README
- (djm) Merge OpenBSD changes:
- markus@cvs.openbsd.org 2000/11/06 16:04:56
[channels.c channels.h clientloop.c nchan.c serverloop.c]
[session.c ssh.c]
agent forwarding and -R for ssh2, based on work from
jhuuskon@messi.uku.fi
- markus@cvs.openbsd.org 2000/11/06 16:13:27
[ssh.c sshconnect.c sshd.c]
do not disabled rhosts(rsa) if server port > 1024; from
pekkas@netcore.fi
- markus@cvs.openbsd.org 2000/11/06 16:16:35
[sshconnect.c]
downgrade client to 1.3 if server is 1.4; help from mdb@juniper.net
- markus@cvs.openbsd.org 2000/11/09 18:04:40
[auth1.c]
typo; from mouring@pconline.com
- markus@cvs.openbsd.org 2000/11/12 12:03:28
[ssh-agent.c]
off-by-one when removing a key from the agent
- markus@cvs.openbsd.org 2000/11/12 12:50:39
[auth-rh-rsa.c auth2.c authfd.c authfd.h]
[authfile.c hostfile.c kex.c kex.h key.c key.h myproposal.h]
[readconf.c readconf.h rsa.c rsa.h servconf.c servconf.h ssh-add.c]
[ssh-agent.c ssh-keygen.1 ssh-keygen.c ssh.1 ssh.c ssh_config]
[sshconnect1.c sshconnect2.c sshd.8 sshd.c sshd_config ssh-dss.c]
[ssh-dss.h ssh-rsa.c ssh-rsa.h dsa.c dsa.h]
add support for RSA to SSH2. please test.
there are now 3 types of keys: RSA1 is used by ssh-1 only,
RSA and DSA are used by SSH2.
you can use 'ssh-keygen -t rsa -f ssh2_rsa_file' to generate RSA
keys for SSH2 and use the RSA keys for hostkeys or for user keys.
SSH2 RSA or DSA keys are added to .ssh/authorised_keys2 as before.
- (djm) Fix up Makefile and Redhat init script to create RSA host keys
20001112
- (bal) SCO Patch to add needed libraries for configure.in. Patch by

View File

@ -35,7 +35,7 @@ INSTALL_SSH_PRNG_CMDS=@INSTALL_SSH_PRNG_CMDS@
TARGETS=ssh$(EXEEXT) sshd$(EXEEXT) ssh-add$(EXEEXT) ssh-keygen$(EXEEXT) ssh-agent$(EXEEXT) scp$(EXEEXT) sftp-server$(EXEEXT) $(EXTRA_TARGETS)
LIBSSH_OBJS=atomicio.o authfd.o authfile.o bufaux.o buffer.o canohost.o channels.o cipher.o cli.o compat.o compress.o crc32.o cygwin_util.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 rijndael.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 cli.o compat.o compress.o crc32.o cygwin_util.o deattack.o dispatch.o hmac.o hostfile.o key.o kex.o log.o match.o mpaux.o nchan.o packet.o radix.o rijndael.o entropy.o readpass.o rsa.o ssh-dss.o ssh-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-getcwd.o bsd-inet_aton.o bsd-inet_ntoa.o bsd-misc.o bsd-mktemp.o bsd-realpath.o bsd-rresvport.o bsd-setenv.o bsd-sigaction.o bsd-snprintf.o bsd-strlcat.o bsd-strlcpy.o bsd-strsep.o bsd-strtok.o bsd-vis.o bsd-setproctitle.o bsd-waitpid.o fake-getaddrinfo.o fake-getnameinfo.o next-posix.o
@ -179,18 +179,24 @@ host-key: ssh-keygen$(EXEEXT)
if [ -f "$(DESTDIR)$(sysconfdir)/ssh_host_key" ] ; then \
echo "$(DESTDIR)$(sysconfdir)/ssh_host_key already exists, skipping." ; \
else \
$(srcdir)/ssh-keygen -b 1024 -f $(DESTDIR)$(sysconfdir)/ssh_host_key -N "" ; \
$(srcdir)/ssh-keygen -t rsa1 -f $(DESTDIR)$(sysconfdir)/ssh_host_key -N "" ; \
fi ; \
if [ -f $(DESTDIR)$(sysconfdir)/ssh_host_dsa_key ] ; then \
echo "$(DESTDIR)$(sysconfdir)/ssh_host_dsa_key already exists, skipping." ; \
else \
$(srcdir)/ssh-keygen -d -f $(DESTDIR)$(sysconfdir)/ssh_host_dsa_key -N "" ; \
$(srcdir)/ssh-keygen -t dsa -f $(DESTDIR)$(sysconfdir)/ssh_host_dsa_key -N "" ; \
fi ; \
if [ -f $(DESTDIR)$(sysconfdir)/ssh_host_rsa_key ] ; then \
echo "$(DESTDIR)$(sysconfdir)/ssh_host_rsa_key already exists, skipping." ; \
else \
$(srcdir)/ssh-keygen -t rsa -f $(DESTDIR)$(sysconfdir)/ssh_host_rsa_key -N "" ; \
fi ; \
fi ;
host-key-force: ssh-keygen$(EXEEXT)
$(srcdir)/ssh-keygen -b 1024 -f $(DESTDIR)$(sysconfdir)/ssh_host_key -N ""
$(srcdir)/ssh-keygen -d -f $(DESTDIR)$(sysconfdir)/ssh_host_dsa_key -N ""
$(srcdir)/ssh-keygen -t rsa1 -f $(DESTDIR)$(sysconfdir)/ssh_host_key -N ""
$(srcdir)/ssh-keygen -t dsa -f $(DESTDIR)$(sysconfdir)/ssh_host_dsa_key -N ""
$(srcdir)/ssh-keygen -t rsa -f $(DESTDIR)$(sysconfdir)/ssh_host_rsa_key -N ""
uninstallall: uninstall
-rm -f $(DESTDIR)$(sysconfdir)/ssh_config

View File

@ -13,7 +13,7 @@
*/
#include "includes.h"
RCSID("$OpenBSD: auth-rh-rsa.c,v 1.17 2000/10/03 18:03:03 markus Exp $");
RCSID("$OpenBSD: auth-rh-rsa.c,v 1.18 2000/11/12 19:50:37 markus Exp $");
#include "packet.h"
#include "ssh.h"
@ -53,10 +53,10 @@ auth_rhosts_rsa(struct passwd *pw, const char *client_user, RSA *client_host_key
debug("Rhosts RSA authentication: canonical host %.900s", canonical_hostname);
/* wrap the RSA key into a 'generic' key */
client_key = key_new(KEY_RSA);
client_key = key_new(KEY_RSA1);
BN_copy(client_key->rsa->e, client_host_key->e);
BN_copy(client_key->rsa->n, client_host_key->n);
found = key_new(KEY_RSA);
found = key_new(KEY_RSA1);
/* Check if we know the host and its host key. */
host_status = check_host_in_hostfile(SSH_SYSTEM_HOSTFILE, canonical_hostname,

View File

@ -10,7 +10,7 @@
*/
#include "includes.h"
RCSID("$OpenBSD: auth1.c,v 1.6 2000/10/11 20:27:23 markus Exp $");
RCSID("$OpenBSD: auth1.c,v 1.7 2000/11/10 01:04:40 markus Exp $");
#ifdef HAVE_OSF_SIA
# include <sia.h>

38
auth2.c
View File

@ -23,7 +23,7 @@
*/
#include "includes.h"
RCSID("$OpenBSD: auth2.c,v 1.20 2000/10/14 12:16:56 markus Exp $");
RCSID("$OpenBSD: auth2.c,v 1.21 2000/11/12 19:50:37 markus Exp $");
#ifdef HAVE_OSF_SIA
# include <sia.h>
@ -52,7 +52,6 @@ RCSID("$OpenBSD: auth2.c,v 1.20 2000/10/14 12:16:56 markus Exp $");
#include "key.h"
#include "kex.h"
#include "dsa.h"
#include "uidswap.h"
#include "auth-options.h"
@ -89,7 +88,7 @@ void protocol_error(int type, int plen, void *ctxt);
/* helper */
Authmethod *authmethod_lookup(const char *name);
struct passwd *pwcopy(struct passwd *pw);
int user_dsa_key_allowed(struct passwd *pw, Key *key);
int user_key_allowed(struct passwd *pw, Key *key);
char *authmethods_get(void);
/* auth */
@ -104,7 +103,7 @@ Authmethod authmethods[] = {
&one},
{"publickey",
userauth_pubkey,
&options.dsa_authentication},
&options.pubkey_authentication},
{"keyboard-interactive",
userauth_kbdint,
&options.kbd_interactive_authentication},
@ -422,7 +421,7 @@ userauth_pubkey(Authctxt *authctxt)
Key *key;
char *pkalg, *pkblob, *sig;
unsigned int alen, blen, slen;
int have_sig;
int have_sig, pktype;
int authenticated = 0;
if (!authctxt->valid) {
@ -431,13 +430,14 @@ userauth_pubkey(Authctxt *authctxt)
}
have_sig = packet_get_char();
pkalg = packet_get_string(&alen);
if (strcmp(pkalg, KEX_DSS) != 0) {
log("bad pkalg %s", pkalg); /*XXX*/
pktype = key_type_from_name(pkalg);
if (pktype == KEY_UNSPEC) {
log("bad pkalg %s", pkalg);
xfree(pkalg);
return 0;
}
pkblob = packet_get_string(&blen);
key = dsa_key_from_blob(pkblob, blen);
key = key_from_blob(pkblob, blen);
if (key != NULL) {
if (have_sig) {
sig = packet_get_string(&slen);
@ -457,14 +457,14 @@ userauth_pubkey(Authctxt *authctxt)
authctxt->service);
buffer_put_cstring(&b, "publickey");
buffer_put_char(&b, have_sig);
buffer_put_cstring(&b, KEX_DSS);
buffer_put_cstring(&b, key_ssh_name(key));
buffer_put_string(&b, pkblob, blen);
#ifdef DEBUG_DSS
#ifdef DEBUG_PK
buffer_dump(&b);
#endif
/* test for correct signature */
if (user_dsa_key_allowed(authctxt->pw, key) &&
dsa_verify(key, sig, slen, buffer_ptr(&b), buffer_len(&b)) == 1)
if (user_key_allowed(authctxt->pw, key) &&
key_verify(key, sig, slen, buffer_ptr(&b), buffer_len(&b)) == 1)
authenticated = 1;
buffer_clear(&b);
xfree(sig);
@ -480,7 +480,7 @@ userauth_pubkey(Authctxt *authctxt)
* if a user is not allowed to login. is this an
* issue? -markus
*/
if (user_dsa_key_allowed(authctxt->pw, key)) {
if (user_key_allowed(authctxt->pw, key)) {
packet_start(SSH2_MSG_USERAUTH_PK_OK);
packet_put_string(pkalg, alen);
packet_put_string(pkblob, blen);
@ -493,6 +493,7 @@ userauth_pubkey(Authctxt *authctxt)
auth_clear_options();
key_free(key);
}
debug2("userauth_pubkey: authenticated %d pkalg %s", authenticated, pkalg);
xfree(pkalg);
xfree(pkblob);
#ifdef HAVE_CYGWIN
@ -560,11 +561,10 @@ authmethod_lookup(const char *name)
/* return 1 if user allows given key */
int
user_dsa_key_allowed(struct passwd *pw, Key *key)
user_key_allowed(struct passwd *pw, Key *key)
{
char line[8192], file[1024];
int found_key = 0;
unsigned int bits = -1;
FILE *f;
unsigned long linenum = 0;
struct stat st;
@ -645,10 +645,10 @@ user_dsa_key_allowed(struct passwd *pw, Key *key)
if (!*cp || *cp == '\n' || *cp == '#')
continue;
bits = key_read(found, &cp);
if (bits == 0) {
if (key_read(found, &cp) == -1) {
/* no key? check if there are options for this key */
int quoted = 0;
debug2("user_key_allowed: check options: '%s'", cp);
options = cp;
for (; *cp && (quoted || (*cp != ' ' && *cp != '\t')); cp++) {
if (*cp == '\\' && cp[1] == '"')
@ -659,8 +659,8 @@ user_dsa_key_allowed(struct passwd *pw, Key *key)
/* Skip remaining whitespace. */
for (; *cp == ' ' || *cp == '\t'; cp++)
;
bits = key_read(found, &cp);
if (bits == 0) {
if (key_read(found, &cp) == -1) {
debug2("user_key_allowed: advance: '%s'", cp);
/* still no key? advance to next line*/
continue;
}

View File

@ -35,7 +35,7 @@
*/
#include "includes.h"
RCSID("$OpenBSD: authfd.c,v 1.29 2000/10/09 21:51:00 markus Exp $");
RCSID("$OpenBSD: authfd.c,v 1.30 2000/11/12 19:50:37 markus Exp $");
#include "ssh.h"
#include "rsa.h"
@ -50,7 +50,6 @@ RCSID("$OpenBSD: authfd.c,v 1.29 2000/10/09 21:51:00 markus Exp $");
#include "key.h"
#include "authfd.h"
#include "kex.h"
#include "dsa.h"
#include "compat.h"
/* helper */
@ -211,8 +210,8 @@ ssh_close_authentication_connection(AuthenticationConnection *auth)
* Returns the first authentication identity held by the agent.
*/
Key *
ssh_get_first_identity(AuthenticationConnection *auth, char **comment, int version)
int
ssh_get_num_identities(AuthenticationConnection *auth, int version)
{
int type, code1 = 0, code2 = 0;
Buffer request;
@ -227,7 +226,7 @@ ssh_get_first_identity(AuthenticationConnection *auth, char **comment, int versi
code2 = SSH2_AGENT_IDENTITIES_ANSWER;
break;
default:
return NULL;
return 0;
}
/*
@ -240,14 +239,14 @@ ssh_get_first_identity(AuthenticationConnection *auth, char **comment, int versi
buffer_clear(&auth->identities);
if (ssh_request_reply(auth, &request, &auth->identities) == 0) {
buffer_free(&request);
return NULL;
return 0;
}
buffer_free(&request);
/* Get message type, and verify that we got a proper answer. */
type = buffer_get_char(&auth->identities);
if (agent_failed(type)) {
return NULL;
return 0;
} else if (type != code2) {
fatal("Bad authentication reply message type: %d", type);
}
@ -258,8 +257,16 @@ ssh_get_first_identity(AuthenticationConnection *auth, char **comment, int versi
fatal("Too many identities in authentication reply: %d\n",
auth->howmany);
/* Return the first entry (if any). */
return ssh_get_next_identity(auth, comment, version);
return auth->howmany;
}
Key *
ssh_get_first_identity(AuthenticationConnection *auth, char **comment, int version)
{
/* get number of identities and return the first entry (if any). */
if (ssh_get_num_identities(auth, version) > 0)
return ssh_get_next_identity(auth, comment, version);
return NULL;
}
Key *
@ -280,7 +287,7 @@ ssh_get_next_identity(AuthenticationConnection *auth, char **comment, int versio
*/
switch(version){
case 1:
key = key_new(KEY_RSA);
key = key_new(KEY_RSA1);
bits = buffer_get_int(&auth->identities);
buffer_get_bignum(&auth->identities, key->rsa->e);
buffer_get_bignum(&auth->identities, key->rsa->n);
@ -292,7 +299,7 @@ ssh_get_next_identity(AuthenticationConnection *auth, char **comment, int versio
case 2:
blob = buffer_get_string(&auth->identities, &blen);
*comment = buffer_get_string(&auth->identities, NULL);
key = dsa_key_from_blob(blob, blen);
key = key_from_blob(blob, blen);
xfree(blob);
break;
default:
@ -324,7 +331,7 @@ ssh_decrypt_challenge(AuthenticationConnection *auth,
int i;
int type;
if (key->type != KEY_RSA)
if (key->type != KEY_RSA1)
return 0;
if (response_type == 0) {
log("Compatibility with ssh protocol version 1.0 no longer supported.");
@ -376,7 +383,7 @@ ssh_agent_sign(AuthenticationConnection *auth,
int type, flags = 0;
int ret = -1;
if (dsa_make_key_blob(key, &blob, &blen) == 0)
if (key_to_blob(key, &blob, &blen) == 0)
return -1;
if (datafellows & SSH_BUG_SIGBLOB)
@ -409,7 +416,7 @@ ssh_agent_sign(AuthenticationConnection *auth,
/* Encode key for a message to the agent. */
void
ssh_encode_identity_rsa(Buffer *b, RSA *key, const char *comment)
ssh_encode_identity_rsa1(Buffer *b, RSA *key, const char *comment)
{
buffer_clear(b);
buffer_put_char(b, SSH_AGENTC_ADD_RSA_IDENTITY);
@ -425,17 +432,29 @@ ssh_encode_identity_rsa(Buffer *b, RSA *key, const char *comment)
}
void
ssh_encode_identity_dsa(Buffer *b, DSA *key, const char *comment)
ssh_encode_identity_ssh2(Buffer *b, Key *key, const char *comment)
{
buffer_clear(b);
buffer_put_char(b, SSH2_AGENTC_ADD_IDENTITY);
buffer_put_cstring(b, KEX_DSS);
buffer_put_bignum2(b, key->p);
buffer_put_bignum2(b, key->q);
buffer_put_bignum2(b, key->g);
buffer_put_bignum2(b, key->pub_key);
buffer_put_bignum2(b, key->priv_key);
buffer_put_string(b, comment, strlen(comment));
buffer_put_cstring(b, key_ssh_name(key));
switch(key->type){
case KEY_RSA:
buffer_put_bignum2(b, key->rsa->n);
buffer_put_bignum2(b, key->rsa->e);
buffer_put_bignum2(b, key->rsa->d);
buffer_put_bignum2(b, key->rsa->iqmp);
buffer_put_bignum2(b, key->rsa->p);
buffer_put_bignum2(b, key->rsa->q);
break;
case KEY_DSA:
buffer_put_bignum2(b, key->dsa->p);
buffer_put_bignum2(b, key->dsa->q);
buffer_put_bignum2(b, key->dsa->g);
buffer_put_bignum2(b, key->dsa->pub_key);
buffer_put_bignum2(b, key->dsa->priv_key);
break;
}
buffer_put_cstring(b, comment);
}
/*
@ -452,11 +471,12 @@ ssh_add_identity(AuthenticationConnection *auth, Key *key, const char *comment)
buffer_init(&msg);
switch (key->type) {
case KEY_RSA:
ssh_encode_identity_rsa(&msg, key->rsa, comment);
case KEY_RSA1:
ssh_encode_identity_rsa1(&msg, key->rsa, comment);
break;
case KEY_RSA:
case KEY_DSA:
ssh_encode_identity_dsa(&msg, key->dsa, comment);
ssh_encode_identity_ssh2(&msg, key, comment);
break;
default:
buffer_free(&msg);
@ -487,13 +507,13 @@ ssh_remove_identity(AuthenticationConnection *auth, Key *key)
buffer_init(&msg);
if (key->type == KEY_RSA) {
if (key->type == KEY_RSA1) {
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);
} else if (key->type == KEY_DSA || key->type == KEY_RSA) {
key_to_blob(key, &blob, &blen);
buffer_put_char(&msg, SSH2_AGENTC_REMOVE_IDENTITY);
buffer_put_string(&msg, blob, blen);
xfree(blob);

View File

@ -11,7 +11,7 @@
* called by a name other than "ssh" or "Secure Shell".
*/
/* RCSID("$OpenBSD: authfd.h,v 1.13 2000/10/09 21:51:00 markus Exp $"); */
/* RCSID("$OpenBSD: authfd.h,v 1.14 2000/11/12 19:50:37 markus Exp $"); */
#ifndef AUTHFD_H
#define AUTHFD_H
@ -74,6 +74,11 @@ AuthenticationConnection *ssh_get_authentication_connection();
*/
void ssh_close_authentication_connection(AuthenticationConnection *auth);
/*
* Returns the number authentication identity held by the agent.
*/
int ssh_get_num_identities(AuthenticationConnection *auth, int version);
/*
* Returns the first authentication identity held by the agent or NULL if
* no identies are available. Caller must free comment and key.

View File

@ -36,11 +36,12 @@
*/
#include "includes.h"
RCSID("$OpenBSD: authfile.c,v 1.20 2000/10/11 20:27:23 markus Exp $");
RCSID("$OpenBSD: authfile.c,v 1.21 2000/11/12 19:50:37 markus Exp $");
#include <openssl/bn.h>
#include <openssl/dsa.h>
#include <openssl/rsa.h>
#include <openssl/err.h>
#include <openssl/pem.h>
#include <openssl/evp.h>
@ -61,7 +62,7 @@ RCSID("$OpenBSD: authfile.c,v 1.20 2000/10/11 20:27:23 markus Exp $");
*/
int
save_private_key_rsa(const char *filename, const char *passphrase,
save_private_key_rsa1(const char *filename, const char *passphrase,
RSA *key, const char *comment)
{
Buffer buffer, encrypted;
@ -155,16 +156,17 @@ save_private_key_rsa(const char *filename, const char *passphrase,
return 1;
}
/* save DSA key in OpenSSL PEM format */
/* save SSH2 key in OpenSSL PEM format */
int
save_private_key_dsa(const char *filename, const char *passphrase,
DSA *dsa, const char *comment)
save_private_key_ssh2(const char *filename, const char *_passphrase,
Key *key, const char *comment)
{
FILE *fp;
int fd;
int success = 1;
int len = strlen(passphrase);
int success = 0;
int len = strlen(_passphrase);
char *passphrase = (len > 0) ? (char *)_passphrase : NULL;
EVP_CIPHER *cipher = (len > 0) ? EVP_des_ede3_cbc() : NULL;
if (len > 0 && len <= 4) {
error("passphrase too short: %d bytes", len);
@ -182,14 +184,15 @@ save_private_key_dsa(const char *filename, const char *passphrase,
close(fd);
return 0;
}
if (len > 0) {
if (!PEM_write_DSAPrivateKey(fp, dsa, EVP_des_ede3_cbc(),
(char *)passphrase, strlen(passphrase), NULL, NULL))
success = 0;
} else {
if (!PEM_write_DSAPrivateKey(fp, dsa, NULL,
NULL, 0, NULL, NULL))
success = 0;
switch (key->type) {
case KEY_DSA:
success = PEM_write_DSAPrivateKey(fp, key->dsa,
cipher, passphrase, len, NULL, NULL);
break;
case KEY_RSA:
success = PEM_write_RSAPrivateKey(fp, key->rsa,
cipher, passphrase, len, NULL, NULL);
break;
}
fclose(fp);
return success;
@ -200,11 +203,12 @@ save_private_key(const char *filename, const char *passphrase, Key *key,
const char *comment)
{
switch (key->type) {
case KEY_RSA:
return save_private_key_rsa(filename, passphrase, key->rsa, comment);
case KEY_RSA1:
return save_private_key_rsa1(filename, passphrase, key->rsa, comment);
break;
case KEY_DSA:
return save_private_key_dsa(filename, passphrase, key->dsa, comment);
case KEY_RSA:
return save_private_key_ssh2(filename, passphrase, key, comment);
break;
default:
break;
@ -246,7 +250,7 @@ load_public_key_rsa(const char *filename, RSA * pub, char **comment_return)
/* Check that it is at least big enought to contain the ID string. */
if (len < strlen(AUTHFILE_ID_STRING) + 1) {
debug("Bad key file %.200s.", filename);
debug3("Bad RSA1 key file %.200s.", filename);
buffer_free(&buffer);
return 0;
}
@ -256,7 +260,7 @@ load_public_key_rsa(const char *filename, RSA * pub, char **comment_return)
*/
for (i = 0; i < (unsigned int) strlen(AUTHFILE_ID_STRING) + 1; i++)
if (buffer_get_char(&buffer) != (u_char) AUTHFILE_ID_STRING[i]) {
debug("Bad key file %.200s.", filename);
debug3("Bad RSA1 key file %.200s.", filename);
buffer_free(&buffer);
return 0;
}
@ -288,10 +292,11 @@ int
load_public_key(const char *filename, Key * key, char **comment_return)
{
switch (key->type) {
case KEY_RSA:
case KEY_RSA1:
return load_public_key_rsa(filename, key->rsa, comment_return);
break;
case KEY_DSA:
case KEY_RSA:
default:
break;
}
@ -306,7 +311,7 @@ load_public_key(const char *filename, Key * key, char **comment_return)
*/
int
load_private_key_rsa(int fd, const char *filename,
load_private_key_rsa1(int fd, const char *filename,
const char *passphrase, RSA * prv, char **comment_return)
{
int i, check1, check2, cipher_type;
@ -326,7 +331,7 @@ load_private_key_rsa(int fd, const char *filename,
if (read(fd, cp, (size_t) len) != (size_t) len) {
debug("Read from key file %.200s failed: %.100s", filename,
strerror(errno));
strerror(errno));
buffer_free(&buffer);
close(fd);
return 0;
@ -335,7 +340,7 @@ load_private_key_rsa(int fd, const char *filename,
/* Check that it is at least big enought to contain the ID string. */
if (len < strlen(AUTHFILE_ID_STRING) + 1) {
debug("Bad key file %.200s.", filename);
debug3("Bad RSA1 key file %.200s.", filename);
buffer_free(&buffer);
return 0;
}
@ -344,8 +349,8 @@ load_private_key_rsa(int fd, const char *filename,
* from the buffer.
*/
for (i = 0; i < (unsigned int) strlen(AUTHFILE_ID_STRING) + 1; i++)
if (buffer_get_char(&buffer) != (unsigned char) AUTHFILE_ID_STRING[i]) {
debug("Bad key file %.200s.", filename);
if (buffer_get_char(&buffer) != (u_char) AUTHFILE_ID_STRING[i]) {
debug3("Bad RSA1 key file %.200s.", filename);
buffer_free(&buffer);
return 0;
}
@ -431,40 +436,59 @@ fail:
}
int
load_private_key_dsa(int fd, const char *passphrase, Key *k, char **comment_return)
load_private_key_ssh2(int fd, const char *passphrase, Key *k, char **comment_return)
{
DSA *dsa;
BIO *in;
FILE *fp;
int success = 0;
EVP_PKEY *pk = NULL;
char *name = "<no key>";
in = BIO_new(BIO_s_file());
if (in == NULL) {
error("BIO_new failed");
return 0;
}
fp = fdopen(fd, "r");
if (fp == NULL) {
error("fdopen failed");
return 0;
}
BIO_set_fp(in, fp, BIO_NOCLOSE);
dsa = PEM_read_bio_DSAPrivateKey(in, NULL, NULL, (char *)passphrase);
if (dsa == NULL) {
debug("PEM_read_bio_DSAPrivateKey failed");
} else {
/* replace k->dsa with loaded key */
DSA_free(k->dsa);
k->dsa = dsa;
}
BIO_free(in);
fclose(fp);
if (comment_return)
*comment_return = xstrdup("dsa w/o comment");
debug("read DSA private key done");
#ifdef DEBUG_DSS
DSA_print_fp(stderr, dsa, 8);
pk = PEM_read_PrivateKey(fp, NULL, NULL, (char *)passphrase);
if (pk == NULL) {
debug("PEM_read_PrivateKey failed");
(void)ERR_get_error();
} else if (pk->type == EVP_PKEY_RSA) {
/* replace k->rsa with loaded key */
if (k->type == KEY_RSA || k->type == KEY_UNSPEC) {
if (k->rsa != NULL)
RSA_free(k->rsa);
k->rsa = EVP_PKEY_get1_RSA(pk);
k->type = KEY_RSA;
name = "rsa w/o comment";
success = 1;
#ifdef DEBUG_PK
RSA_print_fp(stderr, k->rsa, 8);
#endif
return dsa != NULL ? 1 : 0;
}
} else if (pk->type == EVP_PKEY_DSA) {
/* replace k->dsa with loaded key */
if (k->type == KEY_DSA || k->type == KEY_UNSPEC) {
if (k->dsa != NULL)
DSA_free(k->dsa);
k->dsa = EVP_PKEY_get1_DSA(pk);
k->type = KEY_DSA;
name = "dsa w/o comment";
#ifdef DEBUG_PK
DSA_print_fp(stderr, k->dsa, 8);
#endif
success = 1;
}
} else {
error("PEM_read_PrivateKey: mismatch or "
"unknown EVP_PKEY save_type %d", pk->save_type);
}
fclose(fp);
if (pk != NULL)
EVP_PKEY_free(pk);
if (success && comment_return)
*comment_return = xstrdup(name);
debug("read SSH2 private key done: name %s success %d", name, success);
return success;
}
int
@ -496,7 +520,7 @@ load_private_key(const char *filename, const char *passphrase, Key *key,
return 0;
}
switch (key->type) {
case KEY_RSA:
case KEY_RSA1:
if (key->rsa->e != NULL) {
BN_clear_free(key->rsa->e);
key->rsa->e = NULL;
@ -505,11 +529,13 @@ load_private_key(const char *filename, const char *passphrase, Key *key,
BN_clear_free(key->rsa->n);
key->rsa->n = NULL;
}
ret = load_private_key_rsa(fd, filename, passphrase,
ret = load_private_key_rsa1(fd, filename, passphrase,
key->rsa, comment_return);
break;
case KEY_DSA:
ret = load_private_key_dsa(fd, passphrase, key, comment_return);
case KEY_RSA:
case KEY_UNSPEC:
ret = load_private_key_ssh2(fd, passphrase, key, comment_return);
default:
break;
}
@ -521,7 +547,6 @@ int
do_load_public_key(const char *filename, Key *k, char **commentp)
{
FILE *f;
unsigned int bits;
char line[1024];
char *cp;
@ -540,8 +565,7 @@ do_load_public_key(const char *filename, Key *k, char **commentp)
for (; *cp && (*cp == ' ' || *cp == '\t'); cp++)
;
if (*cp) {
bits = key_read(k, &cp);
if (bits != 0) {
if (key_read(k, &cp) == 1) {
if (commentp)
*commentp=xstrdup(filename);
fclose(f);

View File

@ -40,7 +40,7 @@
*/
#include "includes.h"
RCSID("$OpenBSD: channels.c,v 1.72 2000/10/27 07:48:22 markus Exp $");
RCSID("$OpenBSD: channels.c,v 1.73 2000/11/06 23:04:55 markus Exp $");
#include "ssh.h"
#include "packet.h"
@ -588,9 +588,12 @@ channel_post_port_listener(Channel *c, fd_set * readset, fd_set * writeset)
struct sockaddr addr;
int newsock, newch;
socklen_t addrlen;
char buf[1024], *remote_hostname;
char buf[1024], *remote_hostname, *rtype;
int remote_port;
rtype = (c->type == SSH_CHANNEL_RPORT_LISTENER) ?
"forwarded-tcpip" : "direct-tcpip";
if (FD_ISSET(c->sock, readset)) {
debug("Connection to port %d forwarding "
"to %.100s port %d requested.",
@ -608,19 +611,26 @@ channel_post_port_listener(Channel *c, fd_set * readset, fd_set * writeset)
"connect from %.200s port %d",
c->listening_port, c->path, c->host_port,
remote_hostname, remote_port);
newch = channel_new("direct-tcpip",
newch = channel_new(rtype,
SSH_CHANNEL_OPENING, newsock, newsock, -1,
c->local_window_max, c->local_maxpacket,
0, xstrdup(buf), 1);
if (compat20) {
packet_start(SSH2_MSG_CHANNEL_OPEN);
packet_put_cstring("direct-tcpip");
packet_put_cstring(rtype);
packet_put_int(newch);
packet_put_int(c->local_window_max);
packet_put_int(c->local_maxpacket);
/* target host and port */
packet_put_string(c->path, strlen(c->path));
packet_put_int(c->host_port);
if (c->type == SSH_CHANNEL_RPORT_LISTENER) {
/* listen address, port */
packet_put_string(c->path, strlen(c->path));
packet_put_int(c->listening_port);
} else {
/* target host, port */
packet_put_string(c->path, strlen(c->path));
packet_put_int(c->host_port);
}
/* originator host and port */
packet_put_cstring(remote_hostname);
packet_put_int(remote_port);
@ -657,10 +667,20 @@ channel_post_auth_listener(Channel *c, fd_set * readset, fd_set * writeset)
error("accept from auth socket: %.100s", strerror(errno));
return;
}
newch = channel_allocate(SSH_CHANNEL_OPENING, newsock,
xstrdup("accepted auth socket"));
packet_start(SSH_SMSG_AGENT_OPEN);
packet_put_int(newch);
newch = channel_new("accepted auth socket",
SSH_CHANNEL_OPENING, newsock, newsock, -1,
c->local_window_max, c->local_maxpacket,
0, xstrdup("accepted auth socket"), 1);
if (compat20) {
packet_start(SSH2_MSG_CHANNEL_OPEN);
packet_put_cstring("auth-agent@openssh.com");
packet_put_int(newch);
packet_put_int(c->local_window_max);
packet_put_int(c->local_maxpacket);
} else {
packet_start(SSH_SMSG_AGENT_OPEN);
packet_put_int(newch);
}
packet_send();
}
}
@ -820,11 +840,15 @@ channel_handler_init_20(void)
channel_pre[SSH_CHANNEL_OPEN] = &channel_pre_open_20;
channel_pre[SSH_CHANNEL_X11_OPEN] = &channel_pre_x11_open;
channel_pre[SSH_CHANNEL_PORT_LISTENER] = &channel_pre_listener;
channel_pre[SSH_CHANNEL_RPORT_LISTENER] = &channel_pre_listener;
channel_pre[SSH_CHANNEL_X11_LISTENER] = &channel_pre_listener;
channel_pre[SSH_CHANNEL_AUTH_SOCKET] = &channel_pre_listener;
channel_post[SSH_CHANNEL_OPEN] = &channel_post_open_2;
channel_post[SSH_CHANNEL_PORT_LISTENER] = &channel_post_port_listener;
channel_post[SSH_CHANNEL_RPORT_LISTENER] = &channel_post_port_listener;
channel_post[SSH_CHANNEL_X11_LISTENER] = &channel_post_x11_listener;
channel_post[SSH_CHANNEL_AUTH_SOCKET] = &channel_post_auth_listener;
}
void
@ -1326,6 +1350,7 @@ channel_stop_listening()
channel_free(i);
break;
case SSH_CHANNEL_PORT_LISTENER:
case SSH_CHANNEL_RPORT_LISTENER:
case SSH_CHANNEL_X11_LISTENER:
close(channels[i].sock);
channel_free(i);
@ -1369,6 +1394,7 @@ channel_still_open()
case SSH_CHANNEL_FREE:
case SSH_CHANNEL_X11_LISTENER:
case SSH_CHANNEL_PORT_LISTENER:
case SSH_CHANNEL_RPORT_LISTENER:
case SSH_CHANNEL_CLOSED:
case SSH_CHANNEL_AUTH_SOCKET:
continue;
@ -1414,6 +1440,7 @@ channel_open_message()
case SSH_CHANNEL_FREE:
case SSH_CHANNEL_X11_LISTENER:
case SSH_CHANNEL_PORT_LISTENER:
case SSH_CHANNEL_RPORT_LISTENER:
case SSH_CHANNEL_CLOSED:
case SSH_CHANNEL_AUTH_SOCKET:
continue;
@ -1446,19 +1473,44 @@ channel_open_message()
* Initiate forwarding of connections to local port "port" through the secure
* channel to host:port from remote side.
*/
void
channel_request_local_forwarding(u_short port, const char *host,
u_short host_port, int gateway_ports)
channel_request_local_forwarding(u_short listen_port, const char *host_to_connect,
u_short port_to_connect, int gateway_ports)
{
int success, ch, sock, on = 1;
channel_request_forwarding(
NULL, listen_port,
host_to_connect, port_to_connect,
gateway_ports, /*remote_fwd*/ 0);
}
/*
* If 'remote_fwd' is true we have a '-R style' listener for protocol 2
* (SSH_CHANNEL_RPORT_LISTENER).
*/
void
channel_request_forwarding(
const char *listen_address, u_short listen_port,
const char *host_to_connect, u_short port_to_connect,
int gateway_ports, int remote_fwd)
{
int success, ch, sock, on = 1, ctype;
struct addrinfo hints, *ai, *aitop;
char ntop[NI_MAXHOST], strport[NI_MAXSERV];
const char *host;
struct linger linger;
if (remote_fwd) {
host = listen_address;
ctype = SSH_CHANNEL_RPORT_LISTENER;
} else {
host = host_to_connect;
ctype =SSH_CHANNEL_PORT_LISTENER;
}
if (strlen(host) > sizeof(channels[0].path) - 1)
packet_disconnect("Forward host name too long.");
/* XXX listen_address is currently ignored */
/*
* getaddrinfo returns a loopback address if the hostname is
* set to NULL and hints.ai_flags is not AI_PASSIVE
@ -1467,7 +1519,7 @@ channel_request_local_forwarding(u_short port, const char *host,
hints.ai_family = IPv4or6;
hints.ai_flags = gateway_ports ? AI_PASSIVE : 0;
hints.ai_socktype = SOCK_STREAM;
snprintf(strport, sizeof strport, "%d", port);
snprintf(strport, sizeof strport, "%d", listen_port);
if (getaddrinfo(NULL, strport, &hints, &aitop) != 0)
packet_disconnect("getaddrinfo: fatal error");
@ -1477,7 +1529,7 @@ channel_request_local_forwarding(u_short port, const char *host,
continue;
if (getnameinfo(ai->ai_addr, ai->ai_addrlen, ntop, sizeof(ntop),
strport, sizeof(strport), NI_NUMERICHOST|NI_NUMERICSERV) != 0) {
error("channel_request_local_forwarding: getnameinfo failed");
error("channel_request_forwarding: getnameinfo failed");
continue;
}
/* Create a port to listen for the host. */
@ -1515,18 +1567,16 @@ channel_request_local_forwarding(u_short port, const char *host,
continue;
}
/* Allocate a channel number for the socket. */
ch = channel_new(
"port listener", SSH_CHANNEL_PORT_LISTENER,
sock, sock, -1,
ch = channel_new("port listener", ctype, sock, sock, -1,
CHAN_TCP_WINDOW_DEFAULT, CHAN_TCP_PACKET_DEFAULT,
0, xstrdup("port listener"), 1);
strlcpy(channels[ch].path, host, sizeof(channels[ch].path));
channels[ch].host_port = host_port;
channels[ch].listening_port = port;
channels[ch].host_port = port_to_connect;
channels[ch].listening_port = listen_port;
success = 1;
}
if (success == 0)
packet_disconnect("cannot listen port: %d", port);
packet_disconnect("cannot listen port: %d", listen_port); /*XXX ?disconnect? */
freeaddrinfo(aitop);
}
@ -1536,19 +1586,15 @@ channel_request_local_forwarding(u_short port, const char *host,
*/
void
channel_request_remote_forwarding(u_short listen_port, const char *host_to_connect,
u_short port_to_connect)
channel_request_remote_forwarding(u_short listen_port,
const char *host_to_connect, u_short port_to_connect)
{
int payload_len;
int payload_len, type, success = 0;
/* Record locally that connection to this host/port is permitted. */
if (num_permitted_opens >= SSH_MAX_FORWARDS_PER_DIRECTION)
fatal("channel_request_remote_forwarding: too many forwards");
permitted_opens[num_permitted_opens].host_to_connect = xstrdup(host_to_connect);
permitted_opens[num_permitted_opens].port_to_connect = port_to_connect;
permitted_opens[num_permitted_opens].listen_port = listen_port;
num_permitted_opens++;
/* Send the forward request to the remote side. */
if (compat20) {
const char *address_to_bind = "0.0.0.0";
@ -1557,6 +1603,10 @@ channel_request_remote_forwarding(u_short listen_port, const char *host_to_conne
packet_put_char(0); /* boolean: want reply */
packet_put_cstring(address_to_bind);
packet_put_int(listen_port);
packet_send();
packet_write_wait();
/* Assume that server accepts the request */
success = 1;
} else {
packet_start(SSH_CMSG_PORT_FORWARD_REQUEST);
packet_put_int(listen_port);
@ -1564,11 +1614,27 @@ channel_request_remote_forwarding(u_short listen_port, const char *host_to_conne
packet_put_int(port_to_connect);
packet_send();
packet_write_wait();
/*
* Wait for response from the remote side. It will send a disconnect
* message on failure, and we will never see it here.
*/
packet_read_expect(&payload_len, SSH_SMSG_SUCCESS);
/* Wait for response from the remote side. */
type = packet_read(&payload_len);
switch (type) {
case SSH_SMSG_SUCCESS:
success = 1;
break;
case SSH_SMSG_FAILURE:
log("Warning: Server denied remote port forwarding.");
break;
default:
/* Unknown packet */
packet_disconnect("Protocol error for port forward request:"
"received packet type %d.", type);
}
}
if (success) {
permitted_opens[num_permitted_opens].host_to_connect = xstrdup(host_to_connect);
permitted_opens[num_permitted_opens].port_to_connect = port_to_connect;
permitted_opens[num_permitted_opens].listen_port = listen_port;
num_permitted_opens++;
}
}
@ -1598,9 +1664,7 @@ channel_input_port_forward_request(int is_root, int gateway_ports)
packet_disconnect("Requested forwarding of port %d but user is not root.",
port);
#endif
/*
* Initiate forwarding,
*/
/* Initiate forwarding */
channel_request_local_forwarding(port, hostname, host_port, gateway_ports);
/* Free the argument string. */
@ -1656,6 +1720,18 @@ channel_connect_to(const char *host, u_short host_port)
/* success */
return sock;
}
int
channel_connect_by_listen_adress(u_short listen_port)
{
int i;
for (i = 0; i < num_permitted_opens; i++)
if (permitted_opens[i].listen_port == listen_port)
return channel_connect_to(
permitted_opens[i].host_to_connect,
permitted_opens[i].port_to_connect);
debug("channel_connect_by_listen_adress: unknown listen_port %d", listen_port);
return -1;
}
/*
* This is called after receiving PORT_OPEN message. This attempts to
@ -2233,8 +2309,11 @@ auth_input_request_forwarding(struct passwd * pw)
packet_disconnect("listen: %.100s", strerror(errno));
/* Allocate a channel for the authentication agent socket. */
newch = channel_allocate(SSH_CHANNEL_AUTH_SOCKET, sock,
xstrdup("auth socket"));
newch = channel_new("auth socket",
SSH_CHANNEL_AUTH_SOCKET, sock, sock, -1,
CHAN_X11_WINDOW_DEFAULT, CHAN_X11_PACKET_DEFAULT,
0, xstrdup("auth socket"), 1);
strlcpy(channels[newch].path, channel_forwarded_auth_socket_name,
sizeof(channels[newch].path));
return 1;

View File

@ -32,7 +32,7 @@
* (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: channels.h,v 1.22 2000/10/27 07:48:22 markus Exp $"); */
/* RCSID("$OpenBSD: channels.h,v 1.23 2000/11/06 23:04:56 markus Exp $"); */
#ifndef CHANNELS_H
#define CHANNELS_H
@ -49,7 +49,8 @@
#define SSH_CHANNEL_INPUT_DRAINING 8 /* sending remaining data to conn */
#define SSH_CHANNEL_OUTPUT_DRAINING 9 /* sending remaining data to app */
#define SSH_CHANNEL_LARVAL 10 /* larval session */
#define SSH_CHANNEL_MAX_TYPE 11
#define SSH_CHANNEL_RPORT_LISTENER 11 /* Listening to a R-style port */
#define SSH_CHANNEL_MAX_TYPE 12
/*
* Data structure for channel data. This is iniailized in channel_allocate
@ -147,7 +148,6 @@ void channel_input_open_confirmation(int type, int plen, void *ctxt);
void channel_input_open_failure(int type, int plen, void *ctxt);
void channel_input_port_open(int type, int plen, void *ctxt);
void channel_input_window_adjust(int type, int plen, void *ctxt);
void channel_input_open(int type, int plen, void *ctxt);
/* Sets specific protocol options. */
void channel_set_options(int hostname_in_open);
@ -202,12 +202,15 @@ char *channel_open_message(void);
/*
* Initiate forwarding of connections to local port "port" through the secure
* channel to host:port from remote side. This never returns if there was an
* error.
* channel to host:port from remote side.
*/
void
channel_request_local_forwarding(u_short port, const char *host,
u_short remote_port, int gateway_ports);
channel_request_local_forwarding(u_short listen_port,
const char *host_to_connect, u_short port_to_connect, int gateway_ports);
void
channel_request_forwarding(const char *listen_address, u_short listen_port,
const char *host_to_connect, u_short port_to_connect, int gateway_ports,
int remote_fwd);
/*
* Initiate forwarding of connections to port "port" on remote host through
@ -288,6 +291,7 @@ void auth_input_open_request(int type, int plen, void *ctxt);
/* XXX */
int channel_connect_to(const char *host, u_short host_port);
int channel_connect_by_listen_adress(u_short listen_port);
int x11_connect_display(void);
#endif

View File

@ -59,7 +59,7 @@
*/
#include "includes.h"
RCSID("$OpenBSD: clientloop.c,v 1.39 2000/10/27 07:48:22 markus Exp $");
RCSID("$OpenBSD: clientloop.c,v 1.40 2000/11/06 23:04:56 markus Exp $");
#include "xmalloc.h"
#include "ssh.h"
@ -75,6 +75,10 @@ RCSID("$OpenBSD: clientloop.c,v 1.39 2000/10/27 07:48:22 markus Exp $");
#include "buffer.h"
#include "bufaux.h"
#include <openssl/dsa.h>
#include <openssl/rsa.h>
#include "key.h"
#include "authfd.h"
/* import options */
extern Options options;
@ -1016,13 +1020,99 @@ client_input_exit_status(int type, int plen, void *ctxt)
quit_pending = 1;
}
Channel *
client_request_forwarded_tcpip(const char *request_type, int rchan)
{
Channel* c = NULL;
char *listen_address, *originator_address;
int listen_port, originator_port;
int sock, newch;
/* Get rest of the packet */
listen_address = packet_get_string(NULL);
listen_port = packet_get_int();
originator_address = packet_get_string(NULL);
originator_port = packet_get_int();
packet_done();
debug("client_request_forwarded_tcpip: listen %s port %d, originator %s port %d",
listen_address, listen_port, originator_address, originator_port);
sock = channel_connect_by_listen_adress(listen_port);
if (sock >= 0) {
newch = channel_new("forwarded-tcpip",
SSH_CHANNEL_OPEN, sock, sock, -1,
CHAN_TCP_WINDOW_DEFAULT, CHAN_TCP_WINDOW_DEFAULT, 0,
xstrdup(originator_address), 1);
c = channel_lookup(newch);
}
xfree(originator_address);
xfree(listen_address);
return c;
}
Channel*
client_request_x11(const char *request_type, int rchan)
{
Channel *c = NULL;
char *originator;
int originator_port;
int sock, newch;
if (!options.forward_x11) {
error("Warning: ssh server tried X11 forwarding.");
error("Warning: this is probably a break in attempt by a malicious server.");
return NULL;
}
originator = packet_get_string(NULL);
if (datafellows & SSH_BUG_X11FWD) {
debug2("buggy server: x11 request w/o originator_port");
originator_port = 0;
} else {
originator_port = packet_get_int();
}
packet_done();
/* XXX check permission */
sock = x11_connect_display();
if (sock >= 0) {
newch = channel_new("x11",
SSH_CHANNEL_X11_OPEN, sock, sock, -1,
CHAN_TCP_WINDOW_DEFAULT, CHAN_X11_PACKET_DEFAULT, 0,
xstrdup("x11"), 1);
c = channel_lookup(newch);
}
xfree(originator);
return c;
}
Channel*
client_request_agent(const char *request_type, int rchan)
{
Channel *c = NULL;
int sock, newch;
if (!options.forward_agent) {
error("Warning: ssh server tried agent forwarding.");
error("Warning: this is probably a break in attempt by a malicious server.");
return NULL;
}
sock = ssh_get_authentication_socket();
if (sock >= 0) {
newch = channel_new("authentication agent connection",
SSH_CHANNEL_OPEN, sock, sock, -1,
CHAN_X11_WINDOW_DEFAULT, CHAN_TCP_WINDOW_DEFAULT, 0,
xstrdup("authentication agent connection"), 1);
c = channel_lookup(newch);
}
return c;
}
/* XXXX move to generic input handler */
void
client_input_channel_open(int type, int plen, void *ctxt)
{
Channel *c = NULL;
char *ctype;
int id;
unsigned int len;
int rchan;
int rmaxpack;
@ -1036,28 +1126,12 @@ client_input_channel_open(int type, int plen, void *ctxt)
debug("client_input_channel_open: ctype %s rchan %d win %d max %d",
ctype, rchan, rwindow, rmaxpack);
if (strcmp(ctype, "x11") == 0 && options.forward_x11) {
int sock;
char *originator;
int originator_port;
originator = packet_get_string(NULL);
if (datafellows & SSH_BUG_X11FWD) {
debug2("buggy server: x11 request w/o originator_port");
originator_port = 0;
} else {
originator_port = packet_get_int();
}
packet_done();
/* XXX check permission */
xfree(originator);
/* XXX move to channels.c */
sock = x11_connect_display();
if (sock >= 0) {
id = channel_new("x11", SSH_CHANNEL_X11_OPEN,
sock, sock, -1, CHAN_X11_WINDOW_DEFAULT,
CHAN_X11_PACKET_DEFAULT, 0, xstrdup("x11"), 1);
c = channel_lookup(id);
}
if (strcmp(ctype, "forwarded-tcpip") == 0) {
c = client_request_forwarded_tcpip(ctype, rchan);
} else if (strcmp(ctype, "x11") == 0) {
c = client_request_x11(ctype, rchan);
} else if (strcmp(ctype, "auth-agent@openssh.com") == 0) {
c = client_request_agent(ctype, rchan);
}
/* XXX duplicate : */
if (c != NULL) {

View File

@ -19,13 +19,27 @@ RETVAL=0
# Some functions to make the below more readable
KEYGEN=/usr/bin/ssh-keygen
RSA_KEY=/etc/ssh/ssh_host_key
RSA1_KEY=/etc/ssh/ssh_host_key
RSA_KEY=/etc/ssh/ssh_host_rsa_key
DSA_KEY=/etc/ssh/ssh_host_dsa_key
PID_FILE=/var/run/sshd.pid
do_rsa1_keygen() {
if ! test -f $RSA1_KEY ; then
echo -n "Generating SSH1 RSA host key: "
if $KEYGEN -q -t rsa1 -f $RSA1_KEY -C '' -N '' >&/dev/null; then
success "RSA1 key generation"
echo
else
failure "RSA1 key generation"
echo
exit 1
fi
fi
}
do_rsa_keygen() {
if $KEYGEN -R && ! test -f $RSA_KEY ; then
echo -n "Generating SSH RSA host key: "
if $KEYGEN -q -b 1024 -f $RSA_KEY -C '' -N '' >&/dev/null; then
if ! test -f $RSA_KEY ; then
echo -n "Generating SSH2 RSA host key: "
if $KEYGEN -q -t rsa -f $RSA_KEY -C '' -N '' >&/dev/null; then
success "RSA key generation"
echo
else
@ -37,8 +51,8 @@ do_rsa_keygen() {
}
do_dsa_keygen() {
if ! test -f $DSA_KEY ; then
echo -n "Generating SSH DSA host key: "
if $KEYGEN -q -d -b 1024 -f $DSA_KEY -C '' -N '' >&/dev/null; then
echo -n "Generating SSH2 DSA host key: "
if $KEYGEN -q -t dsa -f $DSA_KEY -C '' -N '' >&/dev/null; then
success "DSA key generation"
echo
else
@ -52,6 +66,7 @@ do_dsa_keygen() {
case "$1" in
start)
# Create keys if necessary
do_rsa1_keygen;
do_rsa_keygen;
do_dsa_keygen;

View File

@ -36,7 +36,7 @@
*/
#include "includes.h"
RCSID("$OpenBSD: hostfile.c,v 1.20 2000/09/07 20:27:51 deraadt Exp $");
RCSID("$OpenBSD: hostfile.c,v 1.21 2000/11/12 19:50:37 markus Exp $");
#include "packet.h"
#include "match.h"
@ -54,15 +54,13 @@ RCSID("$OpenBSD: hostfile.c,v 1.20 2000/09/07 20:27:51 deraadt Exp $");
int
hostfile_read_key(char **cpp, unsigned int *bitsp, Key *ret)
{
unsigned int bits;
char *cp;
/* Skip leading whitespace. */
for (cp = *cpp; *cp == ' ' || *cp == '\t'; cp++)
;
bits = key_read(ret, &cp);
if (bits == 0)
if (key_read(ret, &cp) != 1)
return 0;
/* Skip trailing whitespace. */
@ -71,14 +69,14 @@ hostfile_read_key(char **cpp, unsigned int *bitsp, Key *ret)
/* Return results. */
*cpp = cp;
*bitsp = bits;
*bitsp = key_size(ret);
return 1;
}
int
auth_rsa_read_key(char **cpp, unsigned int *bitsp, BIGNUM * e, BIGNUM * n)
{
Key *k = key_new(KEY_RSA);
Key *k = key_new(KEY_RSA1);
int ret = hostfile_read_key(cpp, bitsp, k);
BN_copy(e, k->rsa->e);
BN_copy(n, k->rsa->n);
@ -89,7 +87,7 @@ auth_rsa_read_key(char **cpp, unsigned int *bitsp, BIGNUM * e, BIGNUM * n)
int
hostfile_check_key(int bits, Key *key, const char *host, const char *filename, int linenum)
{
if (key == NULL || key->type != KEY_RSA || key->rsa == NULL)
if (key == NULL || key->type != KEY_RSA1 || key->rsa == NULL)
return 1;
if (bits != BN_num_bits(key->rsa->n)) {
log("Warning: %s, line %d: keysize mismatch for host %s: "

12
kex.c
View File

@ -23,7 +23,7 @@
*/
#include "includes.h"
RCSID("$OpenBSD: kex.c,v 1.12 2000/10/11 20:27:23 markus Exp $");
RCSID("$OpenBSD: kex.c,v 1.13 2000/11/12 19:50:37 markus Exp $");
#include "ssh.h"
#include "ssh2.h"
@ -43,6 +43,7 @@ RCSID("$OpenBSD: kex.c,v 1.12 2000/10/11 20:27:23 markus Exp $");
#include <openssl/pem.h>
#include "kex.h"
#include "key.h"
#define KEX_COOKIE_LEN 16
@ -454,11 +455,12 @@ choose_kex(Kex *k, char *client, char *server)
void
choose_hostkeyalg(Kex *k, char *client, char *server)
{
k->hostkeyalg = get_match(client, server);
if (k->hostkeyalg == NULL)
char *hostkeyalg = get_match(client, server);
if (hostkeyalg == NULL)
fatal("no hostkey alg");
if (strcmp(k->hostkeyalg, KEX_DSS) != 0)
fatal("bad hostkey alg %s", k->hostkeyalg);
k->hostkey_type = key_type_from_name(hostkeyalg);
if (k->hostkey_type == KEY_UNSPEC)
fatal("bad hostkey alg '%s'", hostkeyalg);
}
Kex *

2
kex.h
View File

@ -85,7 +85,7 @@ struct Kex {
int we_need;
int server;
char *name;
char *hostkeyalg;
int hostkey_type;
int kex_type;
};

388
key.c
View File

@ -39,12 +39,14 @@
#include <openssl/evp.h>
#include "xmalloc.h"
#include "key.h"
#include "dsa.h"
#include "rsa.h"
#include "ssh-dss.h"
#include "ssh-rsa.h"
#include "uuencode.h"
#include "buffer.h"
#include "bufaux.h"
RCSID("$OpenBSD: key.c,v 1.11 2000/09/07 20:27:51 deraadt Exp $");
#define SSH_DSS "ssh-dss"
RCSID("$OpenBSD: key.c,v 1.12 2000/11/12 19:50:37 markus Exp $");
Key *
key_new(int type)
@ -57,6 +59,7 @@ key_new(int type)
k->dsa = NULL;
k->rsa = NULL;
switch (k->type) {
case KEY_RSA1:
case KEY_RSA:
rsa = RSA_new();
rsa->n = BN_new();
@ -71,7 +74,7 @@ key_new(int type)
dsa->pub_key = BN_new();
k->dsa = dsa;
break;
case KEY_EMPTY:
case KEY_UNSPEC:
break;
default:
fatal("key_new: bad key type %d", k->type);
@ -79,10 +82,35 @@ key_new(int type)
}
return k;
}
Key *
key_new_private(int type)
{
Key *k = key_new(type);
switch (k->type) {
case KEY_RSA1:
case KEY_RSA:
k->rsa->d = BN_new();
k->rsa->iqmp = BN_new();
k->rsa->q = BN_new();
k->rsa->p = BN_new();
k->rsa->dmq1 = BN_new();
k->rsa->dmp1 = BN_new();
break;
case KEY_DSA:
k->dsa->priv_key = BN_new();
break;
case KEY_UNSPEC:
break;
default:
break;
}
return k;
}
void
key_free(Key *k)
{
switch (k->type) {
case KEY_RSA1:
case KEY_RSA:
if (k->rsa != NULL)
RSA_free(k->rsa);
@ -93,6 +121,8 @@ key_free(Key *k)
DSA_free(k->dsa);
k->dsa = NULL;
break;
case KEY_UNSPEC:
break;
default:
fatal("key_free: bad key type %d", k->type);
break;
@ -105,6 +135,7 @@ key_equal(Key *a, Key *b)
if (a == NULL || b == NULL || a->type != b->type)
return 0;
switch (a->type) {
case KEY_RSA1:
case KEY_RSA:
return a->rsa != NULL && b->rsa != NULL &&
BN_cmp(a->rsa->e, b->rsa->e) == 0 &&
@ -136,8 +167,9 @@ key_fingerprint(Key *k)
int len = 0;
int nlen, elen;
retval[0] = '\0';
switch (k->type) {
case KEY_RSA:
case KEY_RSA1:
nlen = BN_num_bytes(k->rsa->n);
elen = BN_num_bytes(k->rsa->e);
len = nlen + elen;
@ -146,14 +178,16 @@ key_fingerprint(Key *k)
BN_bn2bin(k->rsa->e, blob + nlen);
break;
case KEY_DSA:
dsa_make_key_blob(k, &blob, &len);
case KEY_RSA:
key_to_blob(k, &blob, &len);
break;
case KEY_UNSPEC:
return retval;
break;
default:
fatal("key_fingerprint: bad key type %d", k->type);
break;
}
retval[0] = '\0';
if (blob != NULL) {
int i;
unsigned char digest[EVP_MAX_MD_SIZE];
@ -229,56 +263,106 @@ write_bignum(FILE *f, BIGNUM *num)
free(buf);
return 1;
}
unsigned int
/* returns 1 ok, -1 error, 0 type mismatch */
int
key_read(Key *ret, char **cpp)
{
Key *k;
unsigned int bits = 0;
char *cp;
int len, n;
int success = -1;
char *cp, *space;
int len, n, type;
u_int bits;
unsigned char *blob;
cp = *cpp;
switch(ret->type) {
case KEY_RSA:
case KEY_RSA1:
/* Get number of bits. */
if (*cp < '0' || *cp > '9')
return 0; /* Bad bit count... */
return -1; /* Bad bit count... */
for (bits = 0; *cp >= '0' && *cp <= '9'; cp++)
bits = 10 * bits + *cp - '0';
if (bits == 0)
return 0;
return -1;
*cpp = cp;
/* Get public exponent, public modulus. */
if (!read_bignum(cpp, ret->rsa->e))
return 0;
return -1;
if (!read_bignum(cpp, ret->rsa->n))
return 0;
return -1;
success = 1;
break;
case KEY_UNSPEC:
case KEY_RSA:
case KEY_DSA:
if (strncmp(cp, SSH_DSS " ", 7) != 0)
space = strchr(cp, ' ');
if (space == NULL) {
debug3("key_read: no space");
return -1;
}
*space = '\0';
type = key_type_from_name(cp);
*space = ' ';
if (type == KEY_UNSPEC) {
debug3("key_read: no key found");
return -1;
}
cp = space+1;
if (*cp == '\0') {
debug3("key_read: short string");
return -1;
}
if (ret->type == KEY_UNSPEC) {
ret->type = type;
} else if (ret->type != type) {
/* is a key, but different type */
debug3("key_read: type mismatch");
return 0;
cp += 7;
}
len = 2*strlen(cp);
blob = xmalloc(len);
n = uudecode(cp, blob, len);
if (n < 0) {
error("key_read: uudecode %s failed", cp);
return 0;
return -1;
}
k = dsa_key_from_blob(blob, n);
k = key_from_blob(blob, n);
if (k == NULL) {
error("key_read: dsa_key_from_blob %s failed", cp);
return 0;
error("key_read: key_from_blob %s failed", cp);
return -1;
}
xfree(blob);
if (ret->dsa != NULL)
DSA_free(ret->dsa);
ret->dsa = k->dsa;
k->dsa = NULL;
if (k->type != type) {
error("key_read: type mismatch: encoding error");
key_free(k);
return -1;
}
/*XXXX*/
if (ret->type == KEY_RSA) {
if (ret->rsa != NULL)
RSA_free(ret->rsa);
ret->rsa = k->rsa;
k->rsa = NULL;
success = 1;
#ifdef DEBUG_PK
RSA_print_fp(stderr, ret->rsa, 8);
#endif
} else {
if (ret->dsa != NULL)
DSA_free(ret->dsa);
ret->dsa = k->dsa;
k->dsa = NULL;
success = 1;
#ifdef DEBUG_PK
DSA_print_fp(stderr, ret->dsa, 8);
#endif
}
/*XXXX*/
if (success != 1)
break;
key_free(k);
bits = BN_num_bits(ret->dsa->p);
/* advance cp: skip whitespace and data */
while (*cp == ' ' || *cp == '\t')
cp++;
@ -290,7 +374,7 @@ key_read(Key *ret, char **cpp)
fatal("key_read: bad key type: %d", ret->type);
break;
}
return bits;
return success;
}
int
key_write(Key *key, FILE *f)
@ -298,7 +382,7 @@ key_write(Key *key, FILE *f)
int success = 0;
unsigned int bits = 0;
if (key->type == KEY_RSA && key->rsa != NULL) {
if (key->type == KEY_RSA1 && key->rsa != NULL) {
/* size of modulus 'n' */
bits = BN_num_bits(key->rsa->n);
fprintf(f, "%u", bits);
@ -308,14 +392,15 @@ key_write(Key *key, FILE *f)
} else {
error("key_write: failed for RSA key");
}
} else if (key->type == KEY_DSA && key->dsa != NULL) {
} else if ((key->type == KEY_DSA && key->dsa != NULL) ||
(key->type == KEY_RSA && key->rsa != NULL)) {
int len, n;
unsigned char *blob, *uu;
dsa_make_key_blob(key, &blob, &len);
key_to_blob(key, &blob, &len);
uu = xmalloc(2*len);
n = uuencode(blob, len, uu, 2*len);
if (n > 0) {
fprintf(f, "%s %s", SSH_DSS, uu);
fprintf(f, "%s %s", key_ssh_name(key), uu);
success = 1;
}
xfree(blob);
@ -327,6 +412,9 @@ char *
key_type(Key *k)
{
switch (k->type) {
case KEY_RSA1:
return "RSA1";
break;
case KEY_RSA:
return "RSA";
break;
@ -336,9 +424,23 @@ key_type(Key *k)
}
return "unknown";
}
unsigned int
char *
key_ssh_name(Key *k)
{
switch (k->type) {
case KEY_RSA:
return "ssh-rsa";
break;
case KEY_DSA:
return "ssh-dss";
break;
}
return "ssh-unknown";
}
u_int
key_size(Key *k){
switch (k->type) {
case KEY_RSA1:
case KEY_RSA:
return BN_num_bits(k->rsa->n);
break;
@ -348,3 +450,219 @@ key_size(Key *k){
}
return 0;
}
RSA *
rsa_generate_private_key(unsigned int bits)
{
RSA *private;
private = RSA_generate_key(bits, 35, NULL, NULL);
if (private == NULL)
fatal("rsa_generate_private_key: key generation failed.");
return private;
}
DSA*
dsa_generate_private_key(unsigned int bits)
{
DSA *private = DSA_generate_parameters(bits, NULL, 0, NULL, NULL, NULL, NULL);
if (private == NULL)
fatal("dsa_generate_private_key: DSA_generate_parameters failed");
if (!DSA_generate_key(private))
fatal("dsa_generate_private_key: DSA_generate_key failed.");
if (private == NULL)
fatal("dsa_generate_private_key: NULL.");
return private;
}
Key *
key_generate(int type, unsigned int bits)
{
Key *k = key_new(KEY_UNSPEC);
switch (type) {
case KEY_DSA:
k->dsa = dsa_generate_private_key(bits);
break;
case KEY_RSA:
case KEY_RSA1:
k->rsa = rsa_generate_private_key(bits);
break;
default:
fatal("key_generate: unknown type %d", type);
}
k->type = type;
return k;
}
Key *
key_from_private(Key *k)
{
Key *n = NULL;
switch (k->type) {
case KEY_DSA:
n = key_new(k->type);
BN_copy(n->dsa->p, k->dsa->p);
BN_copy(n->dsa->q, k->dsa->q);
BN_copy(n->dsa->g, k->dsa->g);
BN_copy(n->dsa->pub_key, k->dsa->pub_key);
break;
case KEY_RSA:
case KEY_RSA1:
n = key_new(k->type);
BN_copy(n->rsa->n, k->rsa->n);
BN_copy(n->rsa->e, k->rsa->e);
break;
default:
fatal("key_from_private: unknown type %d", k->type);
break;
}
return n;
}
int
key_type_from_name(char *name)
{
if (strcmp(name, "rsa1") == 0){
return KEY_RSA1;
} else if (strcmp(name, "rsa") == 0){
return KEY_RSA;
} else if (strcmp(name, "dsa") == 0){
return KEY_DSA;
} else if (strcmp(name, "ssh-rsa") == 0){
return KEY_RSA;
} else if (strcmp(name, "ssh-dss") == 0){
return KEY_DSA;
}
debug("key_type_from_name: unknown key type '%s'", name);
return KEY_UNSPEC;
}
Key *
key_from_blob(char *blob, int blen)
{
Buffer b;
char *ktype;
int rlen, type;
Key *key = NULL;
#ifdef DEBUG_PK
dump_base64(stderr, blob, blen);
#endif
buffer_init(&b);
buffer_append(&b, blob, blen);
ktype = buffer_get_string(&b, NULL);
type = key_type_from_name(ktype);
switch(type){
case KEY_RSA:
key = key_new(type);
buffer_get_bignum2(&b, key->rsa->n);
buffer_get_bignum2(&b, key->rsa->e);
#ifdef DEBUG_PK
RSA_print_fp(stderr, key->rsa, 8);
#endif
break;
case KEY_DSA:
key = key_new(type);
buffer_get_bignum2(&b, key->dsa->p);
buffer_get_bignum2(&b, key->dsa->q);
buffer_get_bignum2(&b, key->dsa->g);
buffer_get_bignum2(&b, key->dsa->pub_key);
#ifdef DEBUG_PK
DSA_print_fp(stderr, key->dsa, 8);
#endif
break;
case KEY_UNSPEC:
key = key_new(type);
break;
default:
error("key_from_blob: cannot handle type %s", ktype);
break;
}
rlen = buffer_len(&b);
if (key != NULL && rlen != 0)
error("key_from_blob: remaining bytes in key blob %d", rlen);
xfree(ktype);
buffer_free(&b);
return key;
}
int
key_to_blob(Key *key, unsigned char **blobp, unsigned int *lenp)
{
Buffer b;
int len;
unsigned char *buf;
if (key == NULL) {
error("key_to_blob: key == NULL");
return 0;
}
buffer_init(&b);
switch(key->type){
case KEY_DSA:
buffer_put_cstring(&b, key_ssh_name(key));
buffer_put_bignum2(&b, key->dsa->p);
buffer_put_bignum2(&b, key->dsa->q);
buffer_put_bignum2(&b, key->dsa->g);
buffer_put_bignum2(&b, key->dsa->pub_key);
break;
case KEY_RSA:
buffer_put_cstring(&b, key_ssh_name(key));
buffer_put_bignum2(&b, key->rsa->n);
buffer_put_bignum2(&b, key->rsa->e);
break;
default:
error("key_to_blob: illegal key type %d", key->type);
break;
}
len = buffer_len(&b);
buf = xmalloc(len);
memcpy(buf, buffer_ptr(&b), len);
memset(buffer_ptr(&b), 0, len);
buffer_free(&b);
if (lenp != NULL)
*lenp = len;
if (blobp != NULL)
*blobp = buf;
return len;
}
int
key_sign(
Key *key,
unsigned char **sigp, int *lenp,
unsigned char *data, int datalen)
{
switch(key->type){
case KEY_DSA:
return ssh_dss_sign(key, sigp, lenp, data, datalen);
break;
case KEY_RSA:
return ssh_rsa_sign(key, sigp, lenp, data, datalen);
break;
default:
error("key_sign: illegal key type %d", key->type);
return -1;
break;
}
}
int
key_verify(
Key *key,
unsigned char *signature, int signaturelen,
unsigned char *data, int datalen)
{
switch(key->type){
case KEY_DSA:
return ssh_dss_verify(key, signature, signaturelen, data, datalen);
break;
case KEY_RSA:
return ssh_rsa_verify(key, signature, signaturelen, data, datalen);
break;
default:
error("key_verify: illegal key type %d", key->type);
return -1;
break;
}
}

28
key.h
View File

@ -26,9 +26,10 @@
typedef struct Key Key;
enum types {
KEY_RSA1,
KEY_RSA,
KEY_DSA,
KEY_EMPTY
KEY_UNSPEC
};
struct Key {
int type;
@ -37,12 +38,33 @@ struct Key {
};
Key *key_new(int type);
Key *key_new_private(int type);
void key_free(Key *k);
int key_equal(Key *a, Key *b);
char *key_fingerprint(Key *k);
char *key_type(Key *k);
int key_write(Key *key, FILE *f);
unsigned int key_read(Key *key, char **cpp);
unsigned int key_size(Key *k);
int key_read(Key *key, char **cpp);
u_int key_size(Key *k);
Key *key_generate(int type, unsigned int bits);
Key *key_from_private(Key *k);
int key_type_from_name(char *name);
Key *key_from_blob(char *blob, int blen);
int key_to_blob(Key *key, unsigned char **blobp, unsigned int *lenp);
char *key_ssh_name(Key *k);
int
key_sign(
Key *key,
unsigned char **sigp, int *lenp,
unsigned char *data, int datalen);
int
key_verify(
Key *key,
unsigned char *signature, int signaturelen,
unsigned char *data, int datalen);
#endif

View File

@ -22,7 +22,7 @@
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#define KEX_DEFAULT_KEX "diffie-hellman-group-exchange-sha1,diffie-hellman-group1-sha1"
#define KEX_DEFAULT_PK_ALG "ssh-dss"
#define KEX_DEFAULT_PK_ALG "ssh-rsa,ssh-dss"
#define KEX_DEFAULT_ENCRYPT \
"3des-cbc,blowfish-cbc,cast128-cbc,arcfour," \
"aes128-cbc,aes192-cbc,aes256-cbc," \

View File

@ -23,7 +23,7 @@
*/
#include "includes.h"
RCSID("$OpenBSD: nchan.c,v 1.19 2000/09/07 20:27:52 deraadt Exp $");
RCSID("$OpenBSD: nchan.c,v 1.20 2000/11/06 23:04:56 markus Exp $");
#include "ssh.h"
@ -253,6 +253,8 @@ chan_send_oclose1(Channel *c)
static void
chan_delete_if_full_closed1(Channel *c)
{
debug3("channel %d: chan_delete_if_full_closed1: istate %d ostate %d",
c->self, c->istate, c->ostate);
if (c->istate == CHAN_INPUT_CLOSED && c->ostate == CHAN_OUTPUT_CLOSED) {
debug("channel %d: full closed", c->self);
channel_free(c->self);
@ -403,6 +405,8 @@ chan_send_close2(Channel *c)
static void
chan_delete_if_full_closed2(Channel *c)
{
debug3("channel %d: chan_delete_if_full_closed2: istate %d ostate %d",
c->self, c->istate, c->ostate);
if (c->istate == CHAN_INPUT_CLOSED && c->ostate == CHAN_OUTPUT_CLOSED) {
if (!(c->flags & CHAN_CLOSE_SENT)) {
chan_send_close2(c);

View File

@ -12,7 +12,7 @@
*/
#include "includes.h"
RCSID("$OpenBSD: readconf.c,v 1.49 2000/10/11 20:27:23 markus Exp $");
RCSID("$OpenBSD: readconf.c,v 1.50 2000/11/12 19:50:37 markus Exp $");
#include "ssh.h"
#include "readconf.h"
@ -68,7 +68,7 @@ RCSID("$OpenBSD: readconf.c,v 1.49 2000/10/11 20:27:23 markus Exp $");
# Defaults for various options
Host *
ForwardAgent no
ForwardX11 yes
ForwardX11 no
RhostsAuthentication yes
PasswordAuthentication yes
RSAAuthentication yes
@ -101,8 +101,8 @@ typedef enum {
oGlobalKnownHostsFile, oUserKnownHostsFile, oConnectionAttempts,
oBatchMode, oCheckHostIP, oStrictHostKeyChecking, oCompression,
oCompressionLevel, oKeepAlives, oNumberOfPasswordPrompts, oTISAuthentication,
oUsePrivilegedPort, oLogLevel, oCiphers, oProtocol, oIdentityFile2,
oGlobalKnownHostsFile2, oUserKnownHostsFile2, oDSAAuthentication,
oUsePrivilegedPort, oLogLevel, oCiphers, oProtocol,
oGlobalKnownHostsFile2, oUserKnownHostsFile2, oPubkeyAuthentication,
oKbdInteractiveAuthentication, oKbdInteractiveDevices
} OpCodes;
@ -122,7 +122,8 @@ static struct {
{ "kbdinteractiveauthentication", oKbdInteractiveAuthentication },
{ "kbdinteractivedevices", oKbdInteractiveDevices },
{ "rsaauthentication", oRSAAuthentication },
{ "dsaauthentication", oDSAAuthentication },
{ "pubkeyauthentication", oPubkeyAuthentication },
{ "dsaauthentication", oPubkeyAuthentication }, /* alias */
{ "skeyauthentication", oSkeyAuthentication },
#ifdef KRB4
{ "kerberosauthentication", oKerberosAuthentication },
@ -134,7 +135,7 @@ static struct {
{ "fallbacktorsh", oFallBackToRsh },
{ "usersh", oUseRsh },
{ "identityfile", oIdentityFile },
{ "identityfile2", oIdentityFile2 },
{ "identityfile2", oIdentityFile }, /* alias */
{ "hostname", oHostName },
{ "proxycommand", oProxyCommand },
{ "port", oPort },
@ -300,8 +301,8 @@ parse_flag:
charptr = &options->kbd_interactive_devices;
goto parse_string;
case oDSAAuthentication:
intptr = &options->dsa_authentication;
case oPubkeyAuthentication:
intptr = &options->pubkey_authentication;
goto parse_flag;
case oRSAAuthentication:
@ -386,20 +387,15 @@ parse_flag:
goto parse_int;
case oIdentityFile:
case oIdentityFile2:
arg = strdelim(&s);
if (!arg || *arg == '\0')
fatal("%.200s line %d: Missing argument.", filename, linenum);
if (*activep) {
intptr = (opcode == oIdentityFile) ?
&options->num_identity_files :
&options->num_identity_files2;
intptr = &options->num_identity_files;
if (*intptr >= SSH_MAX_IDENTITY_FILES)
fatal("%.200s line %d: Too many identity files specified (max %d).",
filename, linenum, SSH_MAX_IDENTITY_FILES);
charptr = (opcode == oIdentityFile) ?
&options->identity_files[*intptr] :
&options->identity_files2[*intptr];
charptr = &options->identity_files[*intptr];
*charptr = xstrdup(arg);
*intptr = *intptr + 1;
}
@ -664,7 +660,7 @@ initialize_options(Options * options)
options->use_privileged_port = -1;
options->rhosts_authentication = -1;
options->rsa_authentication = -1;
options->dsa_authentication = -1;
options->pubkey_authentication = -1;
options->skey_authentication = -1;
#ifdef KRB4
options->kerberos_authentication = -1;
@ -692,7 +688,6 @@ initialize_options(Options * options)
options->ciphers = NULL;
options->protocol = SSH_PROTO_UNKNOWN;
options->num_identity_files = 0;
options->num_identity_files2 = 0;
options->hostname = NULL;
options->proxy_command = NULL;
options->user = NULL;
@ -730,8 +725,8 @@ fill_default_options(Options * options)
options->rhosts_authentication = 1;
if (options->rsa_authentication == -1)
options->rsa_authentication = 1;
if (options->dsa_authentication == -1)
options->dsa_authentication = 1;
if (options->pubkey_authentication == -1)
options->pubkey_authentication = 1;
if (options->skey_authentication == -1)
options->skey_authentication = 0;
#ifdef KRB4
@ -779,16 +774,18 @@ fill_default_options(Options * options)
if (options->protocol == SSH_PROTO_UNKNOWN)
options->protocol = SSH_PROTO_1|SSH_PROTO_2|SSH_PROTO_1_PREFERRED;
if (options->num_identity_files == 0) {
options->identity_files[0] =
xmalloc(2 + strlen(SSH_CLIENT_IDENTITY) + 1);
sprintf(options->identity_files[0], "~/%.100s", SSH_CLIENT_IDENTITY);
options->num_identity_files = 1;
}
if (options->num_identity_files2 == 0) {
options->identity_files2[0] =
xmalloc(2 + strlen(SSH_CLIENT_ID_DSA) + 1);
sprintf(options->identity_files2[0], "~/%.100s", SSH_CLIENT_ID_DSA);
options->num_identity_files2 = 1;
if (options->protocol & SSH_PROTO_1) {
options->identity_files[options->num_identity_files] =
xmalloc(2 + strlen(SSH_CLIENT_IDENTITY) + 1);
sprintf(options->identity_files[options->num_identity_files++],
"~/%.100s", SSH_CLIENT_IDENTITY);
}
if (options->protocol & SSH_PROTO_2) {
options->identity_files[options->num_identity_files] =
xmalloc(2 + strlen(SSH_CLIENT_ID_DSA) + 1);
sprintf(options->identity_files[options->num_identity_files++],
"~/%.100s", SSH_CLIENT_ID_DSA);
}
}
if (options->escape_char == -1)
options->escape_char = '~';

View File

@ -11,7 +11,7 @@
* called by a name other than "ssh" or "Secure Shell".
*/
/* RCSID("$OpenBSD: readconf.h,v 1.22 2000/10/11 20:14:39 markus Exp $"); */
/* RCSID("$OpenBSD: readconf.h,v 1.23 2000/11/12 19:50:37 markus Exp $"); */
#ifndef READCONF_H
#define READCONF_H
@ -35,7 +35,7 @@ typedef struct {
int rhosts_rsa_authentication; /* Try rhosts with RSA
* authentication. */
int rsa_authentication; /* Try RSA authentication. */
int dsa_authentication; /* Try DSA authentication. */
int pubkey_authentication; /* Try ssh2 pubkey authentication. */
int skey_authentication; /* Try S/Key or TIS authentication. */
#ifdef KRB4
int kerberos_authentication; /* Try Kerberos
@ -78,10 +78,9 @@ typedef struct {
char *system_hostfile2;
char *user_hostfile2;
int num_identity_files; /* Number of files for RSA identities. */
int num_identity_files2; /* DSA identities. */
int num_identity_files; /* Number of files for RSA/DSA identities. */
char *identity_files[SSH_MAX_IDENTITY_FILES];
char *identity_files2[SSH_MAX_IDENTITY_FILES];
int identity_files_type[SSH_MAX_IDENTITY_FILES];
/* Local TCP/IP forward requests. */
int num_local_forwards;

79
rsa.c
View File

@ -60,82 +60,13 @@
*/
#include "includes.h"
RCSID("$OpenBSD: rsa.c,v 1.16 2000/09/07 20:27:53 deraadt Exp $");
RCSID("$OpenBSD: rsa.c,v 1.17 2000/11/12 19:50:37 markus Exp $");
#include "rsa.h"
#include "ssh.h"
#include "xmalloc.h"
#include "entropy.h"
int rsa_verbose = 1;
int
rsa_alive()
{
RSA *key;
seed_rng();
key = RSA_generate_key(32, 3, NULL, NULL);
if (key == NULL)
return (0);
RSA_free(key);
return (1);
}
/*
* Generates RSA public and private keys. This initializes the data
* structures; they should be freed with rsa_clear_private_key and
* rsa_clear_public_key.
*/
void
rsa_generate_key(RSA *prv, RSA *pub, unsigned int bits)
{
RSA *key;
seed_rng();
if (rsa_verbose) {
printf("Generating RSA keys: ");
fflush(stdout);
}
key = RSA_generate_key(bits, 35, NULL, NULL);
if (key == NULL)
fatal("rsa_generate_key: key generation failed.");
/* Copy public key parameters */
pub->n = BN_new();
BN_copy(pub->n, key->n);
pub->e = BN_new();
BN_copy(pub->e, key->e);
/* Copy private key parameters */
prv->n = BN_new();
BN_copy(prv->n, key->n);
prv->e = BN_new();
BN_copy(prv->e, key->e);
prv->d = BN_new();
BN_copy(prv->d, key->d);
prv->p = BN_new();
BN_copy(prv->p, key->p);
prv->q = BN_new();
BN_copy(prv->q, key->q);
prv->dmp1 = BN_new();
BN_copy(prv->dmp1, key->dmp1);
prv->dmq1 = BN_new();
BN_copy(prv->dmq1, key->dmq1);
prv->iqmp = BN_new();
BN_copy(prv->iqmp, key->iqmp);
RSA_free(key);
if (rsa_verbose)
printf("Key generation complete.\n");
}
void
rsa_public_encrypt(BIGNUM *out, BIGNUM *in, RSA *key)
{
@ -188,11 +119,3 @@ rsa_private_decrypt(BIGNUM *out, BIGNUM *in, RSA *key)
xfree(outbuf);
xfree(inbuf);
}
/* Set whether to output verbose messages during key generation. */
void
rsa_set_verbose(int verbose)
{
rsa_verbose = verbose;
}

13
rsa.h
View File

@ -11,7 +11,7 @@
* called by a name other than "ssh" or "Secure Shell".
*/
/* RCSID("$OpenBSD: rsa.h,v 1.8 2000/09/07 20:27:53 deraadt Exp $"); */
/* RCSID("$OpenBSD: rsa.h,v 1.9 2000/11/12 19:50:38 markus Exp $"); */
#ifndef RSA_H
#define RSA_H
@ -19,17 +19,6 @@
#include <openssl/bn.h>
#include <openssl/rsa.h>
/* Calls SSL RSA_generate_key, only copies to prv and pub */
void rsa_generate_key(RSA * prv, RSA * pub, unsigned int bits);
/*
* Indicates whether the rsa module is permitted to show messages on the
* terminal.
*/
void rsa_set_verbose __P((int verbose));
int rsa_alive __P((void));
void rsa_public_encrypt __P((BIGNUM * out, BIGNUM * in, RSA * prv));
void rsa_private_decrypt __P((BIGNUM * out, BIGNUM * in, RSA * prv));

View File

@ -10,7 +10,7 @@
*/
#include "includes.h"
RCSID("$OpenBSD: servconf.c,v 1.53 2000/10/14 12:12:09 markus Exp $");
RCSID("$OpenBSD: servconf.c,v 1.54 2000/11/12 19:50:38 markus Exp $");
#include "ssh.h"
#include "servconf.h"
@ -29,8 +29,7 @@ initialize_server_options(ServerOptions *options)
options->num_ports = 0;
options->ports_from_cmdline = 0;
options->listen_addrs = NULL;
options->host_key_file = NULL;
options->host_dsa_key_file = NULL;
options->num_host_key_files = 0;
options->pid_file = NULL;
options->server_key_bits = -1;
options->login_grace_time = -1;
@ -50,7 +49,7 @@ initialize_server_options(ServerOptions *options)
options->rhosts_authentication = -1;
options->rhosts_rsa_authentication = -1;
options->rsa_authentication = -1;
options->dsa_authentication = -1;
options->pubkey_authentication = -1;
#ifdef KRB4
options->kerberos_authentication = -1;
options->kerberos_or_local_passwd = -1;
@ -84,14 +83,19 @@ initialize_server_options(ServerOptions *options)
void
fill_default_server_options(ServerOptions *options)
{
if (options->protocol == SSH_PROTO_UNKNOWN)
options->protocol = SSH_PROTO_1|SSH_PROTO_2;
if (options->num_host_key_files == 0) {
/* fill default hostkeys for protocols */
if (options->protocol & SSH_PROTO_1)
options->host_key_files[options->num_host_key_files++] = HOST_KEY_FILE;
if (options->protocol & SSH_PROTO_2)
options->host_key_files[options->num_host_key_files++] = HOST_DSA_KEY_FILE;
}
if (options->num_ports == 0)
options->ports[options->num_ports++] = SSH_DEFAULT_PORT;
if (options->listen_addrs == NULL)
add_listen_addr(options, NULL);
if (options->host_key_file == NULL)
options->host_key_file = HOST_KEY_FILE;
if (options->host_dsa_key_file == NULL)
options->host_dsa_key_file = HOST_DSA_KEY_FILE;
if (options->pid_file == NULL)
options->pid_file = SSH_DAEMON_PID_FILE;
if (options->server_key_bits == -1)
@ -132,8 +136,8 @@ fill_default_server_options(ServerOptions *options)
options->rhosts_rsa_authentication = 0;
if (options->rsa_authentication == -1)
options->rsa_authentication = 1;
if (options->dsa_authentication == -1)
options->dsa_authentication = 1;
if (options->pubkey_authentication == -1)
options->pubkey_authentication = 1;
#ifdef KRB4
if (options->kerberos_authentication == -1)
options->kerberos_authentication = (access(KEYFILE, R_OK) == 0);
@ -162,8 +166,6 @@ fill_default_server_options(ServerOptions *options)
options->use_login = 0;
if (options->allow_tcp_forwarding == -1)
options->allow_tcp_forwarding = 1;
if (options->protocol == SSH_PROTO_UNKNOWN)
options->protocol = SSH_PROTO_1|SSH_PROTO_2;
if (options->gateway_ports == -1)
options->gateway_ports = 0;
if (options->max_startups == -1)
@ -194,8 +196,8 @@ typedef enum {
sStrictModes, sEmptyPasswd, sRandomSeedFile, sKeepAlives, sCheckMail,
sUseLogin, sAllowTcpForwarding,
sAllowUsers, sDenyUsers, sAllowGroups, sDenyGroups,
sIgnoreUserKnownHosts, sHostDSAKeyFile, sCiphers, sProtocol, sPidFile,
sGatewayPorts, sDSAAuthentication, sXAuthLocation, sSubsystem, sMaxStartups
sIgnoreUserKnownHosts, sCiphers, sProtocol, sPidFile,
sGatewayPorts, sPubkeyAuthentication, sXAuthLocation, sSubsystem, sMaxStartups,
} ServerOpCodes;
/* Textual representation of the tokens. */
@ -205,7 +207,7 @@ static struct {
} keywords[] = {
{ "port", sPort },
{ "hostkey", sHostKeyFile },
{ "hostdsakey", sHostDSAKeyFile },
{ "hostdsakey", sHostKeyFile }, /* alias */
{ "pidfile", sPidFile },
{ "serverkeybits", sServerKeyBits },
{ "logingracetime", sLoginGraceTime },
@ -216,7 +218,8 @@ static struct {
{ "rhostsauthentication", sRhostsAuthentication },
{ "rhostsrsaauthentication", sRhostsRSAAuthentication },
{ "rsaauthentication", sRSAAuthentication },
{ "dsaauthentication", sDSAAuthentication },
{ "pubkeyauthentication", sPubkeyAuthentication },
{ "dsaauthentication", sPubkeyAuthentication }, /* alias */
#ifdef KRB4
{ "kerberosauthentication", sKerberosAuthentication },
{ "kerberosorlocalpasswd", sKerberosOrLocalPasswd },
@ -336,6 +339,8 @@ read_server_config(ServerOptions *options, const char *filename)
arg = strdelim(&cp);
if (!*arg || *arg == '#')
continue;
intptr = NULL;
charptr = NULL;
opcode = parse_token(arg, filename, linenum);
switch (opcode) {
case sBadOption:
@ -389,9 +394,13 @@ parse_int:
break;
case sHostKeyFile:
case sHostDSAKeyFile:
charptr = (opcode == sHostKeyFile ) ?
&options->host_key_file : &options->host_dsa_key_file;
intptr = &options->num_host_key_files;
if (*intptr >= MAX_HOSTKEYS) {
fprintf(stderr, "%s line %d: to many host keys specified (max %d).\n",
filename, linenum, MAX_HOSTKEYS);
exit(1);
}
charptr = &options->host_key_files[*intptr];
parse_filename:
arg = strdelim(&cp);
if (!arg || *arg == '\0') {
@ -399,8 +408,12 @@ parse_filename:
filename, linenum);
exit(1);
}
if (*charptr == NULL)
if (*charptr == NULL) {
*charptr = tilde_expand_filename(arg, getuid());
/* increase optional counter */
if (intptr != NULL)
*intptr = *intptr + 1;
}
break;
case sPidFile:
@ -474,8 +487,8 @@ parse_flag:
intptr = &options->rsa_authentication;
goto parse_flag;
case sDSAAuthentication:
intptr = &options->dsa_authentication;
case sPubkeyAuthentication:
intptr = &options->pubkey_authentication;
goto parse_flag;
#ifdef KRB4

View File

@ -11,7 +11,7 @@
* called by a name other than "ssh" or "Secure Shell".
*/
/* RCSID("$OpenBSD: servconf.h,v 1.30 2000/10/14 12:12:09 markus Exp $"); */
/* RCSID("$OpenBSD: servconf.h,v 1.31 2000/11/12 19:50:38 markus Exp $"); */
#ifndef SERVCONF_H
#define SERVCONF_H
@ -23,6 +23,7 @@
#define MAX_ALLOW_GROUPS 256 /* Max # groups on allow list. */
#define MAX_DENY_GROUPS 256 /* Max # groups on deny list. */
#define MAX_SUBSYSTEMS 256 /* Max # subsystems. */
#define MAX_HOSTKEYS 256 /* Max # hostkeys. */
typedef struct {
unsigned int num_ports;
@ -30,8 +31,8 @@ typedef struct {
u_short ports[MAX_PORTS]; /* Port number to listen on. */
char *listen_addr; /* Address on which the server listens. */
struct addrinfo *listen_addrs; /* Addresses on which the server listens. */
char *host_key_file; /* File containing host key. */
char *host_dsa_key_file; /* File containing dsa host key. */
char *host_key_files[MAX_HOSTKEYS]; /* Files containing host keys. */
int num_host_key_files; /* Number of files for host keys. */
char *pid_file; /* Where to put our pid */
int server_key_bits;/* Size of the server key. */
int login_grace_time; /* Disconnect if no auth in this time
@ -59,7 +60,7 @@ typedef struct {
int rhosts_rsa_authentication; /* If true, permit rhosts RSA
* authentication. */
int rsa_authentication; /* If true, permit RSA authentication. */
int dsa_authentication; /* If true, permit DSA authentication. */
int pubkey_authentication; /* If true, permit ssh2 pubkey authentication. */
#ifdef KRB4
int kerberos_authentication; /* If true, permit Kerberos
* authentication. */

View File

@ -35,7 +35,7 @@
*/
#include "includes.h"
RCSID("$OpenBSD: serverloop.c,v 1.34 2000/10/27 07:32:18 markus Exp $");
RCSID("$OpenBSD: serverloop.c,v 1.35 2000/11/06 23:04:56 markus Exp $");
#include "xmalloc.h"
#include "ssh.h"
@ -50,6 +50,7 @@ RCSID("$OpenBSD: serverloop.c,v 1.34 2000/10/27 07:32:18 markus Exp $");
#include "session.h"
#include "dispatch.h"
#include "auth-options.h"
#include "auth.h"
extern ServerOptions options;
@ -739,10 +740,10 @@ server_input_window_size(int type, int plen, void *ctxt)
pty_change_window_size(fdin, row, col, xpixel, ypixel);
}
int
input_direct_tcpip(void)
Channel *
server_request_direct_tcpip(char *ctype)
{
int sock;
int sock, newch;
char *target, *originator;
int target_port, originator_port;
@ -752,23 +753,52 @@ input_direct_tcpip(void)
originator_port = packet_get_int();
packet_done();
debug("open direct-tcpip: from %s port %d to %s port %d",
debug("server_request_direct_tcpip: originator %s port %d, target %s port %d",
originator, originator_port, target, target_port);
/* XXX check permission */
if (no_port_forwarding_flag || !options.allow_tcp_forwarding) {
xfree(target);
xfree(originator);
return -1;
return NULL;
}
sock = channel_connect_to(target, target_port);
xfree(target);
xfree(originator);
if (sock < 0)
return -1;
return channel_new("direct-tcpip", SSH_CHANNEL_OPEN,
return NULL;
newch = channel_new(ctype, SSH_CHANNEL_OPEN,
sock, sock, -1, CHAN_TCP_WINDOW_DEFAULT,
CHAN_TCP_PACKET_DEFAULT, 0, xstrdup("direct-tcpip"), 1);
return (newch >= 0) ? channel_lookup(newch) : NULL;
}
Channel *
server_request_session(char *ctype)
{
int newch;
debug("input_session_request");
packet_done();
/*
* A server session has no fd to read or write until a
* CHANNEL_REQUEST for a shell is made, so we set the type to
* SSH_CHANNEL_LARVAL. Additionally, a callback for handling all
* CHANNEL_REQUEST messages is registered.
*/
newch = channel_new(ctype, SSH_CHANNEL_LARVAL,
-1, -1, -1, 0, CHAN_SES_PACKET_DEFAULT,
0, xstrdup("server-session"), 1);
if (session_open(newch) == 1) {
channel_register_callback(newch, SSH2_MSG_CHANNEL_REQUEST,
session_input_channel_req, (void *)0);
channel_register_cleanup(newch, session_close_by_channel);
return channel_lookup(newch);
} else {
debug("session open failed, free channel %d", newch);
channel_free(newch);
}
return NULL;
}
void
@ -776,7 +806,6 @@ server_input_channel_open(int type, int plen, void *ctxt)
{
Channel *c = NULL;
char *ctype;
int id;
unsigned int len;
int rchan;
int rmaxpack;
@ -791,34 +820,12 @@ server_input_channel_open(int type, int plen, void *ctxt)
ctype, rchan, rwindow, rmaxpack);
if (strcmp(ctype, "session") == 0) {
debug("open session");
packet_done();
/*
* A server session has no fd to read or write
* until a CHANNEL_REQUEST for a shell is made,
* so we set the type to SSH_CHANNEL_LARVAL.
* Additionally, a callback for handling all
* CHANNEL_REQUEST messages is registered.
*/
id = channel_new(ctype, SSH_CHANNEL_LARVAL,
-1, -1, -1, 0, CHAN_SES_PACKET_DEFAULT,
0, xstrdup("server-session"), 1);
if (session_open(id) == 1) {
channel_register_callback(id, SSH2_MSG_CHANNEL_REQUEST,
session_input_channel_req, (void *)0);
channel_register_cleanup(id, session_close_by_channel);
c = channel_lookup(id);
} else {
debug("session open failed, free channel %d", id);
channel_free(id);
}
c = server_request_session(ctype);
} else if (strcmp(ctype, "direct-tcpip") == 0) {
id = input_direct_tcpip();
if (id >= 0)
c = channel_lookup(id);
c = server_request_direct_tcpip(ctype);
}
if (c != NULL) {
debug("confirm %s", ctype);
debug("server_input_channel_open: confirm %s", ctype);
c->remote_id = rchan;
c->remote_window = rwindow;
c->remote_maxpacket = rmaxpack;
@ -830,7 +837,7 @@ server_input_channel_open(int type, int plen, void *ctxt)
packet_put_int(c->local_maxpacket);
packet_send();
} else {
debug("failure %s", ctype);
debug("server_input_channel_open: failure %s", ctype);
packet_start(SSH2_MSG_CHANNEL_OPEN_FAILURE);
packet_put_int(rchan);
packet_put_int(SSH2_OPEN_ADMINISTRATIVELY_PROHIBITED);
@ -841,6 +848,56 @@ server_input_channel_open(int type, int plen, void *ctxt)
xfree(ctype);
}
void
server_input_global_request(int type, int plen, void *ctxt)
{
char *rtype;
int want_reply;
int success = 0;
rtype = packet_get_string(NULL);
want_reply = packet_get_char();
debug("server_input_global_request: rtype %s want_reply %d", rtype, want_reply);
if (strcmp(rtype, "tcpip-forward") == 0) {
struct passwd *pw;
char *listen_address;
u_short listen_port;
pw = auth_get_user();
if (pw == NULL)
fatal("server_input_global_request: no user");
listen_address = packet_get_string(NULL); /* XXX currently ignored */
listen_port = (u_short)packet_get_int();
debug("server_input_global_request: tcpip-forward listen %s port %d",
listen_address, listen_port);
/* check permissions */
if (!options.allow_tcp_forwarding ||
no_port_forwarding_flag ||
(listen_port < IPPORT_RESERVED && pw->pw_uid != 0)) {
success = 0;
packet_send_debug("Server has disabled port forwarding.");
} else {
/* Start listening on the port */
channel_request_forwarding(
listen_address, listen_port,
/*unspec host_to_connect*/ "<unspec host>",
/*unspec port_to_connect*/ 0,
options.gateway_ports, /*remote*/ 1);
success = 1;
}
xfree(listen_address);
}
if (want_reply) {
packet_start(success ?
SSH2_MSG_REQUEST_SUCCESS : SSH2_MSG_REQUEST_FAILURE);
packet_send();
packet_write_wait();
}
xfree(rtype);
}
void
server_init_dispatch_20()
{
@ -855,6 +912,7 @@ server_init_dispatch_20()
dispatch_set(SSH2_MSG_CHANNEL_OPEN_FAILURE, &channel_input_open_failure);
dispatch_set(SSH2_MSG_CHANNEL_REQUEST, &channel_input_channel_request);
dispatch_set(SSH2_MSG_CHANNEL_WINDOW_ADJUST, &channel_input_window_adjust);
dispatch_set(SSH2_MSG_GLOBAL_REQUEST, &server_input_global_request);
}
void
server_init_dispatch_13()

View File

@ -33,7 +33,7 @@
*/
#include "includes.h"
RCSID("$OpenBSD: session.c,v 1.42 2000/10/27 07:32:18 markus Exp $");
RCSID("$OpenBSD: session.c,v 1.43 2000/11/06 23:04:56 markus Exp $");
#include "xmalloc.h"
#include "ssh.h"
@ -1735,6 +1735,19 @@ session_exec_req(Session *s)
return 1;
}
int
session_auth_agent_req(Session *s)
{
static int called = 0;
packet_done();
if (called) {
return 0;
} else {
called = 1;
return auth_input_request_forwarding(s->pw);
}
}
void
session_input_channel_req(int id, void *arg)
{
@ -1771,6 +1784,8 @@ session_input_channel_req(int id, void *arg)
success = session_pty_req(s);
} else if (strcmp(rtype, "x11-req") == 0) {
success = session_x11_req(s);
} else if (strcmp(rtype, "auth-agent-req@openssh.com") == 0) {
success = session_auth_agent_req(s);
} else if (strcmp(rtype, "subsystem") == 0) {
success = session_subsystem_req(s);
}

View File

@ -1,4 +1,4 @@
.\" $OpenBSD: sftp-server.8,v 1.3 2000/10/13 17:20:44 aaron Exp $
.\" $OpenBSD: sftp-server.8,v 1.4 2000/11/10 05:10:40 aaron Exp $
.\"
.\" Copyright (c) 2000 Markus Friedl. All rights reserved.
.\"
@ -48,7 +48,7 @@ for more information.
.Xr ssh-add 1 ,
.Xr ssh-keygen 1 ,
.Xr sshd 8
.Sh AUTHOR
.Sh AUTHORS
Markus Friedl <markus@openbsd.org>
.Sh HISTORY
.Nm

View File

@ -116,7 +116,7 @@ may be necessary to redirect the input from
.Pa /dev/null
to make this work.)
.El
.Sh AUTHOR
.Sh AUTHORS
Tatu Ylonen <ylo@cs.hut.fi>
.Pp
OpenSSH

View File

@ -35,7 +35,7 @@
*/
#include "includes.h"
RCSID("$OpenBSD: ssh-add.c,v 1.22 2000/09/07 20:27:54 deraadt Exp $");
RCSID("$OpenBSD: ssh-add.c,v 1.23 2000/11/12 19:50:38 markus Exp $");
#include <openssl/evp.h>
#include <openssl/rsa.h>
@ -60,10 +60,10 @@ delete_file(AuthenticationConnection *ac, const char *filename)
Key *public;
char *comment;
public = key_new(KEY_RSA);
public = key_new(KEY_RSA1);
if (!load_public_key(filename, public, &comment)) {
key_free(public);
public = key_new(KEY_DSA);
public = key_new(KEY_UNSPEC);
if (!try_load_public_key(filename, public, &comment)) {
printf("Bad key file %s\n", filename);
return;
@ -144,7 +144,7 @@ add_file(AuthenticationConnection *ac, const char *filename)
char buf[1024], msg[1024];
int success;
int interactive = isatty(STDIN_FILENO);
int type = KEY_RSA;
int type = KEY_RSA1;
if (stat(filename, &st) < 0) {
perror(filename);
@ -154,10 +154,10 @@ add_file(AuthenticationConnection *ac, const char *filename)
* try to load the public key. right now this only works for RSA,
* since DSA keys are fully encrypted
*/
public = key_new(KEY_RSA);
public = key_new(KEY_RSA1);
if (!load_public_key(filename, public, &saved_comment)) {
/* ok, so we will asume this is a DSA key */
type = KEY_DSA;
/* ok, so we will assume this is 'some' key */
type = KEY_UNSPEC;
saved_comment = xstrdup(filename);
}
key_free(public);
@ -223,8 +223,9 @@ list_identities(AuthenticationConnection *ac, int fp)
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);
printf("%d %s %s (%s)\n",
key_size(key), key_fingerprint(key),
comment, key_type(key));
} else {
if (!key_write(key, stdout))
fprintf(stderr, "key_write failed");
@ -250,13 +251,6 @@ main(int argc, char **argv)
init_rng();
/* check if RSA support exists */
if (rsa_alive() == 0) {
fprintf(stderr,
"%s: no RSA support in libssl and libcrypto. See ssl(8).\n",
__progname);
exit(1);
}
SSLeay_add_all_algorithms();
/* At first, get a connection to the authentication agent. */

View File

@ -1,4 +1,4 @@
.\" $OpenBSD: ssh-agent.1,v 1.16 2000/09/07 20:27:54 deraadt Exp $
.\" $OpenBSD: ssh-agent.1,v 1.17 2000/11/10 05:10:40 aaron Exp $
.\"
.\" Author: Tatu Ylonen <ylo@cs.hut.fi>
.\" Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@ -160,7 +160,7 @@ authentication agent.
These sockets should only be readable by the owner.
The sockets should get automatically removed when the agent exits.
.El
.Sh AUTHOR
.Sh AUTHORS
Tatu Ylonen <ylo@cs.hut.fi>
.Pp
OpenSSH

View File

@ -1,4 +1,4 @@
/* $OpenBSD: ssh-agent.c,v 1.37 2000/09/21 11:07:51 markus Exp $ */
/* $OpenBSD: ssh-agent.c,v 1.39 2000/11/12 19:50:38 markus Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
@ -37,7 +37,7 @@
*/
#include "includes.h"
RCSID("$OpenBSD: ssh-agent.c,v 1.37 2000/09/21 11:07:51 markus Exp $");
RCSID("$OpenBSD: ssh-agent.c,v 1.39 2000/11/12 19:50:38 markus Exp $");
#include "ssh.h"
#include "rsa.h"
@ -54,7 +54,6 @@ RCSID("$OpenBSD: ssh-agent.c,v 1.37 2000/09/21 11:07:51 markus Exp $");
#include <openssl/rsa.h>
#include "key.h"
#include "authfd.h"
#include "dsa.h"
#include "kex.h"
#include "compat.h"
@ -147,14 +146,14 @@ process_request_identities(SocketEntry *e, int version)
buffer_put_int(&msg, tab->nentries);
for (i = 0; i < tab->nentries; i++) {
Identity *id = &tab->identities[i];
if (id->key->type == KEY_RSA) {
if (id->key->type == KEY_RSA1) {
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);
key_to_blob(id->key, &blob, &blen);
buffer_put_string(&msg, blob, blen);
xfree(blob);
}
@ -178,7 +177,7 @@ process_authentication_challenge1(SocketEntry *e)
unsigned int response_type;
buffer_init(&msg);
key = key_new(KEY_RSA);
key = key_new(KEY_RSA1);
challenge = BN_new();
buffer_get_int(&e->input); /* ignored */
@ -251,11 +250,11 @@ process_sign_request2(SocketEntry *e)
if (flags & SSH_AGENT_OLD_SIGNATURE)
datafellows = SSH_BUG_SIGBLOB;
key = dsa_key_from_blob(blob, blen);
key = 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);
ok = key_sign(private, &signature, &slen, data, dlen);
}
key_free(key);
buffer_init(&msg);
@ -287,7 +286,7 @@ process_remove_identity(SocketEntry *e, int version)
switch(version){
case 1:
key = key_new(KEY_RSA);
key = key_new(KEY_RSA1);
bits = buffer_get_int(&e->input);
buffer_get_bignum(&e->input, key->rsa->e);
buffer_get_bignum(&e->input, key->rsa->n);
@ -298,7 +297,7 @@ process_remove_identity(SocketEntry *e, int version)
break;
case 2:
blob = buffer_get_string(&e->input, &blen);
key = dsa_key_from_blob(blob, blen);
key = key_from_blob(blob, blen);
xfree(blob);
break;
}
@ -315,8 +314,12 @@ process_remove_identity(SocketEntry *e, int version)
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];
if (tab->nentries < 1)
fatal("process_remove_identity: "
"internal error: tab->nentries %d",
tab->nentries);
if (idx != tab->nentries - 1)
tab->identities[idx] = tab->identities[tab->nentries - 1];
tab->nentries--;
success = 1;
}
@ -348,80 +351,81 @@ process_remove_all_identities(SocketEntry *e, int version)
return;
}
void
generate_additional_parameters(RSA *rsa)
{
BIGNUM *aux;
BN_CTX *ctx;
/* Generate additional parameters */
aux = BN_new();
ctx = BN_CTX_new();
BN_sub(aux, rsa->q, BN_value_one());
BN_mod(rsa->dmq1, rsa->d, aux, ctx);
BN_sub(aux, rsa->p, BN_value_one());
BN_mod(rsa->dmp1, rsa->d, aux, ctx);
BN_clear_free(aux);
BN_CTX_free(ctx);
}
void
process_add_identity(SocketEntry *e, int version)
{
Key *k = NULL;
RSA *rsa;
BIGNUM *aux;
BN_CTX *ctx;
char *type;
char *type_name;
char *comment;
int success = 0;
int type, success = 0;
Idtab *tab = idtab_lookup(version);
switch (version) {
case 1:
k = key_new(KEY_RSA);
rsa = k->rsa;
/* allocate mem for private key */
/* XXX rsa->n and rsa->e are already allocated */
rsa->d = BN_new();
rsa->iqmp = BN_new();
rsa->q = BN_new();
rsa->p = BN_new();
rsa->dmq1 = BN_new();
rsa->dmp1 = BN_new();
buffer_get_int(&e->input); /* ignored */
buffer_get_bignum(&e->input, rsa->n);
buffer_get_bignum(&e->input, rsa->e);
buffer_get_bignum(&e->input, rsa->d);
buffer_get_bignum(&e->input, rsa->iqmp);
k = key_new_private(KEY_RSA1);
buffer_get_int(&e->input); /* ignored */
buffer_get_bignum(&e->input, k->rsa->n);
buffer_get_bignum(&e->input, k->rsa->e);
buffer_get_bignum(&e->input, k->rsa->d);
buffer_get_bignum(&e->input, k->rsa->iqmp);
/* SSH and SSL have p and q swapped */
buffer_get_bignum(&e->input, rsa->q); /* p */
buffer_get_bignum(&e->input, rsa->p); /* q */
buffer_get_bignum(&e->input, k->rsa->q); /* p */
buffer_get_bignum(&e->input, k->rsa->p); /* q */
/* Generate additional parameters */
aux = BN_new();
ctx = BN_CTX_new();
BN_sub(aux, rsa->q, BN_value_one());
BN_mod(rsa->dmq1, rsa->d, aux, ctx);
BN_sub(aux, rsa->p, BN_value_one());
BN_mod(rsa->dmp1, rsa->d, aux, ctx);
BN_clear_free(aux);
BN_CTX_free(ctx);
generate_additional_parameters(k->rsa);
break;
case 2:
type = buffer_get_string(&e->input, NULL);
if (strcmp(type, KEX_DSS)) {
type_name = buffer_get_string(&e->input, NULL);
type = key_type_from_name(type_name);
xfree(type_name);
switch(type) {
case KEY_DSA:
k = key_new_private(type);
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;
case KEY_RSA:
k = key_new_private(type);
buffer_get_bignum2(&e->input, k->rsa->n);
buffer_get_bignum2(&e->input, k->rsa->e);
buffer_get_bignum2(&e->input, k->rsa->d);
buffer_get_bignum2(&e->input, k->rsa->iqmp);
buffer_get_bignum2(&e->input, k->rsa->p);
buffer_get_bignum2(&e->input, k->rsa->q);
/* Generate additional parameters */
generate_additional_parameters(k->rsa);
break;
default:
buffer_clear(&e->input);
xfree(type);
goto send;
}
xfree(type);
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);
@ -670,13 +674,6 @@ main(int ac, char **av)
init_rng();
/* check if RSA support exists */
if (rsa_alive() == 0) {
fprintf(stderr,
"%s: no RSA support in libssl and libcrypto. See ssl(8).\n",
__progname);
exit(1);
}
#ifdef __GNU_LIBRARY__
while ((ch = getopt(ac, av, "+cks")) != -1) {
#else /* __GNU_LIBRARY__ */

View File

@ -23,7 +23,7 @@
*/
#include "includes.h"
RCSID("$OpenBSD: dsa.c,v 1.11 2000/09/07 20:27:51 deraadt Exp $");
RCSID("$OpenBSD: ssh-dss.c,v 1.1 2000/11/12 19:50:38 markus Exp $");
#include "ssh.h"
#include "xmalloc.h"
@ -32,88 +32,17 @@ RCSID("$OpenBSD: dsa.c,v 1.11 2000/09/07 20:27:51 deraadt Exp $");
#include "compat.h"
#include <openssl/bn.h>
#include <openssl/dh.h>
#include <openssl/rsa.h>
#include <openssl/dsa.h>
#include <openssl/evp.h>
#include <openssl/bio.h>
#include <openssl/pem.h>
#include <openssl/hmac.h>
#include "kex.h"
#include "key.h"
#include "uuencode.h"
#define INTBLOB_LEN 20
#define SIGBLOB_LEN (2*INTBLOB_LEN)
Key *
dsa_key_from_blob(char *blob, int blen)
{
Buffer b;
char *ktype;
int rlen;
DSA *dsa;
Key *key;
#ifdef DEBUG_DSS
dump_base64(stderr, blob, blen);
#endif
/* fetch & parse DSA/DSS pubkey */
buffer_init(&b);
buffer_append(&b, blob, blen);
ktype = buffer_get_string(&b, NULL);
if (strcmp(KEX_DSS, ktype) != 0) {
error("dsa_key_from_blob: cannot handle type %s", ktype);
buffer_free(&b);
xfree(ktype);
return NULL;
}
key = key_new(KEY_DSA);
dsa = key->dsa;
buffer_get_bignum2(&b, dsa->p);
buffer_get_bignum2(&b, dsa->q);
buffer_get_bignum2(&b, dsa->g);
buffer_get_bignum2(&b, dsa->pub_key);
rlen = buffer_len(&b);
if(rlen != 0)
error("dsa_key_from_blob: remaining bytes in key blob %d", rlen);
buffer_free(&b);
xfree(ktype);
#ifdef DEBUG_DSS
DSA_print_fp(stderr, dsa, 8);
#endif
return key;
}
int
dsa_make_key_blob(Key *key, unsigned char **blobp, unsigned int *lenp)
{
Buffer b;
int len;
unsigned char *buf;
if (key == NULL || key->type != KEY_DSA)
return 0;
buffer_init(&b);
buffer_put_cstring(&b, KEX_DSS);
buffer_put_bignum2(&b, key->dsa->p);
buffer_put_bignum2(&b, key->dsa->q);
buffer_put_bignum2(&b, key->dsa->g);
buffer_put_bignum2(&b, key->dsa->pub_key);
len = buffer_len(&b);
buf = xmalloc(len);
memcpy(buf, buffer_ptr(&b), len);
memset(buffer_ptr(&b), 0, len);
buffer_free(&b);
if (lenp != NULL)
*lenp = len;
if (blobp != NULL)
*blobp = buf;
return len;
}
int
dsa_sign(
ssh_dss_sign(
Key *key,
unsigned char **sigp, int *lenp,
unsigned char *data, int datalen)
@ -130,7 +59,7 @@ dsa_sign(
Buffer b;
if (key == NULL || key->type != KEY_DSA || key->dsa == NULL) {
error("dsa_sign: no DSA key");
error("ssh_dss_sign: no DSA key");
return -1;
}
digest = xmalloc(evp_md->md_size);
@ -140,7 +69,7 @@ dsa_sign(
sig = DSA_do_sign(digest, evp_md->md_size, key->dsa);
if (sig == NULL) {
fatal("dsa_sign: cannot sign");
fatal("ssh_dss_sign: cannot sign");
}
rlen = BN_num_bytes(sig->r);
@ -168,7 +97,7 @@ dsa_sign(
} else {
/* ietf-drafts */
buffer_init(&b);
buffer_put_cstring(&b, KEX_DSS);
buffer_put_cstring(&b, "ssh-dss");
buffer_put_string(&b, sigblob, SIGBLOB_LEN);
len = buffer_len(&b);
ret = xmalloc(len);
@ -182,7 +111,7 @@ dsa_sign(
return 0;
}
int
dsa_verify(
ssh_dss_verify(
Key *key,
unsigned char *signature, int signaturelen,
unsigned char *data, int datalen)
@ -194,12 +123,12 @@ dsa_verify(
EVP_MD_CTX md;
unsigned char *sigblob;
char *txt;
unsigned int len;
unsigned int len, dlen;
int rlen;
int ret;
if (key == NULL || key->type != KEY_DSA || key->dsa == NULL) {
error("dsa_verify: no DSA key");
error("ssh_dss_verify: no DSA key");
return -1;
}
@ -225,8 +154,8 @@ dsa_verify(
buffer_init(&b);
buffer_append(&b, (char *) signature, signaturelen);
ktype = buffer_get_string(&b, NULL);
if (strcmp(KEX_DSS, ktype) != 0) {
error("dsa_verify: cannot handle type %s", ktype);
if (strcmp("ssh-dss", ktype) != 0) {
error("ssh_dss_verify: cannot handle type %s", ktype);
buffer_free(&b);
return -1;
}
@ -258,14 +187,15 @@ dsa_verify(
}
/* sha1 the data */
digest = xmalloc(evp_md->md_size);
dlen = evp_md->md_size;
digest = xmalloc(dlen);
EVP_DigestInit(&md, evp_md);
EVP_DigestUpdate(&md, data, datalen);
EVP_DigestFinal(&md, digest, NULL);
ret = DSA_do_verify(digest, evp_md->md_size, sig, key->dsa);
ret = DSA_do_verify(digest, dlen, sig, key->dsa);
memset(digest, 0, evp_md->md_size);
memset(digest, 0, dlen);
xfree(digest);
DSA_SIG_free(sig);
@ -281,24 +211,6 @@ dsa_verify(
txt = "error";
break;
}
debug("dsa_verify: signature %s", txt);
debug("ssh_dss_verify: signature %s", txt);
return ret;
}
Key *
dsa_generate_key(unsigned int bits)
{
DSA *dsa = DSA_generate_parameters(bits, NULL, 0, NULL, NULL, NULL, NULL);
Key *k;
if (dsa == NULL) {
fatal("DSA_generate_parameters failed");
}
if (!DSA_generate_key(dsa)) {
fatal("DSA_generate_keys failed");
}
k = key_new(KEY_EMPTY);
k->type = KEY_DSA;
k->dsa = dsa;
return k;
}

View File

@ -24,22 +24,16 @@
#ifndef DSA_H
#define DSA_H
Key *dsa_key_from_blob(char *blob, int blen);
int dsa_make_key_blob(Key *key, unsigned char **blobp, unsigned int *lenp);
int
dsa_sign(
ssh_dss_sign(
Key *key,
unsigned char **sigp, int *lenp,
unsigned char *data, int datalen);
int
dsa_verify(
ssh_dss_verify(
Key *key,
unsigned char *signature, int signaturelen,
unsigned char *data, int datalen);
Key *
dsa_generate_key(unsigned int bits);
#endif

View File

@ -43,8 +43,9 @@
.Nd authentication key generation
.Sh SYNOPSIS
.Nm ssh-keygen
.Op Fl dq
.Op Fl q
.Op Fl b Ar bits
.Op Fl t Ar type
.Op Fl N Ar new_passphrase
.Op Fl C Ar comment
.Op Fl f Ar output_keyfile
@ -79,8 +80,8 @@ generates and manages authentication keys for
.Nm
defaults to generating an RSA key for use by protocols 1.3 and 1.5;
specifying the
.Fl d
flag will create a DSA key instead for use by protocol 2.0.
.Fl t
allows you to create a key for use by protocol 2.0.
.Pp
Normally each user wishing to use SSH
with RSA or DSA authentication runs this once to create the authentication
@ -154,6 +155,17 @@ Silence
Used by
.Pa /etc/rc
when creating a new key.
.It Fl t Ar type
Specifies the type of the key to create.
The possible values are
.Dq rsa1
for protocol version 1 and
.Dq rsa
or
.Dq dsa
for protocol version 2.
The default is
.Dq rsa .
.It Fl C Ar comment
Provides the new comment.
.It Fl N Ar new_passphrase
@ -173,7 +185,7 @@ SSH2-compatible private (or public) key file and
print an OpenSSH compatible private (or public) key to stdout.
.It Fl y
This option will read a private
OpenSSH DSA format file and print an OpenSSH DSA public key to stdout.
OpenSSH format file and print an OpenSSH public key to stdout.
.El
.Sh FILES
.Bl -tag -width Ds
@ -211,10 +223,10 @@ Contains the public key for authentication.
The contents of this file should be added to
.Pa $HOME/.ssh/authorized_keys2
on all machines
where you wish to log in using DSA authentication.
where you wish to log in using public key authentication.
There is no need to keep the contents of this file secret.
.El
.Sh AUTHOR
.Sh AUTHORS
Tatu Ylonen <ylo@cs.hut.fi>
.Pp
OpenSSH

View File

@ -12,7 +12,7 @@
*/
#include "includes.h"
RCSID("$OpenBSD: ssh-keygen.c,v 1.32 2000/10/09 21:30:44 markus Exp $");
RCSID("$OpenBSD: ssh-keygen.c,v 1.33 2000/11/12 19:50:38 markus Exp $");
#include <openssl/evp.h>
#include <openssl/pem.h>
@ -23,7 +23,6 @@ RCSID("$OpenBSD: ssh-keygen.c,v 1.32 2000/10/09 21:30:44 markus Exp $");
#include "xmalloc.h"
#include "key.h"
#include "rsa.h"
#include "dsa.h"
#include "authfile.h"
#include "uuencode.h"
@ -67,7 +66,10 @@ char *identity_comment = NULL;
int convert_to_ssh2 = 0;
int convert_from_ssh2 = 0;
int print_public = 0;
int dsa_mode = 0;
/* key type */
int dsa_mode = 0; /* compat */
char *key_type_name = NULL;
/* argv0 */
#ifdef HAVE___PROGNAME
@ -130,12 +132,12 @@ do_convert_to_ssh2(struct passwd *pw)
perror(identity_file);
exit(1);
}
k = key_new(KEY_DSA);
k = key_new(KEY_UNSPEC);
if (!try_load_key(identity_file, k)) {
fprintf(stderr, "load failed\n");
exit(1);
}
dsa_make_key_blob(k, &blob, &len);
key_to_blob(k, &blob, &len);
fprintf(stdout, "%s\n", SSH_COM_PUBLIC_BEGIN);
fprintf(stdout,
"Comment: \"%d-bit %s, converted from OpenSSH by %s@%s\"\n",
@ -266,7 +268,7 @@ do_convert_from_ssh2(struct passwd *pw)
}
k = private ?
do_convert_private_ssh2_from_blob(blob, blen) :
dsa_key_from_blob(blob, blen);
key_from_blob(blob, blen);
if (k == NULL) {
fprintf(stderr, "decode blob failed.\n");
exit(1);
@ -288,8 +290,6 @@ void
do_print_public(struct passwd *pw)
{
Key *k;
int len;
unsigned char *blob;
struct stat st;
if (!have_identity)
@ -298,16 +298,14 @@ do_print_public(struct passwd *pw)
perror(identity_file);
exit(1);
}
k = key_new(KEY_DSA);
k = key_new(KEY_UNSPEC);
if (!try_load_key(identity_file, k)) {
fprintf(stderr, "load failed\n");
exit(1);
}
dsa_make_key_blob(k, &blob, &len);
if (!key_write(k, stdout))
fprintf(stderr, "key_write failed");
key_free(k);
xfree(blob);
fprintf(stdout, "\n");
exit(0);
}
@ -315,12 +313,11 @@ do_print_public(struct passwd *pw)
void
do_fingerprint(struct passwd *pw)
{
/* XXX RSA1 only */
FILE *f;
Key *public;
char *comment = NULL, *cp, *ep, line[16*1024];
int i, skip = 0, num = 1, invalid = 1;
int i, skip = 0, num = 1, invalid = 1, success = 0;
unsigned int ignore;
struct stat st;
@ -330,14 +327,27 @@ do_fingerprint(struct passwd *pw)
perror(identity_file);
exit(1);
}
public = key_new(KEY_RSA);
public = key_new(KEY_RSA1);
if (load_public_key(identity_file, public, &comment)) {
printf("%d %s %s\n", BN_num_bits(public->rsa->n),
key_fingerprint(public), comment);
success = 1;
} else {
key_free(public);
public = key_new(KEY_UNSPEC);
if (try_load_public_key(identity_file, public, &comment))
success = 1;
else
error("try_load_public_key KEY_UNSPEC failed");
}
if (success) {
printf("%d %s %s\n", key_size(public), key_fingerprint(public), comment);
key_free(public);
xfree(comment);
exit(0);
}
/* XXX RSA1 only */
public = key_new(KEY_RSA1);
f = fopen(identity_file, "r");
if (f != NULL) {
while (fgets(line, sizeof(line), f)) {
@ -404,7 +414,7 @@ do_change_passphrase(struct passwd *pw)
struct stat st;
Key *private;
Key *public;
int type = dsa_mode ? KEY_DSA : KEY_RSA;
int type = KEY_RSA1;
if (!have_identity)
ask_filename(pw, "Enter file in which the key is");
@ -412,18 +422,13 @@ do_change_passphrase(struct passwd *pw)
perror(identity_file);
exit(1);
}
if (type == KEY_RSA) {
/* XXX this works currently only for RSA */
public = key_new(type);
if (!load_public_key(identity_file, public, NULL)) {
printf("%s is not a valid key file.\n", identity_file);
exit(1);
}
public = key_new(type);
if (!load_public_key(identity_file, public, NULL)) {
type = KEY_UNSPEC;
} else {
/* Clear the public key since we are just about to load the whole file. */
key_free(public);
}
/* Try to load the file with empty passphrase. */
private = key_new(type);
if (!load_private_key(identity_file, "", private, &comment)) {
@ -508,13 +513,13 @@ do_change_comment(struct passwd *pw)
* Try to load the public key from the file the verify that it is
* readable and of the proper format.
*/
public = key_new(KEY_RSA);
public = key_new(KEY_RSA1);
if (!load_public_key(identity_file, public, NULL)) {
printf("%s is not a valid key file.\n", identity_file);
exit(1);
}
private = key_new(KEY_RSA);
private = key_new(KEY_RSA1);
if (load_private_key(identity_file, "", private, &comment))
passphrase = xstrdup("");
else {
@ -583,7 +588,7 @@ do_change_comment(struct passwd *pw)
void
usage(void)
{
printf("Usage: %s [-lpqxXydc] [-b bits] [-f file] [-C comment] [-N new-pass] [-P pass]\n", __progname);
printf("Usage: %s [-lpqxXyc] [-t type] [-b bits] [-f file] [-C comment] [-N new-pass] [-P pass]\n", __progname);
exit(1);
}
@ -598,8 +603,10 @@ main(int ac, char **av)
int opt;
struct stat st;
FILE *f;
int type = KEY_RSA1;
Key *private;
Key *public;
extern int optind;
extern char *optarg;
@ -618,7 +625,7 @@ main(int ac, char **av)
exit(1);
}
while ((opt = getopt(ac, av, "dqpclRxXyb:f:P:N:C:")) != EOF) {
while ((opt = getopt(ac, av, "dqpclRxXyb:f:t:P:N:C:")) != EOF) {
switch (opt) {
case 'b':
bits = atoi(optarg);
@ -662,10 +669,8 @@ main(int ac, char **av)
break;
case 'R':
if (rsa_alive() == 0)
exit(1);
else
exit(0);
/* unused */
exit(0);
break;
case 'x':
@ -681,9 +686,15 @@ main(int ac, char **av)
break;
case 'd':
key_type_name = "dsa";
dsa_mode = 1;
break;
case 't':
key_type_name = optarg;
dsa_mode = (strcmp(optarg, "dsa") == 0);
break;
case '?':
default:
usage();
@ -697,13 +708,6 @@ main(int ac, char **av)
printf("Can only have one of -p and -c.\n");
usage();
}
/* check if RSA support is needed and exists */
if (dsa_mode == 0 && rsa_alive() == 0) {
fprintf(stderr,
"%s: no RSA support in libssl and libcrypto. See ssl(8).\n",
__progname);
exit(1);
}
if (print_fingerprint)
do_fingerprint(pw);
if (change_passphrase)
@ -719,22 +723,21 @@ main(int ac, char **av)
arc4random_stir();
if (dsa_mode != 0) {
if (!quiet)
printf("Generating DSA parameter and key.\n");
public = private = dsa_generate_key(bits);
if (private == NULL) {
fprintf(stderr, "dsa_generate_keys failed");
if (key_type_name != NULL) {
type = key_type_from_name(key_type_name);
if (type == KEY_UNSPEC) {
fprintf(stderr, "unknown key type %s", key_type_name);
exit(1);
}
} else {
if (quiet)
rsa_set_verbose(0);
/* Generate the rsa key pair. */
public = key_new(KEY_RSA);
private = key_new(KEY_RSA);
rsa_generate_key(private->rsa, public->rsa, bits);
}
if (!quiet)
printf("Generating public/private key pair.\n");
private = key_generate(type, bits);
if (private == NULL) {
fprintf(stderr, "key_generate failed");
exit(1);
}
public = key_from_private(private);
if (!have_identity)
ask_filename(pw, "Enter file in which to save the key");
@ -803,9 +806,7 @@ passphrase_again:
xfree(passphrase1);
/* Clear the private key and the random number generator. */
if (private != public) {
key_free(private);
}
key_free(private);
arc4random_stir();
if (!quiet)

163
ssh-rsa.c Normal file
View File

@ -0,0 +1,163 @@
/*
* Copyright (c) 2000 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.
*
* 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: ssh-rsa.c,v 1.1 2000/11/12 19:50:38 markus Exp $");
#include "ssh.h"
#include "xmalloc.h"
#include "buffer.h"
#include "bufaux.h"
#include <openssl/evp.h>
#include <openssl/dsa.h>
#include <openssl/rsa.h>
#include <openssl/err.h>
#include "key.h"
#define INTBLOB_LEN 20
#define SIGBLOB_LEN (2*INTBLOB_LEN)
/* RSASSA-PKCS1-v1_5 (PKCS #1 v2.0 signature) with SHA1 */
int
ssh_rsa_sign(
Key *key,
unsigned char **sigp, int *lenp,
unsigned char *data, int datalen)
{
EVP_MD *evp_md = EVP_sha1();
EVP_MD_CTX md;
unsigned char *digest, *sig, *ret;
unsigned int slen, dlen, len;
int ok;
Buffer b;
if (key == NULL || key->type != KEY_RSA || key->rsa == NULL) {
error("ssh_rsa_sign: no RSA key");
return -1;
}
slen = RSA_size(key->rsa);
sig = xmalloc(slen);
dlen = evp_md->md_size;
digest = xmalloc(dlen);
EVP_DigestInit(&md, evp_md);
EVP_DigestUpdate(&md, data, datalen);
EVP_DigestFinal(&md, digest, NULL);
ok = RSA_sign(NID_sha1, digest, dlen, sig, &len, key->rsa);
memset(digest, 'd', dlen);
xfree(digest);
if (ok != 1) {
int ecode = ERR_get_error();
error("ssh_rsa_sign: RSA_sign failed: %s", ERR_error_string(ecode, NULL));
xfree(sig);
return -1;
}
if (len < slen) {
int diff = slen - len;
debug("slen %d > len %d", slen, len);
memmove(sig + diff, sig, len);
memset(sig, 0, diff);
} else if (len > slen) {
error("ssh_rsa_sign: slen %d slen2 %d", slen, len);
xfree(sig);
return -1;
}
/* encode signature */
buffer_init(&b);
buffer_put_cstring(&b, "ssh-rsa");
buffer_put_string(&b, sig, slen);
len = buffer_len(&b);
ret = xmalloc(len);
memcpy(ret, buffer_ptr(&b), len);
buffer_free(&b);
memset(sig, 's', slen);
xfree(sig);
if (lenp != NULL)
*lenp = len;
if (sigp != NULL)
*sigp = ret;
debug2("ssh_rsa_sign: done");
return 0;
}
int
ssh_rsa_verify(
Key *key,
unsigned char *signature, int signaturelen,
unsigned char *data, int datalen)
{
Buffer b;
EVP_MD *evp_md = EVP_sha1();
EVP_MD_CTX md;
char *ktype;
unsigned char *sigblob, *digest;
unsigned int len, dlen;
int rlen;
int ret;
if (key == NULL || key->type != KEY_RSA || key->rsa == NULL) {
error("ssh_rsa_verify: no RSA key");
return -1;
}
buffer_init(&b);
buffer_append(&b, (char *) signature, signaturelen);
ktype = buffer_get_string(&b, NULL);
if (strcmp("ssh-rsa", ktype) != 0) {
error("ssh_rsa_verify: cannot handle type %s", ktype);
buffer_free(&b);
xfree(ktype);
return -1;
}
xfree(ktype);
sigblob = (unsigned char *)buffer_get_string(&b, &len);
rlen = buffer_len(&b);
buffer_free(&b);
if(rlen != 0) {
error("ssh_rsa_verify: remaining bytes in signature %d", rlen);
return -1;
}
dlen = evp_md->md_size;
digest = xmalloc(dlen);
EVP_DigestInit(&md, evp_md);
EVP_DigestUpdate(&md, data, datalen);
EVP_DigestFinal(&md, digest, NULL);
ret = RSA_verify(NID_sha1, digest, dlen, sigblob, len, key->rsa);
memset(digest, 'd', dlen);
xfree(digest);
memset(sigblob, 's', len);
xfree(sigblob);
if (ret == 0) {
int ecode = ERR_get_error();
error("ssh_rsa_verify: RSA_verify failed: %s", ERR_error_string(ecode, NULL));
}
debug("ssh_rsa_verify: signature %scorrect", (ret==0) ? "in" : "");
return ret;
}

39
ssh-rsa.h Normal file
View File

@ -0,0 +1,39 @@
/*
* Copyright (c) 2000 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.
*
* 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.
*/
#ifndef SSH_RSA_H
#define SSH_RSA_H
int
ssh_rsa_sign(
Key *key,
unsigned char **sigp, int *lenp,
unsigned char *data, int datalen);
int
ssh_rsa_verify(
Key *key,
unsigned char *signature, int signaturelen,
unsigned char *data, int datalen);
#endif

53
ssh.1
View File

@ -34,7 +34,7 @@
.\" (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: ssh.1,v 1.64 2000/10/16 21:46:31 markus Exp $
.\" $OpenBSD: ssh.1,v 1.68 2000/11/12 19:50:38 markus Exp $
.Dd September 25, 1999
.Dt SSH 1
.Os
@ -209,9 +209,9 @@ At first, the client attempts to authenticate using the public key method.
If this method fails password authentication is tried.
.Pp
The public key method is similar to RSA authentication described
in the previous section except that the DSA algorithm is used
instead of the patented RSA algorithm.
The client uses his private DSA key
in the previous section except that the DSA or RSA algorithm is used
instead.
The client uses his private key
.Pa $HOME/.ssh/id_dsa
to sign the session identifier and sends the result to the server.
The server checks whether the matching public key is listed in
@ -331,7 +331,7 @@ identifications for all hosts it has ever been used with.
RSA host keys are stored in
.Pa $HOME/.ssh/known_hosts
and
DSA host keys are stored in
host keys used in the protocol version 2 are stored in
.Pa $HOME/.ssh/known_hosts2
in the user's home directory.
Additionally, the files
@ -352,7 +352,8 @@ The
.Cm StrictHostKeyChecking
option (see below) can be used to prevent logins to machines whose
host key is not known or has changed.
.Sh OPTIONS
.Pp
The options are as follows:
.Bl -tag -width Ds
.It Fl a
Disables forwarding of the authentication agent connection.
@ -407,7 +408,7 @@ something like
Allows remote hosts to connect to local forwarded ports.
.It Fl i Ar identity_file
Selects the file from which the identity (private key) for
RSA authentication is read.
RSA or DSA authentication is read.
Default is
.Pa $HOME/.ssh/identity
in the user's home directory.
@ -552,6 +553,22 @@ Forces
.Nm
to use IPv6 addresses only.
.El
.Pp
If
.Nm
is not invoked with one of the standard program names
.Pf ( Dq ssh ,
.Dq slogin ,
.Dq rsh ,
.Dq rlogin ,
or
.Dq remsh ) ,
it uses this name as its
.Ar hostname
argument.
This is consistent with traditional
.Xr rsh 1
behavior.
.Sh CONFIGURATION FILES
.Nm
obtains configuration data from the following sources (in this order):
@ -660,14 +677,12 @@ Specifies the number of tries (one per second) to make before falling
back to rsh or exiting.
The argument must be an integer.
This may be useful in scripts if the connection sometimes fails.
.It Cm DSAAuthentication
Specifies whether to try DSA authentication.
.It Cm PubkeyAuthentication
Specifies whether to try public key authentication.
The argument to this keyword must be
.Dq yes
or
.Dq no .
DSA authentication will only be
attempted if a DSA identity file exists.
Note that this option applies to protocol version 2 only.
.It Cm EscapeChar
Sets the escape character (default:
@ -745,16 +760,6 @@ syntax to refer to a user's home directory.
It is possible to have
multiple identity files specified in configuration files; all these
identities will be tried in sequence.
.It Cm IdentityFile2
Specifies the file from which the user's DSA authentication identity
is read (default
.Pa $HOME/.ssh/id_dsa
in the user's home directory).
The file name may use the tilde
syntax to refer to a user's home directory.
It is possible to have
multiple identity files specified in configuration files; all these
identities will be tried in sequence.
.It Cm KeepAlive
Specifies whether the system should send keepalive messages to the
other side.
@ -1096,7 +1101,7 @@ spaces).
This file is not highly sensitive, but the recommended
permissions are read/write for the user, and not accessible by others.
.It Pa $HOME/.ssh/authorized_keys2
Lists the DSA keys that can be used for logging in as this user.
Lists the public keys (DSA/RSA) that can be used for logging in as this user.
This file is not highly sensitive, but the recommended
permissions are read/write for the user, and not accessible by others.
.It Pa /etc/ssh_known_hosts, /etc/ssh_known_hosts2
@ -1104,7 +1109,7 @@ Systemwide list of known host keys.
.Pa /etc/ssh_known_hosts
contains RSA and
.Pa /etc/ssh_known_hosts2
contains DSA keys.
contains DSA or RSA keys for protocol version 2.
These files should be prepared by the
system administrator to contain the public host keys of all machines in the
organization.
@ -1219,7 +1224,7 @@ above.
A version of this library which includes support for the RSA algorithm
is required for proper operation.
.El
.Sh AUTHOR
.Sh AUTHORS
OpenSSH
is a derivative of the original (free) ssh 1.2.12 release by Tatu Ylonen,
but with bugs removed and newer features re-added.

193
ssh.c
View File

@ -39,11 +39,12 @@
*/
#include "includes.h"
RCSID("$OpenBSD: ssh.c,v 1.69 2000/10/27 07:32:19 markus Exp $");
RCSID("$OpenBSD: ssh.c,v 1.72 2000/11/12 19:50:38 markus Exp $");
#include <openssl/evp.h>
#include <openssl/dsa.h>
#include <openssl/rsa.h>
#include <openssl/err.h>
#include "xmalloc.h"
#include "ssh.h"
@ -218,8 +219,9 @@ rsh_connect(char *host, char *user, Buffer * command)
exit(1);
}
int ssh_session(void);
int ssh_session2(void);
int ssh_session(void);
int ssh_session2(void);
int guess_identity_file_type(const char *filename);
/*
* Main program for the ssh client.
@ -370,14 +372,13 @@ main(int ac, char **av)
case 'i':
if (stat(optarg, &st) < 0) {
fprintf(stderr, "Warning: Identity file %s does not exist.\n",
optarg);
optarg);
break;
}
if (options.num_identity_files >= SSH_MAX_IDENTITY_FILES)
fatal("Too many identity files specified (max %d)",
SSH_MAX_IDENTITY_FILES);
options.identity_files[options.num_identity_files++] =
xstrdup(optarg);
SSH_MAX_IDENTITY_FILES);
options.identity_files[options.num_identity_files++] = xstrdup(optarg);
break;
case 't':
tty_flag = 1;
@ -487,6 +488,7 @@ main(int ac, char **av)
usage();
SSLeay_add_all_algorithms();
ERR_load_crypto_strings();
/* Initialize the command to execute on remote host. */
buffer_init(&command);
@ -563,20 +565,6 @@ main(int ac, char **av)
/* reinit */
log_init(av[0], options.log_level, SYSLOG_FACILITY_USER, 0);
/* check if RSA support exists */
if ((options.protocol & SSH_PROTO_1) &&
rsa_alive() == 0) {
log("%s: no RSA support in libssl and libcrypto. See ssl(8).",
__progname);
log("Disabling protocol version 1");
options.protocol &= ~ (SSH_PROTO_1|SSH_PROTO_1_PREFERRED);
}
if (! options.protocol & (SSH_PROTO_1|SSH_PROTO_2)) {
fprintf(stderr, "%s: No protocol version available.\n",
__progname);
exit(1);
}
if (options.user == NULL)
options.user = xstrdup(pw->pw_name);
@ -589,6 +577,8 @@ main(int ac, char **av)
if (!options.use_privileged_port) {
#else
if (original_effective_uid != 0 || !options.use_privileged_port) {
debug("Rhosts Authentication methods disabled, "
"originating port will not be trusted.");
#endif
options.rhosts_authentication = 0;
options.rhosts_rsa_authentication = 0;
@ -635,7 +625,7 @@ main(int ac, char **av)
if (ok && (options.protocol & SSH_PROTO_1)) {
Key k;
host_private_key = RSA_new();
k.type = KEY_RSA;
k.type = KEY_RSA1;
k.rsa = host_private_key;
if (load_private_key(HOST_KEY_FILE, "", &k, NULL))
host_private_key_loaded = 1;
@ -682,23 +672,23 @@ main(int ac, char **av)
}
exit(1);
}
/* Expand ~ in options.identity_files. */
/* Expand ~ in options.identity_files, known host file names. */
/* XXX mem-leaks */
for (i = 0; i < options.num_identity_files; i++)
for (i = 0; i < options.num_identity_files; i++) {
options.identity_files[i] =
tilde_expand_filename(options.identity_files[i], original_real_uid);
for (i = 0; i < options.num_identity_files2; i++)
options.identity_files2[i] =
tilde_expand_filename(options.identity_files2[i], original_real_uid);
/* Expand ~ in known host file names. */
options.system_hostfile = tilde_expand_filename(options.system_hostfile,
original_real_uid);
options.user_hostfile = tilde_expand_filename(options.user_hostfile,
original_real_uid);
options.system_hostfile2 = tilde_expand_filename(options.system_hostfile2,
original_real_uid);
options.user_hostfile2 = tilde_expand_filename(options.user_hostfile2,
original_real_uid);
tilde_expand_filename(options.identity_files[i], original_real_uid);
options.identity_files_type[i] = guess_identity_file_type(options.identity_files[i]);
debug("identity file %s type %d", options.identity_files[i],
options.identity_files_type[i]);
}
options.system_hostfile =
tilde_expand_filename(options.system_hostfile, original_real_uid);
options.user_hostfile =
tilde_expand_filename(options.user_hostfile, original_real_uid);
options.system_hostfile2 =
tilde_expand_filename(options.system_hostfile2, original_real_uid);
options.user_hostfile2 =
tilde_expand_filename(options.user_hostfile2, original_real_uid);
/* Log into the remote system. This never returns if the login fails. */
ssh_login(host_private_key_loaded, host_private_key,
@ -752,16 +742,57 @@ x11_get_proto(char *proto, int proto_len, char *data, int data_len)
}
}
void
ssh_init_forwarding(void)
{
int i;
/* Initiate local TCP/IP port forwardings. */
for (i = 0; i < options.num_local_forwards; i++) {
debug("Connections to local port %d forwarded to remote address %.200s:%d",
options.local_forwards[i].port,
options.local_forwards[i].host,
options.local_forwards[i].host_port);
channel_request_local_forwarding(
options.local_forwards[i].port,
options.local_forwards[i].host,
options.local_forwards[i].host_port,
options.gateway_ports);
}
/* Initiate remote TCP/IP port forwardings. */
for (i = 0; i < options.num_remote_forwards; i++) {
debug("Connections to remote port %d forwarded to local address %.200s:%d",
options.remote_forwards[i].port,
options.remote_forwards[i].host,
options.remote_forwards[i].host_port);
channel_request_remote_forwarding(
options.remote_forwards[i].port,
options.remote_forwards[i].host,
options.remote_forwards[i].host_port);
}
}
void
check_agent_present(void)
{
if (options.forward_agent) {
/* Clear agent forwarding if we don\'t have an agent. */
int authfd = ssh_get_authentication_socket();
if (authfd < 0)
options.forward_agent = 0;
else
ssh_close_authentication_socket(authfd);
}
}
int
ssh_session(void)
{
int type;
int i;
int plen;
int interactive = 0;
int have_tty = 0;
struct winsize ws;
int authfd;
char *cp;
/* Enable compression if requested. */
@ -845,14 +876,10 @@ ssh_session(void)
/* Tell the packet module whether this is an interactive session. */
packet_set_interactive(interactive, options.keepalives);
/* Clear agent forwarding if we don\'t have an agent. */
authfd = ssh_get_authentication_socket();
if (authfd < 0)
options.forward_agent = 0;
else
ssh_close_authentication_socket(authfd);
/* Request authentication agent forwarding if appropriate. */
check_agent_present();
if (options.forward_agent) {
debug("Requesting authentication agent forwarding.");
auth_request_forwarding();
@ -863,28 +890,9 @@ ssh_session(void)
if (type != SSH_SMSG_SUCCESS)
log("Warning: Remote host denied authentication agent forwarding.");
}
/* Initiate local TCP/IP port forwardings. */
for (i = 0; i < options.num_local_forwards; i++) {
debug("Connections to local port %d forwarded to remote address %.200s:%d",
options.local_forwards[i].port,
options.local_forwards[i].host,
options.local_forwards[i].host_port);
channel_request_local_forwarding(options.local_forwards[i].port,
options.local_forwards[i].host,
options.local_forwards[i].host_port,
options.gateway_ports);
}
/* Initiate remote TCP/IP port forwardings. */
for (i = 0; i < options.num_remote_forwards; i++) {
debug("Connections to remote port %d forwarded to local address %.200s:%d",
options.remote_forwards[i].port,
options.remote_forwards[i].host,
options.remote_forwards[i].host_port);
channel_request_remote_forwarding(options.remote_forwards[i].port,
options.remote_forwards[i].host,
options.remote_forwards[i].host_port);
}
/* Initiate port forwardings. */
ssh_init_forwarding();
/* If requested, let ssh continue in the background. */
if (fork_after_authentication_flag)
@ -915,27 +923,10 @@ ssh_session(void)
return client_loop(have_tty, tty_flag ? options.escape_char : -1, 0);
}
void
init_local_fwd(void)
{
int i;
/* Initiate local TCP/IP port forwardings. */
for (i = 0; i < options.num_local_forwards; i++) {
debug("Connections to local port %d forwarded to remote address %.200s:%d",
options.local_forwards[i].port,
options.local_forwards[i].host,
options.local_forwards[i].host_port);
channel_request_local_forwarding(options.local_forwards[i].port,
options.local_forwards[i].host,
options.local_forwards[i].host_port,
options.gateway_ports);
}
}
extern void client_set_session_ident(int id);
void
client_init(int id, void *arg)
ssh_session2_callback(int id, void *arg)
{
int len;
debug("client_init id %d arg %d", id, (int)arg);
@ -974,6 +965,13 @@ client_init(int id, void *arg)
/* XXX wait for reply */
}
check_agent_present();
if (options.forward_agent) {
debug("Requesting authentication agent forwarding.");
channel_request_start(id, "auth-agent-req@openssh.com", 0);
packet_send();
}
len = buffer_len(&command);
if (len > 0) {
if (len > 900)
@ -1016,8 +1014,8 @@ ssh_session2(void)
if (!isatty(err))
set_nonblock(err);
/* should be pre-session */
init_local_fwd();
/* XXX should be pre-session */
ssh_init_forwarding();
/* If requested, let ssh continue in the background. */
if (fork_after_authentication_flag)
@ -1036,7 +1034,28 @@ ssh_session2(void)
xstrdup("client-session"), /*nonblock*/0);
channel_open(id);
channel_register_callback(id, SSH2_MSG_CHANNEL_OPEN_CONFIRMATION, client_init, (void *)0);
channel_register_callback(id, SSH2_MSG_CHANNEL_OPEN_CONFIRMATION,
ssh_session2_callback, (void *)0);
return client_loop(tty_flag, tty_flag ? options.escape_char : -1, id);
}
int
guess_identity_file_type(const char *filename)
{
struct stat st;
Key *public;
int type = KEY_RSA1; /* default */
if (stat(filename, &st) < 0) {
perror(filename);
return KEY_UNSPEC;
}
public = key_new(type);
if (!load_public_key(filename, public, NULL)) {
/* ok, so we will assume this is 'some' key */
type = KEY_UNSPEC;
}
key_free(public);
return type;
}

View File

@ -13,9 +13,9 @@
# Site-wide defaults for various options
# Host *
# ForwardAgent yes
# ForwardX11 yes
# RhostsAuthentication yes
# ForwardAgent no
# ForwardX11 no
# RhostsAuthentication no
# RhostsRSAAuthentication yes
# RSAAuthentication yes
# PasswordAuthentication yes
@ -23,9 +23,12 @@
# UseRsh no
# BatchMode no
# CheckHostIP yes
# StrictHostKeyChecking no
# StrictHostKeyChecking yes
# IdentityFile ~/.ssh/identity
# IdentityFile ~/.ssh/id_dsa
# IdentityFile ~/.ssh/id_rsa1
# IdentityFile ~/.ssh/id_rsa2
# Port 22
# Protocol 2,1
# Protocol 1,2
# Cipher blowfish
# EscapeChar ~

View File

@ -13,7 +13,7 @@
*/
#include "includes.h"
RCSID("$OpenBSD: sshconnect.c,v 1.79 2000/09/17 15:52:51 markus Exp $");
RCSID("$OpenBSD: sshconnect.c,v 1.81 2000/11/06 23:16:35 markus Exp $");
#include <openssl/bn.h>
#include <openssl/dsa.h>
@ -249,9 +249,9 @@ ssh_connect(const char *host, struct sockaddr_storage * hostaddr,
/* Create a socket for connecting. */
sock = ssh_create_socket(original_real_uid,
#ifdef HAVE_CYGWIN
!anonymous && port < IPPORT_RESERVED,
!anonymous,
#else
!anonymous && geteuid() == 0 && port < IPPORT_RESERVED,
!anonymous && geteuid() == 0,
#endif
ai->ai_family);
if (sock < 0)
@ -321,6 +321,7 @@ ssh_exchange_identification()
int remote_major, remote_minor, i, mismatch;
int connection_in = packet_get_connection_in();
int connection_out = packet_get_connection_out();
int minor1 = PROTOCOL_MINOR_1;
/* Read other side\'s version identification. */
for (;;) {
@ -374,9 +375,10 @@ ssh_exchange_identification()
}
if (remote_minor < 3) {
fatal("Remote machine has too old SSH software version.");
} else if (remote_minor == 3) {
} else if (remote_minor == 3 || remote_minor == 4) {
/* We speak 1.3, too. */
enable_compat13();
minor1 = 3;
if (options.forward_agent) {
log("Agent forwarding disabled for protocol 1.3");
options.forward_agent = 0;
@ -402,7 +404,7 @@ ssh_exchange_identification()
/* Send our own protocol version identification. */
snprintf(buf, sizeof buf, "SSH-%d.%d-%.100s\n",
compat20 ? PROTOCOL_MAJOR_2 : PROTOCOL_MAJOR_1,
compat20 ? PROTOCOL_MINOR_2 : PROTOCOL_MINOR_1,
compat20 ? PROTOCOL_MINOR_2 : minor1,
SSH_VERSION);
if (atomicio(write, connection_out, buf, strlen(buf)) != strlen(buf))
fatal("write: %.100s", strerror(errno));

View File

@ -13,7 +13,7 @@
*/
#include "includes.h"
RCSID("$OpenBSD: sshconnect1.c,v 1.8 2000/10/12 09:59:19 markus Exp $");
RCSID("$OpenBSD: sshconnect1.c,v 1.9 2000/11/12 19:50:38 markus Exp $");
#include <openssl/bn.h>
#include <openssl/dsa.h>
@ -62,7 +62,7 @@ try_agent_authentication()
return 0;
challenge = BN_new();
key = key_new(KEY_RSA);
key = key_new(KEY_RSA1);
/* Loop through identities served by the agent. */
for (key = ssh_get_first_identity(auth, &comment, 1);
@ -196,7 +196,7 @@ try_rsa_authentication(const char *authfile)
int plen, clen;
/* Try to load identification for the authentication key. */
public = key_new(KEY_RSA);
public = key_new(KEY_RSA1);
if (!load_public_key(authfile, public, &comment)) {
key_free(public);
/* Could not load it. Fail. */
@ -237,7 +237,7 @@ try_rsa_authentication(const char *authfile)
debug("Received RSA challenge from server.");
private = key_new(KEY_RSA);
private = key_new(KEY_RSA1);
/*
* Load the private key. Try first with empty passphrase; if it
* fails, ask for a passphrase.
@ -760,7 +760,7 @@ ssh_kex(char *host, struct sockaddr *hostaddr)
packet_integrity_check(payload_len,
8 + 4 + sum_len + 0 + 4 + 0 + 0 + 4 + 4 + 4,
SSH_SMSG_PUBLIC_KEY);
k.type = KEY_RSA;
k.type = KEY_RSA1;
k.rsa = host_key;
check_host_key(host, hostaddr, &k,
options.user_hostfile, options.system_hostfile);
@ -994,7 +994,8 @@ ssh_userauth(
/* Try RSA authentication for each identity. */
for (i = 0; i < options.num_identity_files; i++)
if (try_rsa_authentication(options.identity_files[i]))
if (options.identity_files_type[i] == KEY_RSA1 &&
try_rsa_authentication(options.identity_files[i]))
return;
}
/* Try skey authentication if the server supports it. */

View File

@ -23,7 +23,7 @@
*/
#include "includes.h"
RCSID("$OpenBSD: sshconnect2.c,v 1.27 2000/10/19 16:45:16 provos Exp $");
RCSID("$OpenBSD: sshconnect2.c,v 1.28 2000/11/12 19:50:38 markus Exp $");
#include <openssl/bn.h>
#include <openssl/rsa.h>
@ -45,7 +45,6 @@ RCSID("$OpenBSD: sshconnect2.c,v 1.27 2000/10/19 16:45:16 provos Exp $");
#include "kex.h"
#include "myproposal.h"
#include "key.h"
#include "dsa.h"
#include "sshconnect.h"
#include "authfile.h"
#include "cli.h"
@ -196,7 +195,7 @@ ssh_dh1_client(Kex *kex, char *host, struct sockaddr *hostaddr,
/* key, cert */
server_host_key_blob = packet_get_string(&sbloblen);
server_host_key = dsa_key_from_blob(server_host_key_blob, sbloblen);
server_host_key = key_from_blob(server_host_key_blob, sbloblen);
if (server_host_key == NULL)
fatal("cannot decode server_host_key_blob");
@ -258,8 +257,8 @@ ssh_dh1_client(Kex *kex, char *host, struct sockaddr *hostaddr,
fprintf(stderr, "%02x", (hash[i])&0xff);
fprintf(stderr, "\n");
#endif
if (dsa_verify(server_host_key, (unsigned char *)signature, slen, hash, 20) != 1)
fatal("dsa_verify failed for server_host_key");
if (key_verify(server_host_key, (unsigned char *)signature, slen, hash, 20) != 1)
fatal("key_verify failed for server_host_key");
key_free(server_host_key);
kex_derive_keys(kex, hash, shared_secret);
@ -366,7 +365,7 @@ ssh_dhgex_client(Kex *kex, char *host, struct sockaddr *hostaddr,
/* key, cert */
server_host_key_blob = packet_get_string(&sbloblen);
server_host_key = dsa_key_from_blob(server_host_key_blob, sbloblen);
server_host_key = key_from_blob(server_host_key_blob, sbloblen);
if (server_host_key == NULL)
fatal("cannot decode server_host_key_blob");
@ -429,8 +428,8 @@ ssh_dhgex_client(Kex *kex, char *host, struct sockaddr *hostaddr,
fprintf(stderr, "%02x", (hash[i])&0xff);
fprintf(stderr, "\n");
#endif
if (dsa_verify(server_host_key, (unsigned char *)signature, slen, hash, 20) != 1)
fatal("dsa_verify failed for server_host_key");
if (key_verify(server_host_key, (unsigned char *)signature, slen, hash, 20) != 1)
fatal("key_verify failed for server_host_key");
key_free(server_host_key);
kex_derive_keys(kex, hash, shared_secret);
@ -485,7 +484,7 @@ Authmethod *authmethod_lookup(const char *name);
Authmethod authmethods[] = {
{"publickey",
userauth_pubkey,
&options.dsa_authentication,
&options.pubkey_authentication,
NULL},
{"password",
userauth_passwd,
@ -653,8 +652,10 @@ sign_and_send_pubkey(Authctxt *authctxt, Key *k, sign_cb_fn *sign_callback)
int ret = -1;
int have_sig = 1;
dsa_make_key_blob(k, &blob, &bloblen);
if (key_to_blob(k, &blob, &bloblen) == 0) {
/* we cannot handle this key */
return 0;
}
/* data to be signed */
buffer_init(&b);
if (datafellows & SSH_OLD_SESSIONID) {
@ -672,7 +673,7 @@ sign_and_send_pubkey(Authctxt *authctxt, Key *k, sign_cb_fn *sign_callback)
authctxt->service);
buffer_put_cstring(&b, authctxt->method->name);
buffer_put_char(&b, have_sig);
buffer_put_cstring(&b, KEX_DSS);
buffer_put_cstring(&b, key_ssh_name(k));
buffer_put_string(&b, blob, bloblen);
/* generate signature */
@ -682,7 +683,7 @@ sign_and_send_pubkey(Authctxt *authctxt, Key *k, sign_cb_fn *sign_callback)
buffer_free(&b);
return 0;
}
#ifdef DEBUG_DSS
#ifdef DEBUG_PK
buffer_dump(&b);
#endif
if (datafellows & SSH_BUG_PUBKEYAUTH) {
@ -693,7 +694,7 @@ sign_and_send_pubkey(Authctxt *authctxt, Key *k, sign_cb_fn *sign_callback)
buffer_put_cstring(&b, authctxt->service);
buffer_put_cstring(&b, authctxt->method->name);
buffer_put_char(&b, have_sig);
buffer_put_cstring(&b, KEX_DSS);
buffer_put_cstring(&b, key_ssh_name(k));
buffer_put_string(&b, blob, bloblen);
}
xfree(blob);
@ -719,10 +720,10 @@ sign_and_send_pubkey(Authctxt *authctxt, Key *k, sign_cb_fn *sign_callback)
}
/* sign callback */
int dsa_sign_cb(Authctxt *authctxt, Key *key, unsigned char **sigp, int *lenp,
int key_sign_cb(Authctxt *authctxt, Key *key, unsigned char **sigp, int *lenp,
unsigned char *data, int datalen)
{
return dsa_sign(key, sigp, lenp, data, datalen);
return key_sign(key, sigp, lenp, data, datalen);
}
int
@ -738,14 +739,13 @@ userauth_pubkey_identity(Authctxt *authctxt, char *filename)
}
debug("try pubkey: %s", filename);
k = key_new(KEY_DSA);
k = key_new(KEY_UNSPEC);
if (!load_private_key(filename, "", k, NULL)) {
int success = 0;
char *passphrase;
char prompt[300];
snprintf(prompt, sizeof prompt,
"Enter passphrase for %s key '%.100s': ",
key_type(k), filename);
"Enter passphrase for key '%.100s': ", filename);
for (i = 0; i < options.number_of_password_prompts; i++) {
passphrase = read_passphrase(prompt, 0);
if (strcmp(passphrase, "") != 0) {
@ -766,7 +766,7 @@ userauth_pubkey_identity(Authctxt *authctxt, char *filename)
return 0;
}
}
ret = sign_and_send_pubkey(authctxt, k, dsa_sign_cb);
ret = sign_and_send_pubkey(authctxt, k, key_sign_cb);
key_free(k);
return ret;
}
@ -782,24 +782,26 @@ int
userauth_pubkey_agent(Authctxt *authctxt)
{
static int called = 0;
int ret = 0;
char *comment;
Key *k;
int ret;
if (called == 0) {
k = ssh_get_first_identity(authctxt->agent, &comment, 2);
if (ssh_get_num_identities(authctxt->agent, 2) == 0)
debug2("userauth_pubkey_agent: no keys at all");
called = 1;
} else {
k = ssh_get_next_identity(authctxt->agent, &comment, 2);
}
k = ssh_get_next_identity(authctxt->agent, &comment, 2);
if (k == NULL) {
debug2("no more DSA keys from agent");
return 0;
debug2("userauth_pubkey_agent: no more keys");
} else {
debug("userauth_pubkey_agent: trying agent key %s", comment);
xfree(comment);
ret = sign_and_send_pubkey(authctxt, k, agent_sign_cb);
key_free(k);
}
debug("trying DSA agent key %s", comment);
xfree(comment);
ret = sign_and_send_pubkey(authctxt, k, agent_sign_cb);
key_free(k);
if (ret == 0)
debug2("userauth_pubkey_agent: no message sent");
return ret;
}
@ -809,10 +811,17 @@ userauth_pubkey(Authctxt *authctxt)
static int idx = 0;
int sent = 0;
if (authctxt->agent != NULL)
sent = userauth_pubkey_agent(authctxt);
while (sent == 0 && idx < options.num_identity_files2)
sent = userauth_pubkey_identity(authctxt, options.identity_files2[idx++]);
if (authctxt->agent != NULL) {
do {
sent = userauth_pubkey_agent(authctxt);
} while(!sent && authctxt->agent->howmany > 0);
}
while (!sent && idx < options.num_identity_files) {
if (options.identity_files_type[idx] != KEY_RSA1)
sent = userauth_pubkey_identity(authctxt,
options.identity_files[idx]);
idx++;
}
return sent;
}

30
sshd.8
View File

@ -34,7 +34,7 @@
.\" (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: sshd.8,v 1.70 2000/10/16 09:38:44 djm Exp $
.\" $OpenBSD: sshd.8,v 1.72 2000/11/12 19:50:38 markus Exp $
.Dd September 25, 1999
.Dt SSHD 8
.Os
@ -144,7 +144,7 @@ through a cryptographic message authentication code
(hmac-sha1 or hmac-md5).
.Pp
Protocol version 2 provides a public key based
user authentication method (DSAAuthentication)
user authentication method (PubkeyAuthentication)
and conventional password authentication.
.Pp
.Ss Command execution and data forwarding
@ -359,8 +359,8 @@ and
can be used as wildcards in the patterns.
Only user names are valid; a numerical user ID isn't recognized.
By default login is allowed regardless of the user name.
.It Cm DSAAuthentication
Specifies whether DSA authentication is allowed.
.It Cm PubkeyAuthentication
Specifies whether public key authentication is allowed.
The default is
.Dq yes .
Note that this option applies to protocol version 2 only.
@ -373,20 +373,20 @@ or
.Dq no .
The default is
.Dq no .
.It Cm HostDSAKey
Specifies the file containing the private DSA host key (default
.Pa /etc/ssh_host_dsa_key )
used by SSH protocol 2.0.
Note that
.Nm
disables protocol 2.0 if this file is group/world-accessible.
.It Cm HostKey
Specifies the file containing the private RSA host key (default
Specifies the file containing the private host keys (default
.Pa /etc/ssh_host_key )
used by SSH protocols 1.3 and 1.5.
used by SSH protocol versions 1 and 2.
Note that
.Nm
disables protocols 1.3 and 1.5 if this file is group/world-accessible.
if this file is group/world-accessible.
It is possible to have multiple host key files.
.Dq rsa1
keys are used for version 1 and
.Dq dsa
or
.Dq rsa
are used for version 2 of the SSH protocol.
.It Cm IgnoreRhosts
Specifies that
.Pa .rhosts
@ -1039,7 +1039,7 @@ This can be used to specify
machine-specific login-time initializations globally.
This file should be writable only by root, and should be world-readable.
.El
.Sh AUTHOR
.Sh AUTHORS
OpenSSH
is a derivative of the original (free) ssh 1.2.12 release by Tatu Ylonen,
but with bugs removed and newer features re-added.

318
sshd.c
View File

@ -40,7 +40,7 @@
*/
#include "includes.h"
RCSID("$OpenBSD: sshd.c,v 1.132 2000/10/13 18:34:46 markus Exp $");
RCSID("$OpenBSD: sshd.c,v 1.134 2000/11/12 19:50:38 markus Exp $");
#include "xmalloc.h"
#include "rsa.h"
@ -61,7 +61,6 @@ RCSID("$OpenBSD: sshd.c,v 1.132 2000/10/13 18:34:46 markus Exp $");
#include <openssl/dsa.h>
#include <openssl/rsa.h>
#include "key.h"
#include "dsa.h"
#include "dh.h"
#include "auth.h"
@ -140,9 +139,11 @@ char *server_version_string = NULL;
* not very useful. Currently, memory locking is not implemented.
*/
struct {
RSA *private_key; /* Private part of empheral server key. */
RSA *host_key; /* Private part of host key. */
Key *dsa_host_key; /* Private DSA host key. */
Key *server_key; /* empheral server key */
Key *ssh1_host_key; /* ssh1 host key */
Key **host_keys; /* all private host keys */
int have_ssh1_key;
int have_ssh2_key;
} sensitive_data;
/*
@ -154,10 +155,6 @@ int key_used = 0;
/* This is set to true when SIGHUP is received. */
int received_sighup = 0;
/* Public side of the server key. This value is regenerated regularly with
the private key. */
RSA *public_key;
/* session identifier, used by RSA-auth */
unsigned char session_id[16];
@ -266,6 +263,17 @@ grace_alarm_handler(int sig)
*/
/* XXX do we really want this work to be done in a signal handler ? -m */
void
generate_empheral_server_key(void)
{
log("Generating %s%d bit RSA key.", sensitive_data.server_key ? "new " : "",
options.server_key_bits);
if (sensitive_data.server_key != NULL)
key_free(sensitive_data.server_key);
sensitive_data.server_key = key_generate(KEY_RSA1, options.server_key_bits);
arc4random_stir();
log("RSA key generation complete.");
}
void
key_regeneration_alarm(int sig)
{
int save_errno = errno;
@ -273,21 +281,8 @@ key_regeneration_alarm(int sig)
/* Check if we should generate a new key. */
if (key_used) {
/* This should really be done in the background. */
log("Generating new %d bit RSA key.", options.server_key_bits);
if (sensitive_data.private_key != NULL)
RSA_free(sensitive_data.private_key);
sensitive_data.private_key = RSA_new();
if (public_key != NULL)
RSA_free(public_key);
public_key = RSA_new();
rsa_generate_key(sensitive_data.private_key, public_key,
options.server_key_bits);
arc4random_stir();
generate_empheral_server_key();
key_used = 0;
log("RSA key generation complete.");
}
/* Reschedule the alarm. */
signal(SIGALRM, key_regeneration_alarm);
@ -422,18 +417,93 @@ sshd_exchange_identification(int sock_in, int sock_out)
}
/* Destroy the host and server keys. They will no longer be needed. */
void
destroy_sensitive_data(void)
{
/* Destroy the private and public keys. They will no longer be needed. */
if (public_key)
RSA_free(public_key);
if (sensitive_data.private_key)
RSA_free(sensitive_data.private_key);
if (sensitive_data.host_key)
RSA_free(sensitive_data.host_key);
if (sensitive_data.dsa_host_key != NULL)
key_free(sensitive_data.dsa_host_key);
int i;
if (sensitive_data.server_key) {
key_free(sensitive_data.server_key);
sensitive_data.server_key = NULL;
}
for(i = 0; i < options.num_host_key_files; i++) {
if (sensitive_data.host_keys[i]) {
key_free(sensitive_data.host_keys[i]);
sensitive_data.host_keys[i] = NULL;
}
}
sensitive_data.ssh1_host_key = NULL;
}
Key *
load_private_key_autodetect(const char *filename)
{
struct stat st;
int type;
Key *public, *private;
if (stat(filename, &st) < 0) {
perror(filename);
return NULL;
}
/*
* try to load the public key. right now this only works for RSA1,
* since SSH2 keys are fully encrypted
*/
type = KEY_RSA1;
public = key_new(type);
if (!load_public_key(filename, public, NULL)) {
/* ok, so we will assume this is 'some' key */
type = KEY_UNSPEC;
}
key_free(public);
/* Ok, try key with empty passphrase */
private = key_new(type);
if (load_private_key(filename, "", private, NULL)) {
debug("load_private_key_autodetect: type %d %s",
private->type, key_type(private));
return private;
}
key_free(private);
return NULL;
}
char *
list_hostkey_types(void)
{
static char buf[1024];
int i;
buf[0] = '\0';
for(i = 0; i < options.num_host_key_files; i++) {
Key *key = sensitive_data.host_keys[i];
if (key == NULL)
continue;
switch(key->type) {
case KEY_RSA:
case KEY_DSA:
strlcat(buf, key_ssh_name(key), sizeof buf);
strlcat(buf, ",", sizeof buf);
break;
}
}
i = strlen(buf);
if (i > 0 && buf[i-1] == ',')
buf[i-1] = '\0';
debug("list_hostkey_types: %s", buf);
return buf;
}
Key *
get_hostkey_by_type(int type)
{
int i;
for(i = 0; i < options.num_host_key_files; i++) {
Key *key = sensitive_data.host_keys[i];
if (key != NULL && key->type == type)
return key;
}
return NULL;
}
/*
@ -555,7 +625,11 @@ main(int ac, char **av)
options.key_regeneration_time = atoi(optarg);
break;
case 'h':
options.host_key_file = optarg;
if (options.num_host_key_files >= MAX_HOSTKEYS) {
fprintf(stderr, "too many host keys.\n");
exit(1);
}
options.host_key_files[options.num_host_key_files++] = optarg;
break;
case 'V':
client_version_string = optarg;
@ -610,39 +684,39 @@ main(int ac, char **av)
debug("sshd version %.100s", SSH_VERSION);
sensitive_data.dsa_host_key = NULL;
sensitive_data.host_key = NULL;
/* load private host keys */
sensitive_data.host_keys = xmalloc(options.num_host_key_files*sizeof(Key*));
sensitive_data.server_key = NULL;
sensitive_data.ssh1_host_key = NULL;
sensitive_data.have_ssh1_key = 0;
sensitive_data.have_ssh2_key = 0;
/* check if RSA support exists */
if ((options.protocol & SSH_PROTO_1) &&
rsa_alive() == 0) {
log("no RSA support in libssl and libcrypto. See ssl(8)");
log("Disabling protocol version 1");
for(i = 0; i < options.num_host_key_files; i++) {
Key *key = load_private_key_autodetect(options.host_key_files[i]);
if (key == NULL) {
error("Could not load host key: %.200s: %.100s",
options.host_key_files[i], strerror(errno));
continue;
}
switch(key->type){
case KEY_RSA1:
sensitive_data.ssh1_host_key = key;
sensitive_data.have_ssh1_key = 1;
break;
case KEY_RSA:
case KEY_DSA:
sensitive_data.have_ssh2_key = 1;
break;
}
sensitive_data.host_keys[i] = key;
}
if ((options.protocol & SSH_PROTO_1) && !sensitive_data.have_ssh1_key) {
log("Disabling protocol version 1. Could not load host key");
options.protocol &= ~SSH_PROTO_1;
}
/* Load the RSA/DSA host key. It must have empty passphrase. */
if (options.protocol & SSH_PROTO_1) {
Key k;
sensitive_data.host_key = RSA_new();
k.type = KEY_RSA;
k.rsa = sensitive_data.host_key;
errno = 0;
if (!load_private_key(options.host_key_file, "", &k, NULL)) {
error("Could not load host key: %.200s: %.100s",
options.host_key_file, strerror(errno));
log("Disabling protocol version 1");
options.protocol &= ~SSH_PROTO_1;
}
k.rsa = NULL;
}
if (options.protocol & SSH_PROTO_2) {
sensitive_data.dsa_host_key = key_new(KEY_DSA);
if (!load_private_key(options.host_dsa_key_file, "", sensitive_data.dsa_host_key, NULL)) {
error("Could not load DSA host key: %.200s", options.host_dsa_key_file);
log("Disabling protocol version 2");
options.protocol &= ~SSH_PROTO_2;
}
if ((options.protocol & SSH_PROTO_2) && !sensitive_data.have_ssh2_key) {
log("Disabling protocol version 2. Could not load host key");
options.protocol &= ~SSH_PROTO_2;
}
if (! options.protocol & (SSH_PROTO_1|SSH_PROTO_2)) {
if (silent == 0)
@ -664,11 +738,11 @@ main(int ac, char **av)
* hate software patents. I dont know if this can go? Niels
*/
if (options.server_key_bits >
BN_num_bits(sensitive_data.host_key->n) - SSH_KEY_BITS_RESERVED &&
BN_num_bits(sensitive_data.ssh1_host_key->rsa->n) - SSH_KEY_BITS_RESERVED &&
options.server_key_bits <
BN_num_bits(sensitive_data.host_key->n) + SSH_KEY_BITS_RESERVED) {
BN_num_bits(sensitive_data.ssh1_host_key->rsa->n) + SSH_KEY_BITS_RESERVED) {
options.server_key_bits =
BN_num_bits(sensitive_data.host_key->n) + SSH_KEY_BITS_RESERVED;
BN_num_bits(sensitive_data.ssh1_host_key->rsa->n) + SSH_KEY_BITS_RESERVED;
debug("Forcing server key to %d bits to make it differ from host key.",
options.server_key_bits);
}
@ -707,9 +781,6 @@ main(int ac, char **av)
/* Reinitialize the log (because of the fork above). */
log_init(av0, options.log_level, options.log_facility, log_stderr);
/* Do not display messages to stdout in RSA code. */
rsa_set_verbose(0);
/* Initialize the random number generator. */
arc4random_stir();
@ -731,16 +802,8 @@ main(int ac, char **av)
* ttyfd happens to be one of those.
*/
debug("inetd sockets after dupping: %d, %d", sock_in, sock_out);
if (options.protocol & SSH_PROTO_1) {
public_key = RSA_new();
sensitive_data.private_key = RSA_new();
log("Generating %d bit RSA key.", options.server_key_bits);
rsa_generate_key(sensitive_data.private_key, public_key,
options.server_key_bits);
arc4random_stir();
log("RSA key generation complete.");
}
if (options.protocol & SSH_PROTO_1)
generate_empheral_server_key();
} else {
for (ai = options.listen_addrs; ai; ai = ai->ai_next) {
if (ai->ai_family != AF_INET && ai->ai_family != AF_INET6)
@ -818,14 +881,7 @@ main(int ac, char **av)
}
}
if (options.protocol & SSH_PROTO_1) {
public_key = RSA_new();
sensitive_data.private_key = RSA_new();
log("Generating %d bit RSA key.", options.server_key_bits);
rsa_generate_key(sensitive_data.private_key, public_key,
options.server_key_bits);
arc4random_stir();
log("RSA key generation complete.");
generate_empheral_server_key();
/* Schedule server key regeneration alarm. */
signal(SIGALRM, key_regeneration_alarm);
@ -1065,6 +1121,8 @@ main(int ac, char **av)
*/
if (remote_port >= IPPORT_RESERVED ||
remote_port < IPPORT_RESERVED / 2) {
debug("Rhosts Authentication methods disabled, "
"originating port not trusted.");
options.rhosts_authentication = 0;
options.rhosts_rsa_authentication = 0;
}
@ -1145,14 +1203,14 @@ do_ssh1_kex()
packet_put_char(cookie[i]);
/* Store our public server RSA key. */
packet_put_int(BN_num_bits(public_key->n));
packet_put_bignum(public_key->e);
packet_put_bignum(public_key->n);
packet_put_int(BN_num_bits(sensitive_data.server_key->rsa->n));
packet_put_bignum(sensitive_data.server_key->rsa->e);
packet_put_bignum(sensitive_data.server_key->rsa->n);
/* Store our public host RSA key. */
packet_put_int(BN_num_bits(sensitive_data.host_key->n));
packet_put_bignum(sensitive_data.host_key->e);
packet_put_bignum(sensitive_data.host_key->n);
packet_put_int(BN_num_bits(sensitive_data.ssh1_host_key->rsa->n));
packet_put_bignum(sensitive_data.ssh1_host_key->rsa->e);
packet_put_bignum(sensitive_data.ssh1_host_key->rsa->n);
/* Put protocol flags. */
packet_put_int(SSH_PROTOFLAG_HOST_IN_FWD_OPEN);
@ -1190,8 +1248,9 @@ do_ssh1_kex()
packet_send();
packet_write_wait();
debug("Sent %d bit public key and %d bit host key.",
BN_num_bits(public_key->n), BN_num_bits(sensitive_data.host_key->n));
debug("Sent %d bit server key and %d bit host key.",
BN_num_bits(sensitive_data.server_key->rsa->n),
BN_num_bits(sensitive_data.ssh1_host_key->rsa->n));
/* Read clients reply (cipher type and session key). */
packet_read_expect(&plen, SSH_CMSG_SESSION_KEY);
@ -1223,39 +1282,39 @@ do_ssh1_kex()
* Decrypt it using our private server key and private host key (key
* with larger modulus first).
*/
if (BN_cmp(sensitive_data.private_key->n, sensitive_data.host_key->n) > 0) {
if (BN_cmp(sensitive_data.server_key->rsa->n, sensitive_data.ssh1_host_key->rsa->n) > 0) {
/* Private key has bigger modulus. */
if (BN_num_bits(sensitive_data.private_key->n) <
BN_num_bits(sensitive_data.host_key->n) + SSH_KEY_BITS_RESERVED) {
fatal("do_connection: %s: private_key %d < host_key %d + SSH_KEY_BITS_RESERVED %d",
get_remote_ipaddr(),
BN_num_bits(sensitive_data.private_key->n),
BN_num_bits(sensitive_data.host_key->n),
SSH_KEY_BITS_RESERVED);
if (BN_num_bits(sensitive_data.server_key->rsa->n) <
BN_num_bits(sensitive_data.ssh1_host_key->rsa->n) + SSH_KEY_BITS_RESERVED) {
fatal("do_connection: %s: server_key %d < host_key %d + SSH_KEY_BITS_RESERVED %d",
get_remote_ipaddr(),
BN_num_bits(sensitive_data.server_key->rsa->n),
BN_num_bits(sensitive_data.ssh1_host_key->rsa->n),
SSH_KEY_BITS_RESERVED);
}
rsa_private_decrypt(session_key_int, session_key_int,
sensitive_data.private_key);
sensitive_data.server_key->rsa);
rsa_private_decrypt(session_key_int, session_key_int,
sensitive_data.host_key);
sensitive_data.ssh1_host_key->rsa);
} else {
/* Host key has bigger modulus (or they are equal). */
if (BN_num_bits(sensitive_data.host_key->n) <
BN_num_bits(sensitive_data.private_key->n) + SSH_KEY_BITS_RESERVED) {
fatal("do_connection: %s: host_key %d < private_key %d + SSH_KEY_BITS_RESERVED %d",
get_remote_ipaddr(),
BN_num_bits(sensitive_data.host_key->n),
BN_num_bits(sensitive_data.private_key->n),
SSH_KEY_BITS_RESERVED);
if (BN_num_bits(sensitive_data.ssh1_host_key->rsa->n) <
BN_num_bits(sensitive_data.server_key->rsa->n) + SSH_KEY_BITS_RESERVED) {
fatal("do_connection: %s: host_key %d < server_key %d + SSH_KEY_BITS_RESERVED %d",
get_remote_ipaddr(),
BN_num_bits(sensitive_data.ssh1_host_key->rsa->n),
BN_num_bits(sensitive_data.server_key->rsa->n),
SSH_KEY_BITS_RESERVED);
}
rsa_private_decrypt(session_key_int, session_key_int,
sensitive_data.host_key);
sensitive_data.ssh1_host_key->rsa);
rsa_private_decrypt(session_key_int, session_key_int,
sensitive_data.private_key);
sensitive_data.server_key->rsa);
}
compute_session_id(session_id, cookie,
sensitive_data.host_key->n,
sensitive_data.private_key->n);
sensitive_data.ssh1_host_key->rsa->n,
sensitive_data.server_key->rsa->n);
/* Destroy the private and public keys. They will no longer be needed. */
destroy_sensitive_data();
@ -1269,8 +1328,8 @@ do_ssh1_kex()
len = BN_num_bytes(session_key_int);
if (len < 0 || len > sizeof(session_key))
fatal("do_connection: bad len from %s: session_key_int %d > sizeof(session_key) %d",
get_remote_ipaddr(),
len, (int) sizeof(session_key));
get_remote_ipaddr(),
len, sizeof(session_key));
memset(session_key, 0, sizeof(session_key));
BN_bn2bin(session_key_int, session_key + sizeof(session_key) - len);
@ -1314,6 +1373,8 @@ do_ssh2_kex()
myproposal[PROPOSAL_ENC_ALGS_CTOS] =
myproposal[PROPOSAL_ENC_ALGS_STOC] = options.ciphers;
}
myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] = list_hostkey_types();
server_kexinit = kex_init(myproposal);
client_kexinit = xmalloc(sizeof(*client_kexinit));
buffer_init(client_kexinit);
@ -1379,6 +1440,11 @@ ssh_dh1_server(Kex *kex, Buffer *client_kexinit, Buffer *server_kexinit)
BIGNUM *shared_secret = 0;
DH *dh;
BIGNUM *dh_client_pub = 0;
Key *hostkey;
hostkey = get_hostkey_by_type(kex->hostkey_type);
if (hostkey == NULL)
fatal("Unsupported hostkey type %d", kex->hostkey_type);
/* KEXDH */
debug("Wait SSH2_MSG_KEXDH_INIT.");
@ -1431,8 +1497,7 @@ ssh_dh1_server(Kex *kex, Buffer *client_kexinit, Buffer *server_kexinit)
xfree(kbuf);
/* XXX precompute? */
dsa_make_key_blob(sensitive_data.dsa_host_key,
&server_host_key_blob, &sbloblen);
key_to_blob(hostkey, &server_host_key_blob, &sbloblen);
/* calc H */ /* XXX depends on 'kex' */
hash = kex_hash(
@ -1463,7 +1528,7 @@ ssh_dh1_server(Kex *kex, Buffer *client_kexinit, Buffer *server_kexinit)
/* sign H */
/* XXX hashlen depends on KEX */
dsa_sign(sensitive_data.dsa_host_key, &signature, &slen, hash, 20);
key_sign(hostkey, &signature, &slen, hash, 20);
destroy_sensitive_data();
@ -1503,6 +1568,11 @@ ssh_dhgex_server(Kex *kex, Buffer *client_kexinit, Buffer *server_kexinit)
BIGNUM *shared_secret = 0;
DH *dh;
BIGNUM *dh_client_pub = 0;
Key *hostkey;
hostkey = get_hostkey_by_type(kex->hostkey_type);
if (hostkey == NULL)
fatal("Unsupported hostkey type %d", kex->hostkey_type);
/* KEXDHGEX */
debug("Wait SSH2_MSG_KEX_DH_GEX_REQUEST.");
@ -1564,8 +1634,7 @@ ssh_dhgex_server(Kex *kex, Buffer *client_kexinit, Buffer *server_kexinit)
xfree(kbuf);
/* XXX precompute? */
dsa_make_key_blob(sensitive_data.dsa_host_key,
&server_host_key_blob, &sbloblen);
key_to_blob(hostkey, &server_host_key_blob, &sbloblen);
/* calc H */ /* XXX depends on 'kex' */
hash = kex_hash_gex(
@ -1597,7 +1666,7 @@ ssh_dhgex_server(Kex *kex, Buffer *client_kexinit, Buffer *server_kexinit)
/* sign H */
/* XXX hashlen depends on KEX */
dsa_sign(sensitive_data.dsa_host_key, &signature, &slen, hash, 20);
key_sign(hostkey, &signature, &slen, hash, 20);
destroy_sensitive_data();
@ -1617,4 +1686,3 @@ ssh_dhgex_server(Kex *kex, Buffer *client_kexinit, Buffer *server_kexinit)
/* have keys, free DH */
DH_free(dh);
}

View File

@ -5,6 +5,8 @@ Port 22
ListenAddress 0.0.0.0
#ListenAddress ::
HostKey /etc/ssh_host_key
HostKey /etc/ssh_host_rsa_key
HostKey /etc/ssh_host_dsa_key
ServerKeyBits 768
LoginGraceTime 600
KeyRegenerationInterval 3600