- (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 20001113
- (djm) Add pointer to http://www.imasy.or.jp/~gotoh/connect.c to - (djm) Add pointer to http://www.imasy.or.jp/~gotoh/connect.c to
contrib/README 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 20001112
- (bal) SCO Patch to add needed libraries for configure.in. Patch by - (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) 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 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 \ if [ -f "$(DESTDIR)$(sysconfdir)/ssh_host_key" ] ; then \
echo "$(DESTDIR)$(sysconfdir)/ssh_host_key already exists, skipping." ; \ echo "$(DESTDIR)$(sysconfdir)/ssh_host_key already exists, skipping." ; \
else \ 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 ; \ fi ; \
if [ -f $(DESTDIR)$(sysconfdir)/ssh_host_dsa_key ] ; then \ if [ -f $(DESTDIR)$(sysconfdir)/ssh_host_dsa_key ] ; then \
echo "$(DESTDIR)$(sysconfdir)/ssh_host_dsa_key already exists, skipping." ; \ echo "$(DESTDIR)$(sysconfdir)/ssh_host_dsa_key already exists, skipping." ; \
else \ 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 ; \
fi ; fi ;
host-key-force: ssh-keygen$(EXEEXT) host-key-force: ssh-keygen$(EXEEXT)
$(srcdir)/ssh-keygen -b 1024 -f $(DESTDIR)$(sysconfdir)/ssh_host_key -N "" $(srcdir)/ssh-keygen -t rsa1 -f $(DESTDIR)$(sysconfdir)/ssh_host_key -N ""
$(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 ""
$(srcdir)/ssh-keygen -t rsa -f $(DESTDIR)$(sysconfdir)/ssh_host_rsa_key -N ""
uninstallall: uninstall uninstallall: uninstall
-rm -f $(DESTDIR)$(sysconfdir)/ssh_config -rm -f $(DESTDIR)$(sysconfdir)/ssh_config

View File

@ -13,7 +13,7 @@
*/ */
#include "includes.h" #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 "packet.h"
#include "ssh.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); debug("Rhosts RSA authentication: canonical host %.900s", canonical_hostname);
/* wrap the RSA key into a 'generic' key */ /* 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->e, client_host_key->e);
BN_copy(client_key->rsa->n, client_host_key->n); 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. */ /* Check if we know the host and its host key. */
host_status = check_host_in_hostfile(SSH_SYSTEM_HOSTFILE, canonical_hostname, host_status = check_host_in_hostfile(SSH_SYSTEM_HOSTFILE, canonical_hostname,

View File

@ -10,7 +10,7 @@
*/ */
#include "includes.h" #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 #ifdef HAVE_OSF_SIA
# include <sia.h> # include <sia.h>

38
auth2.c
View File

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

View File

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

View File

@ -11,7 +11,7 @@
* called by a name other than "ssh" or "Secure Shell". * 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 #ifndef AUTHFD_H
#define AUTHFD_H #define AUTHFD_H
@ -74,6 +74,11 @@ AuthenticationConnection *ssh_get_authentication_connection();
*/ */
void ssh_close_authentication_connection(AuthenticationConnection *auth); 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 * Returns the first authentication identity held by the agent or NULL if
* no identies are available. Caller must free comment and key. * no identies are available. Caller must free comment and key.

View File

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

View File

@ -40,7 +40,7 @@
*/ */
#include "includes.h" #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 "ssh.h"
#include "packet.h" #include "packet.h"
@ -588,9 +588,12 @@ channel_post_port_listener(Channel *c, fd_set * readset, fd_set * writeset)
struct sockaddr addr; struct sockaddr addr;
int newsock, newch; int newsock, newch;
socklen_t addrlen; socklen_t addrlen;
char buf[1024], *remote_hostname; char buf[1024], *remote_hostname, *rtype;
int remote_port; int remote_port;
rtype = (c->type == SSH_CHANNEL_RPORT_LISTENER) ?
"forwarded-tcpip" : "direct-tcpip";
if (FD_ISSET(c->sock, readset)) { if (FD_ISSET(c->sock, readset)) {
debug("Connection to port %d forwarding " debug("Connection to port %d forwarding "
"to %.100s port %d requested.", "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", "connect from %.200s port %d",
c->listening_port, c->path, c->host_port, c->listening_port, c->path, c->host_port,
remote_hostname, remote_port); remote_hostname, remote_port);
newch = channel_new("direct-tcpip",
newch = channel_new(rtype,
SSH_CHANNEL_OPENING, newsock, newsock, -1, SSH_CHANNEL_OPENING, newsock, newsock, -1,
c->local_window_max, c->local_maxpacket, c->local_window_max, c->local_maxpacket,
0, xstrdup(buf), 1); 0, xstrdup(buf), 1);
if (compat20) { if (compat20) {
packet_start(SSH2_MSG_CHANNEL_OPEN); packet_start(SSH2_MSG_CHANNEL_OPEN);
packet_put_cstring("direct-tcpip"); packet_put_cstring(rtype);
packet_put_int(newch); packet_put_int(newch);
packet_put_int(c->local_window_max); packet_put_int(c->local_window_max);
packet_put_int(c->local_maxpacket); packet_put_int(c->local_maxpacket);
/* target host and port */ if (c->type == SSH_CHANNEL_RPORT_LISTENER) {
packet_put_string(c->path, strlen(c->path)); /* listen address, port */
packet_put_int(c->host_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 */ /* originator host and port */
packet_put_cstring(remote_hostname); packet_put_cstring(remote_hostname);
packet_put_int(remote_port); 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)); error("accept from auth socket: %.100s", strerror(errno));
return; return;
} }
newch = channel_allocate(SSH_CHANNEL_OPENING, newsock, newch = channel_new("accepted auth socket",
xstrdup("accepted auth socket")); SSH_CHANNEL_OPENING, newsock, newsock, -1,
packet_start(SSH_SMSG_AGENT_OPEN); c->local_window_max, c->local_maxpacket,
packet_put_int(newch); 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(); packet_send();
} }
} }
@ -820,11 +840,15 @@ channel_handler_init_20(void)
channel_pre[SSH_CHANNEL_OPEN] = &channel_pre_open_20; channel_pre[SSH_CHANNEL_OPEN] = &channel_pre_open_20;
channel_pre[SSH_CHANNEL_X11_OPEN] = &channel_pre_x11_open; channel_pre[SSH_CHANNEL_X11_OPEN] = &channel_pre_x11_open;
channel_pre[SSH_CHANNEL_PORT_LISTENER] = &channel_pre_listener; 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_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_OPEN] = &channel_post_open_2;
channel_post[SSH_CHANNEL_PORT_LISTENER] = &channel_post_port_listener; 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_X11_LISTENER] = &channel_post_x11_listener;
channel_post[SSH_CHANNEL_AUTH_SOCKET] = &channel_post_auth_listener;
} }
void void
@ -1326,6 +1350,7 @@ channel_stop_listening()
channel_free(i); channel_free(i);
break; break;
case SSH_CHANNEL_PORT_LISTENER: case SSH_CHANNEL_PORT_LISTENER:
case SSH_CHANNEL_RPORT_LISTENER:
case SSH_CHANNEL_X11_LISTENER: case SSH_CHANNEL_X11_LISTENER:
close(channels[i].sock); close(channels[i].sock);
channel_free(i); channel_free(i);
@ -1369,6 +1394,7 @@ channel_still_open()
case SSH_CHANNEL_FREE: case SSH_CHANNEL_FREE:
case SSH_CHANNEL_X11_LISTENER: case SSH_CHANNEL_X11_LISTENER:
case SSH_CHANNEL_PORT_LISTENER: case SSH_CHANNEL_PORT_LISTENER:
case SSH_CHANNEL_RPORT_LISTENER:
case SSH_CHANNEL_CLOSED: case SSH_CHANNEL_CLOSED:
case SSH_CHANNEL_AUTH_SOCKET: case SSH_CHANNEL_AUTH_SOCKET:
continue; continue;
@ -1414,6 +1440,7 @@ channel_open_message()
case SSH_CHANNEL_FREE: case SSH_CHANNEL_FREE:
case SSH_CHANNEL_X11_LISTENER: case SSH_CHANNEL_X11_LISTENER:
case SSH_CHANNEL_PORT_LISTENER: case SSH_CHANNEL_PORT_LISTENER:
case SSH_CHANNEL_RPORT_LISTENER:
case SSH_CHANNEL_CLOSED: case SSH_CHANNEL_CLOSED:
case SSH_CHANNEL_AUTH_SOCKET: case SSH_CHANNEL_AUTH_SOCKET:
continue; continue;
@ -1446,19 +1473,44 @@ channel_open_message()
* Initiate forwarding of connections to local port "port" through the secure * Initiate forwarding of connections to local port "port" through the secure
* channel to host:port from remote side. * channel to host:port from remote side.
*/ */
void void
channel_request_local_forwarding(u_short port, const char *host, channel_request_local_forwarding(u_short listen_port, const char *host_to_connect,
u_short host_port, int gateway_ports) 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; struct addrinfo hints, *ai, *aitop;
char ntop[NI_MAXHOST], strport[NI_MAXSERV]; char ntop[NI_MAXHOST], strport[NI_MAXSERV];
const char *host;
struct linger linger; 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) if (strlen(host) > sizeof(channels[0].path) - 1)
packet_disconnect("Forward host name too long."); packet_disconnect("Forward host name too long.");
/* XXX listen_address is currently ignored */
/* /*
* getaddrinfo returns a loopback address if the hostname is * getaddrinfo returns a loopback address if the hostname is
* set to NULL and hints.ai_flags is not AI_PASSIVE * 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_family = IPv4or6;
hints.ai_flags = gateway_ports ? AI_PASSIVE : 0; hints.ai_flags = gateway_ports ? AI_PASSIVE : 0;
hints.ai_socktype = SOCK_STREAM; 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) if (getaddrinfo(NULL, strport, &hints, &aitop) != 0)
packet_disconnect("getaddrinfo: fatal error"); packet_disconnect("getaddrinfo: fatal error");
@ -1477,7 +1529,7 @@ channel_request_local_forwarding(u_short port, const char *host,
continue; continue;
if (getnameinfo(ai->ai_addr, ai->ai_addrlen, ntop, sizeof(ntop), if (getnameinfo(ai->ai_addr, ai->ai_addrlen, ntop, sizeof(ntop),
strport, sizeof(strport), NI_NUMERICHOST|NI_NUMERICSERV) != 0) { strport, sizeof(strport), NI_NUMERICHOST|NI_NUMERICSERV) != 0) {
error("channel_request_local_forwarding: getnameinfo failed"); error("channel_request_forwarding: getnameinfo failed");
continue; continue;
} }
/* Create a port to listen for the host. */ /* Create a port to listen for the host. */
@ -1515,18 +1567,16 @@ channel_request_local_forwarding(u_short port, const char *host,
continue; continue;
} }
/* Allocate a channel number for the socket. */ /* Allocate a channel number for the socket. */
ch = channel_new( ch = channel_new("port listener", ctype, sock, sock, -1,
"port listener", SSH_CHANNEL_PORT_LISTENER,
sock, sock, -1,
CHAN_TCP_WINDOW_DEFAULT, CHAN_TCP_PACKET_DEFAULT, CHAN_TCP_WINDOW_DEFAULT, CHAN_TCP_PACKET_DEFAULT,
0, xstrdup("port listener"), 1); 0, xstrdup("port listener"), 1);
strlcpy(channels[ch].path, host, sizeof(channels[ch].path)); strlcpy(channels[ch].path, host, sizeof(channels[ch].path));
channels[ch].host_port = host_port; channels[ch].host_port = port_to_connect;
channels[ch].listening_port = port; channels[ch].listening_port = listen_port;
success = 1; success = 1;
} }
if (success == 0) if (success == 0)
packet_disconnect("cannot listen port: %d", port); packet_disconnect("cannot listen port: %d", listen_port); /*XXX ?disconnect? */
freeaddrinfo(aitop); freeaddrinfo(aitop);
} }
@ -1536,19 +1586,15 @@ channel_request_local_forwarding(u_short port, const char *host,
*/ */
void void
channel_request_remote_forwarding(u_short listen_port, const char *host_to_connect, channel_request_remote_forwarding(u_short listen_port,
u_short port_to_connect) 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. */ /* Record locally that connection to this host/port is permitted. */
if (num_permitted_opens >= SSH_MAX_FORWARDS_PER_DIRECTION) if (num_permitted_opens >= SSH_MAX_FORWARDS_PER_DIRECTION)
fatal("channel_request_remote_forwarding: too many forwards"); 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. */ /* Send the forward request to the remote side. */
if (compat20) { if (compat20) {
const char *address_to_bind = "0.0.0.0"; 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_char(0); /* boolean: want reply */
packet_put_cstring(address_to_bind); packet_put_cstring(address_to_bind);
packet_put_int(listen_port); packet_put_int(listen_port);
packet_send();
packet_write_wait();
/* Assume that server accepts the request */
success = 1;
} else { } else {
packet_start(SSH_CMSG_PORT_FORWARD_REQUEST); packet_start(SSH_CMSG_PORT_FORWARD_REQUEST);
packet_put_int(listen_port); 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_put_int(port_to_connect);
packet_send(); packet_send();
packet_write_wait(); packet_write_wait();
/*
* Wait for response from the remote side. It will send a disconnect /* Wait for response from the remote side. */
* message on failure, and we will never see it here. type = packet_read(&payload_len);
*/ switch (type) {
packet_read_expect(&payload_len, SSH_SMSG_SUCCESS); 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.", packet_disconnect("Requested forwarding of port %d but user is not root.",
port); port);
#endif #endif
/* /* Initiate forwarding */
* Initiate forwarding,
*/
channel_request_local_forwarding(port, hostname, host_port, gateway_ports); channel_request_local_forwarding(port, hostname, host_port, gateway_ports);
/* Free the argument string. */ /* Free the argument string. */
@ -1656,6 +1720,18 @@ channel_connect_to(const char *host, u_short host_port)
/* success */ /* success */
return sock; 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 * 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)); packet_disconnect("listen: %.100s", strerror(errno));
/* Allocate a channel for the authentication agent socket. */ /* Allocate a channel for the authentication agent socket. */
newch = channel_allocate(SSH_CHANNEL_AUTH_SOCKET, sock, newch = channel_new("auth socket",
xstrdup("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, strlcpy(channels[newch].path, channel_forwarded_auth_socket_name,
sizeof(channels[newch].path)); sizeof(channels[newch].path));
return 1; return 1;

View File

@ -32,7 +32,7 @@
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * 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 #ifndef CHANNELS_H
#define CHANNELS_H #define CHANNELS_H
@ -49,7 +49,8 @@
#define SSH_CHANNEL_INPUT_DRAINING 8 /* sending remaining data to conn */ #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_OUTPUT_DRAINING 9 /* sending remaining data to app */
#define SSH_CHANNEL_LARVAL 10 /* larval session */ #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 * 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_open_failure(int type, int plen, void *ctxt);
void channel_input_port_open(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_window_adjust(int type, int plen, void *ctxt);
void channel_input_open(int type, int plen, void *ctxt);
/* Sets specific protocol options. */ /* Sets specific protocol options. */
void channel_set_options(int hostname_in_open); 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 * 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 * channel to host:port from remote side.
* error.
*/ */
void void
channel_request_local_forwarding(u_short port, const char *host, channel_request_local_forwarding(u_short listen_port,
u_short remote_port, int gateway_ports); 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 * 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 */ /* XXX */
int channel_connect_to(const char *host, u_short host_port); 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); int x11_connect_display(void);
#endif #endif

View File

@ -59,7 +59,7 @@
*/ */
#include "includes.h" #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 "xmalloc.h"
#include "ssh.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 "buffer.h"
#include "bufaux.h" #include "bufaux.h"
#include <openssl/dsa.h>
#include <openssl/rsa.h>
#include "key.h"
#include "authfd.h"
/* import options */ /* import options */
extern Options options; extern Options options;
@ -1016,13 +1020,99 @@ client_input_exit_status(int type, int plen, void *ctxt)
quit_pending = 1; 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 */ /* XXXX move to generic input handler */
void void
client_input_channel_open(int type, int plen, void *ctxt) client_input_channel_open(int type, int plen, void *ctxt)
{ {
Channel *c = NULL; Channel *c = NULL;
char *ctype; char *ctype;
int id;
unsigned int len; unsigned int len;
int rchan; int rchan;
int rmaxpack; 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", debug("client_input_channel_open: ctype %s rchan %d win %d max %d",
ctype, rchan, rwindow, rmaxpack); ctype, rchan, rwindow, rmaxpack);
if (strcmp(ctype, "x11") == 0 && options.forward_x11) { if (strcmp(ctype, "forwarded-tcpip") == 0) {
int sock; c = client_request_forwarded_tcpip(ctype, rchan);
char *originator; } else if (strcmp(ctype, "x11") == 0) {
int originator_port; c = client_request_x11(ctype, rchan);
originator = packet_get_string(NULL); } else if (strcmp(ctype, "auth-agent@openssh.com") == 0) {
if (datafellows & SSH_BUG_X11FWD) { c = client_request_agent(ctype, rchan);
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);
}
} }
/* XXX duplicate : */ /* XXX duplicate : */
if (c != NULL) { if (c != NULL) {

View File

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

View File

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

12
kex.c
View File

@ -23,7 +23,7 @@
*/ */
#include "includes.h" #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 "ssh.h"
#include "ssh2.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 <openssl/pem.h>
#include "kex.h" #include "kex.h"
#include "key.h"
#define KEX_COOKIE_LEN 16 #define KEX_COOKIE_LEN 16
@ -454,11 +455,12 @@ choose_kex(Kex *k, char *client, char *server)
void void
choose_hostkeyalg(Kex *k, char *client, char *server) choose_hostkeyalg(Kex *k, char *client, char *server)
{ {
k->hostkeyalg = get_match(client, server); char *hostkeyalg = get_match(client, server);
if (k->hostkeyalg == NULL) if (hostkeyalg == NULL)
fatal("no hostkey alg"); fatal("no hostkey alg");
if (strcmp(k->hostkeyalg, KEX_DSS) != 0) k->hostkey_type = key_type_from_name(hostkeyalg);
fatal("bad hostkey alg %s", k->hostkeyalg); if (k->hostkey_type == KEY_UNSPEC)
fatal("bad hostkey alg '%s'", hostkeyalg);
} }
Kex * Kex *

2
kex.h
View File

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

388
key.c
View File

@ -39,12 +39,14 @@
#include <openssl/evp.h> #include <openssl/evp.h>
#include "xmalloc.h" #include "xmalloc.h"
#include "key.h" #include "key.h"
#include "dsa.h" #include "rsa.h"
#include "ssh-dss.h"
#include "ssh-rsa.h"
#include "uuencode.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 $"); RCSID("$OpenBSD: key.c,v 1.12 2000/11/12 19:50:37 markus Exp $");
#define SSH_DSS "ssh-dss"
Key * Key *
key_new(int type) key_new(int type)
@ -57,6 +59,7 @@ key_new(int type)
k->dsa = NULL; k->dsa = NULL;
k->rsa = NULL; k->rsa = NULL;
switch (k->type) { switch (k->type) {
case KEY_RSA1:
case KEY_RSA: case KEY_RSA:
rsa = RSA_new(); rsa = RSA_new();
rsa->n = BN_new(); rsa->n = BN_new();
@ -71,7 +74,7 @@ key_new(int type)
dsa->pub_key = BN_new(); dsa->pub_key = BN_new();
k->dsa = dsa; k->dsa = dsa;
break; break;
case KEY_EMPTY: case KEY_UNSPEC:
break; break;
default: default:
fatal("key_new: bad key type %d", k->type); fatal("key_new: bad key type %d", k->type);
@ -79,10 +82,35 @@ key_new(int type)
} }
return k; 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 void
key_free(Key *k) key_free(Key *k)
{ {
switch (k->type) { switch (k->type) {
case KEY_RSA1:
case KEY_RSA: case KEY_RSA:
if (k->rsa != NULL) if (k->rsa != NULL)
RSA_free(k->rsa); RSA_free(k->rsa);
@ -93,6 +121,8 @@ key_free(Key *k)
DSA_free(k->dsa); DSA_free(k->dsa);
k->dsa = NULL; k->dsa = NULL;
break; break;
case KEY_UNSPEC:
break;
default: default:
fatal("key_free: bad key type %d", k->type); fatal("key_free: bad key type %d", k->type);
break; break;
@ -105,6 +135,7 @@ key_equal(Key *a, Key *b)
if (a == NULL || b == NULL || a->type != b->type) if (a == NULL || b == NULL || a->type != b->type)
return 0; return 0;
switch (a->type) { switch (a->type) {
case KEY_RSA1:
case KEY_RSA: case KEY_RSA:
return a->rsa != NULL && b->rsa != NULL && return a->rsa != NULL && b->rsa != NULL &&
BN_cmp(a->rsa->e, b->rsa->e) == 0 && BN_cmp(a->rsa->e, b->rsa->e) == 0 &&
@ -136,8 +167,9 @@ key_fingerprint(Key *k)
int len = 0; int len = 0;
int nlen, elen; int nlen, elen;
retval[0] = '\0';
switch (k->type) { switch (k->type) {
case KEY_RSA: case KEY_RSA1:
nlen = BN_num_bytes(k->rsa->n); nlen = BN_num_bytes(k->rsa->n);
elen = BN_num_bytes(k->rsa->e); elen = BN_num_bytes(k->rsa->e);
len = nlen + elen; len = nlen + elen;
@ -146,14 +178,16 @@ key_fingerprint(Key *k)
BN_bn2bin(k->rsa->e, blob + nlen); BN_bn2bin(k->rsa->e, blob + nlen);
break; break;
case KEY_DSA: 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; break;
default: default:
fatal("key_fingerprint: bad key type %d", k->type); fatal("key_fingerprint: bad key type %d", k->type);
break; break;
} }
retval[0] = '\0';
if (blob != NULL) { if (blob != NULL) {
int i; int i;
unsigned char digest[EVP_MAX_MD_SIZE]; unsigned char digest[EVP_MAX_MD_SIZE];
@ -229,56 +263,106 @@ write_bignum(FILE *f, BIGNUM *num)
free(buf); free(buf);
return 1; return 1;
} }
unsigned int
/* returns 1 ok, -1 error, 0 type mismatch */
int
key_read(Key *ret, char **cpp) key_read(Key *ret, char **cpp)
{ {
Key *k; Key *k;
unsigned int bits = 0; int success = -1;
char *cp; char *cp, *space;
int len, n; int len, n, type;
u_int bits;
unsigned char *blob; unsigned char *blob;
cp = *cpp; cp = *cpp;
switch(ret->type) { switch(ret->type) {
case KEY_RSA: case KEY_RSA1:
/* Get number of bits. */ /* Get number of bits. */
if (*cp < '0' || *cp > '9') if (*cp < '0' || *cp > '9')
return 0; /* Bad bit count... */ return -1; /* Bad bit count... */
for (bits = 0; *cp >= '0' && *cp <= '9'; cp++) for (bits = 0; *cp >= '0' && *cp <= '9'; cp++)
bits = 10 * bits + *cp - '0'; bits = 10 * bits + *cp - '0';
if (bits == 0) if (bits == 0)
return 0; return -1;
*cpp = cp; *cpp = cp;
/* Get public exponent, public modulus. */ /* Get public exponent, public modulus. */
if (!read_bignum(cpp, ret->rsa->e)) if (!read_bignum(cpp, ret->rsa->e))
return 0; return -1;
if (!read_bignum(cpp, ret->rsa->n)) if (!read_bignum(cpp, ret->rsa->n))
return 0; return -1;
success = 1;
break; break;
case KEY_UNSPEC:
case KEY_RSA:
case KEY_DSA: 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; return 0;
cp += 7; }
len = 2*strlen(cp); len = 2*strlen(cp);
blob = xmalloc(len); blob = xmalloc(len);
n = uudecode(cp, blob, len); n = uudecode(cp, blob, len);
if (n < 0) { if (n < 0) {
error("key_read: uudecode %s failed", cp); 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) { if (k == NULL) {
error("key_read: dsa_key_from_blob %s failed", cp); error("key_read: key_from_blob %s failed", cp);
return 0; return -1;
} }
xfree(blob); xfree(blob);
if (ret->dsa != NULL) if (k->type != type) {
DSA_free(ret->dsa); error("key_read: type mismatch: encoding error");
ret->dsa = k->dsa; key_free(k);
k->dsa = NULL; 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); key_free(k);
bits = BN_num_bits(ret->dsa->p);
/* advance cp: skip whitespace and data */ /* advance cp: skip whitespace and data */
while (*cp == ' ' || *cp == '\t') while (*cp == ' ' || *cp == '\t')
cp++; cp++;
@ -290,7 +374,7 @@ key_read(Key *ret, char **cpp)
fatal("key_read: bad key type: %d", ret->type); fatal("key_read: bad key type: %d", ret->type);
break; break;
} }
return bits; return success;
} }
int int
key_write(Key *key, FILE *f) key_write(Key *key, FILE *f)
@ -298,7 +382,7 @@ key_write(Key *key, FILE *f)
int success = 0; int success = 0;
unsigned int bits = 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' */ /* size of modulus 'n' */
bits = BN_num_bits(key->rsa->n); bits = BN_num_bits(key->rsa->n);
fprintf(f, "%u", bits); fprintf(f, "%u", bits);
@ -308,14 +392,15 @@ key_write(Key *key, FILE *f)
} else { } else {
error("key_write: failed for RSA key"); 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; int len, n;
unsigned char *blob, *uu; unsigned char *blob, *uu;
dsa_make_key_blob(key, &blob, &len); key_to_blob(key, &blob, &len);
uu = xmalloc(2*len); uu = xmalloc(2*len);
n = uuencode(blob, len, uu, 2*len); n = uuencode(blob, len, uu, 2*len);
if (n > 0) { if (n > 0) {
fprintf(f, "%s %s", SSH_DSS, uu); fprintf(f, "%s %s", key_ssh_name(key), uu);
success = 1; success = 1;
} }
xfree(blob); xfree(blob);
@ -327,6 +412,9 @@ char *
key_type(Key *k) key_type(Key *k)
{ {
switch (k->type) { switch (k->type) {
case KEY_RSA1:
return "RSA1";
break;
case KEY_RSA: case KEY_RSA:
return "RSA"; return "RSA";
break; break;
@ -336,9 +424,23 @@ key_type(Key *k)
} }
return "unknown"; 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){ key_size(Key *k){
switch (k->type) { switch (k->type) {
case KEY_RSA1:
case KEY_RSA: case KEY_RSA:
return BN_num_bits(k->rsa->n); return BN_num_bits(k->rsa->n);
break; break;
@ -348,3 +450,219 @@ key_size(Key *k){
} }
return 0; 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; typedef struct Key Key;
enum types { enum types {
KEY_RSA1,
KEY_RSA, KEY_RSA,
KEY_DSA, KEY_DSA,
KEY_EMPTY KEY_UNSPEC
}; };
struct Key { struct Key {
int type; int type;
@ -37,12 +38,33 @@ struct Key {
}; };
Key *key_new(int type); Key *key_new(int type);
Key *key_new_private(int type);
void key_free(Key *k); void key_free(Key *k);
int key_equal(Key *a, Key *b); int key_equal(Key *a, Key *b);
char *key_fingerprint(Key *k); char *key_fingerprint(Key *k);
char *key_type(Key *k); char *key_type(Key *k);
int key_write(Key *key, FILE *f); int key_write(Key *key, FILE *f);
unsigned int key_read(Key *key, char **cpp); int key_read(Key *key, char **cpp);
unsigned int key_size(Key *k); 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 #endif

View File

@ -22,7 +22,7 @@
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * 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_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 \ #define KEX_DEFAULT_ENCRYPT \
"3des-cbc,blowfish-cbc,cast128-cbc,arcfour," \ "3des-cbc,blowfish-cbc,cast128-cbc,arcfour," \
"aes128-cbc,aes192-cbc,aes256-cbc," \ "aes128-cbc,aes192-cbc,aes256-cbc," \

View File

@ -23,7 +23,7 @@
*/ */
#include "includes.h" #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" #include "ssh.h"
@ -253,6 +253,8 @@ chan_send_oclose1(Channel *c)
static void static void
chan_delete_if_full_closed1(Channel *c) 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) { if (c->istate == CHAN_INPUT_CLOSED && c->ostate == CHAN_OUTPUT_CLOSED) {
debug("channel %d: full closed", c->self); debug("channel %d: full closed", c->self);
channel_free(c->self); channel_free(c->self);
@ -403,6 +405,8 @@ chan_send_close2(Channel *c)
static void static void
chan_delete_if_full_closed2(Channel *c) 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->istate == CHAN_INPUT_CLOSED && c->ostate == CHAN_OUTPUT_CLOSED) {
if (!(c->flags & CHAN_CLOSE_SENT)) { if (!(c->flags & CHAN_CLOSE_SENT)) {
chan_send_close2(c); chan_send_close2(c);

View File

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

View File

@ -11,7 +11,7 @@
* called by a name other than "ssh" or "Secure Shell". * 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 #ifndef READCONF_H
#define READCONF_H #define READCONF_H
@ -35,7 +35,7 @@ typedef struct {
int rhosts_rsa_authentication; /* Try rhosts with RSA int rhosts_rsa_authentication; /* Try rhosts with RSA
* authentication. */ * authentication. */
int rsa_authentication; /* Try 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. */ int skey_authentication; /* Try S/Key or TIS authentication. */
#ifdef KRB4 #ifdef KRB4
int kerberos_authentication; /* Try Kerberos int kerberos_authentication; /* Try Kerberos
@ -78,10 +78,9 @@ typedef struct {
char *system_hostfile2; char *system_hostfile2;
char *user_hostfile2; char *user_hostfile2;
int num_identity_files; /* Number of files for RSA identities. */ int num_identity_files; /* Number of files for RSA/DSA identities. */
int num_identity_files2; /* DSA identities. */
char *identity_files[SSH_MAX_IDENTITY_FILES]; 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. */ /* Local TCP/IP forward requests. */
int num_local_forwards; int num_local_forwards;

79
rsa.c
View File

@ -60,82 +60,13 @@
*/ */
#include "includes.h" #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 "rsa.h"
#include "ssh.h" #include "ssh.h"
#include "xmalloc.h" #include "xmalloc.h"
#include "entropy.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 void
rsa_public_encrypt(BIGNUM *out, BIGNUM *in, RSA *key) 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(outbuf);
xfree(inbuf); 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". * 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 #ifndef RSA_H
#define RSA_H #define RSA_H
@ -19,17 +19,6 @@
#include <openssl/bn.h> #include <openssl/bn.h>
#include <openssl/rsa.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_public_encrypt __P((BIGNUM * out, BIGNUM * in, RSA * prv));
void rsa_private_decrypt __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" #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 "ssh.h"
#include "servconf.h" #include "servconf.h"
@ -29,8 +29,7 @@ initialize_server_options(ServerOptions *options)
options->num_ports = 0; options->num_ports = 0;
options->ports_from_cmdline = 0; options->ports_from_cmdline = 0;
options->listen_addrs = NULL; options->listen_addrs = NULL;
options->host_key_file = NULL; options->num_host_key_files = 0;
options->host_dsa_key_file = NULL;
options->pid_file = NULL; options->pid_file = NULL;
options->server_key_bits = -1; options->server_key_bits = -1;
options->login_grace_time = -1; options->login_grace_time = -1;
@ -50,7 +49,7 @@ initialize_server_options(ServerOptions *options)
options->rhosts_authentication = -1; options->rhosts_authentication = -1;
options->rhosts_rsa_authentication = -1; options->rhosts_rsa_authentication = -1;
options->rsa_authentication = -1; options->rsa_authentication = -1;
options->dsa_authentication = -1; options->pubkey_authentication = -1;
#ifdef KRB4 #ifdef KRB4
options->kerberos_authentication = -1; options->kerberos_authentication = -1;
options->kerberos_or_local_passwd = -1; options->kerberos_or_local_passwd = -1;
@ -84,14 +83,19 @@ initialize_server_options(ServerOptions *options)
void void
fill_default_server_options(ServerOptions *options) 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) if (options->num_ports == 0)
options->ports[options->num_ports++] = SSH_DEFAULT_PORT; options->ports[options->num_ports++] = SSH_DEFAULT_PORT;
if (options->listen_addrs == NULL) if (options->listen_addrs == NULL)
add_listen_addr(options, 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) if (options->pid_file == NULL)
options->pid_file = SSH_DAEMON_PID_FILE; options->pid_file = SSH_DAEMON_PID_FILE;
if (options->server_key_bits == -1) if (options->server_key_bits == -1)
@ -132,8 +136,8 @@ fill_default_server_options(ServerOptions *options)
options->rhosts_rsa_authentication = 0; options->rhosts_rsa_authentication = 0;
if (options->rsa_authentication == -1) if (options->rsa_authentication == -1)
options->rsa_authentication = 1; options->rsa_authentication = 1;
if (options->dsa_authentication == -1) if (options->pubkey_authentication == -1)
options->dsa_authentication = 1; options->pubkey_authentication = 1;
#ifdef KRB4 #ifdef KRB4
if (options->kerberos_authentication == -1) if (options->kerberos_authentication == -1)
options->kerberos_authentication = (access(KEYFILE, R_OK) == 0); options->kerberos_authentication = (access(KEYFILE, R_OK) == 0);
@ -162,8 +166,6 @@ fill_default_server_options(ServerOptions *options)
options->use_login = 0; options->use_login = 0;
if (options->allow_tcp_forwarding == -1) if (options->allow_tcp_forwarding == -1)
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) if (options->gateway_ports == -1)
options->gateway_ports = 0; options->gateway_ports = 0;
if (options->max_startups == -1) if (options->max_startups == -1)
@ -194,8 +196,8 @@ typedef enum {
sStrictModes, sEmptyPasswd, sRandomSeedFile, sKeepAlives, sCheckMail, sStrictModes, sEmptyPasswd, sRandomSeedFile, sKeepAlives, sCheckMail,
sUseLogin, sAllowTcpForwarding, sUseLogin, sAllowTcpForwarding,
sAllowUsers, sDenyUsers, sAllowGroups, sDenyGroups, sAllowUsers, sDenyUsers, sAllowGroups, sDenyGroups,
sIgnoreUserKnownHosts, sHostDSAKeyFile, sCiphers, sProtocol, sPidFile, sIgnoreUserKnownHosts, sCiphers, sProtocol, sPidFile,
sGatewayPorts, sDSAAuthentication, sXAuthLocation, sSubsystem, sMaxStartups sGatewayPorts, sPubkeyAuthentication, sXAuthLocation, sSubsystem, sMaxStartups,
} ServerOpCodes; } ServerOpCodes;
/* Textual representation of the tokens. */ /* Textual representation of the tokens. */
@ -205,7 +207,7 @@ static struct {
} keywords[] = { } keywords[] = {
{ "port", sPort }, { "port", sPort },
{ "hostkey", sHostKeyFile }, { "hostkey", sHostKeyFile },
{ "hostdsakey", sHostDSAKeyFile }, { "hostdsakey", sHostKeyFile }, /* alias */
{ "pidfile", sPidFile }, { "pidfile", sPidFile },
{ "serverkeybits", sServerKeyBits }, { "serverkeybits", sServerKeyBits },
{ "logingracetime", sLoginGraceTime }, { "logingracetime", sLoginGraceTime },
@ -216,7 +218,8 @@ static struct {
{ "rhostsauthentication", sRhostsAuthentication }, { "rhostsauthentication", sRhostsAuthentication },
{ "rhostsrsaauthentication", sRhostsRSAAuthentication }, { "rhostsrsaauthentication", sRhostsRSAAuthentication },
{ "rsaauthentication", sRSAAuthentication }, { "rsaauthentication", sRSAAuthentication },
{ "dsaauthentication", sDSAAuthentication }, { "pubkeyauthentication", sPubkeyAuthentication },
{ "dsaauthentication", sPubkeyAuthentication }, /* alias */
#ifdef KRB4 #ifdef KRB4
{ "kerberosauthentication", sKerberosAuthentication }, { "kerberosauthentication", sKerberosAuthentication },
{ "kerberosorlocalpasswd", sKerberosOrLocalPasswd }, { "kerberosorlocalpasswd", sKerberosOrLocalPasswd },
@ -336,6 +339,8 @@ read_server_config(ServerOptions *options, const char *filename)
arg = strdelim(&cp); arg = strdelim(&cp);
if (!*arg || *arg == '#') if (!*arg || *arg == '#')
continue; continue;
intptr = NULL;
charptr = NULL;
opcode = parse_token(arg, filename, linenum); opcode = parse_token(arg, filename, linenum);
switch (opcode) { switch (opcode) {
case sBadOption: case sBadOption:
@ -389,9 +394,13 @@ parse_int:
break; break;
case sHostKeyFile: case sHostKeyFile:
case sHostDSAKeyFile: intptr = &options->num_host_key_files;
charptr = (opcode == sHostKeyFile ) ? if (*intptr >= MAX_HOSTKEYS) {
&options->host_key_file : &options->host_dsa_key_file; 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: parse_filename:
arg = strdelim(&cp); arg = strdelim(&cp);
if (!arg || *arg == '\0') { if (!arg || *arg == '\0') {
@ -399,8 +408,12 @@ parse_filename:
filename, linenum); filename, linenum);
exit(1); exit(1);
} }
if (*charptr == NULL) if (*charptr == NULL) {
*charptr = tilde_expand_filename(arg, getuid()); *charptr = tilde_expand_filename(arg, getuid());
/* increase optional counter */
if (intptr != NULL)
*intptr = *intptr + 1;
}
break; break;
case sPidFile: case sPidFile:
@ -474,8 +487,8 @@ parse_flag:
intptr = &options->rsa_authentication; intptr = &options->rsa_authentication;
goto parse_flag; goto parse_flag;
case sDSAAuthentication: case sPubkeyAuthentication:
intptr = &options->dsa_authentication; intptr = &options->pubkey_authentication;
goto parse_flag; goto parse_flag;
#ifdef KRB4 #ifdef KRB4

View File

@ -11,7 +11,7 @@
* called by a name other than "ssh" or "Secure Shell". * 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 #ifndef SERVCONF_H
#define SERVCONF_H #define SERVCONF_H
@ -23,6 +23,7 @@
#define MAX_ALLOW_GROUPS 256 /* Max # groups on allow list. */ #define MAX_ALLOW_GROUPS 256 /* Max # groups on allow list. */
#define MAX_DENY_GROUPS 256 /* Max # groups on deny list. */ #define MAX_DENY_GROUPS 256 /* Max # groups on deny list. */
#define MAX_SUBSYSTEMS 256 /* Max # subsystems. */ #define MAX_SUBSYSTEMS 256 /* Max # subsystems. */
#define MAX_HOSTKEYS 256 /* Max # hostkeys. */
typedef struct { typedef struct {
unsigned int num_ports; unsigned int num_ports;
@ -30,8 +31,8 @@ typedef struct {
u_short ports[MAX_PORTS]; /* Port number to listen on. */ u_short ports[MAX_PORTS]; /* Port number to listen on. */
char *listen_addr; /* Address on which the server listens. */ char *listen_addr; /* Address on which the server listens. */
struct addrinfo *listen_addrs; /* Addresses 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_key_files[MAX_HOSTKEYS]; /* Files containing host keys. */
char *host_dsa_key_file; /* File containing dsa host key. */ int num_host_key_files; /* Number of files for host keys. */
char *pid_file; /* Where to put our pid */ char *pid_file; /* Where to put our pid */
int server_key_bits;/* Size of the server key. */ int server_key_bits;/* Size of the server key. */
int login_grace_time; /* Disconnect if no auth in this time 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 int rhosts_rsa_authentication; /* If true, permit rhosts RSA
* authentication. */ * authentication. */
int rsa_authentication; /* If true, permit 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 #ifdef KRB4
int kerberos_authentication; /* If true, permit Kerberos int kerberos_authentication; /* If true, permit Kerberos
* authentication. */ * authentication. */

View File

@ -35,7 +35,7 @@
*/ */
#include "includes.h" #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 "xmalloc.h"
#include "ssh.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 "session.h"
#include "dispatch.h" #include "dispatch.h"
#include "auth-options.h" #include "auth-options.h"
#include "auth.h"
extern ServerOptions options; 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); pty_change_window_size(fdin, row, col, xpixel, ypixel);
} }
int Channel *
input_direct_tcpip(void) server_request_direct_tcpip(char *ctype)
{ {
int sock; int sock, newch;
char *target, *originator; char *target, *originator;
int target_port, originator_port; int target_port, originator_port;
@ -752,23 +753,52 @@ input_direct_tcpip(void)
originator_port = packet_get_int(); originator_port = packet_get_int();
packet_done(); 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); originator, originator_port, target, target_port);
/* XXX check permission */ /* XXX check permission */
if (no_port_forwarding_flag || !options.allow_tcp_forwarding) { if (no_port_forwarding_flag || !options.allow_tcp_forwarding) {
xfree(target); xfree(target);
xfree(originator); xfree(originator);
return -1; return NULL;
} }
sock = channel_connect_to(target, target_port); sock = channel_connect_to(target, target_port);
xfree(target); xfree(target);
xfree(originator); xfree(originator);
if (sock < 0) if (sock < 0)
return -1; return NULL;
return channel_new("direct-tcpip", SSH_CHANNEL_OPEN, newch = channel_new(ctype, SSH_CHANNEL_OPEN,
sock, sock, -1, CHAN_TCP_WINDOW_DEFAULT, sock, sock, -1, CHAN_TCP_WINDOW_DEFAULT,
CHAN_TCP_PACKET_DEFAULT, 0, xstrdup("direct-tcpip"), 1); 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 void
@ -776,7 +806,6 @@ server_input_channel_open(int type, int plen, void *ctxt)
{ {
Channel *c = NULL; Channel *c = NULL;
char *ctype; char *ctype;
int id;
unsigned int len; unsigned int len;
int rchan; int rchan;
int rmaxpack; int rmaxpack;
@ -791,34 +820,12 @@ server_input_channel_open(int type, int plen, void *ctxt)
ctype, rchan, rwindow, rmaxpack); ctype, rchan, rwindow, rmaxpack);
if (strcmp(ctype, "session") == 0) { if (strcmp(ctype, "session") == 0) {
debug("open session"); c = server_request_session(ctype);
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);
}
} else if (strcmp(ctype, "direct-tcpip") == 0) { } else if (strcmp(ctype, "direct-tcpip") == 0) {
id = input_direct_tcpip(); c = server_request_direct_tcpip(ctype);
if (id >= 0)
c = channel_lookup(id);
} }
if (c != NULL) { if (c != NULL) {
debug("confirm %s", ctype); debug("server_input_channel_open: confirm %s", ctype);
c->remote_id = rchan; c->remote_id = rchan;
c->remote_window = rwindow; c->remote_window = rwindow;
c->remote_maxpacket = rmaxpack; 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_put_int(c->local_maxpacket);
packet_send(); packet_send();
} else { } else {
debug("failure %s", ctype); debug("server_input_channel_open: failure %s", ctype);
packet_start(SSH2_MSG_CHANNEL_OPEN_FAILURE); packet_start(SSH2_MSG_CHANNEL_OPEN_FAILURE);
packet_put_int(rchan); packet_put_int(rchan);
packet_put_int(SSH2_OPEN_ADMINISTRATIVELY_PROHIBITED); packet_put_int(SSH2_OPEN_ADMINISTRATIVELY_PROHIBITED);
@ -841,6 +848,56 @@ server_input_channel_open(int type, int plen, void *ctxt)
xfree(ctype); 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 void
server_init_dispatch_20() 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_OPEN_FAILURE, &channel_input_open_failure);
dispatch_set(SSH2_MSG_CHANNEL_REQUEST, &channel_input_channel_request); 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_CHANNEL_WINDOW_ADJUST, &channel_input_window_adjust);
dispatch_set(SSH2_MSG_GLOBAL_REQUEST, &server_input_global_request);
} }
void void
server_init_dispatch_13() server_init_dispatch_13()

View File

@ -33,7 +33,7 @@
*/ */
#include "includes.h" #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 "xmalloc.h"
#include "ssh.h" #include "ssh.h"
@ -1735,6 +1735,19 @@ session_exec_req(Session *s)
return 1; 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 void
session_input_channel_req(int id, void *arg) 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); success = session_pty_req(s);
} else if (strcmp(rtype, "x11-req") == 0) { } else if (strcmp(rtype, "x11-req") == 0) {
success = session_x11_req(s); 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) { } else if (strcmp(rtype, "subsystem") == 0) {
success = session_subsystem_req(s); 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. .\" Copyright (c) 2000 Markus Friedl. All rights reserved.
.\" .\"
@ -48,7 +48,7 @@ for more information.
.Xr ssh-add 1 , .Xr ssh-add 1 ,
.Xr ssh-keygen 1 , .Xr ssh-keygen 1 ,
.Xr sshd 8 .Xr sshd 8
.Sh AUTHOR .Sh AUTHORS
Markus Friedl <markus@openbsd.org> Markus Friedl <markus@openbsd.org>
.Sh HISTORY .Sh HISTORY
.Nm .Nm

View File

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

View File

@ -35,7 +35,7 @@
*/ */
#include "includes.h" #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/evp.h>
#include <openssl/rsa.h> #include <openssl/rsa.h>
@ -60,10 +60,10 @@ delete_file(AuthenticationConnection *ac, const char *filename)
Key *public; Key *public;
char *comment; char *comment;
public = key_new(KEY_RSA); public = key_new(KEY_RSA1);
if (!load_public_key(filename, public, &comment)) { if (!load_public_key(filename, public, &comment)) {
key_free(public); key_free(public);
public = key_new(KEY_DSA); public = key_new(KEY_UNSPEC);
if (!try_load_public_key(filename, public, &comment)) { if (!try_load_public_key(filename, public, &comment)) {
printf("Bad key file %s\n", filename); printf("Bad key file %s\n", filename);
return; return;
@ -144,7 +144,7 @@ add_file(AuthenticationConnection *ac, const char *filename)
char buf[1024], msg[1024]; char buf[1024], msg[1024];
int success; int success;
int interactive = isatty(STDIN_FILENO); int interactive = isatty(STDIN_FILENO);
int type = KEY_RSA; int type = KEY_RSA1;
if (stat(filename, &st) < 0) { if (stat(filename, &st) < 0) {
perror(filename); 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, * try to load the public key. right now this only works for RSA,
* since DSA keys are fully encrypted * since DSA keys are fully encrypted
*/ */
public = key_new(KEY_RSA); public = key_new(KEY_RSA1);
if (!load_public_key(filename, public, &saved_comment)) { if (!load_public_key(filename, public, &saved_comment)) {
/* ok, so we will asume this is a DSA key */ /* ok, so we will assume this is 'some' key */
type = KEY_DSA; type = KEY_UNSPEC;
saved_comment = xstrdup(filename); saved_comment = xstrdup(filename);
} }
key_free(public); key_free(public);
@ -223,8 +223,9 @@ list_identities(AuthenticationConnection *ac, int fp)
key = ssh_get_next_identity(ac, &comment, version)) { key = ssh_get_next_identity(ac, &comment, version)) {
had_identities = 1; had_identities = 1;
if (fp) { if (fp) {
printf("%d %s %s\n", printf("%d %s %s (%s)\n",
key_size(key), key_fingerprint(key), comment); key_size(key), key_fingerprint(key),
comment, key_type(key));
} else { } else {
if (!key_write(key, stdout)) if (!key_write(key, stdout))
fprintf(stderr, "key_write failed"); fprintf(stderr, "key_write failed");
@ -250,13 +251,6 @@ main(int argc, char **argv)
init_rng(); 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(); SSLeay_add_all_algorithms();
/* At first, get a connection to the authentication agent. */ /* 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> .\" Author: Tatu Ylonen <ylo@cs.hut.fi>
.\" Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland .\" 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. These sockets should only be readable by the owner.
The sockets should get automatically removed when the agent exits. The sockets should get automatically removed when the agent exits.
.El .El
.Sh AUTHOR .Sh AUTHORS
Tatu Ylonen <ylo@cs.hut.fi> Tatu Ylonen <ylo@cs.hut.fi>
.Pp .Pp
OpenSSH 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> * Author: Tatu Ylonen <ylo@cs.hut.fi>
@ -37,7 +37,7 @@
*/ */
#include "includes.h" #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 "ssh.h"
#include "rsa.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 <openssl/rsa.h>
#include "key.h" #include "key.h"
#include "authfd.h" #include "authfd.h"
#include "dsa.h"
#include "kex.h" #include "kex.h"
#include "compat.h" #include "compat.h"
@ -147,14 +146,14 @@ process_request_identities(SocketEntry *e, int version)
buffer_put_int(&msg, tab->nentries); buffer_put_int(&msg, tab->nentries);
for (i = 0; i < tab->nentries; i++) { for (i = 0; i < tab->nentries; i++) {
Identity *id = &tab->identities[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_int(&msg, BN_num_bits(id->key->rsa->n));
buffer_put_bignum(&msg, id->key->rsa->e); buffer_put_bignum(&msg, id->key->rsa->e);
buffer_put_bignum(&msg, id->key->rsa->n); buffer_put_bignum(&msg, id->key->rsa->n);
} else { } else {
unsigned char *blob; unsigned char *blob;
unsigned int blen; unsigned int blen;
dsa_make_key_blob(id->key, &blob, &blen); key_to_blob(id->key, &blob, &blen);
buffer_put_string(&msg, blob, blen); buffer_put_string(&msg, blob, blen);
xfree(blob); xfree(blob);
} }
@ -178,7 +177,7 @@ process_authentication_challenge1(SocketEntry *e)
unsigned int response_type; unsigned int response_type;
buffer_init(&msg); buffer_init(&msg);
key = key_new(KEY_RSA); key = key_new(KEY_RSA1);
challenge = BN_new(); challenge = BN_new();
buffer_get_int(&e->input); /* ignored */ buffer_get_int(&e->input); /* ignored */
@ -251,11 +250,11 @@ process_sign_request2(SocketEntry *e)
if (flags & SSH_AGENT_OLD_SIGNATURE) if (flags & SSH_AGENT_OLD_SIGNATURE)
datafellows = SSH_BUG_SIGBLOB; datafellows = SSH_BUG_SIGBLOB;
key = dsa_key_from_blob(blob, blen); key = key_from_blob(blob, blen);
if (key != NULL) { if (key != NULL) {
private = lookup_private_key(key, NULL, 2); private = lookup_private_key(key, NULL, 2);
if (private != NULL) if (private != NULL)
ok = dsa_sign(private, &signature, &slen, data, dlen); ok = key_sign(private, &signature, &slen, data, dlen);
} }
key_free(key); key_free(key);
buffer_init(&msg); buffer_init(&msg);
@ -287,7 +286,7 @@ process_remove_identity(SocketEntry *e, int version)
switch(version){ switch(version){
case 1: case 1:
key = key_new(KEY_RSA); key = key_new(KEY_RSA1);
bits = buffer_get_int(&e->input); bits = buffer_get_int(&e->input);
buffer_get_bignum(&e->input, key->rsa->e); buffer_get_bignum(&e->input, key->rsa->e);
buffer_get_bignum(&e->input, key->rsa->n); buffer_get_bignum(&e->input, key->rsa->n);
@ -298,7 +297,7 @@ process_remove_identity(SocketEntry *e, int version)
break; break;
case 2: case 2:
blob = buffer_get_string(&e->input, &blen); blob = buffer_get_string(&e->input, &blen);
key = dsa_key_from_blob(blob, blen); key = key_from_blob(blob, blen);
xfree(blob); xfree(blob);
break; break;
} }
@ -315,8 +314,12 @@ process_remove_identity(SocketEntry *e, int version)
Idtab *tab = idtab_lookup(version); Idtab *tab = idtab_lookup(version);
key_free(tab->identities[idx].key); key_free(tab->identities[idx].key);
xfree(tab->identities[idx].comment); xfree(tab->identities[idx].comment);
if (idx != tab->nentries) if (tab->nentries < 1)
tab->identities[idx] = tab->identities[tab->nentries]; 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--; tab->nentries--;
success = 1; success = 1;
} }
@ -348,80 +351,81 @@ process_remove_all_identities(SocketEntry *e, int version)
return; 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 void
process_add_identity(SocketEntry *e, int version) process_add_identity(SocketEntry *e, int version)
{ {
Key *k = NULL; Key *k = NULL;
RSA *rsa; char *type_name;
BIGNUM *aux;
BN_CTX *ctx;
char *type;
char *comment; char *comment;
int success = 0; int type, success = 0;
Idtab *tab = idtab_lookup(version); Idtab *tab = idtab_lookup(version);
switch (version) { switch (version) {
case 1: case 1:
k = key_new(KEY_RSA); k = key_new_private(KEY_RSA1);
rsa = k->rsa; buffer_get_int(&e->input); /* ignored */
buffer_get_bignum(&e->input, k->rsa->n);
/* allocate mem for private key */ buffer_get_bignum(&e->input, k->rsa->e);
/* XXX rsa->n and rsa->e are already allocated */ buffer_get_bignum(&e->input, k->rsa->d);
rsa->d = BN_new(); buffer_get_bignum(&e->input, k->rsa->iqmp);
rsa->iqmp = BN_new();
rsa->q = BN_new();
rsa->p = BN_new();
rsa->dmq1 = BN_new();
rsa->dmp1 = BN_new();
buffer_get_int(&e->input); /* ignored */
buffer_get_bignum(&e->input, rsa->n);
buffer_get_bignum(&e->input, rsa->e);
buffer_get_bignum(&e->input, rsa->d);
buffer_get_bignum(&e->input, rsa->iqmp);
/* SSH and SSL have p and q swapped */ /* SSH and SSL have p and q swapped */
buffer_get_bignum(&e->input, rsa->q); /* p */ buffer_get_bignum(&e->input, k->rsa->q); /* p */
buffer_get_bignum(&e->input, rsa->p); /* q */ buffer_get_bignum(&e->input, k->rsa->p); /* q */
/* Generate additional parameters */ /* Generate additional parameters */
aux = BN_new(); generate_additional_parameters(k->rsa);
ctx = BN_CTX_new();
BN_sub(aux, rsa->q, BN_value_one());
BN_mod(rsa->dmq1, rsa->d, aux, ctx);
BN_sub(aux, rsa->p, BN_value_one());
BN_mod(rsa->dmp1, rsa->d, aux, ctx);
BN_clear_free(aux);
BN_CTX_free(ctx);
break; break;
case 2: case 2:
type = buffer_get_string(&e->input, NULL); type_name = buffer_get_string(&e->input, NULL);
if (strcmp(type, KEX_DSS)) { 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); buffer_clear(&e->input);
xfree(type);
goto send; 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; break;
} }
comment = buffer_get_string(&e->input, NULL); comment = buffer_get_string(&e->input, NULL);
if (k == NULL) { if (k == NULL) {
xfree(comment); xfree(comment);
@ -670,13 +674,6 @@ main(int ac, char **av)
init_rng(); 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__ #ifdef __GNU_LIBRARY__
while ((ch = getopt(ac, av, "+cks")) != -1) { while ((ch = getopt(ac, av, "+cks")) != -1) {
#else /* __GNU_LIBRARY__ */ #else /* __GNU_LIBRARY__ */

View File

@ -23,7 +23,7 @@
*/ */
#include "includes.h" #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 "ssh.h"
#include "xmalloc.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 "compat.h"
#include <openssl/bn.h> #include <openssl/bn.h>
#include <openssl/dh.h>
#include <openssl/rsa.h> #include <openssl/rsa.h>
#include <openssl/dsa.h> #include <openssl/dsa.h>
#include <openssl/evp.h> #include <openssl/evp.h>
#include <openssl/bio.h>
#include <openssl/pem.h>
#include <openssl/hmac.h>
#include "kex.h"
#include "key.h" #include "key.h"
#include "uuencode.h"
#define INTBLOB_LEN 20 #define INTBLOB_LEN 20
#define SIGBLOB_LEN (2*INTBLOB_LEN) #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 int
dsa_make_key_blob(Key *key, unsigned char **blobp, unsigned int *lenp) ssh_dss_sign(
{
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(
Key *key, Key *key,
unsigned char **sigp, int *lenp, unsigned char **sigp, int *lenp,
unsigned char *data, int datalen) unsigned char *data, int datalen)
@ -130,7 +59,7 @@ dsa_sign(
Buffer b; Buffer b;
if (key == NULL || key->type != KEY_DSA || key->dsa == NULL) { 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; return -1;
} }
digest = xmalloc(evp_md->md_size); digest = xmalloc(evp_md->md_size);
@ -140,7 +69,7 @@ dsa_sign(
sig = DSA_do_sign(digest, evp_md->md_size, key->dsa); sig = DSA_do_sign(digest, evp_md->md_size, key->dsa);
if (sig == NULL) { if (sig == NULL) {
fatal("dsa_sign: cannot sign"); fatal("ssh_dss_sign: cannot sign");
} }
rlen = BN_num_bytes(sig->r); rlen = BN_num_bytes(sig->r);
@ -168,7 +97,7 @@ dsa_sign(
} else { } else {
/* ietf-drafts */ /* ietf-drafts */
buffer_init(&b); buffer_init(&b);
buffer_put_cstring(&b, KEX_DSS); buffer_put_cstring(&b, "ssh-dss");
buffer_put_string(&b, sigblob, SIGBLOB_LEN); buffer_put_string(&b, sigblob, SIGBLOB_LEN);
len = buffer_len(&b); len = buffer_len(&b);
ret = xmalloc(len); ret = xmalloc(len);
@ -182,7 +111,7 @@ dsa_sign(
return 0; return 0;
} }
int int
dsa_verify( ssh_dss_verify(
Key *key, Key *key,
unsigned char *signature, int signaturelen, unsigned char *signature, int signaturelen,
unsigned char *data, int datalen) unsigned char *data, int datalen)
@ -194,12 +123,12 @@ dsa_verify(
EVP_MD_CTX md; EVP_MD_CTX md;
unsigned char *sigblob; unsigned char *sigblob;
char *txt; char *txt;
unsigned int len; unsigned int len, dlen;
int rlen; int rlen;
int ret; int ret;
if (key == NULL || key->type != KEY_DSA || key->dsa == NULL) { 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; return -1;
} }
@ -225,8 +154,8 @@ dsa_verify(
buffer_init(&b); buffer_init(&b);
buffer_append(&b, (char *) signature, signaturelen); buffer_append(&b, (char *) signature, signaturelen);
ktype = buffer_get_string(&b, NULL); ktype = buffer_get_string(&b, NULL);
if (strcmp(KEX_DSS, ktype) != 0) { if (strcmp("ssh-dss", ktype) != 0) {
error("dsa_verify: cannot handle type %s", ktype); error("ssh_dss_verify: cannot handle type %s", ktype);
buffer_free(&b); buffer_free(&b);
return -1; return -1;
} }
@ -258,14 +187,15 @@ dsa_verify(
} }
/* sha1 the data */ /* sha1 the data */
digest = xmalloc(evp_md->md_size); dlen = evp_md->md_size;
digest = xmalloc(dlen);
EVP_DigestInit(&md, evp_md); EVP_DigestInit(&md, evp_md);
EVP_DigestUpdate(&md, data, datalen); EVP_DigestUpdate(&md, data, datalen);
EVP_DigestFinal(&md, digest, NULL); 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); xfree(digest);
DSA_SIG_free(sig); DSA_SIG_free(sig);
@ -281,24 +211,6 @@ dsa_verify(
txt = "error"; txt = "error";
break; break;
} }
debug("dsa_verify: signature %s", txt); debug("ssh_dss_verify: signature %s", txt);
return ret; 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 #ifndef DSA_H
#define 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 int
dsa_sign( ssh_dss_sign(
Key *key, Key *key,
unsigned char **sigp, int *lenp, unsigned char **sigp, int *lenp,
unsigned char *data, int datalen); unsigned char *data, int datalen);
int int
dsa_verify( ssh_dss_verify(
Key *key, Key *key,
unsigned char *signature, int signaturelen, unsigned char *signature, int signaturelen,
unsigned char *data, int datalen); unsigned char *data, int datalen);
Key *
dsa_generate_key(unsigned int bits);
#endif #endif

View File

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

View File

@ -12,7 +12,7 @@
*/ */
#include "includes.h" #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/evp.h>
#include <openssl/pem.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 "xmalloc.h"
#include "key.h" #include "key.h"
#include "rsa.h" #include "rsa.h"
#include "dsa.h"
#include "authfile.h" #include "authfile.h"
#include "uuencode.h" #include "uuencode.h"
@ -67,7 +66,10 @@ char *identity_comment = NULL;
int convert_to_ssh2 = 0; int convert_to_ssh2 = 0;
int convert_from_ssh2 = 0; int convert_from_ssh2 = 0;
int print_public = 0; int print_public = 0;
int dsa_mode = 0;
/* key type */
int dsa_mode = 0; /* compat */
char *key_type_name = NULL;
/* argv0 */ /* argv0 */
#ifdef HAVE___PROGNAME #ifdef HAVE___PROGNAME
@ -130,12 +132,12 @@ do_convert_to_ssh2(struct passwd *pw)
perror(identity_file); perror(identity_file);
exit(1); exit(1);
} }
k = key_new(KEY_DSA); k = key_new(KEY_UNSPEC);
if (!try_load_key(identity_file, k)) { if (!try_load_key(identity_file, k)) {
fprintf(stderr, "load failed\n"); fprintf(stderr, "load failed\n");
exit(1); 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, "%s\n", SSH_COM_PUBLIC_BEGIN);
fprintf(stdout, fprintf(stdout,
"Comment: \"%d-bit %s, converted from OpenSSH by %s@%s\"\n", "Comment: \"%d-bit %s, converted from OpenSSH by %s@%s\"\n",
@ -266,7 +268,7 @@ do_convert_from_ssh2(struct passwd *pw)
} }
k = private ? k = private ?
do_convert_private_ssh2_from_blob(blob, blen) : do_convert_private_ssh2_from_blob(blob, blen) :
dsa_key_from_blob(blob, blen); key_from_blob(blob, blen);
if (k == NULL) { if (k == NULL) {
fprintf(stderr, "decode blob failed.\n"); fprintf(stderr, "decode blob failed.\n");
exit(1); exit(1);
@ -288,8 +290,6 @@ void
do_print_public(struct passwd *pw) do_print_public(struct passwd *pw)
{ {
Key *k; Key *k;
int len;
unsigned char *blob;
struct stat st; struct stat st;
if (!have_identity) if (!have_identity)
@ -298,16 +298,14 @@ do_print_public(struct passwd *pw)
perror(identity_file); perror(identity_file);
exit(1); exit(1);
} }
k = key_new(KEY_DSA); k = key_new(KEY_UNSPEC);
if (!try_load_key(identity_file, k)) { if (!try_load_key(identity_file, k)) {
fprintf(stderr, "load failed\n"); fprintf(stderr, "load failed\n");
exit(1); exit(1);
} }
dsa_make_key_blob(k, &blob, &len);
if (!key_write(k, stdout)) if (!key_write(k, stdout))
fprintf(stderr, "key_write failed"); fprintf(stderr, "key_write failed");
key_free(k); key_free(k);
xfree(blob);
fprintf(stdout, "\n"); fprintf(stdout, "\n");
exit(0); exit(0);
} }
@ -315,12 +313,11 @@ do_print_public(struct passwd *pw)
void void
do_fingerprint(struct passwd *pw) do_fingerprint(struct passwd *pw)
{ {
/* XXX RSA1 only */
FILE *f; FILE *f;
Key *public; Key *public;
char *comment = NULL, *cp, *ep, line[16*1024]; char *comment = NULL, *cp, *ep, line[16*1024];
int i, skip = 0, num = 1, invalid = 1; int i, skip = 0, num = 1, invalid = 1, success = 0;
unsigned int ignore; unsigned int ignore;
struct stat st; struct stat st;
@ -330,14 +327,27 @@ do_fingerprint(struct passwd *pw)
perror(identity_file); perror(identity_file);
exit(1); exit(1);
} }
public = key_new(KEY_RSA); public = key_new(KEY_RSA1);
if (load_public_key(identity_file, public, &comment)) { if (load_public_key(identity_file, public, &comment)) {
printf("%d %s %s\n", BN_num_bits(public->rsa->n), success = 1;
key_fingerprint(public), comment); } else {
key_free(public); 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); exit(0);
} }
/* XXX RSA1 only */
public = key_new(KEY_RSA1);
f = fopen(identity_file, "r"); f = fopen(identity_file, "r");
if (f != NULL) { if (f != NULL) {
while (fgets(line, sizeof(line), f)) { while (fgets(line, sizeof(line), f)) {
@ -404,7 +414,7 @@ do_change_passphrase(struct passwd *pw)
struct stat st; struct stat st;
Key *private; Key *private;
Key *public; Key *public;
int type = dsa_mode ? KEY_DSA : KEY_RSA; int type = KEY_RSA1;
if (!have_identity) if (!have_identity)
ask_filename(pw, "Enter file in which the key is"); ask_filename(pw, "Enter file in which the key is");
@ -412,18 +422,13 @@ do_change_passphrase(struct passwd *pw)
perror(identity_file); perror(identity_file);
exit(1); exit(1);
} }
public = key_new(type);
if (type == KEY_RSA) { if (!load_public_key(identity_file, public, NULL)) {
/* XXX this works currently only for RSA */ type = KEY_UNSPEC;
public = key_new(type); } else {
if (!load_public_key(identity_file, public, NULL)) {
printf("%s is not a valid key file.\n", identity_file);
exit(1);
}
/* Clear the public key since we are just about to load the whole file. */ /* Clear the public key since we are just about to load the whole file. */
key_free(public); key_free(public);
} }
/* Try to load the file with empty passphrase. */ /* Try to load the file with empty passphrase. */
private = key_new(type); private = key_new(type);
if (!load_private_key(identity_file, "", private, &comment)) { 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 * Try to load the public key from the file the verify that it is
* readable and of the proper format. * readable and of the proper format.
*/ */
public = key_new(KEY_RSA); public = key_new(KEY_RSA1);
if (!load_public_key(identity_file, public, NULL)) { if (!load_public_key(identity_file, public, NULL)) {
printf("%s is not a valid key file.\n", identity_file); printf("%s is not a valid key file.\n", identity_file);
exit(1); exit(1);
} }
private = key_new(KEY_RSA); private = key_new(KEY_RSA1);
if (load_private_key(identity_file, "", private, &comment)) if (load_private_key(identity_file, "", private, &comment))
passphrase = xstrdup(""); passphrase = xstrdup("");
else { else {
@ -583,7 +588,7 @@ do_change_comment(struct passwd *pw)
void void
usage(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); exit(1);
} }
@ -598,8 +603,10 @@ main(int ac, char **av)
int opt; int opt;
struct stat st; struct stat st;
FILE *f; FILE *f;
int type = KEY_RSA1;
Key *private; Key *private;
Key *public; Key *public;
extern int optind; extern int optind;
extern char *optarg; extern char *optarg;
@ -618,7 +625,7 @@ main(int ac, char **av)
exit(1); 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) { switch (opt) {
case 'b': case 'b':
bits = atoi(optarg); bits = atoi(optarg);
@ -662,10 +669,8 @@ main(int ac, char **av)
break; break;
case 'R': case 'R':
if (rsa_alive() == 0) /* unused */
exit(1); exit(0);
else
exit(0);
break; break;
case 'x': case 'x':
@ -681,9 +686,15 @@ main(int ac, char **av)
break; break;
case 'd': case 'd':
key_type_name = "dsa";
dsa_mode = 1; dsa_mode = 1;
break; break;
case 't':
key_type_name = optarg;
dsa_mode = (strcmp(optarg, "dsa") == 0);
break;
case '?': case '?':
default: default:
usage(); usage();
@ -697,13 +708,6 @@ main(int ac, char **av)
printf("Can only have one of -p and -c.\n"); printf("Can only have one of -p and -c.\n");
usage(); 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) if (print_fingerprint)
do_fingerprint(pw); do_fingerprint(pw);
if (change_passphrase) if (change_passphrase)
@ -719,22 +723,21 @@ main(int ac, char **av)
arc4random_stir(); arc4random_stir();
if (dsa_mode != 0) { if (key_type_name != NULL) {
if (!quiet) type = key_type_from_name(key_type_name);
printf("Generating DSA parameter and key.\n"); if (type == KEY_UNSPEC) {
public = private = dsa_generate_key(bits); fprintf(stderr, "unknown key type %s", key_type_name);
if (private == NULL) {
fprintf(stderr, "dsa_generate_keys failed");
exit(1); 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) if (!have_identity)
ask_filename(pw, "Enter file in which to save the key"); ask_filename(pw, "Enter file in which to save the key");
@ -803,9 +806,7 @@ passphrase_again:
xfree(passphrase1); xfree(passphrase1);
/* Clear the private key and the random number generator. */ /* Clear the private key and the random number generator. */
if (private != public) { key_free(private);
key_free(private);
}
arc4random_stir(); arc4random_stir();
if (!quiet) 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 .\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. .\" 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 .Dd September 25, 1999
.Dt SSH 1 .Dt SSH 1
.Os .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. If this method fails password authentication is tried.
.Pp .Pp
The public key method is similar to RSA authentication described The public key method is similar to RSA authentication described
in the previous section except that the DSA algorithm is used in the previous section except that the DSA or RSA algorithm is used
instead of the patented RSA algorithm. instead.
The client uses his private DSA key The client uses his private key
.Pa $HOME/.ssh/id_dsa .Pa $HOME/.ssh/id_dsa
to sign the session identifier and sends the result to the server. to sign the session identifier and sends the result to the server.
The server checks whether the matching public key is listed in 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 RSA host keys are stored in
.Pa $HOME/.ssh/known_hosts .Pa $HOME/.ssh/known_hosts
and and
DSA host keys are stored in host keys used in the protocol version 2 are stored in
.Pa $HOME/.ssh/known_hosts2 .Pa $HOME/.ssh/known_hosts2
in the user's home directory. in the user's home directory.
Additionally, the files Additionally, the files
@ -352,7 +352,8 @@ The
.Cm StrictHostKeyChecking .Cm StrictHostKeyChecking
option (see below) can be used to prevent logins to machines whose option (see below) can be used to prevent logins to machines whose
host key is not known or has changed. host key is not known or has changed.
.Sh OPTIONS .Pp
The options are as follows:
.Bl -tag -width Ds .Bl -tag -width Ds
.It Fl a .It Fl a
Disables forwarding of the authentication agent connection. Disables forwarding of the authentication agent connection.
@ -407,7 +408,7 @@ something like
Allows remote hosts to connect to local forwarded ports. Allows remote hosts to connect to local forwarded ports.
.It Fl i Ar identity_file .It Fl i Ar identity_file
Selects the file from which the identity (private key) for Selects the file from which the identity (private key) for
RSA authentication is read. RSA or DSA authentication is read.
Default is Default is
.Pa $HOME/.ssh/identity .Pa $HOME/.ssh/identity
in the user's home directory. in the user's home directory.
@ -552,6 +553,22 @@ Forces
.Nm .Nm
to use IPv6 addresses only. to use IPv6 addresses only.
.El .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 .Sh CONFIGURATION FILES
.Nm .Nm
obtains configuration data from the following sources (in this order): 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. back to rsh or exiting.
The argument must be an integer. The argument must be an integer.
This may be useful in scripts if the connection sometimes fails. This may be useful in scripts if the connection sometimes fails.
.It Cm DSAAuthentication .It Cm PubkeyAuthentication
Specifies whether to try DSA authentication. Specifies whether to try public key authentication.
The argument to this keyword must be The argument to this keyword must be
.Dq yes .Dq yes
or or
.Dq no . .Dq no .
DSA authentication will only be
attempted if a DSA identity file exists.
Note that this option applies to protocol version 2 only. Note that this option applies to protocol version 2 only.
.It Cm EscapeChar .It Cm EscapeChar
Sets the escape character (default: Sets the escape character (default:
@ -745,16 +760,6 @@ syntax to refer to a user's home directory.
It is possible to have It is possible to have
multiple identity files specified in configuration files; all these multiple identity files specified in configuration files; all these
identities will be tried in sequence. 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 .It Cm KeepAlive
Specifies whether the system should send keepalive messages to the Specifies whether the system should send keepalive messages to the
other side. other side.
@ -1096,7 +1101,7 @@ spaces).
This file is not highly sensitive, but the recommended This file is not highly sensitive, but the recommended
permissions are read/write for the user, and not accessible by others. permissions are read/write for the user, and not accessible by others.
.It Pa $HOME/.ssh/authorized_keys2 .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 This file is not highly sensitive, but the recommended
permissions are read/write for the user, and not accessible by others. permissions are read/write for the user, and not accessible by others.
.It Pa /etc/ssh_known_hosts, /etc/ssh_known_hosts2 .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 .Pa /etc/ssh_known_hosts
contains RSA and contains RSA and
.Pa /etc/ssh_known_hosts2 .Pa /etc/ssh_known_hosts2
contains DSA keys. contains DSA or RSA keys for protocol version 2.
These files should be prepared by the These files should be prepared by the
system administrator to contain the public host keys of all machines in the system administrator to contain the public host keys of all machines in the
organization. organization.
@ -1219,7 +1224,7 @@ above.
A version of this library which includes support for the RSA algorithm A version of this library which includes support for the RSA algorithm
is required for proper operation. is required for proper operation.
.El .El
.Sh AUTHOR .Sh AUTHORS
OpenSSH OpenSSH
is a derivative of the original (free) ssh 1.2.12 release by Tatu Ylonen, is a derivative of the original (free) ssh 1.2.12 release by Tatu Ylonen,
but with bugs removed and newer features re-added. but with bugs removed and newer features re-added.

193
ssh.c
View File

@ -39,11 +39,12 @@
*/ */
#include "includes.h" #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/evp.h>
#include <openssl/dsa.h> #include <openssl/dsa.h>
#include <openssl/rsa.h> #include <openssl/rsa.h>
#include <openssl/err.h>
#include "xmalloc.h" #include "xmalloc.h"
#include "ssh.h" #include "ssh.h"
@ -218,8 +219,9 @@ rsh_connect(char *host, char *user, Buffer * command)
exit(1); exit(1);
} }
int ssh_session(void); int ssh_session(void);
int ssh_session2(void); int ssh_session2(void);
int guess_identity_file_type(const char *filename);
/* /*
* Main program for the ssh client. * Main program for the ssh client.
@ -370,14 +372,13 @@ main(int ac, char **av)
case 'i': case 'i':
if (stat(optarg, &st) < 0) { if (stat(optarg, &st) < 0) {
fprintf(stderr, "Warning: Identity file %s does not exist.\n", fprintf(stderr, "Warning: Identity file %s does not exist.\n",
optarg); optarg);
break; break;
} }
if (options.num_identity_files >= SSH_MAX_IDENTITY_FILES) if (options.num_identity_files >= SSH_MAX_IDENTITY_FILES)
fatal("Too many identity files specified (max %d)", fatal("Too many identity files specified (max %d)",
SSH_MAX_IDENTITY_FILES); SSH_MAX_IDENTITY_FILES);
options.identity_files[options.num_identity_files++] = options.identity_files[options.num_identity_files++] = xstrdup(optarg);
xstrdup(optarg);
break; break;
case 't': case 't':
tty_flag = 1; tty_flag = 1;
@ -487,6 +488,7 @@ main(int ac, char **av)
usage(); usage();
SSLeay_add_all_algorithms(); SSLeay_add_all_algorithms();
ERR_load_crypto_strings();
/* Initialize the command to execute on remote host. */ /* Initialize the command to execute on remote host. */
buffer_init(&command); buffer_init(&command);
@ -563,20 +565,6 @@ main(int ac, char **av)
/* reinit */ /* reinit */
log_init(av[0], options.log_level, SYSLOG_FACILITY_USER, 0); 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) if (options.user == NULL)
options.user = xstrdup(pw->pw_name); options.user = xstrdup(pw->pw_name);
@ -589,6 +577,8 @@ main(int ac, char **av)
if (!options.use_privileged_port) { if (!options.use_privileged_port) {
#else #else
if (original_effective_uid != 0 || !options.use_privileged_port) { if (original_effective_uid != 0 || !options.use_privileged_port) {
debug("Rhosts Authentication methods disabled, "
"originating port will not be trusted.");
#endif #endif
options.rhosts_authentication = 0; options.rhosts_authentication = 0;
options.rhosts_rsa_authentication = 0; options.rhosts_rsa_authentication = 0;
@ -635,7 +625,7 @@ main(int ac, char **av)
if (ok && (options.protocol & SSH_PROTO_1)) { if (ok && (options.protocol & SSH_PROTO_1)) {
Key k; Key k;
host_private_key = RSA_new(); host_private_key = RSA_new();
k.type = KEY_RSA; k.type = KEY_RSA1;
k.rsa = host_private_key; k.rsa = host_private_key;
if (load_private_key(HOST_KEY_FILE, "", &k, NULL)) if (load_private_key(HOST_KEY_FILE, "", &k, NULL))
host_private_key_loaded = 1; host_private_key_loaded = 1;
@ -682,23 +672,23 @@ main(int ac, char **av)
} }
exit(1); exit(1);
} }
/* Expand ~ in options.identity_files. */ /* Expand ~ in options.identity_files, known host file names. */
/* XXX mem-leaks */ /* 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] = options.identity_files[i] =
tilde_expand_filename(options.identity_files[i], original_real_uid); tilde_expand_filename(options.identity_files[i], original_real_uid);
for (i = 0; i < options.num_identity_files2; i++) options.identity_files_type[i] = guess_identity_file_type(options.identity_files[i]);
options.identity_files2[i] = debug("identity file %s type %d", options.identity_files[i],
tilde_expand_filename(options.identity_files2[i], original_real_uid); options.identity_files_type[i]);
/* Expand ~ in known host file names. */ }
options.system_hostfile = tilde_expand_filename(options.system_hostfile, options.system_hostfile =
original_real_uid); tilde_expand_filename(options.system_hostfile, original_real_uid);
options.user_hostfile = tilde_expand_filename(options.user_hostfile, options.user_hostfile =
original_real_uid); tilde_expand_filename(options.user_hostfile, original_real_uid);
options.system_hostfile2 = tilde_expand_filename(options.system_hostfile2, options.system_hostfile2 =
original_real_uid); tilde_expand_filename(options.system_hostfile2, original_real_uid);
options.user_hostfile2 = tilde_expand_filename(options.user_hostfile2, options.user_hostfile2 =
original_real_uid); tilde_expand_filename(options.user_hostfile2, original_real_uid);
/* Log into the remote system. This never returns if the login fails. */ /* Log into the remote system. This never returns if the login fails. */
ssh_login(host_private_key_loaded, host_private_key, 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 int
ssh_session(void) ssh_session(void)
{ {
int type; int type;
int i;
int plen; int plen;
int interactive = 0; int interactive = 0;
int have_tty = 0; int have_tty = 0;
struct winsize ws; struct winsize ws;
int authfd;
char *cp; char *cp;
/* Enable compression if requested. */ /* Enable compression if requested. */
@ -845,14 +876,10 @@ ssh_session(void)
/* Tell the packet module whether this is an interactive session. */ /* Tell the packet module whether this is an interactive session. */
packet_set_interactive(interactive, options.keepalives); 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. */ /* Request authentication agent forwarding if appropriate. */
check_agent_present();
if (options.forward_agent) { if (options.forward_agent) {
debug("Requesting authentication agent forwarding."); debug("Requesting authentication agent forwarding.");
auth_request_forwarding(); auth_request_forwarding();
@ -863,28 +890,9 @@ ssh_session(void)
if (type != SSH_SMSG_SUCCESS) if (type != SSH_SMSG_SUCCESS)
log("Warning: Remote host denied authentication agent forwarding."); 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. */ /* Initiate port forwardings. */
for (i = 0; i < options.num_remote_forwards; i++) { ssh_init_forwarding();
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);
}
/* If requested, let ssh continue in the background. */ /* If requested, let ssh continue in the background. */
if (fork_after_authentication_flag) if (fork_after_authentication_flag)
@ -915,27 +923,10 @@ ssh_session(void)
return client_loop(have_tty, tty_flag ? options.escape_char : -1, 0); 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); extern void client_set_session_ident(int id);
void void
client_init(int id, void *arg) ssh_session2_callback(int id, void *arg)
{ {
int len; int len;
debug("client_init id %d arg %d", id, (int)arg); debug("client_init id %d arg %d", id, (int)arg);
@ -974,6 +965,13 @@ client_init(int id, void *arg)
/* XXX wait for reply */ /* 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); len = buffer_len(&command);
if (len > 0) { if (len > 0) {
if (len > 900) if (len > 900)
@ -1016,8 +1014,8 @@ ssh_session2(void)
if (!isatty(err)) if (!isatty(err))
set_nonblock(err); set_nonblock(err);
/* should be pre-session */ /* XXX should be pre-session */
init_local_fwd(); ssh_init_forwarding();
/* If requested, let ssh continue in the background. */ /* If requested, let ssh continue in the background. */
if (fork_after_authentication_flag) if (fork_after_authentication_flag)
@ -1036,7 +1034,28 @@ ssh_session2(void)
xstrdup("client-session"), /*nonblock*/0); xstrdup("client-session"), /*nonblock*/0);
channel_open(id); channel_open(id);
channel_register_callback(id, SSH2_MSG_CHANNEL_OPEN_CONFIRMATION, client_init, (void *)0); channel_register_callback(id, SSH2_MSG_CHANNEL_OPEN_CONFIRMATION,
ssh_session2_callback, (void *)0);
return client_loop(tty_flag, tty_flag ? options.escape_char : -1, id); 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 # Site-wide defaults for various options
# Host * # Host *
# ForwardAgent yes # ForwardAgent no
# ForwardX11 yes # ForwardX11 no
# RhostsAuthentication yes # RhostsAuthentication no
# RhostsRSAAuthentication yes # RhostsRSAAuthentication yes
# RSAAuthentication yes # RSAAuthentication yes
# PasswordAuthentication yes # PasswordAuthentication yes
@ -23,9 +23,12 @@
# UseRsh no # UseRsh no
# BatchMode no # BatchMode no
# CheckHostIP yes # CheckHostIP yes
# StrictHostKeyChecking no # StrictHostKeyChecking yes
# IdentityFile ~/.ssh/identity # IdentityFile ~/.ssh/identity
# IdentityFile ~/.ssh/id_dsa
# IdentityFile ~/.ssh/id_rsa1
# IdentityFile ~/.ssh/id_rsa2
# Port 22 # Port 22
# Protocol 2,1 # Protocol 1,2
# Cipher blowfish # Cipher blowfish
# EscapeChar ~ # EscapeChar ~

View File

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

View File

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

View File

@ -23,7 +23,7 @@
*/ */
#include "includes.h" #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/bn.h>
#include <openssl/rsa.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 "kex.h"
#include "myproposal.h" #include "myproposal.h"
#include "key.h" #include "key.h"
#include "dsa.h"
#include "sshconnect.h" #include "sshconnect.h"
#include "authfile.h" #include "authfile.h"
#include "cli.h" #include "cli.h"
@ -196,7 +195,7 @@ ssh_dh1_client(Kex *kex, char *host, struct sockaddr *hostaddr,
/* key, cert */ /* key, cert */
server_host_key_blob = packet_get_string(&sbloblen); 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) if (server_host_key == NULL)
fatal("cannot decode server_host_key_blob"); 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, "%02x", (hash[i])&0xff);
fprintf(stderr, "\n"); fprintf(stderr, "\n");
#endif #endif
if (dsa_verify(server_host_key, (unsigned char *)signature, slen, hash, 20) != 1) if (key_verify(server_host_key, (unsigned char *)signature, slen, hash, 20) != 1)
fatal("dsa_verify failed for server_host_key"); fatal("key_verify failed for server_host_key");
key_free(server_host_key); key_free(server_host_key);
kex_derive_keys(kex, hash, shared_secret); kex_derive_keys(kex, hash, shared_secret);
@ -366,7 +365,7 @@ ssh_dhgex_client(Kex *kex, char *host, struct sockaddr *hostaddr,
/* key, cert */ /* key, cert */
server_host_key_blob = packet_get_string(&sbloblen); 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) if (server_host_key == NULL)
fatal("cannot decode server_host_key_blob"); 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, "%02x", (hash[i])&0xff);
fprintf(stderr, "\n"); fprintf(stderr, "\n");
#endif #endif
if (dsa_verify(server_host_key, (unsigned char *)signature, slen, hash, 20) != 1) if (key_verify(server_host_key, (unsigned char *)signature, slen, hash, 20) != 1)
fatal("dsa_verify failed for server_host_key"); fatal("key_verify failed for server_host_key");
key_free(server_host_key); key_free(server_host_key);
kex_derive_keys(kex, hash, shared_secret); kex_derive_keys(kex, hash, shared_secret);
@ -485,7 +484,7 @@ Authmethod *authmethod_lookup(const char *name);
Authmethod authmethods[] = { Authmethod authmethods[] = {
{"publickey", {"publickey",
userauth_pubkey, userauth_pubkey,
&options.dsa_authentication, &options.pubkey_authentication,
NULL}, NULL},
{"password", {"password",
userauth_passwd, userauth_passwd,
@ -653,8 +652,10 @@ sign_and_send_pubkey(Authctxt *authctxt, Key *k, sign_cb_fn *sign_callback)
int ret = -1; int ret = -1;
int have_sig = 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 */ /* data to be signed */
buffer_init(&b); buffer_init(&b);
if (datafellows & SSH_OLD_SESSIONID) { if (datafellows & SSH_OLD_SESSIONID) {
@ -672,7 +673,7 @@ sign_and_send_pubkey(Authctxt *authctxt, Key *k, sign_cb_fn *sign_callback)
authctxt->service); authctxt->service);
buffer_put_cstring(&b, authctxt->method->name); buffer_put_cstring(&b, authctxt->method->name);
buffer_put_char(&b, have_sig); 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); buffer_put_string(&b, blob, bloblen);
/* generate signature */ /* generate signature */
@ -682,7 +683,7 @@ sign_and_send_pubkey(Authctxt *authctxt, Key *k, sign_cb_fn *sign_callback)
buffer_free(&b); buffer_free(&b);
return 0; return 0;
} }
#ifdef DEBUG_DSS #ifdef DEBUG_PK
buffer_dump(&b); buffer_dump(&b);
#endif #endif
if (datafellows & SSH_BUG_PUBKEYAUTH) { 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->service);
buffer_put_cstring(&b, authctxt->method->name); buffer_put_cstring(&b, authctxt->method->name);
buffer_put_char(&b, have_sig); 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); buffer_put_string(&b, blob, bloblen);
} }
xfree(blob); xfree(blob);
@ -719,10 +720,10 @@ sign_and_send_pubkey(Authctxt *authctxt, Key *k, sign_cb_fn *sign_callback)
} }
/* 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) unsigned char *data, int datalen)
{ {
return dsa_sign(key, sigp, lenp, data, datalen); return key_sign(key, sigp, lenp, data, datalen);
} }
int int
@ -738,14 +739,13 @@ userauth_pubkey_identity(Authctxt *authctxt, char *filename)
} }
debug("try pubkey: %s", filename); debug("try pubkey: %s", filename);
k = key_new(KEY_DSA); k = key_new(KEY_UNSPEC);
if (!load_private_key(filename, "", k, NULL)) { if (!load_private_key(filename, "", k, NULL)) {
int success = 0; int success = 0;
char *passphrase; char *passphrase;
char prompt[300]; char prompt[300];
snprintf(prompt, sizeof prompt, snprintf(prompt, sizeof prompt,
"Enter passphrase for %s key '%.100s': ", "Enter passphrase for key '%.100s': ", filename);
key_type(k), filename);
for (i = 0; i < options.number_of_password_prompts; i++) { for (i = 0; i < options.number_of_password_prompts; i++) {
passphrase = read_passphrase(prompt, 0); passphrase = read_passphrase(prompt, 0);
if (strcmp(passphrase, "") != 0) { if (strcmp(passphrase, "") != 0) {
@ -766,7 +766,7 @@ userauth_pubkey_identity(Authctxt *authctxt, char *filename)
return 0; 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); key_free(k);
return ret; return ret;
} }
@ -782,24 +782,26 @@ int
userauth_pubkey_agent(Authctxt *authctxt) userauth_pubkey_agent(Authctxt *authctxt)
{ {
static int called = 0; static int called = 0;
int ret = 0;
char *comment; char *comment;
Key *k; Key *k;
int ret;
if (called == 0) { 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; called = 1;
} else {
k = ssh_get_next_identity(authctxt->agent, &comment, 2);
} }
k = ssh_get_next_identity(authctxt->agent, &comment, 2);
if (k == NULL) { if (k == NULL) {
debug2("no more DSA keys from agent"); debug2("userauth_pubkey_agent: no more keys");
return 0; } 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); if (ret == 0)
xfree(comment); debug2("userauth_pubkey_agent: no message sent");
ret = sign_and_send_pubkey(authctxt, k, agent_sign_cb);
key_free(k);
return ret; return ret;
} }
@ -809,10 +811,17 @@ userauth_pubkey(Authctxt *authctxt)
static int idx = 0; static int idx = 0;
int sent = 0; int sent = 0;
if (authctxt->agent != NULL) if (authctxt->agent != NULL) {
sent = userauth_pubkey_agent(authctxt); do {
while (sent == 0 && idx < options.num_identity_files2) sent = userauth_pubkey_agent(authctxt);
sent = userauth_pubkey_identity(authctxt, options.identity_files2[idx++]); } 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; return sent;
} }

30
sshd.8
View File

@ -34,7 +34,7 @@
.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF .\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. .\" 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 .Dd September 25, 1999
.Dt SSHD 8 .Dt SSHD 8
.Os .Os
@ -144,7 +144,7 @@ through a cryptographic message authentication code
(hmac-sha1 or hmac-md5). (hmac-sha1 or hmac-md5).
.Pp .Pp
Protocol version 2 provides a public key based Protocol version 2 provides a public key based
user authentication method (DSAAuthentication) user authentication method (PubkeyAuthentication)
and conventional password authentication. and conventional password authentication.
.Pp .Pp
.Ss Command execution and data forwarding .Ss Command execution and data forwarding
@ -359,8 +359,8 @@ and
can be used as wildcards in the patterns. can be used as wildcards in the patterns.
Only user names are valid; a numerical user ID isn't recognized. Only user names are valid; a numerical user ID isn't recognized.
By default login is allowed regardless of the user name. By default login is allowed regardless of the user name.
.It Cm DSAAuthentication .It Cm PubkeyAuthentication
Specifies whether DSA authentication is allowed. Specifies whether public key authentication is allowed.
The default is The default is
.Dq yes . .Dq yes .
Note that this option applies to protocol version 2 only. Note that this option applies to protocol version 2 only.
@ -373,20 +373,20 @@ or
.Dq no . .Dq no .
The default is The default is
.Dq no . .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 .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 ) .Pa /etc/ssh_host_key )
used by SSH protocols 1.3 and 1.5. used by SSH protocol versions 1 and 2.
Note that Note that
.Nm .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 .It Cm IgnoreRhosts
Specifies that Specifies that
.Pa .rhosts .Pa .rhosts
@ -1039,7 +1039,7 @@ This can be used to specify
machine-specific login-time initializations globally. machine-specific login-time initializations globally.
This file should be writable only by root, and should be world-readable. This file should be writable only by root, and should be world-readable.
.El .El
.Sh AUTHOR .Sh AUTHORS
OpenSSH OpenSSH
is a derivative of the original (free) ssh 1.2.12 release by Tatu Ylonen, is a derivative of the original (free) ssh 1.2.12 release by Tatu Ylonen,
but with bugs removed and newer features re-added. but with bugs removed and newer features re-added.

318
sshd.c
View File

@ -40,7 +40,7 @@
*/ */
#include "includes.h" #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 "xmalloc.h"
#include "rsa.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/dsa.h>
#include <openssl/rsa.h> #include <openssl/rsa.h>
#include "key.h" #include "key.h"
#include "dsa.h"
#include "dh.h" #include "dh.h"
#include "auth.h" #include "auth.h"
@ -140,9 +139,11 @@ char *server_version_string = NULL;
* not very useful. Currently, memory locking is not implemented. * not very useful. Currently, memory locking is not implemented.
*/ */
struct { struct {
RSA *private_key; /* Private part of empheral server key. */ Key *server_key; /* empheral server key */
RSA *host_key; /* Private part of host key. */ Key *ssh1_host_key; /* ssh1 host key */
Key *dsa_host_key; /* Private DSA host key. */ Key **host_keys; /* all private host keys */
int have_ssh1_key;
int have_ssh2_key;
} sensitive_data; } sensitive_data;
/* /*
@ -154,10 +155,6 @@ int key_used = 0;
/* This is set to true when SIGHUP is received. */ /* This is set to true when SIGHUP is received. */
int received_sighup = 0; 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 */ /* session identifier, used by RSA-auth */
unsigned char session_id[16]; 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 */ /* XXX do we really want this work to be done in a signal handler ? -m */
void 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) key_regeneration_alarm(int sig)
{ {
int save_errno = errno; int save_errno = errno;
@ -273,21 +281,8 @@ key_regeneration_alarm(int sig)
/* Check if we should generate a new key. */ /* Check if we should generate a new key. */
if (key_used) { if (key_used) {
/* This should really be done in the background. */ /* This should really be done in the background. */
log("Generating new %d bit RSA key.", options.server_key_bits); generate_empheral_server_key();
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();
key_used = 0; key_used = 0;
log("RSA key generation complete.");
} }
/* Reschedule the alarm. */ /* Reschedule the alarm. */
signal(SIGALRM, key_regeneration_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 void
destroy_sensitive_data(void) destroy_sensitive_data(void)
{ {
/* Destroy the private and public keys. They will no longer be needed. */ int i;
if (public_key)
RSA_free(public_key); if (sensitive_data.server_key) {
if (sensitive_data.private_key) key_free(sensitive_data.server_key);
RSA_free(sensitive_data.private_key); sensitive_data.server_key = NULL;
if (sensitive_data.host_key) }
RSA_free(sensitive_data.host_key); for(i = 0; i < options.num_host_key_files; i++) {
if (sensitive_data.dsa_host_key != NULL) if (sensitive_data.host_keys[i]) {
key_free(sensitive_data.dsa_host_key); 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); options.key_regeneration_time = atoi(optarg);
break; break;
case 'h': 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; break;
case 'V': case 'V':
client_version_string = optarg; client_version_string = optarg;
@ -610,39 +684,39 @@ main(int ac, char **av)
debug("sshd version %.100s", SSH_VERSION); debug("sshd version %.100s", SSH_VERSION);
sensitive_data.dsa_host_key = NULL; /* load private host keys */
sensitive_data.host_key = NULL; 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 */ for(i = 0; i < options.num_host_key_files; i++) {
if ((options.protocol & SSH_PROTO_1) && Key *key = load_private_key_autodetect(options.host_key_files[i]);
rsa_alive() == 0) { if (key == NULL) {
log("no RSA support in libssl and libcrypto. See ssl(8)"); error("Could not load host key: %.200s: %.100s",
log("Disabling protocol version 1"); 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; options.protocol &= ~SSH_PROTO_1;
} }
/* Load the RSA/DSA host key. It must have empty passphrase. */ if ((options.protocol & SSH_PROTO_2) && !sensitive_data.have_ssh2_key) {
if (options.protocol & SSH_PROTO_1) { log("Disabling protocol version 2. Could not load host key");
Key k; options.protocol &= ~SSH_PROTO_2;
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_1|SSH_PROTO_2)) { if (! options.protocol & (SSH_PROTO_1|SSH_PROTO_2)) {
if (silent == 0) if (silent == 0)
@ -664,11 +738,11 @@ main(int ac, char **av)
* hate software patents. I dont know if this can go? Niels * hate software patents. I dont know if this can go? Niels
*/ */
if (options.server_key_bits > 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 < 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 = 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.", debug("Forcing server key to %d bits to make it differ from host key.",
options.server_key_bits); options.server_key_bits);
} }
@ -707,9 +781,6 @@ main(int ac, char **av)
/* Reinitialize the log (because of the fork above). */ /* Reinitialize the log (because of the fork above). */
log_init(av0, options.log_level, options.log_facility, log_stderr); 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. */ /* Initialize the random number generator. */
arc4random_stir(); arc4random_stir();
@ -731,16 +802,8 @@ main(int ac, char **av)
* ttyfd happens to be one of those. * ttyfd happens to be one of those.
*/ */
debug("inetd sockets after dupping: %d, %d", sock_in, sock_out); debug("inetd sockets after dupping: %d, %d", sock_in, sock_out);
if (options.protocol & SSH_PROTO_1)
if (options.protocol & SSH_PROTO_1) { generate_empheral_server_key();
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.");
}
} else { } else {
for (ai = options.listen_addrs; ai; ai = ai->ai_next) { for (ai = options.listen_addrs; ai; ai = ai->ai_next) {
if (ai->ai_family != AF_INET && ai->ai_family != AF_INET6) 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) { if (options.protocol & SSH_PROTO_1) {
public_key = RSA_new(); generate_empheral_server_key();
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.");
/* Schedule server key regeneration alarm. */ /* Schedule server key regeneration alarm. */
signal(SIGALRM, key_regeneration_alarm); signal(SIGALRM, key_regeneration_alarm);
@ -1065,6 +1121,8 @@ main(int ac, char **av)
*/ */
if (remote_port >= IPPORT_RESERVED || if (remote_port >= IPPORT_RESERVED ||
remote_port < IPPORT_RESERVED / 2) { remote_port < IPPORT_RESERVED / 2) {
debug("Rhosts Authentication methods disabled, "
"originating port not trusted.");
options.rhosts_authentication = 0; options.rhosts_authentication = 0;
options.rhosts_rsa_authentication = 0; options.rhosts_rsa_authentication = 0;
} }
@ -1145,14 +1203,14 @@ do_ssh1_kex()
packet_put_char(cookie[i]); packet_put_char(cookie[i]);
/* Store our public server RSA key. */ /* Store our public server RSA key. */
packet_put_int(BN_num_bits(public_key->n)); packet_put_int(BN_num_bits(sensitive_data.server_key->rsa->n));
packet_put_bignum(public_key->e); packet_put_bignum(sensitive_data.server_key->rsa->e);
packet_put_bignum(public_key->n); packet_put_bignum(sensitive_data.server_key->rsa->n);
/* Store our public host RSA key. */ /* Store our public host RSA key. */
packet_put_int(BN_num_bits(sensitive_data.host_key->n)); packet_put_int(BN_num_bits(sensitive_data.ssh1_host_key->rsa->n));
packet_put_bignum(sensitive_data.host_key->e); packet_put_bignum(sensitive_data.ssh1_host_key->rsa->e);
packet_put_bignum(sensitive_data.host_key->n); packet_put_bignum(sensitive_data.ssh1_host_key->rsa->n);
/* Put protocol flags. */ /* Put protocol flags. */
packet_put_int(SSH_PROTOFLAG_HOST_IN_FWD_OPEN); packet_put_int(SSH_PROTOFLAG_HOST_IN_FWD_OPEN);
@ -1190,8 +1248,9 @@ do_ssh1_kex()
packet_send(); packet_send();
packet_write_wait(); packet_write_wait();
debug("Sent %d bit public key and %d bit host key.", debug("Sent %d bit server key and %d bit host key.",
BN_num_bits(public_key->n), BN_num_bits(sensitive_data.host_key->n)); 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). */ /* Read clients reply (cipher type and session key). */
packet_read_expect(&plen, SSH_CMSG_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 * Decrypt it using our private server key and private host key (key
* with larger modulus first). * 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. */ /* Private key has bigger modulus. */
if (BN_num_bits(sensitive_data.private_key->n) < if (BN_num_bits(sensitive_data.server_key->rsa->n) <
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) {
fatal("do_connection: %s: private_key %d < host_key %d + SSH_KEY_BITS_RESERVED %d", fatal("do_connection: %s: server_key %d < host_key %d + SSH_KEY_BITS_RESERVED %d",
get_remote_ipaddr(), get_remote_ipaddr(),
BN_num_bits(sensitive_data.private_key->n), BN_num_bits(sensitive_data.server_key->rsa->n),
BN_num_bits(sensitive_data.host_key->n), BN_num_bits(sensitive_data.ssh1_host_key->rsa->n),
SSH_KEY_BITS_RESERVED); SSH_KEY_BITS_RESERVED);
} }
rsa_private_decrypt(session_key_int, session_key_int, 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, rsa_private_decrypt(session_key_int, session_key_int,
sensitive_data.host_key); sensitive_data.ssh1_host_key->rsa);
} else { } else {
/* Host key has bigger modulus (or they are equal). */ /* Host key has bigger modulus (or they are equal). */
if (BN_num_bits(sensitive_data.host_key->n) < if (BN_num_bits(sensitive_data.ssh1_host_key->rsa->n) <
BN_num_bits(sensitive_data.private_key->n) + SSH_KEY_BITS_RESERVED) { BN_num_bits(sensitive_data.server_key->rsa->n) + SSH_KEY_BITS_RESERVED) {
fatal("do_connection: %s: host_key %d < private_key %d + SSH_KEY_BITS_RESERVED %d", fatal("do_connection: %s: host_key %d < server_key %d + SSH_KEY_BITS_RESERVED %d",
get_remote_ipaddr(), get_remote_ipaddr(),
BN_num_bits(sensitive_data.host_key->n), BN_num_bits(sensitive_data.ssh1_host_key->rsa->n),
BN_num_bits(sensitive_data.private_key->n), BN_num_bits(sensitive_data.server_key->rsa->n),
SSH_KEY_BITS_RESERVED); SSH_KEY_BITS_RESERVED);
} }
rsa_private_decrypt(session_key_int, session_key_int, 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, rsa_private_decrypt(session_key_int, session_key_int,
sensitive_data.private_key); sensitive_data.server_key->rsa);
} }
compute_session_id(session_id, cookie, compute_session_id(session_id, cookie,
sensitive_data.host_key->n, sensitive_data.ssh1_host_key->rsa->n,
sensitive_data.private_key->n); sensitive_data.server_key->rsa->n);
/* Destroy the private and public keys. They will no longer be needed. */ /* Destroy the private and public keys. They will no longer be needed. */
destroy_sensitive_data(); destroy_sensitive_data();
@ -1269,8 +1328,8 @@ do_ssh1_kex()
len = BN_num_bytes(session_key_int); len = BN_num_bytes(session_key_int);
if (len < 0 || len > sizeof(session_key)) if (len < 0 || len > sizeof(session_key))
fatal("do_connection: bad len from %s: session_key_int %d > sizeof(session_key) %d", fatal("do_connection: bad len from %s: session_key_int %d > sizeof(session_key) %d",
get_remote_ipaddr(), get_remote_ipaddr(),
len, (int) sizeof(session_key)); len, sizeof(session_key));
memset(session_key, 0, sizeof(session_key)); memset(session_key, 0, sizeof(session_key));
BN_bn2bin(session_key_int, session_key + sizeof(session_key) - len); 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_CTOS] =
myproposal[PROPOSAL_ENC_ALGS_STOC] = options.ciphers; myproposal[PROPOSAL_ENC_ALGS_STOC] = options.ciphers;
} }
myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] = list_hostkey_types();
server_kexinit = kex_init(myproposal); server_kexinit = kex_init(myproposal);
client_kexinit = xmalloc(sizeof(*client_kexinit)); client_kexinit = xmalloc(sizeof(*client_kexinit));
buffer_init(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; BIGNUM *shared_secret = 0;
DH *dh; DH *dh;
BIGNUM *dh_client_pub = 0; 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 */ /* KEXDH */
debug("Wait SSH2_MSG_KEXDH_INIT."); debug("Wait SSH2_MSG_KEXDH_INIT.");
@ -1431,8 +1497,7 @@ ssh_dh1_server(Kex *kex, Buffer *client_kexinit, Buffer *server_kexinit)
xfree(kbuf); xfree(kbuf);
/* XXX precompute? */ /* XXX precompute? */
dsa_make_key_blob(sensitive_data.dsa_host_key, key_to_blob(hostkey, &server_host_key_blob, &sbloblen);
&server_host_key_blob, &sbloblen);
/* calc H */ /* XXX depends on 'kex' */ /* calc H */ /* XXX depends on 'kex' */
hash = kex_hash( hash = kex_hash(
@ -1463,7 +1528,7 @@ ssh_dh1_server(Kex *kex, Buffer *client_kexinit, Buffer *server_kexinit)
/* sign H */ /* sign H */
/* XXX hashlen depends on KEX */ /* 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(); destroy_sensitive_data();
@ -1503,6 +1568,11 @@ ssh_dhgex_server(Kex *kex, Buffer *client_kexinit, Buffer *server_kexinit)
BIGNUM *shared_secret = 0; BIGNUM *shared_secret = 0;
DH *dh; DH *dh;
BIGNUM *dh_client_pub = 0; 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 */ /* KEXDHGEX */
debug("Wait SSH2_MSG_KEX_DH_GEX_REQUEST."); 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); xfree(kbuf);
/* XXX precompute? */ /* XXX precompute? */
dsa_make_key_blob(sensitive_data.dsa_host_key, key_to_blob(hostkey, &server_host_key_blob, &sbloblen);
&server_host_key_blob, &sbloblen);
/* calc H */ /* XXX depends on 'kex' */ /* calc H */ /* XXX depends on 'kex' */
hash = kex_hash_gex( hash = kex_hash_gex(
@ -1597,7 +1666,7 @@ ssh_dhgex_server(Kex *kex, Buffer *client_kexinit, Buffer *server_kexinit)
/* sign H */ /* sign H */
/* XXX hashlen depends on KEX */ /* 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(); destroy_sensitive_data();
@ -1617,4 +1686,3 @@ ssh_dhgex_server(Kex *kex, Buffer *client_kexinit, Buffer *server_kexinit)
/* have keys, free DH */ /* have keys, free DH */
DH_free(dh); DH_free(dh);
} }

View File

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